Jump to content

  • Log In with Google      Sign In   
  • Create Account


Per-Pixel Point Light


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
18 replies to this topic

#1 Medo3337   Members   -  Reputation: 665

Like
-1Likes
Like

Posted 15 July 2013 - 05:50 PM

I have been having some troubles to get point light to work, I looked into some code samples, but always getting a problem when trying to implement point light.

 

Can someone show me how do I modify my shader to implement point light? 

matrix World;
matrix View;
matrix Projection;

// Point light variables
float4 lightPosition;
float lightRange;
float4 lightDiffuse;
float4 lightAmbient;
float4 lightSpecular;

// Texture
texture colorMapTexture;

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

struct PS_INPUT
{
   float4 Pos : SV_POSITION;
   float2 UV : TEXCOORD0;
   float3 Normal : TEXCOORD1;
};

struct VS_INPUT 
{
   float4 Pos : SV_POSITION;
   float2 UV : TEXCOORD0;
   float3 Normal : TEXCOORD1;
};

struct VS_OUTPUT 
{
   float4 Pos : SV_POSITION;
   float2 UV : TEXCOORD0;
   float3 Normal : TEXCOORD1;
};

//-----------------------------------------------------------------------
// Vertex shader function
//-----------------------------------------------------------------------
VS_OUTPUT VS( VS_INPUT IN )
{
    VS_OUTPUT Out;
    Out = (VS_OUTPUT)0;
    Out.Pos = mul (IN.Pos, World);
    Out.Pos = mul (Out.Pos, View);
    Out.Pos = mul (Out.Pos, Projection);
    Out.UV = IN.UV;
    Out.Normal = mul(IN.Normal, (float3x3)World);
    return Out;
}

//-----------------------------------------------------------------------
// Pixel shader function
//-----------------------------------------------------------------------
float4 PS( PS_INPUT IN ) : COLOR
{
     // *** I need to modify this function for point light ***
     return tex2D(colorMap, IN.UV);
}

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

 


Edited by Medo3337, 15 July 2013 - 06:37 PM.


Sponsor:

#2 Medo3337   Members   -  Reputation: 665

Like
0Likes
Like

Posted 15 July 2013 - 11:44 PM

Okay, I have been trying for a while to do basic lighting in shader and here is what I got so far (Point Light):

5948.png

 

So here I have 2 problems:

1. The point light is weird (as shown in the screenshot)

2. When the mesh move away from the point light it get black

 

Shader code:

float4x4 World;
float4x4 View;
float4x4 Projection;

// Point light
float4 lightPosition;
float4 lightDiffuse;
float4 lightAmbient;
float4 lightSpecular;
float lightRange;

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

float4 globalAmbient;

// Camera position
float eyePos;

// Texture
texture colorMapTexture;

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

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

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

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

//-----------------------------------------------------------------------
// 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);
    Out.worldPos = mul(float4(IN.Pos, 1.0f), World).xyz;
    return Out;
}

