1
votes

I'm currently trying to write a shader that should include a simple point light in OpenGL ES 2.0, but it's not quite working.

I built my own small SceneGraph and each Object (currently only Boxes) can have its own translation/rotation/scale and rendering works fine. Each of the boxes assigns its own modelView and normals matrix and all of them use the same projection matrix.

For each object I pass the matrices and the light position to the shader as a uniform.

If the Object does not rotate the light works fine, but as soon as the Object rotates the light seems to rotate with the object instead of staying at the same position.

Here is some Code. First the creating the matrices:

GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f);
GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, 0.0f);

Each of the nodes computes an own transformation matrix containing the translation/rotation/scale and multiplies it with the modelViewMatrix:

modelViewMatrix = GLKMatrix4Multiply(modelViewMatrix, transformation);

This matrix is passed to the shader and after the object has been rendered the old matrix is recovered.

The normal matrix is calculated as follows:

GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL);

Vertex-Shader:

attribute vec4 Position;
attribute vec2 TexCoordIn;
attribute vec3 Normal;

uniform mat4 modelViewProjectionMatrix;
uniform mat4 modelViewMatrix;
uniform mat3 normalMatrix;

uniform vec3 lightPosition;

varying vec2 TexCoordOut;
varying vec3 n, PointToLight;

void main(void) {
    gl_Position =  modelViewProjectionMatrix * Position;
    n = normalMatrix * Normal;

    PointToLight = ((modelViewMatrix * vec4(lightPosition,1.0)) - (modelViewMatrix * Position)).xyz;

    // Pass texCoord
    TexCoordOut = TexCoordIn;
}

Fragment-Shader:

varying lowp vec2 TexCoordOut;
varying highp vec3 n, PointToLight;

uniform sampler2D Texture;

void main(void) {
    gl_FragColor = texture2D(Texture, TexCoordOut);

    highp vec3 nn = normalize(n);
    highp vec3 L = normalize(PointToLight);

    lowp float NdotL = clamp(dot(n, L), -0.8, 1.0);
    gl_FragColor *= (NdotL+1.)/2.;
}

I guess the PointToLight is computed wrong, but I can't figure out what's going wrong.

1

1 Answers

3
votes

I finally figured out what went wrong.

Instead of multiplying the lightPosition with the modelViewMatrix, I just need to multiply it with the viewMatrix, which only contains the transformations of the camera and not the transformations for the box:

PointToLight = ((viewMatrix * vec4(lightPosition,1.0)) - (viewMatrix * modelMatrix * Position)).xyz;

Now it works fine.