Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411507 Posts in 69374 Topics- by 58429 Members - Latest Member: Alternalo

April 26, 2024, 04:49:55 AM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsDeveloperTechnical (Moderator: ThemsAllTook)Point light has dead area?
Pages: [1]
Print
Author Topic: Point light has dead area?  (Read 915 times)
FTLRalph
Level 1
*

What?


View Profile
« on: March 24, 2015, 09:29:25 AM »

So I have a pretty simple GLSL shader for point lights. I simply iterate through my lights and draw them to the scene with the following fragment shader:
Code:
#version 330

in vec4 v_color;
in vec2 v_texCoord;

uniform sampler2D u_texture;
uniform sampler2D u_normal;

uniform float lightRadius;  // Radius of light (screen coords)
uniform vec2 lightCoord;    // Position of point light (screen coords)
uniform vec4 lightColor;    // Color of light, a is intensity
uniform float lightZ;        // Z-index of light (0-1)

layout(location = 0) out vec4 lightBuffer;

void main()
{
    // RGBA of diffuse color.
    vec4 diffuseRGBA = texture2D(u_texture, v_texCoord);

    // RGB of normal map, invert g in normal map for accuracy.
    vec3 normalRGB = texture2D(u_normal, v_texCoord).rgb;
    normalRGB.g = 1.0 - normalRGB.g;
   
    // The delta position of the light.
    vec2 lightDir = vec2(lightCoord - gl_FragCoord.xy);
   
    // Distance to light.
    float distance = length(lightDir);
   
    // Attenuation.
    float attenuation = clamp(1.0 - ((distance * distance) / (lightRadius * lightRadius)), 0.0, 1.0);

    // Normalize vectors.
    vec3 N = normalize(normalRGB * 2.0 - 1.0);
    vec3 L = vec3(normalize(lightDir), lightZ);
   
    // Pre-multiply light color with intensity then perform "N dot L" to determine diffuse term.
    vec3 diffuse = (lightColor.rgb * lightColor.a) * max(dot(N, L), 0.0);
   
    // The calculation which brings it all together.
    vec3 intensity = diffuse * attenuation;
    vec3 finalColor = diffuseRGBA.rgb * intensity;
   
    // Done.
    lightBuffer = v_color * vec4(finalColor, diffuseRGBA.a);
}

Here's the output:


(I upped the intensity a bunch to make it clearer.)

Can someone smarter than me help me out and tell me what could be the reason for the "dead area" in the top-right area of each light? I've been scratching my head about it for a while now.

Thanks.
Logged
powly
Level 4
****



View Profile WWW
« Reply #1 on: March 25, 2015, 11:44:49 PM »

It doesn't intuitively make sense to me why you normalize the 2D version of the light direction and then add a third component instead of normalizing the whole vector. I'd also double check that the blue channel truly corresponds to Z (in which case your normal map is mostly bluish.)
Logged
Polyflare
Level 0
**



View Profile WWW
« Reply #2 on: March 26, 2015, 01:03:41 AM »

There is definitely an issue with this line:
Code:
vec3 L = vec3(normalize(lightDir), lightZ);

If `lightZ` is non-zero then the vector `L` is not of length 1 resulting in an incorrect lighting equation. It should be changed to:

Code:
vec3 L = normalize(vec3(lightDir, lightZ));

I also agree with powly that there is a chance that your normal map is incorrect.
Logged

I code stuff.
@Polyflare/@UnitVec
Schrompf
Level 9
****

C++ professional, game dev sparetime


View Profile WWW
« Reply #3 on: March 26, 2015, 06:54:56 AM »

Looks like the normal buffer is all white (or black).
Logged

Snake World, multiplayer worm eats stuff and grows DevLog
Pages: [1]
Print
Jump to:  

Theme orange-lt created by panic