Light doesn't work without bump map

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

I created a point light on the terrain and it works perfectly, however when I remove the bump map, it doesn't work anymore.

When I do the following I don't see the light on the terrain:


float3 n = normalize(IN.Normal);

When I do the following I see the light:


float3 n = normalize(tex2D(normalMap, IN.UV).rgb * 2.0f - 1.0f);

I checked to see if the mesh has normal and found that it has normal.

Advertisement

Are you multiplying the normal with the world inverse transposed inside the vertex shader?


OUT.normal = mul(IN.normal, (float3x3)worldInverseTransposeMatrix);

3 suggestions:

1. Even though you know the mesh has normals, check that the normals are passed all the way from your Direct3D code (C/C++?) to the shader where you're doing the lighting (HLSL). Does your vertex declaration include a normal? If you're doing per pixel lighting, perhaps the normal is available in the vertex shader, but it's not being passed to the pixel shader?

2. You can use PIX to debug graphics issues (just google "pix debug tutorial")

3. Post the full shader code here

Here is the shader code:


float4x4 World;
float4x4 View;
float4x4 Projection;
float4x4 worldInverseTransposeMatrix;

float3 cameraPos;
float materialPower;
float4 materialDiffuse;
float4 materialAmbient;
float4 materialSpecular;

float3 lightPosition;
float4 lightDiffuse;
float4 lightSpecular;
float lightRange;

float4 globalAmbient;

texture colorMapTexture;
sampler2D colorMap = sampler_state
{
    Texture = <colorMapTexture>;
    MagFilter = Linear;
    MinFilter = Anisotropic;
    MipFilter = Linear;
    MaxAnisotropy = 16;
};

// Bump map
texture normalMapTexture;
sampler2D normalMap = sampler_state
{
    Texture = <normalMapTexture>;
    MagFilter = Linear;
    MinFilter = Anisotropic;
    MipFilter = Linear;
    MaxAnisotropy = 16;
};

struct VERTEX
{
    float3 Pos : POSITION;
    float3 Normal : NORMAL;
    float2 UV : TEXCOORD0;
};

struct VS_OUTPUT
{
   float4 Pos : POSITION;
   float2 UV : TEXCOORD0;
   float3 Normal : TEXCOORD1;
   float4 worldPos : TEXCOORD2;
};

VS_OUTPUT VS( VERTEX IN )
{
     VS_OUTPUT OUT;
     OUT = (VS_OUTPUT)0;
     float4x4 WVP = mul(World, mul(View, Projection));
     OUT.Pos = mul(float4(IN.Pos, 1.0f), WVP);
     OUT.Normal = mul(IN.Normal, (float3x3)worldInverseTransposeMatrix);
     OUT.UV = IN.UV;
     OUT.worldPos = mul(float4(IN.Pos, 1.0f), World);
     return OUT;
}

float4 PS( VS_OUTPUT IN ) : COLOR
{
    float3 viewDir = cameraPos - IN.worldPos;
    float3 lightDir = (lightPosition - IN.worldPos) / lightRange;
    float atten = saturate(1.0f - dot(lightDir, lightDir));


    float3 n =  normalize(IN.Normal); 
    // *** LIGHT ONLY WORKS WHEN I REPLACE THE ABOVE LINE WITH THIS LINE --> normalize(tex2D(normalMap, IN.UV).rgb * 2.0f - 1.0f); ***
    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 = (nDotL == 0.0f) ? 0.0f : pow(nDotH, materialPower);


    float4 diffuse = materialDiffuse * lightDiffuse;
    float4 specular = materialSpecular * lightSpecular;
    float4 lightColor = (materialAmbient + globalAmbient) + 
                             (diffuse * nDotL * atten) + 
                             (specular * power * atten);
    return tex2D(colorMap, IN.UV) * lightColor;
}

technique TerrainTech
{
    pass p0
    {
        VertexShader = compile vs_3_0 VS();
        PixelShader  = compile ps_3_0 PS();
    }
}

Yes, the vertex declaration include Normal.

I agree with gfxgansta, even though you have the normals in the vertex declarations, it may be possible that they are not correctly passed from the cpu to the gpu.

Try visualising the normals, like: PS: return float4(IN.Normal, 1.0f);

FastCall22: "I want to make the distinction that my laptop is a whore-box that connects to different network"

Blog about... stuff (GDNet, WordPress): www.gamedev.net/blog/1882-the-cuboid-zone/, cuboidzone.wordpress.com/

I'm sure this problem is related to the light shader itself.

The light DOES work on some meshes, while it doesn't work on the terrain, also I THINK it's not working correctly on other meshes, the mesh sometimes is lighting from one side even the mesh is over the light (it should light from other sides as well) then when I move it it get some light from sides.

I believe the shader light is not correct, can someone check the shader and let me know if it's a VALID light shader?

@Migi0027: Tried that, it doesn't work.

I created a point light on the terrain and it works perfectly, however when I remove the bump map, it doesn't work anymore.

When I do the following I don't see the light on the terrain:


float3 n = normalize(IN.Normal);

When I do the following I see the light:


float3 n = normalize(tex2D(normalMap, IN.UV).rgb * 2.0f - 1.0f);

I checked to see if the mesh has normal and found that it has normal.

The first line depends on IN.Normal. The second line only depends on IN.UV. I'm no lighting expert, but I'm fairly sure that the normals from your texture are supposed to be transformed in some way.

How does your bump map work perfectly? You are calculating a normal for each vertex and then throwing them away. That cannot be intentional.

@Pink Horror: Check out my shader above, when I apply bump map it DOES look very well.

When I remove the bump map I don't see the light, I tried to move the terrain upwards, now I get to see the light, I also get to see the light when I set large amount of "point light radius".

I guess the light get positioned incorrectly when I don't use bump map.

In Vertex Shader, I'm transforming the normal as the following:


OUT.Normal = mul(IN.Normal, (float3x3)worldInverseTransposeMatrix);

What do you mean by, it does not work? Is it black?

Try normalizing them and then visualize them, if there is literally no color change around the terrain, with the normal visualisation, that means that the normals are not passed to the shader.

FastCall22: "I want to make the distinction that my laptop is a whore-box that connects to different network"

Blog about... stuff (GDNet, WordPress): www.gamedev.net/blog/1882-the-cuboid-zone/, cuboidzone.wordpress.com/

@Migi0027: The light EXISTS, but it's not on the valid position (on the terrain), I can only see it when I move the terrain up or increase the light radius.

Though, the light is affecting other objects over the terrain.

EDIT: After testing, I notice that the light ONLY affect the terrain when its position is colliding with the terrain, however you know that point light position doesn't necessarily have to collide with the mesh, it could affect the mesh from some distance (according to the light radius/range).

I also tested to make sure that the normals are passed and found that the program pass it to the shader, however, still the same issue.

This topic is closed to new replies.

Advertisement