postprocessing icon indicating copy to clipboard operation
postprocessing copied to clipboard

MipMapBlur ugly rendering on mac with transparent background

Open Beilinson opened this issue 2 years ago • 24 comments

Description of the bug

When using the BloomEffect/SelectiveBloom effect with mipmapBlur: true on windows with a transparent background the effect has a nice roll-off, especially with higher radius and low smoothing values.

The exact same setup on MacOS renders with ugly banding and what seems like significantly lower mipMap levels, to the point that there is no roll-off.

To Reproduce

I have replicated the exact settings used by <model-viewer> in this sandbox.

https://codesandbox.io/s/bloom-transparent-zpn7iw?file=/src/App.js

Screenshots

Windows, IOS render like this: image

MacOS renders like this: Screen Shot 2023-04-10 at 23 02 39

Library versions used

  • Three: [e.g. 1.151.3]
  • Post Processing: [e.g. 6.30.2]

Desktop

  • OS: MacOS
  • Browser [Chrome, Firefox]
  • Graphics hardware: [M1, Intel HD Graphics]

Additional comments:

I have checked all WebGL compatibility issues I could have thought of, with https://webglreport.com/?v=2. Both desktops that created the screenshots support OES_texture_float_linear, 'highp' precision. The max samples is different (16 vs 8), but that is not enough to explain the difference since the default mimapblur uses 8 levels and I have not altered it. I can also confirm this does not happen with alpha: false on the WebGLRenderer.

Beilinson avatar Apr 10 '23 20:04 Beilinson

After several hours of testing different options and playing with chrome://flags and comparing chrome://gpu settings I have found the issue: The sRGB transfer function of the display. The default display color profile Color LCD on macbooks has the following transfer function:

0.0777*x + 0 if x < 0.0450 else (0.9495*x + 0.0495)**2.3955 + 0.0003

I'm not too sure how exactly the transfer function works, but switching the color profile from Color LCD to sRGB (which is the default transfer function on windows) completely fixed the issue. I'm interested to figure out if this could be considered a WebGL/three.js issue; I noticed that if I take a screenshot using the firefox screenshot tool, the end result does not have the transfer function issue. However if I screenshot using the inbuilt mac screenshot tool then the issue persists.

Beilinson avatar Apr 11 '23 13:04 Beilinson

Thanks for reporting and investigating this :+1:

It doesn't look like this can be fixed in postprocessing. I'll add the device issue tag for now.

vanruesc avatar Apr 11 '23 23:04 vanruesc

image

I have reproduced it on windows as well by setting the Color Profile to anything but the default sRGB IEC61966-2.1, so this isn't a platform specific issue at all, just that only macOS sets the default Color Profile to something other than sRGB.

Beilinson avatar Apr 12 '23 00:04 Beilinson

@mrdoob Any idea if this is a three.js issue? I'm hoping since the results are consistent across devices and browsers (only affected by the color profile) that it's not a WebGL problem.

elalish avatar Apr 12 '23 16:04 elalish

@Beilinson The fullscreen materials in postprocessing all use NoBlending. Could you please try setting that to NormalBlending on macOS to see if that changes anything?

  effectPass.fullscreenMaterial.blending = NormalBlending;
  bloomEffect.luminanceMaterial.blending = NormalBlending;
  bloomEffect.mipmapBlurPass.upsamplingMaterial.blending = NormalBlending;
  bloomEffect.mipmapBlurPass.downsamplingMaterial.blending = NormalBlending;

vanruesc avatar Apr 12 '23 21:04 vanruesc

@vanruesc Just tested it, makes no difference.

Beilinson avatar Apr 12 '23 21:04 Beilinson

Alright, was worth a shot. Thanks for checking :+1:

vanruesc avatar Apr 12 '23 21:04 vanruesc

@WestLangley This is the example I was talking about where colorspace is causing a very visible artifact. FYI @donmccurdy since you've been working on related things. I have no idea what exactly is causing this bug, but hoping one of you might have an idea.

