Sign in to follow this  
Endemoniada

World Inverse Transpose

Recommended Posts

Hi guys,

I'm rendering a cube with a basic diffuse vertex shader. It works fine when I transform the normal with the WorldInverseTranspose but does not work at all when I transform with the World. I am only doing translation, not scaling or even rotation. Most tutorials I see transform the normal by the World so I don't see what I can be doing wrong. I'm using D3D9. Here is the shader code:

// diffuse vertex shader

float4x4 World;
// float4x4 WorldInverseTranspose;
float4x4 WorldViewProjection;

float4 LightDirection;

struct VS_INPUT
{
float4 position : POSITION;
float4 normal : NORMAL;
};

struct VS_OUTPUT
{
float4 position : POSITION;
float4 color : COLOR;
};


VS_OUTPUT vshader(VS_INPUT input)
{
VS_OUTPUT output;

output.position=mul(input.position,WorldViewProjection);

float4 N=normalize(mul(input.normal,World));
float4 L=normalize(LightDirection);

float NL=saturate(dot(N,L));

output.color=float4(NL,NL,NL,1);

return output;
}


float4 pshader(VS_OUTPUT input) : COLOR
{
return input.color;
}

Please help.

Share this post


Link to post
Share on other sites
Hey, I figured it out.

It works when I do:

mul(World,input.normal);

instead of:

mul(input.normal,World);

Will someone please explain, in layman's terms, why that works. Thanks guys.

EDIT: actually, that doesn't seem to work when rotation is applied.

Share this post


Link to post
Share on other sites
Multiplication with matricies is not [url="http://en.wikipedia.org/wiki/Commutative_property"]commutative[/url].

Instead of using [font="Courier New"]input.normal[/font], you want to use [font="Courier New"]float4(input.normal.xyz, 0.0)[/font]. The reason is that the 4th component of the vector acts as a scaling factor for the translation part of the matrix. You only want your normals to be rotated (not translated!), so a 4th component of zero should be used.

Share this post


Link to post
Share on other sites
Hi,
Instead of:
float4 N=normalize(mul(float4(input.normal.xyz, 0),World));
use
float3 N=normalize( mul( input.normal.xyz, (float3x3)World));
and float3 for light direction (.w component is not used anyway)
This saves some inst.

Share this post


Link to post
Share on other sites
[quote name='kociolek' timestamp='1308081505' post='4823341']Instead of:
float4 N=normalize(mul(float4(input.normal.xyz, 0),World));
use
float3 N=normalize( mul( input.normal.xyz, (float3x3)World));[/quote]They both actually compile to the same assembly code (last I tested) [img]http://public.gamedev.net/public/style_emoticons/default/biggrin.gif[/img]

Share this post


Link to post
Share on other sites
Yeah the compiler will aggressively optimize out multiplications with 0 or 1, or additions with 0, etc. You can take advantage of this to make your code more intuitive, especially if you're auto-generating many permutations of shaders.

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