Shading Broken on Certain Modern Devices Browsers

I wrote a basic custom shader for some instances and it looks fine on most devices and browsers but looks wonky on others. Any clue as to why the different results across devices and browsers?

GOOD WIREFRAME


WONKY WIREFRAME

GOOD MODEL RENDER

WONKY MODEL RENDER

BABYLON.Effect.ShadersStore["testVertexShader"] = `
	#ifdef GL_ES
	  precision highp float;
	#endif
	// Attributes
	attribute vec3 position;
	attribute vec2 uv;
    // Set Per Instance
	attribute vec2 uv_offset;
    attribute vec3 tint;

	uniform mat4 viewProjection;
	varying vec2 vUV;
    varying vec3 vTint;

    #include<instancesDeclaration>

	void main(void) {

        #include<instancesVertex>

        vec4 worldPos = finalWorld * vec4(position, 1.0);
        gl_Position = viewProjection * worldPos;
        vUV = uv;
        vTint = tint;
        
	}	        
    `;

BABYLON.Effect.ShadersStore["testFragmentShader"] = `
	#ifdef GL_ES
	  precision highp float;
	#endif
	varying vec2 vUV;
  varying vec3 vTint;
  uniform sampler2D textureSampler;
  uniform sampler2D hairSampler;

	void main(void) {
    if(vTint.r<1.)
      gl_FragColor = texture2D(hairSampler,vUV) * vec4(vTint, 1.);
    else
      gl_FragColor = texture2D(textureSampler,vUV) * vec4(vTint, 1.);
	}    
    `;

OTHER WONKY RENDERS ( but only on some devices / browsers )

2 Likes

Any ideas @EVGENI_POPOV ? The beards in the last image seem to render ok as if to suggest the tinting multiplier in the line:
gl_FragColor = texture2D(hairSampler,vUV) * vec4(vTint, 1.);
is working fine while the line:
gl_FragColor = texture2D(textureSampler,vUV) * vec4(vTint, 1.);
is messing things up when multiplied by the sampled texel. The vTint in that case would be ( 1.0 , 1.0 , 1.0 ).

or perhaps:

#ifdef GL_ES
precision highp float;
#endif

should be replaced with:

#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif

?

@SirFizX, could you share which devices and browsers are giving this issue?

1 Like

Hi @gbz ! I’m helping @SirFizX test out this issue and I am one of the people who notices that strange effect. I am on Windows on Chrome 88.0.4324.150, which I think is the latest. I do NOT notice the effect on my Android phone on Chrome.

2 Likes

We’re seeing this mostly on Windows 10, consistently in Firefox, Chrome, Edge, etc.

Less so on Mac and Linux, but I think there were a few instances where it was seen there depending on OS version + browser. Can’t speak to that personally, but we can get more detailed info if needed.

2 Likes

Have you looked at the console of the browser to see if there are any errors here?

If you can setup a repro it’s a must…

1 Like

Thanks @Evgeni_Popov . There aren’t any errors in the browser as far as I am aware. I happens on other’s devices not mine. I will dig deeper.

Here is a playground.
https://playground.babylonjs.com/#MC9QYZ

I see what I’d expect:

Another user sees this on their machine (Debian Linux, Firefox):
wonky_rendering_on_playground

They don’t get the spottiness in this version without the tinting.
https://playground.babylonjs.com/#MC9QYZ#1

My WebGL1 Report MacOS Chrome:

My WebGL2 Report MacOS Chrome:

Debian_Linux_Firefox_WebGL1_Report:

Debian_Linux_Firefox_WebGL2_Report:

I also saw the “correct”, solid version on windows chrome when I turned OFF hardware acceleration on the browser, then I saw the “wonky” version when I turned hardware acceleration ON. I have an RTX 3090 (not trying to flex haha, just noting in case important) @gbz @Evgeni_Popov

2 Likes

Perhaps there is a CPU side race condition in setting up the GPU state which causes varied results across devices and graphics settings?

This seems to fix it:

https://playground.babylonjs.com/#MC9QYZ#5

There seems to be some variation in the way “out of range behavior” for APIs are handled across OpenGL implementations.

It seems the interpolation between (1,1,1) and (1,1,1) to generate the varying vTint does not always result to (1,1,1), hence your problems… It is probably due to some floating point precision issues.

Using < 0.9999 does also fix the problem (if you use a (1,1,1) tint color for the head).

However, I think the best way to handle this is to have a separate material for each part:

https://playground.babylonjs.com/#MC9QYZ#9

1 Like