elalish avatar Apr 14 '23 22:04 elalish

A couple notes:

  • The issue goes away if the luminance pass is disabled, or if the luminance threshold is decreased to zero.
  • On macOS with an sRGB display, the issue only appears if I force the OS into using a Display P3 profile.
  • On macOS with a Display P3 display, the issue appears by default but goes away if I force the OS into using an sRGB profile.
  • Is it intentional that alpha is multiplied by intensity here?

Some color changes at the OS level are to be expected, but I'm not sure why the alpha behaves so differently depending on the display profile here. It would be interesting to try exporting the canvas output to a transparent PNG or EXR, loading that image back into a WebGL canvas, and seeing if the issue persists.

donmccurdy avatar Apr 17 '23 20:04 donmccurdy

Is it intentional that alpha is multiplied by intensity here?

I don't think much thought went into that part. Does changing it fix the issue on macOS?

bloomEffect.fragmentShader = `#ifdef FRAMEBUFFER_PRECISION_HIGH

	uniform mediump sampler2D map;

#else

	uniform lowp sampler2D map;

#endif

uniform float intensity;

void mainImage(const in vec4 inputColor, const in vec2 uv, out vec4 outputColor) {

	vec4 texel = texture2D(map, uv);
	outputColor = vec4(texel.rgb * intensity, texel.a);

}`;

vanruesc avatar Apr 17 '23 22:04 vanruesc

Same result, unfortunately!

donmccurdy avatar Apr 24 '23 01:04 donmccurdy

Can this issue still be reproduced on latest MacOS?

vanruesc avatar Sep 19 '23 22:09 vanruesc

Yes.

elalish avatar Sep 20 '23 15:09 elalish

Same with this updated sandbox? https://codesandbox.io/s/bloom-transparent-forked-8l4ds6

vanruesc avatar Sep 20 '23 16:09 vanruesc

Yep: image On MacOS 13.5.2

elalish avatar Sep 20 '23 16:09 elalish

Windows 10 (10.0.19045 Build 19045)

image

mokargas avatar Sep 28 '23 00:09 mokargas

After testing a few more things, I found that you can get results that look similar to the cutoff issue on an sRGB display when you multiply the output colors with the alpha channel. The issue with Display P3 might be related to premultipliedAlpha in some way.

Adjusting the luminance material to keep the original input alpha instead of setting alpha to luminance fixes the cutoff, but this introduces undesired dark haloing and bad gradients: https://codesandbox.io/s/bloom-transparent-forked-hlwyf7?file=/src/App.js https://hlwyf7.csb.app/

Simply setting the clear alpha to 1 also fixes the issue without having to change any materials, which could mean that this is a canvas compositing issue: https://codesandbox.io/s/bloom-transparent-forked-yfc992?file=/src/App.js https://yfc992.csb.app/

vanruesc avatar Sep 30 '23 00:09 vanruesc

I've tested this again with this sandbox which uses the latest alpha of postprocessing v7 and there is no cutoff. Tested on macOS, Sonoma, Chrome 121.

There's also been a fix for the luminance threshold in v6.34.3, so it would be great if someone could test with that version.

vanruesc avatar Feb 11 '24 23:02 vanruesc

I thought at first that you'd fixed it based on this before/after (6.33.3 vs 6.34.3): image image But unfortunately, the problem still persists in other examples, unchanged: image

elalish avatar Feb 13 '24 00:02 elalish

I see, thanks for checking! That's such an annoying bug :grimacing: Could you also test this sandbox with different bloom intensities like 1, 3, 5, 10, 100?

Maybe the clipping is related to HalfFloatType buffers (luminance/bloom) and/or mediump sampler2D precision declaration :thinking: I'll experiment with that next.

vanruesc avatar Feb 13 '24 00:02 vanruesc

Your sandbox looks just fine on all those bloom settings. Maybe you can grab the models from our examples and see if you can make a local repro with those? I think tone mapping may be affecting it too.

elalish avatar Feb 13 '24 01:02 elalish