shader lighting problem

Hey guys, I’m very new to opengl and am trying to teach myself. I have a terrain in my game and am using the dot product of the normals of the terrain and my light source to calculate a value between 0-1 and then setting the brightness of the value at that point. However, in some angles I’m just getting a big block of black coloring since it is facing away from the light. I attached a picture for reference[ATTACH=CONFIG]1892[/ATTACH].

Is there a better technique or something I can add to my code so that I can get some lighting where the block of dark coloring is?

This is my vertex shader code:


void main(void){
    //added
    vec3 normal = normal * 2.0 - 1.0;

    vec4 worldPosition = transformationMatrix * vec4(position,1.0);

    gl_ClipDistance[0] = dot(worldPosition, plane);

    vec4 positionRelativeToCam = viewMatrix * worldPosition;
    gl_Position = projectionMatrix * positionRelativeToCam;
    pass_textureCoordinates = textureCoordinates;

    surfaceNormal = (transformationMatrix * vec4(normal,0.0)).xyz;
    for(int i=0;i<4;i++){
        toLightVector[i] = lightPosition[i] - worldPosition.xyz;
    }
    toCameraVector = (inverse(viewMatrix) * vec4(0.0,0.0,0.0,1.0)).xyz - worldPosition.xyz;

    float distance = length(positionRelativeToCam.xyz);
    visibility = exp(-pow((distance*density),gradient));
    visibility = clamp(visibility,0.0,1.0);
}

and my fragment shader code:


void main(void){

    vec4 blendMapColour = texture(blendMap, pass_textureCoordinates);

    float backTextureAmount = 1 - (blendMapColour.r + blendMapColour.g + blendMapColour.b);
    vec2 tiledCoords = pass_textureCoordinates * 30.0;
    vec4 backgroundTextureColour = vec4(0.26, 0.36, 0.05, 1) * backTextureAmount;
    vec4 rTextureColour = vec4(0.26, 0.36, 0.05, 1) * blendMapColour.r;
    vec4 gTextureColour = vec4(0.26, 0.36, 0.05, 1) * blendMapColour.g;
    vec4 bTextureColour =vec4(0.26, 0.36, 0.05, 1) * blendMapColour.b;

    vec4 totalColour = backgroundTextureColour + rTextureColour + gTextureColour + bTextureColour;

    vec3 unitNormal = normalize(surfaceNormal);
    vec3 unitVectorToCamera = normalize(toCameraVector);

    vec3 totalDiffuse = vec3(0.0);
    vec3 totalSpecular = vec3(0.0);

    for(int i=0;i<4;i++){
        float distance = length(toLightVector[i]);
        float attFactor = attenuation[i].x + (attenuation[i].y * distance) + (attenuation[i].z * distance * distance);
        vec3 unitLightVector = normalize(toLightVector[i]);
        float nDotl = dot(unitNormal,unitLightVector);
        float brightness = max(nDotl,0.0);
        vec3 lightDirection = -unitLightVector;
        vec3 reflectedLightDirection = reflect(lightDirection,unitNormal);
        float specularFactor = dot(reflectedLightDirection , unitVectorToCamera);
        specularFactor = max(specularFactor,0.5);
        float dampedFactor = pow(specularFactor,shineDamper);

        totalDiffuse = totalDiffuse + (brightness * lightColour[i])/attFactor;

        totalSpecular = totalSpecular + (dampedFactor * reflectivity * lightColour[i])/attFactor;
    }
    totalDiffuse = max(totalDiffuse, 0.3);

    out_Color =  vec4(totalDiffuse,1.0) * totalColour + vec4(totalSpecular,1.0);
    out_Color = mix(vec4(skyColour,1.0),out_Color, visibility);
}

Hi,

it looks like you’re doing your lighting calculations in world space. It may be easier to do them in view space (camera space) instead. All you need to do is express the light position in view space:

lightPositionView = viewMatrix * lightPositionWorld

and then it becomes trivial to calculate

toCameraVector = normalize( -1.0 * positionRelativeToCam )

Don’t forget to also transform your normals to view space. Easiest way to do that is by passing a “normal matrix” to the shader:

mat3 normalMatrix = transpose( inverse( mat3( modelViewMatrix ) ) );
vec3 surfaceNormal = normalMatrix * normal;

To reduce the darkness of the areas in shadow, you could do a few things:

[ul]
[li]add some bias to the dotproduct: [/li]```
float brightness = 0.1 + 0.9 * max( 0.0, nDotL );


[li]add some solid ambient color: [/li]```
outColor.rgb += ambientColor.rgb;

[li]add hemispherical ambient. Pass the “world up vector” (normalized) to the fragment shader and then do: [/li]```
float hemi = dot( worldUp, unitNormal ) * 0.5 + 0.5;
vec3 ambientColor = mix( groundColor, skyColor, hemi );


[li]add more light sources[/li][li]add global illumination (outside the scope of this answer)[/li][/ul]


-Paul