Artifacts from Fragment Shading in OpenGL

Trying to learn 3D programming, I am currently implementing a class that batch displays OpenGL cubes by clicking on each frame's GPU. I tried to do some unlit lighting: 1) Sending each face normal to the GPU as part of the vertex attributes. 2) Checking the direction of the normal and dimming each fragment arbitrarily, for example:

Fragment shader

#version 330 in vec2 ex_TexCoord; in vec3 ex_Normal; out vec4 out_Color; uniform sampler2D textureSampler; void main(void) { float lightAmplifier = 1.0; if (ex_Normal.z == 1.0) { lightAmplifier = .8; } else if (ex_Normal.x == 1.0) { lightAmplifier = .65; } else if (ex_Normal.x == -1.0) { lightAmplifier = .50; } out_Color = vec4(texture2D(textureSampler, ex_TexCoord).rgb * lightAmplifier, 1.0); } 

As a result:

Screenshot

Although I am not very good at GLSL, my intuition says that this is not the right behavior. But a few google searches later, I'm still not sure what I'm doing wrong.

+7
c ++ shader opengl glsl
source share
2 answers

This is a floating point precision issue. Note that the coordinates of the vertices are interpolated when for each fragment. This can always lead to problems when comparing floating point numbers with equality.

As a possible solution, you can use epsilon (for example, 0.01) and change the comparison with < -0.99 and > 0.99 :

 if (ex_Normal.z > 0.99) { lightAmplifier = .8; } else if (ex_Normal.x > 0.99) { lightAmplifier = .65; } else if (ex_Normal.x < -0.99) { lightAmplifier = .50; } 


Another possibility would be to use the flat interpolation qualifier, which forces us not to interpolate the value:

Vertex shader:

 flat out vec3 ex_Normal; 

Fragment Shader:

 flat in vec3 ex_Normal; 
+6
source share

Rabbid76 is (probably) right about an erroneous appearance resulting from precision / floating point precision.

I would like to add that setting a constant value based on testing the interpolated value is rarely a good idea (some algorithms depend on it, although, for example, on a shadow display). Changing the test from ==1 to >=0.99 simply puts the error at 0.99, starting at 1.0. It is more likely that you want to interpolate a value when it falls within a certain range, for example. using mix .

+2
source share

All Articles