//-----------------------------------------------------------------------
// Pixel shader function
//-----------------------------------------------------------------------
float4 PS( PS_INPUT IN ) : COLOR
{
     float3 viewDir = eyePos - IN.worldPos;
     float3 lightDir = (lightPosition - IN.worldPos) / lightRange;


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


    float3 n = normalize(tex2D(colorMap, 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 FinalDiffuse = materialDiffuse * lightDiffuse;
    float4 FinalSpecular = materialSpecular * lightSpecular;


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

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

 



#3 menohack   Members   -  Reputation: 216

Like
0Likes
Like

Posted 16 July 2013 - 07:36 AM

The whiteness looks like your specularity is too high (if materialPower is too big) and the darkness is something you should expect from a point light. The brightness decreases with the square of the distance. So it may be the case that it is just falling off too quickly from lightRange being too small.

 

VS_OUTPUT and PS_INPUT are the same thing--use a typedef or just use one of them to avoid mistakes.



#4 Medo3337   Members   -  Reputation: 665

Like
0Likes
Like

Posted 16 July 2013 - 10:26 AM

@menohack: I notice that the whiteness decrease when I give higher materialPower.

 

However, it still doesn't look like specular light, I see just white pixels on the mesh.

 

How do I avoid the darkness? For example, when there is a fire, there should be a point light, however the point light should not make everything black

 

lightRange is not too small, I notice in a direction the falloff decrease smoothly, while in the other direction it decrease not smoothly (like in the screenshot).

 

So, I guess that there is something wrong with the Shader code.



#5 belfegor   Crossbones+   -  Reputation: 2494

Like
0Likes
Like

Posted 16 July 2013 - 10:54 AM

I am confused as you are trying to use diffuse map as normal, WTF?

Do following changes and report back if it works as expected:

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


#6 Medo3337   Members   -  Reputation: 665

Like
0Likes
Like

Posted 16 July 2013 - 11:19 AM

@belfegor: Okay, the problem is partly resolved, the falloff transition is now smooth.

 

But I have two problems:

1. I don't see the speular light anymore

2. The mesh get black when it's far away from the light, how do I make it never black? the mesh should be AFFECTED by the light but never get black



#7 belfegor   Crossbones+   -  Reputation: 2494

Like
0Likes
Like

Posted 16 July 2013 - 12:12 PM

By my logic, this:

float4 color = (materialAmbient * (globalAmbient + (atten * lightAmbient))) + ...

should be like this:

// ambients should be added not multiplied or modified by light attenaution
float4 color = (materialAmbient + globalAmbient) + ...

When you fix this above also set some reasonable values for specular color and "materialPower".


Edited by belfegor, 16 July 2013 - 12:14 PM.


#8 Medo3337   Members   -  Reputation: 665

Like
0Likes
Like

Posted 16 July 2013 - 12:36 PM

@belfegor: When I change the line to:

float4 color = (materialAmbient + globalAmbient) + (FinalDiffuse * nDotL * atten) + (FinalSpecular * power * atten);

I don't see the light anymore.


Edited by Medo3337, 16 July 2013 - 12:36 PM.


#9 belfegor   Crossbones+   -  Reputation: 2494

Like
0Likes
Like

Posted 16 July 2013 - 12:52 PM


I don't see the light anymore.

This is not descriptive enough.

Give me all your color values that you are sending to shader.



#10 Medo3337   Members   -  Reputation: 665

Like
0Likes
Like

Posted 16 July 2013 - 01:04 PM

@belfegor:

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

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

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


// Material
float materialDiffuse[4] = {1.0f, 1.0f, 1.0f, 255.0f};
float materialAmbient[4] = {1.0f, 1.0f, 1.0f, 255.0f};
float materialSpecular[4] = {1.0f, 1.0f, 1.0f, 1.0f};
float materialPower = 20;
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 LightPos[4] = {0.0f, 0.0f, -50.1f, 0.0f};
pEffect->SetValue("lightPosition", &LightPos, sizeof(LightPos));
pEffect->SetValue("eyePos", &camera->GetPosition(), sizeof(camera->GetPosition()));

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

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

model->Render();

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

Here is the current shader code as well:

float4x4 World;
float4x4 View;
float4x4 Projection;


// Point light
float4 lightPosition;
float4 lightDiffuse;
float4 lightAmbient;
float4 lightSpecular;
float lightRange;

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

float4 globalAmbient;

// Camera position
float eyePos;

// Texture
texture colorMapTexture;

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

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

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

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

//-----------------------------------------------------------------------
// 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);
    Out.worldPos = mul(float4(IN.Pos, 1.0f), World).xyz;
    return Out;
}

//-----------------------------------------------------------------------
// Pixel shader function
//-----------------------------------------------------------------------
float4 PS( PS_INPUT IN ) : COLOR
{
     float3 viewDir = eyePos - 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));
    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 + (atten * lightAmbient))) +
    //               (FinalDiffuse * nDotL * atten) + (FinalSpecular * power * atten);
    
    float4 color = (materialAmbient + globalAmbient) + (FinalDiffuse * nDotL * atten) + (FinalSpecular * power * atten);
    return color * tex2D(colorMap, IN.UV);
}

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

 



#11 belfegor   Crossbones+   -  Reputation: 2494

Like
0Likes
Like

Posted 16 July 2013 - 01:26 PM

Color values should be in 0 - 1 range, ambients should be relatively small, so try this:

