Strange square lighting artifacts in OpenGL

I have a program that generates a height map and then displays it as a grid with OpenGL. When I try to add lighting, it ends with strange square shapes covering the grid. They are more visible in some areas than others, but always there.

I used a square grid, but after switching to a triangular grid, nothing has changed. I used at least three different methods to calculate vertex normals, all with the same effect. I did the lighting manually using shaders, but nothing changes when using the built-in OpenGL lighting system.

My last normal code (faces are an array of indices in verts, an array of vertices):

int i; for (i = 0; i < NINDEX; i += 3) { vec v[3]; v[0] = verts[faces[i + 0]]; v[1] = verts[faces[i + 1]]; v[2] = verts[faces[i + 2]]; vec v1 = vec_sub(v[1], v[0]); vec v2 = vec_sub(v[2], v[0]); vec n = vec_norm(vec_cross(v2, v1)); norms[faces[i + 0]] = vec_add(norms[faces[i + 0]], n); norms[faces[i + 1]] = vec_add(norms[faces[i + 1]], n); norms[faces[i + 2]] = vec_add(norms[faces[i + 2]], n); } for (i = 0; i < NVERTS; i++) { norms[i] = vec_norm(norms[i]); } 

Although this is not the only code I used, I doubt that this is the cause of the problem.

I draw a grid with:

 glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3, GL_FLOAT, 0, verts); glEnableClientState(GL_NORMAL_ARRAY); glNormalPointer(GL_FLOAT, 0, norms); glDrawElements(GL_TRIANGLES, NINDEX, GL_UNSIGNED_SHORT, faces); 

And currently I do not use shaders.

What could be the reason for this?

EDIT: a more complete set of screenshots:

In the latter case, the shader code

Vertex:

 varying vec3 lightvec, normal; void main() { vec3 lightpos = vec3(0, 0, 100); vec3 v = vec3(gl_ModelViewMatrix * gl_Vertex); normal = gl_NormalMatrix * gl_Normal; lightvec = normalize(lightpos - v); gl_Position = ftransform(); } 

Fragment:

 varying vec3 lightvec, normal; void main(void) { float l = dot(lightvec, normal); gl_FragColor = vec4(l, l, l, 1); } 
+7
source share
2 answers

You need to either normalize the normal in the fragment shader, for example:

 varying vec3 lightvec, normal; void main(void) { vec3 normalNormed = normalize(normal); float l = dot(lightvec, normalNormed); gl_FragColor = vec4(l, l, l, 1); } 

It can be expensive. What will also work in this case with directional lights is to use vertex lighting. So calculate the light value in the vertex shader

 varying float lightItensity; void main() { vec3 lightpos = vec3(0, 0, 100); vec3 v = vec3(gl_ModelViewMatrix * gl_Vertex); normal = gl_NormalMatrix * gl_Normal; lightvec = normalize(lightpos - v); lightItensity = dot(normal, lightvec); gl_Position = ftransform(); } 

and use it in the fragment shader,

 varying float light; void main(void) { float l = light; gl_FragColor = vec4(l, l, l, 1); } 

Hope this fixes let me know if this is not the case.

EDIT: Here is a small chart that explains what is most likely happening

enter image description here

EDIT2:

If this does not help, add more triangles. Interpolate the values ​​of your height map and add several vertices between them.

Alternatively, try changing the tessellation pattern. For example, a grid of equilateral triangles, as this could make artifacts less noticeable.

enter image description here

You will need to do some interpolation on your height map.

Otherwise, I have no idea ... Good luck!

+2
source

I don’t have a final answer for non-shader versions, but I wanted to add that if you are doing pixel lighting in your fragment shader, you should probably normalize the normal and lightvec inside the fragment shader.

If you do not, they are not a unit length (linear interpolation between two normalized vectors is not necessarily normalized). This may explain some of the artifacts that you see in the shader version, since the size of the product-point will vary depending on the distance from the vertices, which is similar to what you see.

EDIT: Another thought: do you perform uneven scaling (different x, y, z) of the grid when rendering the version without a shader? If you scale it, you need to either change the normals to the inverse scale factor, or set glEnable(GL_NORMALIZE) . See here for more details: http://www.lighthouse3d.com/tutorials/glsl-tutorial/normalization-issues/

+1
source

All Articles