Light doesn't work without bump map

Started by
25 comments, last by Medo Mex 10 years, 8 months ago

@belfegor: After checking for awhile, I notice that when I set the light color to a certain color (for example: red) and set material ambient to something like 0.8

The whole terrain become reddish

Light gLight = { D3DXVECTOR3(0.0f, 2.0f, 0.0f), 5.0f, D3DXVECTOR3(1.0f, 0.0f, 0.0f) };
Material gMaterial = { D3DXVECTOR3(1.0f, 1.0f, 1.0f), 80.0f, 0.8f };

Advertisement

Well, yes. You are using your point light as a normal point light with attenuation, but it also provides the ambient lighting to your terrain. So the terrain ambient lighting and the light color are the same. You only have one light, so what is not touched by the light is black.

You should provide the terrain ambient lighting by a different light source, probably directional. Alternatively, you could add a flat ambient lighting to the terrain, independent on any light source.

@DwarvesH: I don't want the terrain to be black when there is no light in certain places.

If there is no light source on certain parts, it should be affected by global ambient.

I would recommend that you first have a go at playing around with the shader and make sure you understand what is what and what it does. This way you will be able to build upon the foundation shader on your own.

For starters, you could go int you bump mapped pixel shader, and replace:


float atten     = saturate(1.0f - dot(lightDir, lightDir)) + MaterialAmbient;

with:



float atten     = saturate(1.0f - dot(lightDir, lightDir));

Now you can see the actual extents of a classical point light. You can then use the controls of your demo to change position and radius and see how the light looks in isolation.

Then you can try removing the attenuation and see how the shading looks only with direction being important:


float atten     = 1;

Then you can try a very simple and very ugly basic ambient coefficient:


float atten     = saturate(1.0f - dot(lightDir, lightDir));

...

float3 diffuse  = LightDiffuse * MaterialDiffuse * texDiffuse * (nDotL * atten );
float3 specular = LightDiffuse * power * atten;
float3 ambient = float3(0.4f, 0.4f, 0.4f) * texDiffuse;

OUT.Color.rgb = diffuse + specular + ambient;
OUT.Color.a   = 1.0f;

This will look like crap and you will only have bump mapping and specular effect in the area lit by the point light.

Now that you have a global ambient component, you can replace the values that give ugly results with better one. Like in the step where we set atten to 1:


float3x3 tangentBasis = float3x3(normalize(IN.TangentW), normalize(IN.BinormalW), normalize(IN.NormalW));
	float3 n              = normalize(mul(bump.xyz, tangentBasis));

    float3 l = normalize(lightDir);
    float3 v = normalize(viewDir);
    float3 h = normalize(l + v);
    
    float nDotL = saturate(dot(n, l));
    float nDotH = saturate(dot(n, h));
    float power = pow(nDotH, MaterialPower);

	float3 diffuse  = LightDiffuse * MaterialDiffuse * texDiffuse * (nDotL * atten );
	float3 specular = LightDiffuse * power * atten;
	float3 ambient = LightDiffuse * MaterialAmbient * texDiffuse * nDotL;

	OUT.Color.rgb = diffuse + specular + ambient;
	OUT.Color.a   = 1.0f;

This will give a very dark result. The material properties are not set up correctly for these equations, especially since I changed the interpretation of the values.

I'm not saying that things look good, or are correct. There are a lot of ways to do what you want and first you need to decide exactly on the lighting scheme you want. For interior scenes, especially with a lot of rooms, you can use multiple point lights. Exterior scenes, especially terrain are well served by one master directional light, which does a fair job of approximating the Sun. A point light is not well suited for approximating the sun because it has a radius and the intensity of the light changes rapidly when moving in that radius. If you place the point light as a sun too far, one corner of you map will be brighter than the others. If you place it in a central position, the problem repeats. If you lower it too much, the middle of the map will be shinny while the corners will be just right.

^ +1 what he said.

Hmm.. Here is what I got so far...

The following code works, however, I don't see specular light :/


float3 texDiffuse = tex2D(colorMap, IN.UV).rgb;

float3 viewDir  = cameraPos - IN.worldPos;
float3 lightDir = (lightPosition - IN.worldPos) / lightRange;
float atten     = saturate(1.0f - dot(lightDir, lightDir));

float3 n = normalize(IN.normal);
float3 l = normalize(lightDir);
float3 v = normalize(viewDir);
float3 h = normalize(l + v);
    
float nDotL = saturate(dot(n, l)) + (globalAmbient + materialAmbient);
float nDotH = saturate(dot(n, h));
float power = pow(nDotH, materialPower);

float3 diffuse  = lightDiffuse * nDotL * atten;
float3 specular = lightSpecular * power * atten;

return float4(texDiffuse * (materialAmbient + globalAmbient + diffuse + specular), 1.0);

I guess the problem is partly resolved, anyway..

Thanks everyone smile.png

This topic is closed to new replies.

Advertisement