0
votes

I am implementing a diffuse per-vertex shader from the OpenGL 4.0 Shading Language Cookbook, but have modified slightly in order to fit my project.

This is my vertex shader code:

layout(location = 0) in vec4 vertexCoord;
layout(location = 1) in vec3 vertexNormal;

uniform vec4 position; // Light position, initalized to vec4(100, 100, 100, 1)
uniform vec3 diffuseReflectivity; // Initialized to vec3(0.8, 0.2, 0.7)
uniform vec3 sourceIntensity; // Initialized to vec3(0.9, 1, 0.3)

uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;

out vec3 LightIntensity;

void main(void) {
    // model should be the normalMatrix here in case that
    // non-uniform scaling has been applied.
    vec3 tnorm = normalize(vec3(model * vec4(vertexNormal, 0.0)));

    // Convert to eye/camera space
    vec4 eyeCoordsLightPos = view * model * position;
    vec4 eyeCoords = view * model * vertexCoord;
    vec3 s = normalize(vec3(eyeCoordsLightPos - eyeCoords));

    // Diffuse shading equation
    LightIntensity = sourceIntensity * diffuseReflectivity * max(dot(s,tnorm), 0.0);

    gl_Position = projection * view * model * vertexCoord;
}

And this is my fragment shader:

in vec3 LightIntensity;

layout(location = 0) out vec4 FragColor;

void main(){
    FragColor = vec4(LightIntensity, 1.0);
}

I am rendering a box, and I have values for all normals. However the box is just black. Assuming my uniforms are set correctly on rendering, is there anything obviously wrong with my shader code?

What I have changed compared to the code from the book is I use the model matrix as a normal matrix and I have my light position passed in model space, but convert it to camera space in the shader.

Image of rendering, do not be confused by the shaded background which is a texture: Image of rendering, do not be confused by the shaded background which is a texture.

Picture when rendering with FragColor = vec4(f_vertexNormal, 1.0); in fragment shader: enter image description here

Updated code with tnorm in eye space suggestion:

void main(void) {
    // model should be the normalMatrix here in case that
    // non-uniform scaling has been applied.
    vec3 tnorm = normalize(vec3(model * vec4(vertexNormal, 0.0)));

    // Convert to eye/camera space
    vec3 eyeTnorm = vec3(view * vec4(tnorm, 0.0));
    vec4 eyeCoordsLightPos = view * position;
    vec4 eyeCoords = view * model * vertexCoord;
    vec3 s = normalize(vec3(eyeCoordsLightPos - eyeCoords));

    // Diffuse shading equation
    LightIntensity = sourceIntensity * diffuseReflectivity * max(dot(s,eyeTnorm), 0.0);

    gl_Position = projection * view * model * vertexCoord;
    f_vertexNormal = vertexNormal;
}
1
Have you tried outputting some intermediate signals? If you color the box with s is it black? If you color the box with vertexNormal is it black? Also it seems a little weird to me that you would transform the light position by the model matrix, though I don't think that would necessarily cause it to not function. - Tim
added a picture where I use the vertexnormal as color. Looks correct to me. I agree with the model matrix, it should not be necessarily. - toeplitz

1 Answers

2
votes

In addition with my comment above, you're dot-ing a world space vector tnorm with an eye space vector s. You should only dot vectors in the same space. So you might want to consider transforming tnorm to eye space as well.