Jump to content
  • Advertisement
Sign in to follow this  
VanillaSnake21

DX11 Directional light implementation in the pixel shader

Recommended Posts

I'm trying to implement lighting in my engine but running into some issue. I'm using Frank Luna's book Beginner's Guide to Programming with DirectX 11, but I'm not sure that I'm reading the descriptions right.

 

This is the pseudocode that I wrote based on the book's guidelines.

1) Calculate vertex normals for the mesh (on the cpu)

2) Find angle between light direction and vertex normal (in the pixel shader)

               angle = max( dotproduct(light_dir, vertex_normal), 0)

3) Find the color of the pixel if the texture was applied to it

              textured_pixel_color = sample(texture)

4) Combine the light color with the textured pixel color 

              final_color = lightColor * textured_pixel_color

5) Combine the intensity with the final_color to get the final_pixel_color_and_intensity

                final_pixel_color_and_intensity = angle * final_color

 

This is it implemented in the pixel shader

cbuffer DirectionalLight : register (b2)
{
	float3 LightDirection;
	float3 LightColor;
};


struct TexturedLitVertex
{
	float4 Pos :   SV_POSITION;
	float3 Normal: NORMAL;
	float2 Uv:     TEXCOORD;
};

float4 PS_DirectionalLight(TexturedLitVertex psInput) : SV_Target
{
	float4 colorAfterTexture = txDiffuse.Sample(triLinearSampler, psInput.Uv);
	
	float lightNormalAngle = max(dot(LightDirection, psInput.Normal), 0.0f);

	return lightNormalAngle * (colorAfterTexture*float4(LightColor, 1.0f));
}

 

This is the result I'm getting (see image).  What could be the problem?

Sample.jpg

Share this post


Link to post
Share on other sites
Advertisement

What are the DirectionalLight values u pass as a uniform?

Also you should normalize

psInput.Normal

as it is a per pixel lightning and the normal interpolates.

Share this post


Link to post
Share on other sites
Posted (edited)
5 hours ago, JohnnyCode said:

What are the DirectionalLight values u pass as a uniform?

Also you should normalize


psInput.Normal

as it is a per pixel lightning and the normal interpolates.

The light direction is (0.57, -0.57, 0.57) the light color is (1.0f, 1.0f, 1.0f, 1.0f)

The vertex normal is normalized in the vertex shader. 

 

What do you mean this is a per pixel lighting? I'm trying to do per vertex lighting.

Edited by VanillaSnake21

Share this post


Link to post
Share on other sites
Posted (edited)

I ended up just using the version in the DirectX samples (June 2010) Tutorial 06: Lighting the pixel shader is much more simplified but it works:

cbuffer DirectionalLight : register (b2)
{
	float3 LightDirection;
	float4 LightColor;
};


struct TexturedLitVertex
{
	float4 Pos :   SV_POSITION;
	float3 Normal: NORMAL;
	float2 Uv:     TEXCOORD;
};


TexturedLitVertex VS_DirectionalLight(float4 Pos : POSITION, float3 Normal : NORMAL, float2 Uv : TEXCOORD0)
{
	TexturedLitVertex vsOut = (TexturedLitVertex)0;

	vsOut.Pos = mul(Pos, World);
	vsOut.Pos = mul(vsOut.Pos, View);
	vsOut.Pos = mul(vsOut.Pos, Projection);

	vsOut.Normal = mul(Normal, (float3x3)World);
	vsOut.Uv = Uv;
	
	return vsOut;
}

float4 PS_DirectionalLight(TexturedLitVertex psInput) : SV_Target
{
	psInput.Normal = normalize(psInput.Normal);

	float4 finalColor = 0;

	//do NdotL lighting
	float4 lcolor = { 1.0f, 1.0f, 1.0f, 1.0f };
	finalColor += saturate(dot((float3)LightDirection, psInput.Normal) * lcolor * txDiffuse.Sample(triLinearSampler, psInput.Uv));
	
	finalColor.a = 1;
	return finalColor;
	
}

 

This is the working image of it:

WorkingSample.jpg

Edited by VanillaSnake21

Share this post


Link to post
Share on other sites

I do all shading in the fragment shader (OpenGL term for pixel shader, i think) and remember having had similar effects.

 

This may be a stupid hint, but may it be that you are lighting the scene from below ? What happens when you change sign of Light direction in:

float lightNormalAngle = max(dot(LightDirection, psInput.Normal), 0.0f);

or change the light position to be positive on all axes ?

 

Just a random thought ...

Share this post


Link to post
Share on other sites
17 hours ago, VanillaSnake21 said:

float4 PS_DirectionalLight(TexturedLitVertex psInput) : SV_Target { float4 colorAfterTexture = txDiffuse.Sample(triLinearSampler, psInput.Uv); float lightNormalAngle = max(dot(LightDirection, psInput.Normal), 0.0f); return lightNormalAngle * (colorAfterTexture*float4(LightColor, 1.0f)); }

Since you perform taxture sampling in the function I take it for granted you perform the dot product between light direction and normal in pixel function as well, and that is why you need to normalize it in pixel function again, normalizing in vertex function is not sufficient, since as I said, it interpolates.

And I will add up you seem to have a correct result now? Is there still a problem?

Edited by JohnnyCode
add up

Share this post


Link to post
Share on other sites
7 hours ago, Green_Baron said:

I do all shading in the fragment shader (OpenGL term for pixel shader, i think) and remember having had similar effects.

 

This may be a stupid hint, but may it be that you are lighting the scene from below ? What happens when you change sign of Light direction in:


float lightNormalAngle = max(dot(LightDirection, psInput.Normal), 0.0f);

or change the light position to be positive on all axes ?

 

Just a random thought ...

 Yes, I think I was lighting it from the bottom. I'm not sure it was the only issue though. The light direction values the DirectX sample had were opposite of mine (mine were (0.577, -0.577, 0.577) the sample had ({ -0.577f, 0.577f, -0.577f }) so it might have very well been the issue, but it works now as far as i can tell. 

5 hours ago, JohnnyCode said:

Since you perform taxture sampling in the function I take it for granted you perform the dot product between light direction and normal in pixel function as well, and that is why you need to normalize it in pixel function again, normalizing in vertex function is not sufficient, since as I said, it interpolates.

 

 I added the normalization as you suggested (see code in my previous post), but I'm not sure I understand the reason for it. I'm not changing the value of the normal in the pixel shader. The only time I use it is in the dot product with the light, but why would that change it's value? Anyways, thanks, it works now.

Share this post


Link to post
Share on other sites
39 minutes ago, VanillaSnake21 said:

I added the normalization as you suggested (see code in my previous post), but I'm not sure I understand the reason for it. I'm not changing the value of the normal in the pixel shader. The only time I use it is in the dot product with the light,

Pixel function inputs are streamed from vertex function and are interpolated (wheather a number or a multiple dimension vector) across the rasterized triangle, based on baricentric cordinates of pixel inside the triangle between the verticies. And interpolation does not preserve the length of multidimensional vector, thus to recieve a correct interpretation of dot product, you need to normalize it.

Share this post


Link to post
Share on other sites
1 hour ago, JohnnyCode said:

Pixel function inputs are streamed from vertex function and are interpolated (wheather a number or a multiple dimension vector) across the rasterized triangle, based on baricentric cordinates of pixel inside the triangle between the verticies. And interpolation does not preserve the length of multidimensional vector, thus to recieve a correct interpretation of dot product, you need to normalize it.

That's interesting, I just didn't know that something was done to the vectors in between the vertex and pixel function. It makes sense now, thanks!

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!