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 ) );
}

 

posted @ 2013-07-24 21:21  Jun_cd  阅读(259)  评论(0)    收藏  举报