justaguy
justaguy

Reputation: 21

GLSL normal map lighting dark areas and light facing odd direction

I can't seem to figure out why my fragment and vertex shaders aren't working. I think I either have my view/perspective wrong, or maybe my normal map has negative values (since black is showing up lit). Either way, I've been at this for days and I can't seem to make traction.

The lighting system I copied into my project is from here: https://github.com/mattdesl/lwjgl-basics/wiki/ShaderLesson6

The only texture with a normal map is the building, and it seems to light up properly, but only from the bottom left. I would think too, that everything else would be totally dark. I also think my lights are supposed to be circular, not directional.

https://www.dropbox.com/s/pd8und7xbqz0kfh/Screenshot%202014-09-22%2023.17.22.png?dl=0

EDIT: Some research indicates that if I set my normal map's r,g,b values to .5 if they're less than .5 in the fragment shader, then at least those images without a normal map do not get lit up indicating part of the issue may have to do with negative normal map values.

ANOTHER EDIT: I'm using ftransform() in my vertex shader. Even if I do the fix above to darken everything not normal mapped, I can't figure out why my light source is angled. Messing with values won't get my light source to be circular unless I set NdotL to max(dot(N, L), 1.0);. This is what leads me to believe either my coordinate system isn't being translated correctly or that I have weird/negative values in my normal map causing issues. I don't understand this math well enough to tell what is going wrong.

One more thing, since I only created a normal for the one building, I'm passing in -1 as the textureId for the other images' normal maps. Could that be a problem?

Here's my vertex shader:

attribute vec4 Color;

varying vec2 vTexCoord;
varying vec4 vColor;

void main() {

    vColor = Color;
    vTexCoord = gl_MultiTexCoord0;
    gl_Position = ftransform();
}

and my fragment shader:

struct Light{
    //float intensity;
    vec4 color;
    vec3 position;
    //vec3 direction;
};

//attributes from vertex shader
varying vec4 vColor;
varying vec2 vTexCoord;

//our texture samplers
uniform sampler2D u_texture;   //diffuse map
uniform sampler2D u_normals;   //normal map


//values used for shading algorithm...
uniform vec2 Resolution;      //resolution of screen
uniform Light Lights[50];        //light position, normalized
uniform vec4 AmbientColor;    //ambient RGBA -- alpha is intensity 
uniform vec3 Falloff;         //attenuation coefficients

uniform int LightCount;

void main() {
    vec3 Sum = vec3(0.0);


    //RGBA of our diffuse color
    vec4 DiffuseColor = texture2D(u_texture, vTexCoord);

    //set our defuse color to whatever color the image actually is.
    //vec4 vColor = DiffuseColor;

    //RGB of our normal map
    vec3 NormalMap = texture2D(u_normals, vTexCoord).rgb;

    //pre-multiply ambient color with intensity
    vec3 Ambient = AmbientColor.rgb * AmbientColor.a;

    int i = 0;
    while(i < LightCount){
        vec3 ThisLightPosition = Lights[i].position;
        vec4 ThisLightColor = Lights[i].color;

        //The delta position of light
        vec3 LightDir = vec3(ThisLightPosition.xy - (gl_FragCoord.xy / Resolution.xy), ThisLightPosition.z);

        //Correct for aspect ratio
        LightDir.x *= Resolution.x / Resolution.y;

        //Determine distance (used for attenuation) BEFORE we normalize our LightDir
        float D = length(LightDir);

        //normalize our vectors
        vec3 N = normalize(NormalMap * 2.0 - 1.0);
        vec3 L = normalize(LightDir);
        float NdotL = max(dot(N, L), 0.0);
        //Pre-multiply light color with intensity
        //Then perform "N dot L" to determine our diffuse term
        vec3 Diffuse = (ThisLightColor.rgb * ThisLightColor.a) * NdotL;

        //calculate attenuation
        float Attenuation = 1.0 / ( Falloff.x + (Falloff.y*D) + (Falloff.z*D*D));

        //the calculation which brings it all together
        vec3 Intensity = Ambient + Diffuse * Attenuation;
        vec3 FinalColor = DiffuseColor.rgb * Intensity;
        Sum += FinalColor;
        i++;
    }

    gl_FragColor = vColor * vec4(Sum, DiffuseColor.a);
}

Upvotes: 0

Views: 1802

Answers (1)

justaguy
justaguy

Reputation: 21

The problem was my normal maps. I was using the base rbg(0,0,0) as a blank normal, when in reality a blank normal map should be (128,128,255) (I.E. (.5,.5,1)).

Upvotes: 0

Related Questions