Jump to content
  • Advertisement
Sign in to follow this  
kobaj

Incorrect shader/normal issue in Directx

This topic is 2990 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

Hello! (First post, go easy)

I'm having the strangest issue with point lights and a diffuse shader I've written. To save some time, I've drawn up my problem,

http://img208.imageshack.us/img208/5818/helpka.png

As you can see, its as if the 'sides' of my models need to be rotated 180 degrees. I thought it had an issue to do with handedness and culling, but I've tried both

matProjection = Matrix.PerspectiveFovRH/LH (same for my view projection)

With multiple culls,

device.RenderState.CullMode = Cull.None/Clockwise/CounterClockwise;

And even changing every Z vertex to be its negative,

Vertices.Pos.Z = -Vertices.Pos.Z;

But its always the same.

My only thought is that the order that I'm writing the vertices, (IE, my indices) are for some reason not correct. But I don't /really/ have the ability to modify those (I mean, I can if thats the problem, but would prefer to avoid it).

As I said, I'm new to the forums, so I dont know how to post large chunks of code (is it just BB?). If anyone wants to see my shader or other big bits, I can post them. Otherwise, help?

Share this post


Link to post
Share on other sites
Advertisement
I'm curious to see your shader. I think your vertex shader may be flipping things around.

You can post it using either ['source]['/source] (get rid of the ').

-- Steve.

Share this post


Link to post
Share on other sites
Sure thing,


struct EngineToVertex
{
float4 Position : POSITION0;
float3 Normal : NORMAL0;
float2 TexCoords : TEXCOORD0;
float4 Tangent : TANGENT0;
};

struct VertexToPixel
{
float4 Position : POSITION0;
float3 Normal : TEXCOORD0;
float2 TexCoords : TEXCOORD1;
float3 Position3D : TEXCOORD3;
};


float3 LightDirection = float3(45,45,45);

float4x4 xViewProjection;

VertexToPixel SimplestVertexShader(EngineToVertex input)
{
VertexToPixel Output = (VertexToPixel)0;

Output.Position = mul(input.Position, xViewProjection);
Output.Position3D = input.Position;

Output.TexCoords = input.TexCoords;

Output.Normal = input.Normal;

return Output;
}

float4 OurFirstPixelShader(VertexToPixel input) : COLOR0
{
float4 Output = (float4)0;

float4 Diffuse = saturate(dot(normalize(LightDirection - input.Position3D), input.Normal));
Output = Diffuse + float4(.1f,.1f,.1f,1.0f);
Output.w = 1.0f;

return Output;
}




Thats the gist of it :).

Share this post


Link to post
Share on other sites
Okay, sorry for the late reply. The shader looks perfect--is this from Riemer's tutorial by any chance? :)

A couple more questions I should have asked:

1. What's the orientation of the cube? (What's the camera and cube position? Or, the face on the top is in the X-Z plane, the face on the right is in the Y-Z plane, and the face on the left is in the X-Y plane, right?)

2. What's the other side of the cube look like? Can you move the camera there so we can see what that looks like?

3. You generated that corrected cube image outside your program, right? (Photoshop or something?)

The answer to my second question is particularly important: I have a hunch that your two faces that you show rotating in your figure are actually correctly lit, and the one closest to us (on the left in your figure) is actually incorrect. If we get to the other side of the cube (rotate the camera 180 deg around the cube's Y axis) and find that the other face is dark, I would say both those faces have their normals pointing inwards. The light is on the other side of the face we see is lit, and the face you think is right actually has its normal pointing inwards toward the center of the cube (at the light) and is thus getting lit incorrectly. If the opposing face is dark, its normal is wrong too. Try flipping it and see what happens. (There's a chance that if one's flipped, they're all flipped, so stick a negative sign in front of them in your shader and see if things look right; if things look worse, undo that and try flipping them one by one in your code to find the bad one.) That was probably a bad explanation; if I had the art skills I would draw it. But does that make sense?

You might have already done those things--sorry if I'm asking a lot of the same questions you've asked yourself! Just trying to get oriented. I'm interested in this kind of problem though, because it's the little gnat that bugs you when you're programming, maybe for a couple days, but when you realize your mistake (it can sometimes be a silly one, like a negative sign), you'll recognize the situation (or a similar one) later and know how to fix it immediately.

In the meantime...let me try and come up with a picture to explain what I'm saying...

Good luck!

-- Steve.

Share this post


Link to post
Share on other sites
Quote:
Original post by STufaro
Okay, sorry for the late reply. The shader looks perfect--is this from Riemer's tutorial by any chance? :)

A couple more questions I should have asked:

1. What's the orientation of the cube? (What's the camera and cube position? Or, the face on the top is in the X-Z plane, the face on the right is in the Y-Z plane, and the face on the left is in the X-Y plane, right?)

2. What's the other side of the cube look like? Can you move the camera there so we can see what that looks like?

3. You generated that corrected cube image outside your program, right? (Photoshop or something?)

*snip*

Good luck!

-- Steve.


Heh, the shader is part Riemers, part RandomChaos and part my own.

