Search code examples
c#openglglslopentkdeferred-rendering

OpenGL deferred rendering: point light implementation


I'm trying to write a deferred renderer using C# and OpenGL (with OpenTK).

But don't understand how should I implement the normal calculation for a point light.

The point light fragment shader:

    vec2 texCoord = gl_FragCoord.xy / ScreenSize;

    vec3 pixelPos = texture2D(PositionBuffer,texCoord).xyz;
    vec3 pixelNormal = normalize(texture2D(NormalBuffer, texCoord).xyz);
    vec3 diffuseColor = texture2D(ColorBuffer, texCoord).xyz;

    vec3 toLight = LightCenter - pixelPos;

    float attenuation = clamp(1.0 - length(toLight)/LightRadius,0.0,1.0); 

    toLight = normalize(toLight);

    float nDotL = max(dot(pixelNormal, toLight),0.0);

    vec3 diffuseLight = diffuseColor * nDotL;

    LightMap = LightIntensity * attenuation * vec4(diffuseLight,1.0);

Result: The result

It looks fine. But the light is on a 10*10 flat surface, and the radius of the light is 5, so the light should almost cover the surface.

I understand the problem, I just don't know how to fix it...

Normal problem

nDotL of further pixels will be smaller, which leads to this "artifact".

If I remove the "* nDotL" part the light looks like this:

enter image description here

In this case the range is fine, but the bottom of the floor is lit too...

I would be grateful if somebody could tell me how to fix this.

Also the source code is here if it's needed.


Solution

  • vec3 distance = toLight * (1.0 / LightRadius);
    float attenuation = clamp(1 - dot(distance, distance), 0, 1);
    attenuation = attenuation * attenuation;
    

    Using this "formula" it looks like it's working as it should.