three.js: bloompass bug:flashing black block

Description

After use the bloompass, the shader and some models with transparent pass will frequently flash black blocks. Example: https://github.com/mrdoob/three.js/assets/28917209/c003d339-9b19-474e-9d07-486afb69996a

Reproduction steps

  1. use shader exmaple:webgl_shader.
  2. change bloom example:webgl_postprocessing_unreal_bloom code, add mesh with ShaderMaterial

Code

                         const geometry = new THREE.CircleGeometry(.5, 32);

			uniforms = {
				time: { value: 2. }
			};

			const material = new THREE.ShaderMaterial({
				transparent: false,
				opacity: 0,
				uniforms: uniforms,
				vertexShader: document.getElementById('vertexShader').textContent,
				fragmentShader: document.getElementById('fragmentShader').textContent

			});

			const mesh = new THREE.Mesh(geometry, material);
			scene.add(mesh);


                        animate() {
                                  ...
                                  uniforms['time'].value = performance.now() / 1000
                        }

Live example

https://github.com/mrdoob/three.js/assets/28917209/1c47eacb-22be-4e0d-8d14-263330e45c2b

Screenshots

https://github.com/mrdoob/three.js/assets/28917209/b23ebc0e-bbf0-4761-89a3-87f9325a7119

Version

“version”: “0.160.0”

Device

Desktop

Browser

Chrome

OS

Windows, MacOS

About this issue

  • Original URL
  • State: closed
  • Created 4 months ago
  • Comments: 22

Most upvoted comments

There’s no BloomPass bug here - this is just exposing a problem in the custom shader where NaN values are produced which are then propagated during the bloom effect. Different hardware handle NaN differently possibly depending on floating point calculations etc so it may or may not show up depending on what machine you’re trying to reproduce this on.

Adding this to the end of the custom shader produces red flashes instead of black ones:

if ( any( isnan( gl_FragColor ) ) ) {

  gl_FragColor = vec4( 100000000, 0, 0, 1 );

}

On hardware my hardware (M1 macbook) you can create a NaN value with 0.0 / 0.0.

@gkjohnson As you have already mentioned, the issue can’t be fixed on the browser side. Here is the response at the Chromium bug tracker:

It’s not possible to enforce uniform behavior across GPU types for NaN values produced in shaders. Some shading languages on top of which WebGL is implemented do not have universally available primitives to even query whether values are NaN. Even if this were universally supported, interposing upon every arithmetic operation in the shader would be prohibitively expensive at run time. If there appears to be some other issue causing this problem, please feel free to comment here and I’ll reopen this bug, but in the meantime I’m closing it as infeasible.

So at least we have an official browser dev statement that this issue needs to be fixed on app level by avoiding NaN values in shaders whenever possible.

But for some models, after turning on the bloom pass, still flashing, how to fix it?

Your custom shader needs to not perform calculations that result in NaN values or check for them and handle them gracefully.