To answer your questions,
1. I honestly don't know. I wrote the constructor for my cubes about 2 years back (yeah...I've been working on my game for a long time XD...JUST now getting to shaders...shhh). As well as I wrote it for a Right handed system, and Directx is a Left handed. (Which, surprise, was my problem).

2.The other side, opposite the "completely white" one was "completely black".

3.Yeah, Gimp.

LONG story short, as I found out my constructor was fubar. Re-wrote it, added a ton to my shader, and now I have some good looking renders if I do say so myself.

http://img693.imageshack.us/img693/4164/22241303.png
(Dont ask what it is, just a work in progress ;D).

(Code thanks to Riemers, RandomChaos, and Catlin's Experiments)

struct EngineToVertex
{
float4 Position : POSITION0;
float3 Normal : NORMAL0;
float2 TexCoords : TEXCOORD0;
float4 Tangent : TANGENT0;
};

struct VertexToPixel
{
float4 Position : POSITION0;
float3 Normal : TEXCOORD0;
float2 TexCoords : TEXCOORD1;
float3 Position3D : TEXCOORD2;
float3 LightDirection : TexCoord3;
float3 LightDirectionUnmodified : TEXCOORD4;
};

//lights, none ambient
float DiffuseIntensity;
float4 DiffuseColor;
float3 LightPosition;

float3 CameraPosition : CameraPosition;

//on the cpu the intensity is calculated.
float4 AmbientColor;

float4x4 xViewProjection;

//texture data
texture xTexture;
sampler TextureSampler = sampler_state { texture = <xTexture> ; magfilter = Linear; minfilter = Linear; mipfilter = Linear; AddressU = mirror; AddressV = mirror;};
Texture xGlow;
sampler GlowSampler = sampler_state { texture = <xGlow> ; magfilter = Linear; minfilter = Linear; mipfilter = Linear; AddressU = mirror; AddressV = mirror;};
Texture xReflect;
sampler ReflectSampler = sampler_state { texture = <xReflect> ; magfilter = Linear; minfilter = Linear; mipfilter = Linear; AddressU = mirror; AddressV = mirror;};
Texture xBump;
sampler BumpSampler = sampler_state { texture = <xBump> ; magfilter = Linear; minfilter = Linear; mipfilter = Linear; AddressU = mirror; AddressV = mirror;};

VertexToPixel SimplestVertexShader(EngineToVertex input)
{
VertexToPixel Output = (VertexToPixel)0;

Output.Position = mul(input.Position, xViewProjection);
Output.Position3D = input.Position;

Output.LightDirection = LightPosition - input.Position;
Output.LightDirectionUnmodified = Output.LightDirection;

Output.TexCoords = input.TexCoords;

Output.Normal = input.Normal;

float3 b = cross(input.Tangent.xyz,input.Normal) * input.Tangent.w;
float3x3 tbnMatrix = float3x3(input.Tangent.x, b.x, input.Normal.x,
input.Tangent.y, b.y, input.Normal.y,
input.Tangent.z, b.z, input.Normal.z);

Output.LightDirection = mul(Output.LightDirection,tbnMatrix);

return Output;
}


float4 OurFirstPixelShader(VertexToPixel input) : COLOR0
{
float4 Output = (float4)0;

//textures
float4 Texture = tex2D(TextureSampler,input.TexCoords);
float4 Glow = tex2D(GlowSampler, input.TexCoords);
float4 ReflectTex = tex2D(ReflectSampler, input.TexCoords);

//specular
float3 reflectionVector = normalize(reflect(-normalize(input.LightDirectionUnmodified), input.Normal));
float3 directionToCamera = normalize(CameraPosition - input.Position3D);
float specularLight = 1.0 * pow( saturate(dot(reflectionVector, directionToCamera)), 32);
float4 SpecularFinal = specularLight * ReflectTex;

//setup bumpmapping
input.Normal = (2 * (tex2D(BumpSampler,input.TexCoords))) - 1.0;

//diffuse
float Diffuse = saturate(dot(normalize(input.LightDirection), input.Normal));
float4 DiffuseFinal = (DiffuseColor * DiffuseIntensity) * Diffuse * Texture;

//glow
float4 GlowFinal = Glow * saturate(.5f-Diffuse);

Output = (SpecularFinal * Diffuse) + DiffuseFinal + GlowFinal;

return Output;
}

float4 AmbientPixelShader(VertexToPixel input) : COLOR0
{
float4 Output = (float4)0;

Output = AmbientColor;

return Output;
}

technique Simplest
{
pass Pass0
{
VertexShader = compile vs_2_0 SimplestVertexShader();
PixelShader = compile ps_2_0 OurFirstPixelShader();
}

pass Ambient
{
VertexShader = compile vs_2_0 SimplestVertexShader();
PixelShader = compile ps_2_0 AmbientPixelShader();
}
}



Everything works perfectly (Well, mostly).

Thanks for the help :).

Share this post


Link to post
Share on other sites
Excellent! I've never had to deal with a coordinate system mix-up, but now I know what one looks like. And I know what you mean about long works in progress...

Anyway, glad I could help throw stuff out there.

-- Steve.

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!