How to disable DirectX in JUCE 8?

Although this seems simple on the surface, after a bit of investigation this change raises some difficult issues:

Essentially, ClearType rendering is unsuitable when

  • the render target has translucent pixels underneath rendered text, or
  • the render ouput is rotated, scaled, subpixel-translated, or otherwise transformed before display.

This necessitates avoiding ClearType when rendering into transparent bitmaps. Unfortunately, a commmon use-case for transparent bitmaps is buffered component images. If ClearType were enabled for opaque targets but disabled otherwise, ClearType text could then end up displaying next to non-ClearType text rendered to an intermediate texture, leading to an inconsistent appearance.

In short, I’m inclined to revert the antialiasing change, and to go back to using grayscale rendering unconditionally. This approach is guaranteed to give a consistent appearance whether rendering directly to the screen or to a bitmap. My feeling is that consistent grayscale rendering is preferable to mixing ClearType and grayscale - does that sound like a reasonable assumption?

4 Likes

Are you sure of that?
My whole main component is scaled (resizable UI) and the subpixel coloring seems to be working as expected.
Or do you mean when specifically rendered to an image?

Could this be settable so we can choose to use it or not? Ideally for a given context, but this could also be a simple define.

I’m talking about rendering to an image. Subpixel antialiasing relies on the exact locations of the subpixels, so if the image is transformed after rendering then it may no longer line up exactly with the expected subpixels, leading to colour fringing.

I’ve discussed my preference for runtime options over buildtime flags earlier in this thread. I also don’t think a global flag is a good fit. Even if we allow ClearType in opaque windows, users may then want to toggle it when rendering to images depending on whether the text drawn into those images falls on opaque or transparent background pixels.

I’m struggling a bit with how a runtime API would look. Intuitively, we’d add a setTextAntiAliasingKind function onto Graphics, but this wouldn’t be very usable. To modify the antialiasing kind of an existing component, a user would need to modify or override the paint function of that component to update the antialiasing mode before drawing each piece of text. This would quickly get unweildy for deep trees of components.

Given that:

  • mixing grayscale and ClearType is likely to look bad,
  • adding a new antialiasing API is likely to require large changes to the framework in order to be usable,
  • the only anti-aliasing option available previously on Windows was grayscale (not subpixel), and
  • the only anti-aliasing mode available on other platforms (macOS, iOS, Linux, Android) is grayscale, so a new API would only affect rendering on Windows,

I’m inclined to say that we should stick with grayscale rendering and avoid ClearType.

2 Likes

This is very bad news as finally, JUCE text rendering started to look okay on Windows. Instead of just reverting the changes, please make them at least optional for those of use who care about how text looks next to ā€œnativeā€ apps on the Windows platform.

1 Like

Or you could just fork, make the change and continuously (automated with a GitHub workflow) merge any JUCE changes into your fork. Then you have an always up to date version with your cleartype change.

If the image is scaled then the font will be a blurry mess anyway.

By the way this is exactly what happens when using bufferedToImage with a scaled UI: fonts are often blurry due to rounding errors forcing a resize of the image. This forced me to get rid of bufferedToImage components altogether, and Direct2D made this possible while maintaining good (even better) performance.

ref: https://forum.juce.com/t/alternatives-to-affinetransform-scale-for-ui-scaling/60543

Regarding integration challenges in the framework, I understand your point, but I allow me to try and convince you otherwise :slight_smile:

JUCE7 was indeed using greyscale but I would say the new hinting method in JUCE8 make the issues more visible.
I don’t know how cleartype integration could be addressed, but speaking for myself I would be happy with a global setting (be it a define or a runtime thing) that would do the right thing when enabled (ie using cleartype when it is set in the OS, and resort to greyscale for images).

Font rendering is an important consideration, and I would love to see JUCE8 improve over JUCE7 on this. I feel like cleartype support would really bring something to the table and should warrant a define, like we already have for other font aspects for woth Windows and MacOS (eg JUCE_DISABLE_COREGRAPHICS_FONT_SMOOTHING and JUCE_USE_DIRECTWRITE).

A scaled-up image with ClearType text can look objectively worse due to the colored subpixel fringes being more visible. Scaling down an image even slightly can cause these subpixels to misalign.

Microsoft has shifted away from using ClearType in many of its native apps in Windows 11. For instance, the redesigned Windows Terminal and Paint apps in Windows 11 do not use ClearType, nor do apps such as Calendar, Calculator, Store, and Photos. Even the Start menu in the latest Windows 11 also lacks ClearType. Microsoft has also removed ClearType as the default option in Office apps such as Word and Excel since the 2013 versions.

