Jump to content

  • Log In with Google      Sign In   
  • Create Account

TheGering

Member Since 17 Aug 2010
Offline Last Active Apr 28 2012 02:06 AM

Topics I've Started

Help understand GLSL directional light on iOS

15 April 2012 - 02:34 PM

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);
    ...
}   

PARTNERS