Jump to content
  • Advertisement
Sign in to follow this  
LHLaurini

Specular highlights appear flat even though diffuse lighting is smooth

This topic is 977 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi!

 

I've implemented the Blinn-Phong shading model some time ago and noticed that even though the diffuse component looks smooth, the specular one doesn't (it looks good on flat surfaces). Look at the screenshot (ignore the crappy shadows):

[attachment=29608:Captura de Tela (10).png]

 

These are my vertex and pixel shaders (I've simplified it a lot and removed shadow mapping):

cbuffer cbChangesOnTime: register(b0)
{
	float4 SunColor;
	float3 SunDir;
	float4 AmbientColor;
}

cbuffer cbChangesEveryFrame: register(b1)
{
	matrix World;
	matrix View;
	matrix Projection;
	matrix LightView;
	matrix LightProjection;
	float3 CameraPosition;
	float4 DiffuseColor;
	float4 SpecularColor;
	float SpecularPower;
	float AmbientIntensity;
}

struct VSInput
{
	float4 pos: POSITION;
	float2 uv: TEXCOORD;
	float3 norm: NORMAL;
};

struct PSShadowedInput
{
	float4 pos: SV_POSITION;
	float2 uv: TEXCOORD;
	float3 norm: NORMAL;
	float4 worldPos: POSITION;
	float4 lightViewPos: POSITION2;
};

///////////////////////////////
// This is the Vertex Shader //
///////////////////////////////

PSShadowedInput VSShadowed(VSInput input)
{
	PSShadowedInput output;

	output.pos = mul(World, input.pos);
	output.pos = mul(View, output.pos);
	output.pos = mul(Projection, output.pos);

	output.uv = input.uv;

	output.norm = normalize(mul((float3x3)World, input.norm));

	output.worldPos = mul(World, input.pos);

	/* SHADOW MAPPING */

	return output;
}

//////////////////////////////
// This is the Pixel Shader //
//////////////////////////////

float4 PSShadowedLambertian(PSShadowedInput input) : SV_Target
{
	float3 ViewDirection = normalize(CameraPosition - input.worldPos.xyz);

	float4 Diffuse = max(dot(-SunDir, input.norm), 0.0f) * SunColor * DiffuseColor;
	float4 Specular = pow(max(dot(input.norm, normalize(-SunDir + ViewDirection)), 0.0f), SpecularPower) * SpecularColor;
	float4 Ambient = AmbientColor * AmbientIntensity * DiffuseColor;

	/* SHADOW MAPPING */

	return pow(max(Diffuse + Specular + Ambient, 0.0f), 1.0f / 2.2f);
}

What am I doing wrong? What's missing?

 

Thank you for spending your time reading this topic.

Edited by LHLaurini

Share this post


Link to post
Share on other sites
Advertisement

Not sure it'll be the cause, but you can't normalize your normal in the vertex shader and expect it still to be normalised in the pixel shader after interpolation. Try normalizing input.norm and see if that helps?

Share this post


Link to post
Share on other sites

Not sure it'll be the cause, but you can't normalize your normal in the vertex shader and expect it still to be normalised in the pixel shader after interpolation. Try normalizing input.norm and see if that helps?

 

But it's already in the vertex shader, in the line "output.norm = normalize(mul((float3x3)World, input.norm));". See the function name: "VSShadowed"? It's a Vertex Shader. Sorry, I should've made that more clear. Thanks for the quick response.

Share this post


Link to post
Share on other sites

But you're not normalizing the input.norm in the pixel shader. You need to. Interpolated normal vectors may no longer be normal.

Edited by phil_t

Share this post


Link to post
Share on other sites

But you're not normalizing the input.norm in the pixel shader. You need to. Interpolated normal vectors may no longer be normal.

 

Oh, sorry I read that wrong. I read it like "can't you normalize your normal in the vertex shader...". I'm going to try that out.

Share this post


Link to post
Share on other sites

 

Not sure it'll be the cause, but you can't normalize your normal in the vertex shader and expect it still to be normalised in the pixel shader after interpolation. Try normalizing input.norm and see if that helps?

 

But it's already in the vertex shader, in the line "output.norm = normalize(mul((float3x3)World, input.norm));". See the function name: "VSShadowed"? It's a Vertex Shader. Sorry, I should've made that more clear. Thanks for the quick response.

 

 

Doesn't matter if it's normalized in the vertex shader, it still has to be normalized again in the pixel shader. (To clarify, for proper results normals should be normalized in both vertex and pixel shader.)

 

The normals will be linearly interpolated between vertices; as a result they will be shorter than expected away from the vertices. The exponentiation for the specular component means that this manifests most clearly in the specular highlights looking very much like vertex-shaded highlights.

Edited by Anthony Serrano

Share this post


Link to post
Share on other sites

Not sure it'll be the cause, but you can't normalize your normal in the vertex shader and expect it still to be normalised in the pixel shader after interpolation. Try normalizing input.norm and see if that helps?

 

 

But you're not normalizing the input.norm in the pixel shader. You need to. Interpolated normal vectors may no longer be normal.

 

 

 

 

Not sure it'll be the cause, but you can't normalize your normal in the vertex shader and expect it still to be normalised in the pixel shader after interpolation. Try normalizing input.norm and see if that helps?

 

But it's already in the vertex shader, in the line "output.norm = normalize(mul((float3x3)World, input.norm));". See the function name: "VSShadowed"? It's a Vertex Shader. Sorry, I should've made that more clear. Thanks for the quick response.

 

 

Doesn't matter if it's normalized in the vertex shader, it still has to be normalized again in the pixel shader.

 

The normals will be linearly interpolated between vertices; as a result they will be shorter than expected away from the vertices. The exponentiation for the specular component means that this manifests most clearly in the specular highlights looking very much like vertex-shaded highlights.

 

Thank you all so much. It works perfectly now.

 

I didn't even realised interpolation would ruin the normalization. I could've noticed that if I wasn't so dumb. Also, thanks for the explanation, Anthony. It make a lot of sense.

 

Thank you so much.

 

PS: Also, why should they be normalized in both VS and PS?

Edited by LHLaurini

Share this post


Link to post
Share on other sites

PS: Also, why should they be normalized in both VS and PS?

Because the results will be different if you do not.

For easy imagination, imagine vertex-shader vectors [1,0] and [0,1] (both normalized). 50% between them is [0.5,0.5], which normalizes to [0.70711,0.70711] in the pixel shader (hence why you have to normalized in the pixel shader).
Now imagine vertex-shader vectors [100,0] and [0,1] (not normalized). 50% between them is [50,0.5], which normalizes in the pixel shader to [0.99995,0.0099995] (hence why you have to normalize in the vertex shader).


L. Spiro Edited by L. Spiro

Share this post


Link to post
Share on other sites

 

PS: Also, why should they be normalized in both VS and PS?

Yes.


L. Spiro

 

Um... Okay, but why? It's working just fine normalizing only in the Pixel Shader.

Edited by LHLaurini

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

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

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!