NormalMap
NormalMap:传入一张包含每个像素法线的法线贴图,计算光照时应有这个法线,注意要在切线
空间中进行计算,因为传入的图的法线是定义在切线空间(TangentSpace)中的.
关键字:TBN,视图空间,切线空间.
TBN:切线空间到模型空间的变换矩阵
参考:
http://www.zwqxin.com/archives/shaderglsl/review-normal-map-bump-map.html
monkey具体配置及效果

具体shader
VS
float4x4 matViewProjection; float4x4 matView; float4 fLightPosition; float4 fEyePosition; struct VS_INPUT { float4 Position : POSITION0; float2 Texcoord : TEXCOORD0; float3 Normal : NORMAL0; float3 Binormal : BINORMAL0; float3 Tangent : TANGENT0; }; struct VS_OUTPUT { float4 Position : POSITION0; float2 Texcoord : TEXCOORD0; float3 LightDirTS : TEXCOORD1; float3 ViewDirection : TEXCOORD2; }; VS_OUTPUT vs_main( VS_INPUT Input ) { VS_OUTPUT Output; //模型在视图空间中的位置 float4 vObjectPos = mul(Input.Position,matView); ; //视图空间中的法线、副法线、切线 float3 vNormalVS = mul(Input.Normal,matView); float3 vBinormalVS = mul(Input.Binormal,matView); float3 vTangentVS = mul(Input.Tangent,matView); //视图空间中视线方向 float3 vEyeDir = (fEyePosition.xyz - vObjectPos.xyz); //视图空间中顶点指向光源的方向 float3 vLightDir = ( fLightPosition.xyz - vObjectPos.xyz); Output.Position = mul( Input.Position,matViewProjection); Output.Texcoord = Input.Texcoord; Output.LightDirTS.x = dot(vTangentVS,vLightDir); Output.LightDirTS.y = dot(vBinormalVS,vLightDir); Output.LightDirTS.z = dot(vNormalVS,vLightDir); Output.ViewDirection.x = dot(vTangentVS,vEyeDir); Output.ViewDirection.y = dot(vBinormalVS,vEyeDir); Output.ViewDirection.z = dot(vNormalVS,vEyeDir); return( Output ); }
PS
sampler2D BaseMap; sampler2D BumpMap; float4 Ambient; float4 Diffuse; float4 Specular; struct PS_INPUT { float4 Position : POSITION0; float2 Texcoord : TEXCOORD0; float3 LightDirTS : TEXCOORD1; float3 ViewDirection : TEXCOORD2; }; float4 ps_main(PS_INPUT Input) : COLOR0 { //重新normalize float3 fLightDir = normalize(Input.LightDirTS); float3 fViewDir = normalize(Input.ViewDirection); //获得法线贴图的法线,转换到[-1, 1]空间之中 float3 vNormalTS = normalize(tex2D(BumpMap, Input.Texcoord).xyz * 2.0f - 1.0f); float fNDotL = dot(vNormalTS,fLightDir); //Blin_Phong float3 HalfVec = normalize(fViewDir + fLightDir); float NDotH = max(0.0f,dot(vNormalTS,HalfVec)); //Phong float3 fvReflection = normalize( ( ( 2.0f * vNormalTS ) * ( fNDotL ) ) - fLightDir ); float fRDotV = max( 0.0f, dot( fvReflection, fViewDir ) ); //基础色 float4 baseColor = tex2D(BaseMap,Input.Texcoord); float4 fvTotalAmbient = Ambient * baseColor; float4 fvTotalDiffuse = Diffuse * fNDotL * baseColor; float4 fvTotalSpecular = Specular * pow( NDotH ,25.0); return ( saturate( fvTotalAmbient + fvTotalDiffuse + fvTotalSpecular ) ); }


浙公网安备 33010602011771号