Help understand GLSL directional light on iOS (left handed coord system)

Posted by Robse on Game Development See other posts from Game Development or by Robse
Published on 2012-04-13T12:09:29Z Indexed on 2012/04/13 17:44 UTC
Read the original article Hit count: 246

Filed under:
|
|
|
|

I now have changed from GLKBaseEffect to a own shader implementation. I have a shader management, which compiles and applies a shader to the right time and does some shader setup like lights. Please have a look at my vertex shader code. Now, light direction should be provided in eye space, but I think there is something I don't get right.

After I setup my view with camera I save a lightMatrix to transform the light from global space to eye space.

My modelview and projection setup:

- (void)setupViewWithWidth:(int)width height:(int)height camera:(N3DCamera *)aCamera {

    aCamera.aspect = (float)width / (float)height;
    float aspect = aCamera.aspect;
    float far = aCamera.far;
    float near = aCamera.near;
    float vFOV = aCamera.fieldOfView;

    float top = near * tanf(M_PI * vFOV / 360.0f);
    float bottom = -top;
    float right = aspect * top;
    float left = -right;

    // projection
    GLKMatrixStackLoadMatrix4(projectionStack, GLKMatrix4MakeFrustum(left, right, bottom, top, near, far));

    // identity modelview
    GLKMatrixStackLoadMatrix4(modelviewStack, GLKMatrix4Identity);

    // switch to left handed coord system (forward = z+)
    GLKMatrixStackMultiplyMatrix4(modelviewStack, GLKMatrix4MakeScale(1, 1, -1));  

    // transform camera
    GLKMatrixStackMultiplyMatrix4(modelviewStack, GLKMatrix4MakeWithMatrix3(GLKMatrix3Transpose(aCamera.orientation)));
    GLKMatrixStackTranslate(modelviewStack, -aCamera.position.x, -aCamera.position.y, -aCamera.position.z);
}

- (GLKMatrix4)modelviewMatrix {
    return GLKMatrixStackGetMatrix4(modelviewStack);
}

- (GLKMatrix4)projectionMatrix {
    return GLKMatrixStackGetMatrix4(projectionStack);
}

- (GLKMatrix4)modelviewProjectionMatrix {
    return GLKMatrix4Multiply([self projectionMatrix], [self modelviewMatrix]);
}

- (GLKMatrix3)normalMatrix {
    return GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3([self modelviewProjectionMatrix]), NULL);
}

After that, I save the lightMatrix like this:

[self.renderer setupViewWithWidth:view.drawableWidth height:view.drawableHeight camera:self.camera];
self.lightMatrix = [self.renderer modelviewProjectionMatrix];

And just before I render a 3d entity of the scene graph, I setup the light config for its shader with the lightMatrix like this:

- (N3DLight)transformedLight:(N3DLight)light transformation:(GLKMatrix4)matrix {
    N3DLight transformedLight = N3DLightMakeDisabled();
    if (N3DLightIsDirectional(light)) {
        GLKVector3 direction = GLKVector3MakeWithArray(GLKMatrix4MultiplyVector4(matrix, light.position).v);
        direction = GLKVector3Negate(direction);    // HACK -> TODO: get lightMatrix right!
        transformedLight = N3DLightMakeDirectional(direction, light.diffuse, light.specular);
    } else {
        ...
    } 
    return transformedLight;
}

You see the line, where I negate the direction!? I can't explain why I need to do that, but if I do, the lights are correct as far as I can tell.

Please help me, to get rid of the hack.

I'am scared that this has something to do, with my switch to left handed coord system.

My vertex shader looks like this:

attribute highp     vec4    inPosition;
attribute lowp      vec4    inNormal;
...

uniform highp   mat4    MVP;
uniform highp   mat4    MV;
uniform lowp    mat3    N;

uniform lowp    vec4    constantColor;
uniform lowp    vec4    ambient;
uniform lowp    vec4    light0Position;
uniform lowp    vec4    light0Diffuse;
uniform lowp    vec4    light0Specular;

varying lowp    vec4    vColor;
varying lowp    vec3    vTexCoord0;

vec4 calcDirectional(vec3 dir, vec4 diffuse, vec4 specular, vec3 normal) {
    float NdotL = max(dot(normal, dir), 0.0);
    return NdotL * diffuse;
}

...    

vec4 calcLight(vec4 pos, vec4 diffuse, vec4 specular, vec3 normal) {
    if (pos.w == 0.0) {             // Directional Light
        return calcDirectional(normalize(pos.xyz), diffuse, specular, normal);
    } else {
        ...
    }
}

void main(void) {

    // position
    highp vec4 position = MVP * inPosition;        
    gl_Position = position;

    // normal
    lowp vec3 normal = inNormal.xyz / inNormal.w;
    normal = N * normal;
    normal = normalize(normal);

    // colors
    vColor = constantColor * ambient;

    // add lights
    vColor += calcLight(light0Position, light0Diffuse, light0Specular, normal);

    ...
}   

© Game Development or respective owner

Related posts about shaders

Related posts about ios