3
\$\begingroup\$

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.

Light attenuation of point light covering whole scene

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?

\$\endgroup\$
1
\$\begingroup\$

How stupid of me. Problem was here:

vec3 pixelPosition = (world.xyz / world.w) * 3;

What I was previously doing with that, I was experimenting as I seemed to have wrong pixel coordinates in view space. This is correct:

vec3 pixelPosition = (world.xyz / world.w);

enter image description here

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.