Fragment Changing the diffuse value with the location / rotation of the camera

I am trying to get simple diffuse lighting to work in GLSL. I have a cube that is passed as an array of points, and I calculate the normals of the face inside my geometric shader (because I intend to warp the grid at run time, so I need new face normals.)

My problem is that the diffuse value changes when I move the camera around the world. therefore, the shading on the face of my cube changes as the camera moves. I could not understand what I do not have, what causes it. My shaders look like this:

Vertex:

#version 330 core layout(location = 0) in vec3 vertexPosition_modelspace; uniform mat4 MVP; void main(){ gl_Position = MVP * vec4(vertexPosition_modelspace,1); } 

Geometry:

 #version 330 precision highp float; layout (triangles) in; layout (triangle_strip) out; layout (max_vertices = 3) out; out vec3 normal; uniform mat4 MVP; uniform mat4 MV; void main(void) { for (int i = 0; i < gl_in.length(); i++) { gl_Position = gl_in[i].gl_Position; vec3 U = gl_in[1].gl_Position.xyz - gl_in[0].gl_Position.xyz; vec3 V = gl_in[2].gl_Position.xyz - gl_in[0].gl_Position.xyz; normal.x = (Uy * Vz) - (Uz * Vy); normal.y = (Uz * Vx) - (Ux * Vz); normal.z = (Ux * Vy) - (Uy * Vx); normal = normalize(transpose(inverse(MV)) * vec4(normal,1)).xyz; EmitVertex(); } EndPrimitive(); } 

Fragment:

 #version 330 core in vec3 normal; out vec4 out_color; const vec3 lightDir = vec3(-1,-1,1); uniform mat4 MV; void main() { vec3 nlightDir = normalize(vec4(lightDir,1)).xyz; float diffuse = clamp(dot(nlightDir,normal),0,1); out_color = vec4(diffuse*vec3(0,1,0),1.0); } 

thanks

+4
source share
1 answer

There are many wrong things in the code. Most of your problems are related to completely forgetting what space the various vectors are in. You cannot meaningfully perform calculations between vectors located in different spaces.

 normal = normalize(transpose(inverse(MV)) * vec4(normal,1)).xyz; 

Using 1 as the fourth component of the normal, you completely break this calculation. This causes the normal to be translated, which is not suitable.

In addition, your normal value is calculated based on gl_Position . And gl_Position is in clip space, not model space. Thus, all you get is a normal space for clips, which is not what you need, need or can even use.

If you want to calculate the normal camera space, then calculate it from the camera position. Or calculate the normal of the model space from the positions of the model space and use the model / view matrix to convert it to camera space.

In addition, invert / transpose the CPU and transfer it to the shader. Oh, and get all the normal calculations out of the loop; you need to do this only once per triangle (save it in a local variable and copy it to the output for each vertex). And stop doing cross-product manually; use the built-in GLSL cross function.

 vec3 nlightDir = normalize(vec4(lightDir,1)).xyz; 

This makes no sense than using 1 as the fourth component in your conversion before. Just normalize lightDir directly.

It is equally important if you are lighting in the space of the camera, then the direction of the light must be changed with the camera so that it remains in the same visible direction in the world. Thus, you will need to take its place in world space and convert it into camera space (usually on a processor transferred as a whole).

+8
source

Source: https://habr.com/ru/post/1481313/


All Articles