Directional Light

Started by
35 comments, last by belfegor 10 years, 9 months ago

@LancerSolurus:

1) I'm setting the light direction to (1, 0, 1), it's a directional light (no position).

2) Not sure what you mean exactly

Here is the entire effect file:


float4x4 World;
float4x4 View;
float4x4 Projection;

// Light
float3 lightDirection;  // Directional light
float4 lightDiffuse;
float4 lightAmbient;
float4 lightSpecular;

// Material
float4 materialDiffuse;
float4 materialAmbient;
float4 materialSpecular;
float materialPower;

float4 globalAmbient;

// Camera position
float3 cameraPos;

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

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

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

//-----------------------------------------------------------------------
// Vertex shader function
//-----------------------------------------------------------------------
VS_OUTPUT VS( VS_INPUT 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.UV = IN.UV;
    Out.Normal = mul(IN.Normal, (float3x3)World).xyz;
    Out.worldPos = mul(float4(IN.Pos, 1.0f), World).xyz;
    return Out;
}

//-----------------------------------------------------------------------
// Pixel shader function
//-----------------------------------------------------------------------
float4 PS( VS_OUTPUT IN ) : COLOR
{
    float3 viewDir = normalize(cameraPos - IN.worldPos);
    float3 lightDir = normalize(-lightDirection);
    float3 halfVector = normalize(lightDir + viewDir);

    float3 n = normalize(IN.Normal);
    float3 h = normalize(halfVector);
    float3 l = normalize(lightDir);
    
    float nDotL = saturate(dot(n, l));
    float nDotH = saturate(dot(n, h));
    float power = (nDotL <= 0.0f) ? 0.0f : pow(nDotH, materialPower);

    float4 FinalDiffuse = materialDiffuse * lightDiffuse;
    float4 FinalSpecular = materialSpecular * lightSpecular;

    float4 color = (materialAmbient + globalAmbient) + (FinalDiffuse * nDotL) + (FinalSpecular * power);
    return color * tex2D(colorMap, IN.UV);
}

//-----------------------------------------------------------------------------
// Techniques.
//-----------------------------------------------------------------------------
technique DirectionalLight
{
    pass
    {
        AlphaBlendEnable = false;
        ZEnable = true;
        VertexShader = compile vs_3_0 VS();
        PixelShader = compile ps_3_0 PS();
    }
}
Advertisement

nDotL and nDotH are saturated (clamped to 0 - 1 range) so i see no reason to check anything as it will return valid number, just make sure that your "materialPower" > 0

//float power = (nDotL <= 0.0f) ? 0.0f : pow(nDotH, materialPower);
float power = pow(nDotH, materialPower);

@belfegor: That won't really help, I still have the same problem, you might want to check my shader code to see yourself what's going on :)

Copy/paste your cpp and whole shader again so i can see everything involved, try not to remove/edit something out.

@belfegor:

C++:


D3DXHANDLE hTechnique;
hTechnique = pEffect->GetTechniqueByName("DirectionalLighting");
if (FAILED(pEffect->SetTechnique(hTechnique)))
    return;

D3DXMATRIX view = camera->viewMatrix();
D3DXMATRIX proj = camera->projectionMatrix();

pEffect->SetMatrix("View", &view);
pEffect->SetMatrix("Projection", &proj);

// Light
float lightDiffuse[4] = {0.9f, 0.9f, 0.9f, 1.0f};
float lightSpecular[4] = {1.0f, 0.0f, 0.0f, 0.0f};
pEffect->SetValue("lightDiffuse", &lightDiffuse, sizeof(lightDiffuse));
pEffect->SetValue("lightSpecular", &lightSpecular, sizeof(lightSpecular));

// Material
float materialDiffuse[4] = {1.0f, 1.0f, 1.0f, 1.0f};
float materialAmbient[4] = {0.15f, 0.15f, 0.15f, 1.0f};
float materialSpecular[4] = {1.0f, 1.0f, 1.0f, 1.0f};
float materialPower = 20.0f;

pEffect->SetValue("materialDiffuse", &materialDiffuse, sizeof(materialDiffuse));
pEffect->SetValue("materialAmbient", &materialAmbient, sizeof(materialAmbient));
pEffect->SetValue("materialSpecular", &materialSpecular, sizeof(materialSpecular));
pEffect->SetValue("materialPower", &materialPower, sizeof(materialPower));

