c++ - HLSL Normal Mapping Matrix Multiplication -


i'm working in directx9 , have following code normal mapping:

(vertex shader):

float4x4 gworldmatrix; float4x4 gworldviewprojectionmatrix;  float4 gworldlightposition; float4 gworldcameraposition;  struct vs_input  {    float4 mposition : position;    float3 mnormal: normal;    float3 mtangent: tangent;    float3 mbinormal: binormal;    float2 muv: texcoord0; };  struct vs_output  {    float4 mposition : position;    float2 muv: texcoord0;    float3 mlightdir: texcoord1;    float3 mviewdir: texcoord2;    float3 t: texcoord3;    float3 b: texcoord4;    float3 n: texcoord5; };  vs_output vs_main( vs_input input ) {    vs_output output;     output.mposition = mul( input.mposition, gworldviewprojectionmatrix );     output.muv = input.muv;     float4 worldposition = mul( input.mposition, gworldmatrix );     float3 lightdir = worldposition.xyz - gworldlightposition.xyz;    output.mlightdir = normalize( lightdir );     float3 viewdir = normalize( worldposition.xyz - gworldcameraposition.xyz );    output.mviewdir = viewdir;     //object space=>world space    float3 worldnormal = mul( input.mnormal, (float3x3)gworldmatrix );    output.n = normalize( worldnormal );     float3 worldtangent = mul( input.mtangent, (float3x3)gworldmatrix );    output.t = normalize( worldtangent );     float3 worldbinormal = mul( input.mbinormal, (float3x3)gworldmatrix );    output.b = normalize( worldbinormal);     return output; } 

(pixel shader)

struct ps_input {    float2 muv : texcoord0;    float3 mlightdir: texcoord1;    float3 mviewdir: texcoord2;    float3 t: texcoord3;    float3 b: texcoord4;    float3 n: texcoord5; };  sampler2d diffusesampler; sampler2d specularsampler; sampler2d normalsampler;  float3 glightcolor;  float4 ps_main(ps_input input) : color {    //read normal tex    float3 tangentnormal = tex2d( normalsampler, input.muv ).xyz;    tangentnormal = normalize( tangentnormal * 2 - 1 ); //convert 0~1 -1~+1.     //read vertex shader    float3x3 tbn = float3x3( normalize(input.t), normalize(input.b),       normalize(input.n) ); //transforms world=>tangent space     tbn = transpose( tbn ); //transform tangent space=>world     float3 worldnormal = mul( tbn, tangentnormal ); //note: mat * scalar    //(since tbn row matrix)     float3 lightdir = normalize( input.mlightdir );     float3 diffuse = saturate( dot(worldnormal, -lightdir) );     float4 albedo = tex2d( diffusesampler, input.muv );    diffuse = glightcolor * albedo.rgb * diffuse;     float3 specular = 0;    if ( diffuse.x > 0 )    {       float3 reflection = reflect( lightdir, worldnormal );       float3 viewdir = normalize( input.mviewdir );        specular = saturate( dot(reflection, -viewdir) );       specular = pow( specular, 20.0f );        //further adjustments specular (since texture 2d)       float specularintensity = tex2d( specularsampler, input.muv );       specular *= specularintensity * glightcolor;    }     float3 ambient = float3(0.1f, 0.1f, 0.1f) * albedo;     return float4(ambient + diffuse + specular, 1); } 

the code works, don't quite understand why need

tbn = transpose( tbn ); in pixel shader.

the tbn values passed through vertex shader in world space (hence why multiplied gworldmatrix), yet i'm told that

float3x3 tbn = float3x3( normalize(input.t), normalize(input.b), normalize(input.n) );

transforms world=>tangent(surface) space.

why this?

you need line

tbn = transpose( tbn );  

because you're multipling tangent-space normal right matrix. therefore it's considered column vector, while base vectors in rows of matrix. matrix must transposed, base transformation can applied. can omit transposition, if youre switch multiplication to

float3 worldnormal = mul( tangentnormal, tbn ); 

because multiplied t,n , b vector worldmatrix tbn matrix transforms tangent space world space (tbn transforms object-space, after world transforms worldspace). other implementations multiply tbn world inverse transpose matrix. resulting tbn can transform light vector world tangent space , compare tangent normal. think 1 told tbn transforms world tangent space uses approach (it saves performance, because heavy matrix-operations done in vertexshader).


Comments

Popular posts from this blog

jquery - How can I dynamically add a browser tab? -

node.js - Getting the socket id,user id pair of a logged in user(s) -

keyboard - C++ GetAsyncKeyState alternative -