Here are some screenshots of various apps mentioned above, showing they do not use ClearType. I’ve verified that ClearType was enabled and confirmed this on another system with a fresh install of Windows 11 as well.

Test System: Windows 11 23H2

Word
ms-word

Terminal
ms-terminal

Start Menu
start-menu

1 Like

Some details about this.

1 Like

This shows that using clearType or not is a situational decision, not a framework one, and should be up to the designer of the application.

Beside, considering the environment our apps will typically be used into, I checked different DAWs to see what type of font smoothing they were using:

  • Reaper: clearType
  • Ableton Live: clearType
  • FL Studio: clearType
  • Cubase: clearType
  • ProTools: clearType
  • StudioOne: clearType
  • Cakewalk: mix of clearType and greyscale
  • Bitwig Studio: clearType
  • Tracktion: greyScale
2 Likes

The problem is that ā€œdoing the right thingā€ is a difficult problem, and is evidently subjective.

I’ve already explained that a global setting is not a good fit for this feature. Using grayscale unconditionally when rendering to an image is not a good solution, because it’s likely that cleartype and non-cleartype text will end up displayed in close proximity when buffering component images. To cover all use-cases, users would end up needing to toggle ClearType on an image-by-image basis, or even for each run of text inside an image.

JUCE_USE_DIRECTWRITE no longer has any effect. JUCE_DISABLE_COREGRAPHICS_FONT_SMOOTHING is less situational than ClearType: text rendering to screen and to image will work and look consistent, whether rendering to screen or to image, and whether this option is set or not.

I agree, and to allow such a situational decision, we’d ideally have some way of enabling/disabling ClearType before rendering any given piece of text. However, adding such an API is very difficult to justify given that it would require large changes to the framework for a feature that would only have an effect on Windows.

This isn’t an easy decision; it feels like there are trade-offs to every potential solution here. However, I think that sticking to grayscale rendering everywhere is the least bad option for all of the reasons I’ve previously mentioned.

Can we get a warning from JUCE in case the client project that uses JUCE still #defines it?

Many developers like me share the same desire of the JUCE team to reduce the dependency upon compile time macros. It would be nice if we could get a warning when a compile time macro for JUCE gets phased out and setting it in the client project has no longer any effect. Thanks

2 Likes

One thing I realized: most of my comparisons (software vs d2d with or without cleartype) have been done with a standalone app and a 200% DPI setting, and with a scalable UI (ie scale transform on the main component based on window size).

For some reason it looks like in this context VST3 does not suffer the same problems, at least not to the same amount: software and d2d are much closer.

Even more suprising: it looks like d2d SVG rendering is also worse in standalone mode whereas it is pretty similar (and better) to software in VST3 mode.

Could this be due to UI scale (both affine transforme and OS DPI) not being interpreted correctly in standalone?

The main difference between Standalone and VST3 scaling is that VST3s are dependent on the host to both provide a scaling-aware window, and to provide an appropriate scale factor to use. A JUCE Standalone will normally take the display’s native scale into account automatically. I’m assuming you’re testing in a host that renders the plugin view at the display’s scale (if in Live, ensure auto-scaling of plugin windows is off).

I think that JUCE plugins on Windows always treat the display as having a scale of 1 (96 DPI). I wonder whether Direct2D adjusts anti-aliasing or other aspects of text rendering based on the target DPI. I haven’t investigated this, so this is just a theory, but it might account for differences between Standalone and VST3 rendering. If this were happening, then I’d expect the Standalone to be passing the correct screen DPI into the D2D context, so the results should be better there.

This is surprising. Are you able to provide some side-by-side examples of rendering in the Standalone and VST3 so that we can see the differences? ā€œworseā€ is subjective, so it’d be helpful to see exactly what is different between the two targets.

1 Like

That is also my hunch, maybe hinting?

I am using Reaper which correctly handle DPI settings.

I will try to build an example, but from what I remember there is a difference in what g.getInternalContext().getPhysicalPixelScaleFactor() reports in standalone vs VST3. It should be the product of the affine transform scale and DPI setting, but this is not the case for all formats IIRC.

To follow up, the text antialiasing on develop has now been reverted to grayscale mode:

Hi there
We would also like to continue supporting Windows 7, while using Juce 8.
Is there a way to achieve this ?
Thanks

I was wondering why not DirectX 11.0 instead of the latest?
I thought the Windows platform can cope with all past versions of it.

The JUCE Direct2D renderer is built on top of Direct2D 1.3, which in turn runs on top of Direct3D 11.

Matt

1 Like

I see, OK, thanks. Windows 7 was shipped with 11.0 it seems. Why can’t we build with that one?