// Light
float lightDiffuse[4] = {1.0f, 1.0f, 1.0f, 1.0f};
//float lightAmbient[4] = {0.0f, 0.0f, 0.0f, 1.0f};
float lightSpecular[4] = {1.0f, 1.0f, 1.0f, 1.0f};
float lightRange = 100.0f;
...

// Material
float materialDiffuse[4] = {1.0f, 1.0f, 1.0f, 1.0f};
float materialAmbient[4] = {0.05f, 0.05f, 0.05f, 1.0f};
float materialSpecular[4] = {1.0f, 1.0f, 1.0f, 1.0f};
float materialPower = 8.0f;
...

 

and you are missing "globalAmbient":

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


#12 Medo3337   Members   -  Reputation: 665

Like
0Likes
Like

Posted 16 July 2013 - 02:07 PM

@belfegor: Now, the mesh is completely black all the time.



#13 belfegor   Crossbones+   -  Reputation: 2494

Like
0Likes
Like

Posted 16 July 2013 - 02:13 PM

It should not be completely black, have you enabled dx debug runtime? Check any dx debug messages in output window!

Repost your cpp code and shader.


Edited by belfegor, 16 July 2013 - 02:15 PM.


#14 Medo3337   Members   -  Reputation: 665

Like
0Likes
Like

Posted 16 July 2013 - 02:14 PM

@belfegor: Nothing really in the output window, the shader is working correctly, but the mesh is black all the time.

 

You might want to the check the shader code...


Edited by Medo3337, 16 July 2013 - 02:15 PM.


#15 belfegor   Crossbones+   -  Reputation: 2494

Like
0Likes
Like

Posted 16 July 2013 - 02:19 PM

It can't be pure black, should have at least ambient of 0.2 no matter the view and light angles, unless you have done something wrong in cpp code and then it skips shader.

I ask you again have you enbled dx debug runtime and set proper options in dx control panel?

Repost your cpp and shader!

 

I see you have your camera position in shader as single float set it as float3.


Edited by belfegor, 16 July 2013 - 02:26 PM.


#16 Medo3337   Members   -  Reputation: 665

Like
0Likes
Like

Posted 16 July 2013 - 02:39 PM

@belfegor: Now, the mesh is not black, however I see the texture and it's dark and I don't see any light affecting it when it's very close to the light position.

 

Shader:

float4x4 World;
float4x4 View;
float4x4 Projection;

// Point light
float4 lightPosition;
float4 lightDiffuse;
float4 lightAmbient;
float4 lightSpecular;
float lightRange;

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

float4 globalAmbient;

// Camera position
float3 eyePos;

// Texture
texture colorMapTexture;

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

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

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

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

//-----------------------------------------------------------------------
// 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);
    Out.worldPos = mul(float4(IN.Pos, 1.0f), World).xyz;
    return Out;
}

//-----------------------------------------------------------------------
// Pixel shader function
//-----------------------------------------------------------------------
float4 PS( PS_INPUT IN ) : COLOR
{
    float3 viewDir = eyePos - 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));
    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 + (atten * lightAmbient))) +
    //             (FinalDiffuse * nDotL * atten) + (FinalSpecular * power * atten);
    
    float4 color = (materialAmbient + globalAmbient) + (FinalDiffuse * nDotL * atten) + (FinalSpecular * power * atten);
    return color * tex2D(colorMap, IN.UV);
}


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

 



#17 Medo3337   Members   -  Reputation: 665

Like
0Likes
Like

Posted 16 July 2013 - 04:25 PM

I notice that the global ambient color is the only color that affect the mesh, there is no light at all.

 

The weird thing is that the light works perfectly when I change this line:

float3 n = normalize(IN.Normal);

To the old invalid value:

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

blink.png

 

What's going on?


Edited by Medo3337, 16 July 2013 - 05:00 PM.


#18 Medo3337   Members   -  Reputation: 665

Like
-1Likes
Like

Posted 17 July 2013 - 03:37 AM

Bump



#19 Waaayoff   Members   -  Reputation: 780

Like
1Likes
Like

Posted 18 July 2013 - 11:52 AM

Output the normals from the pixel shader as colour. Do they look correct?


"Spending your life waiting for the messiah to come save the world is like waiting around for the straight piece to come in Tetris...even if it comes, by that time you've accumulated a mountain of shit so high that you're fucked no matter what you do. "




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS