Incorrect lighting results with deferred rendering
- by Lasse
I am trying to render a light-pass to a texture which I will later apply on the scene. But I seem to calculate the light position wrong. I am working on view-space.
In the image above, I am outputting the attenuation of a point light which is currently covering the whole screen. The light is at 0,10,0 position, and I transform it to view-space first:
Vector4 pos;
Vector4 tmp = new Vector4 (light.Position, 1);
// Transform light position for shader
Vector4.Transform (ref tmp, ref Camera.ViewMatrix, out pos);
shader.SendUniform ("LightViewPosition", ref pos);
Now to me that does not look as it should. What I think it should look like is that the white area should be on the center of the scene. The camera is at the corner of the scene, and it seems as if the light would move along with the camera.
Here's the fragment shader code:
void main(){
// default black color
vec3 color = vec3(0);
// Pixel coordinates on screen without depth
vec2 PixelCoordinates = gl_FragCoord.xy / ScreenSize;
// Get pixel position using depth from texture
vec4 depthtexel = texture( DepthTexture, PixelCoordinates );
float depthSample = unpack_depth(depthtexel);
// Get pixel coordinates on camera-space by multiplying the
// coordinate on screen-space by inverse projection matrix
vec4 world = (ImP * RemapMatrix * vec4(PixelCoordinates, depthSample, 1.0));
// Undo the perspective calculations
vec3 pixelPosition = (world.xyz / world.w) * 3;
// How far the light should reach from it's point of origin
float lightReach = LightColor.a / 2;
// Vector in between light and pixel
vec3 lightDir = (LightViewPosition.xyz - pixelPosition);
float lightDistance = length(lightDir);
vec3 lightDirN = normalize(lightDir);
// Discard pixels too far from light source
//if(lightReach < lightDistance) discard;
// Get normal from texture
vec3 normal = normalize((texture( NormalTexture, PixelCoordinates ).xyz * 2) - 1);
// Half vector between the light direction and eye, used for specular component
vec3 halfVector = normalize(lightDirN + normalize(-pixelPosition));
// Dot product of normal and light direction
float NdotL = dot(normal, lightDirN);
float attenuation = pow(lightReach / lightDistance, LightFalloff);
// If pixel is lit by the light
if(NdotL > 0) {
// I have moved stuff from here to above so I can debug them.
// Diffuse light color
color += LightColor.rgb * NdotL * attenuation;
// Specular light color
color += LightColor.xyz * pow(max(dot(halfVector, normal), 0.0), 4.0) * attenuation;
}
RT0 = vec4(color, 1);
//RT0 = vec4(pixelPosition, 1);
//RT0 = vec4(depthSample, depthSample, depthSample, 1);
//RT0 = vec4(NdotL, NdotL, NdotL, 1);
RT0 = vec4(attenuation, attenuation, attenuation, 1);
//RT0 = vec4(lightReach, lightReach, lightReach, 1);
//RT0 = depthtexel;
//RT0 = 100 / vec4(lightDistance, lightDistance, lightDistance, 1);
//RT0 = vec4(lightDirN, 1);
//RT0 = vec4(halfVector, 1);
//RT0 = vec4(LightColor.xyz,1);
//RT0 = vec4(LightViewPosition.xyz/100, 1);
//RT0 = vec4(LightPosition.xyz, 1);
//RT0 = vec4(normal,1);
}
What am I doing wrong here?