float gAmbient[4] = { 0.2f, 0.2f, 0.2f, 0.0f };
pEffect->SetValue("globalAmbient", &gAmbient, sizeof(gAmbient));

float lightDirection[3] = {1.0f, 0.0f, 1.0f};
pEffect->SetValue("lightDirection", &lightDirection, sizeof(lightDirection));

float cameraPos[3] = {camera->position().x, camera->position().y, camera->position().z};
pEffect->SetValue("cameraPos", cameraPos, sizeof(cameraPos));

pEffect->SetTexture("colorMapTexture", texture);

UINT passes = 0;
pEffect->Begin(&passes, 0);
pEffect->BeginPass(0);

D3DXMATRIX mWorld = model->worldMatrix();
pEffect->SetMatrix("World", &mWorld);

model->render(dt);

pEffect->EndPass();
pEffect->End();

Shader:


float4x4 World;
float4x4 View;
float4x4 Projection;

// Light
float4 lightDiffuse;
float4 lightSpecular;
float3 lightDirection;  // Directional light

// Material
float4 materialDiffuse;
float4 materialAmbient;
float4 materialSpecular;
float materialPower;

float4 globalAmbient;

// Camera position
float3 cameraPos;

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

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

struct VS_OUTPUT
{
   float4 Pos : POSITION;
   float2 UV : TEXCOORD0;
   float3 Normal : NORMAL;
   float3 worldPos : TEXCOORD4;
};

//-----------------------------------------------------------------------
// Vertex shader function
//-----------------------------------------------------------------------
VS_OUTPUT VS( VS_INPUT 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.UV = IN.UV;
    Out.Normal = mul(IN.Normal, (float3x3)World).xyz;
    Out.worldPos = mul(float4(IN.Pos, 1.0f), World).xyz;
    return Out;
}

//-----------------------------------------------------------------------
// Pixel shader function
//-----------------------------------------------------------------------
float4 PS( VS_OUTPUT IN ) : COLOR
{
    float3 viewDir = normalize(cameraPos - IN.worldPos);

    float3 lightDir = normalize(-lightDirection);
    float3 halfVector = normalize(lightDir + viewDir);

    float3 n = normalize(IN.Normal);
    float3 h = normalize(halfVector);
    float3 l = normalize(lightDir);
    
    float nDotL = saturate(dot(n, l));
    float nDotH = saturate(dot(n, h));
    float power = pow(nDotH, materialPower);

    float4 FinalDiffuse = materialDiffuse * lightDiffuse;
    float4 FinalSpecular = materialSpecular * lightSpecular;

    float4 color = (materialAmbient + globalAmbient) + (FinalDiffuse * nDotL) + (FinalSpecular * power);
    return color * tex2D(colorMap, IN.UV);
}

//-----------------------------------------------------------------------------
// Techniques.
//-----------------------------------------------------------------------------
technique DirectionalLighting
{
    pass
    {
        AlphaBlendEnable = false;
        ZEnable = true;
        VertexShader = compile vs_3_0 VS();
        PixelShader = compile ps_3_0 PS();
    }
}

I have just plugged your code and shader in some of my project, changed only light specular to pure white:

test2013-07-2122-21-01.jpg

try D3DXCreateTeapot instead of your model for test.

@belfegor: Have you tried to scale and move the teapot?

It works much better with the teapot, but when I scale and move it sometimes I see weird specular (Like the one I posted in the screenshot).

Generally, the diffuse light works well with any mesh, but the specular disappear with my box mesh, sometimes it show up, but it looks weird.

I believe there is a problem with the shader code.

@belfegor: Okay, after testing for sometime

I notice that the shapes I create manually works much better with the shader light (D3DXCreateTeapot, D3DXCreateBox, D3DXCreateSphere, etc...) All works very well with the light.

However, when I load a mesh using D3DXLoadMeshFromX(), the specular light get messed up.

Up

@belfegor: Okay, after testing for sometime

I notice that the shapes I create manually works much better with the shader light (D3DXCreateTeapot, D3DXCreateBox, D3DXCreateSphere, etc...) All works very well with the light.

However, when I load a mesh using D3DXLoadMeshFromX(), the specular light get messed up.

did you clone the mesh so it has NORMALS?

:)

This topic is closed to new replies.

Advertisement