Ogre中将法线贴图和硬件蒙皮结合

原文链接:http://www.ogre3d.org/tikiwiki/Normal+Mapping+with+Hardware+Skinning+and+Specular&structure=Cookbook

原本标题:Normal Mapping with Hardware Skinning and Specular - Combined normal mapping and hardware skinning

官网中关于法线贴图(Normal Mapping)和置换贴图(Displacement Mapping)的例子有很多,但是它们都不能与硬件蒙皮(Hardware Skinning)一起发挥作用。为了帮助遇到同样问题的人,我写了这篇文章。

使用(Usage)

只需将animatedNormalSpecular赋予你的物体。硬件蒙皮设置为每个顶点(Vertex)绑定三个骨骼(Bone),但你可以根据自己的需要进行更改。

材质中使用了Ogre例子中的阴影片段程序(Shadow Program),如果你的资源路径中已经包含了Ogre SDK中的media文件夹就不必考虑这个问题,否则找到它并添加到你的资源路径中。

材质文件(Material File)

  1. vertex_program AnimatedNormalSpecular_VP hlsl  
  2.  {  
  3.     source animatedNormalSpecular.hlsl  
  4.     entry_point main_vp  
  5.     target vs_2_0  
  6.     column_major_matrices false     //required for hlsl skinning   
  7.    
  8.     includes_skeletal_animation true  
  9.    
  10.     default_params  
  11.     {  
  12.        param_named_auto worldviewprojmatrix worldviewproj_matrix  
  13.        param_named_auto light_position light_position_object_space 0  
  14.        param_named_auto eye_position camera_position_object_space  
  15.    
  16.        param_named_auto worldMatrix3x4Array world_matrix_array_3x4  
  17.        param_named_auto viewProjectionMatrix viewproj_matrix  
  18.        param_named_auto invworldmatrix inverse_world_matrix  
  19.     }  
  20.  }  
vertex_program AnimatedNormalSpecular_VP hlsl
 {
    source animatedNormalSpecular.hlsl
    entry_point main_vp
    target vs_2_0
    column_major_matrices false		//required for hlsl skinning
 
    includes_skeletal_animation true
 
    default_params
    {
       param_named_auto worldviewprojmatrix worldviewproj_matrix
       param_named_auto light_position light_position_object_space 0
       param_named_auto eye_position camera_position_object_space
 
       param_named_auto worldMatrix3x4Array world_matrix_array_3x4
       param_named_auto viewProjectionMatrix viewproj_matrix
       param_named_auto invworldmatrix inverse_world_matrix
    }
 }

  1. fragment_program AnimatedNormalSpecular_FP hlsl  
  2.  {  
  3.     source animatedNormalSpecular.hlsl  
  4.     entry_point main_fp  
  5.     target ps_2_0  
  6.    
  7.     default_params  
  8.     {   
  9.         param_named_auto lightDiffuse light_diffuse_colour 0  
  10.         param_named_auto ambientLight ambient_light_colour  
  11.         param_named_auto specularLight light_specular_colour 0  
  12.         param_named specular_power float 64  
  13.         param_named bumpiness float 1  
  14.     }  
  15.  }  
fragment_program AnimatedNormalSpecular_FP hlsl
 {
 	source animatedNormalSpecular.hlsl
 	entry_point main_fp
 	target ps_2_0
 
 	default_params
 	{ 
 		param_named_auto lightDiffuse light_diffuse_colour 0
 		param_named_auto ambientLight ambient_light_colour
 		param_named_auto specularLight light_specular_colour 0
 		param_named specular_power float 64
 		param_named bumpiness float 1
 	}
 }
  1. material animatedNormalSpecular  
  2.  {  
  3.     technique  
  4.     {  
  5.         pass Single Pass  
  6.         {  
  7.             vertex_program_ref AnimatedNormalSpecular_VP  
  8.             {  
  9.             }  
  10.    
  11.             fragment_program_ref AnimatedNormalSpecular_FP  
  12.             {  
  13.             }  
  14.             shadow_caster_vertex_program_ref HardwareSkinningFourShadow     //this part is in the ogre samples somewhere   
  15.             {  
  16.             }  
  17.    
  18.             //diffuse map   
  19.             texture_unit  
  20.             {  
  21.                 texture_alias base_map  
  22.                 texture diffuse.tga  
  23.                 filtering linear linear linear  
  24.             }  
  25.    
  26.             //normal map   
  27.             texture_unit  
  28.             {  
  29.                 texture_alias bump_map  
  30.                 texture diffuse_normal.tga  
  31.                 filtering linear linear linear  
  32.             }  
  33.    
  34.                     // specular map   
  35.               texture_unit specular_map  
  36.               {  
  37.                 texture_alias specular_map  
  38.                 texture specular.png  
  39.               }  
  40.    
  41.         }  
  42.    
  43.     }  
  44.  }  
material animatedNormalSpecular
 {
 	technique
 	{
 		pass Single Pass
 		{
 			vertex_program_ref AnimatedNormalSpecular_VP
 			{
 			}
 
 			fragment_program_ref AnimatedNormalSpecular_FP
 			{
 			}
 			shadow_caster_vertex_program_ref HardwareSkinningFourShadow		//this part is in the ogre samples somewhere
 			{
 			}
 
 			//diffuse map
 			texture_unit
 			{
 				texture_alias base_map
 				texture diffuse.tga
 				filtering linear linear linear
 			}
 
 			//normal map
 			texture_unit
 			{
 				texture_alias bump_map
 				texture diffuse_normal.tga
 				filtering linear linear linear
 			}
 
 		            // specular map
 			  texture_unit specular_map
 			  {
 				texture_alias specular_map
 				texture specular.png
 			  }
 
 		}
 
 	}
 }
animatedNormalSpecular.hlsl
  1. void main_vp(      
  2.      float4 position : POSITION,  
  3.      float2 uv       : TEXCOORD0,   
  4.      float3 normal   : NORMAL,  
  5.      float3 tangent  : TANGENT0,  
  6.    
  7.      float4 blendIdx : BLENDINDICES,  
  8.      float4 blendWgt : BLENDWEIGHT,  
  9.    
  10.      out float4 oPosition    : POSITION,  
  11.      out float2 oUV          : TEXCOORD0,  
  12.      out float3 oLightVector : TEXCOORD1,  
  13.      out float3 oHalfAngle   : TEXCOORD2,  
  14.    
  15.      uniform float4x4 worldviewprojmatrix,  
  16.      uniform float4   light_position,  
  17.      uniform float4   eye_position,  
  18.      uniform float3x4 worldMatrix3x4Array[60],  
  19.      uniform float4x4 viewProjectionMatrix,  
  20.      uniform float4x4 invworldmatrix  
  21.   ) {  
  22.      // Calculate the pixel position using the perspective matrix.   
  23.      oUV = uv;     
  24.    
  25.      // transform by indexed matrix   
  26.      float4 blendPos = float4(0,0,0,0);  
  27.      int i;  
  28.      for (i = 0; i < 3; ++i)  
  29.      {  
  30.          blendPos += float4(mul(worldMatrix3x4Array[blendIdx[i]], position).xyz, 1.0) * blendWgt[i];  
  31.      }  
  32.      // view / projection   
  33.      oPosition = mul(viewProjectionMatrix, blendPos);  
  34.    
  35.    
  36.      // transform normal   
  37.      float3 newnormal = float3(0,0,0);  
  38.      for (i = 0; i < 3; ++i)  
  39.      {  
  40.          newnormal += mul((float3x3)worldMatrix3x4Array[blendIdx[i]], normal) *      blendWgt[i];  
  41.      }  
  42.      newnormal = mul((float3x3)invworldmatrix, newnormal);   
  43.      newnormal = normalize(newnormal);  
  44.    
  45.      // transform tangent   
  46.      float3 newtangent = float3(0,0,0);  
  47.      for (i = 0; i < 3; ++i)  
  48.      {  
  49.          newtangent += mul((float3x3)worldMatrix3x4Array[blendIdx[i]], tangent) *      blendWgt[i];  
  50.      }  
  51.      newtangent = mul((float3x3)invworldmatrix, newtangent);   
  52.      newtangent = normalize(newtangent);  
  53.    
  54.    
  55.    
  56.    
  57.      float3 binormal = cross(newtangent, newnormal);  
  58.      float3x3 rotation = float3x3(newtangent, binormal, newnormal);  
  59.    
  60.      // Calculate the light vector in object space,   
  61.      // and then transform it into texture space.   
  62.      float3 temp_lightDir0 = normalize(light_position.xyz -  (blendPos * light_position.w));  
  63.      temp_lightDir0 = normalize(mul(rotation, temp_lightDir0));  
  64.      oLightVector = temp_lightDir0;  
  65.    
  66.    
  67.      // Calculate the view vector in object space,   
  68.      // and then transform it into texture space.   
  69.      float3 eyeDir = normalize(eye_position - blendPos);  
  70.      eyeDir = normalize(mul(rotation, eyeDir.xyz));  
  71.    
  72.      // Calculate the half angle   
  73.      oHalfAngle = oLightVector + eyeDir;  
  74.    
  75.  }  
  76.    
  77.    
  78.    
  79.    
  80.    
  81.  float4 lightDiffuse ;  
  82.  float4 ambientLight;  
  83.  float4 specularLight;  
  84.  float specular_power;  
  85.  float bumpiness;  
  86.  sampler base_map;  
  87.  sampler bump_map;  
  88.  sampler specular_map;  
  89.    
  90.  struct PS_INPUT_STRUCT  
  91.  {  
  92.     float2 uv:     TEXCOORD0;  
  93.     float3 light_vector: TEXCOORD1;  
  94.     float3 half_angle:   TEXCOORD2;  
  95.  };  
  96.    
  97.  struct PS_OUTPUT_STRUCT  
  98.  {  
  99.     float4 color0:       COLOR0;  
  100.  };  
  101.    
  102.  PS_OUTPUT_STRUCT main_fp( PS_INPUT_STRUCT psInStruct )  
  103.  {  
  104.     PS_OUTPUT_STRUCT psOutStruct;   
  105.    
  106.    float3 base = tex2D( base_map, psInStruct.uv );  
  107.    float3 bump = tex2D( bump_map, psInStruct.uv );  
  108.    float specularLevel = tex2D(specular_map, psInStruct.uv).r;  
  109.    
  110.    //normalise   
  111.    float3 normalized_light_vector = normalize( psInStruct.light_vector );  
  112.    float3 normalized_half_angle = normalize( psInStruct.half_angle );  
  113.    
  114.    // "Smooth out" the bump based on the bumpiness parameter.   
  115.    // This is simply a linear interpolation between a "flat"   
  116.    // normal and a "bumped" normal.  Note that this "flat"   
  117.    // normal is based on the texture space coordinate basis.   
  118.    float3 smooth = { 0.5f, 0.5f, 1.0f };  
  119.    bump = lerp( smooth, bump, bumpiness );  
  120.    bump = normalize( ( bump * 2.0f ) - 1.0f );  
  121.    
  122.    // These dot products are used for the lighting model   
  123.    // equations.  The surface normal dotted with the light   
  124.    // vector is denoted by n_dot_l.  The normal vector   
  125.    // dotted with the half angle vector is denoted by n_dot_h.   
  126.    float4 n_dot_l = dot( bump, normalized_light_vector );  
  127.    float4 n_dot_h = dot( bump, normalized_half_angle );  
  128.    
  129.    // Calculate the resulting pixel color,   
  130.    // based on our lighting model.   
  131.    // Ambient + Diffuse + Specular   
  132.    psOutStruct.color0.rgb =  
  133.       ( base * ambientLight) +  
  134.       ( base * lightDiffuse * max( 0, n_dot_l ) ) +  
  135.       ( specularLight * specularLevel * pow( max( 0, n_dot_h ), specular_power ) );  
  136.    psOutStruct.color0.a = 1.0f; //** Set the alpha component manually   
  137.    
  138.    return psOutStruct;  
  139.  }  
void main_vp(    
     float4 position : POSITION,
     float2 uv       : TEXCOORD0, 
     float3 normal   : NORMAL,
     float3 tangent  : TANGENT0,
 
     float4 blendIdx : BLENDINDICES,
     float4 blendWgt : BLENDWEIGHT,
 
     out float4 oPosition    : POSITION,
     out float2 oUV          : TEXCOORD0,
     out float3 oLightVector : TEXCOORD1,
     out float3 oHalfAngle   : TEXCOORD2,
 
     uniform float4x4 worldviewprojmatrix,
     uniform float4   light_position,
     uniform float4   eye_position,
     uniform float3x4 worldMatrix3x4Array[60],
     uniform float4x4 viewProjectionMatrix,
     uniform float4x4 invworldmatrix
  ) {
     // Calculate the pixel position using the perspective matrix.
     oUV = uv;   
 
     // transform by indexed matrix
     float4 blendPos = float4(0,0,0,0);
     int i;
     for (i = 0; i < 3; ++i)
     {
         blendPos += float4(mul(worldMatrix3x4Array[blendIdx[i]], position).xyz, 1.0) * blendWgt[i];
     }
     // view / projection
     oPosition = mul(viewProjectionMatrix, blendPos);
 
 
     // transform normal
     float3 newnormal = float3(0,0,0);
     for (i = 0; i < 3; ++i)
     {
         newnormal += mul((float3x3)worldMatrix3x4Array[blendIdx[i]], normal) *      blendWgt[i];
     }
     newnormal = mul((float3x3)invworldmatrix, newnormal); 
     newnormal = normalize(newnormal);
 
     // transform tangent
     float3 newtangent = float3(0,0,0);
     for (i = 0; i < 3; ++i)
     {
         newtangent += mul((float3x3)worldMatrix3x4Array[blendIdx[i]], tangent) *      blendWgt[i];
     }
     newtangent = mul((float3x3)invworldmatrix, newtangent); 
     newtangent = normalize(newtangent);
 
 
 
 
     float3 binormal = cross(newtangent, newnormal);
     float3x3 rotation = float3x3(newtangent, binormal, newnormal);
 
     // Calculate the light vector in object space,
     // and then transform it into texture space.
     float3 temp_lightDir0 = normalize(light_position.xyz -  (blendPos * light_position.w));
     temp_lightDir0 = normalize(mul(rotation, temp_lightDir0));
     oLightVector = temp_lightDir0;
 
 
     // Calculate the view vector in object space,
     // and then transform it into texture space.
     float3 eyeDir = normalize(eye_position - blendPos);
     eyeDir = normalize(mul(rotation, eyeDir.xyz));
 
     // Calculate the half angle
     oHalfAngle = oLightVector + eyeDir;
 
 }
 
 
 
 
 
 float4 lightDiffuse ;
 float4 ambientLight;
 float4 specularLight;
 float specular_power;
 float bumpiness;
 sampler base_map;
 sampler bump_map;
 sampler specular_map;
 
 struct PS_INPUT_STRUCT
 {
    float2 uv:     TEXCOORD0;
    float3 light_vector: TEXCOORD1;
    float3 half_angle:   TEXCOORD2;
 };
 
 struct PS_OUTPUT_STRUCT
 {
    float4 color0:       COLOR0;
 };
 
 PS_OUTPUT_STRUCT main_fp( PS_INPUT_STRUCT psInStruct )
 {
    PS_OUTPUT_STRUCT psOutStruct; 
 
   float3 base = tex2D( base_map, psInStruct.uv );
   float3 bump = tex2D( bump_map, psInStruct.uv );
   float specularLevel = tex2D(specular_map, psInStruct.uv).r;
 
   //normalise
   float3 normalized_light_vector = normalize( psInStruct.light_vector );
   float3 normalized_half_angle = normalize( psInStruct.half_angle );
 
   // "Smooth out" the bump based on the bumpiness parameter.
   // This is simply a linear interpolation between a "flat"
   // normal and a "bumped" normal.  Note that this "flat"
   // normal is based on the texture space coordinate basis.
   float3 smooth = { 0.5f, 0.5f, 1.0f };
   bump = lerp( smooth, bump, bumpiness );
   bump = normalize( ( bump * 2.0f ) - 1.0f );
 
   // These dot products are used for the lighting model
   // equations.  The surface normal dotted with the light
   // vector is denoted by n_dot_l.  The normal vector
   // dotted with the half angle vector is denoted by n_dot_h.
   float4 n_dot_l = dot( bump, normalized_light_vector );
   float4 n_dot_h = dot( bump, normalized_half_angle );
 
   // Calculate the resulting pixel color,
   // based on our lighting model.
   // Ambient + Diffuse + Specular
   psOutStruct.color0.rgb =
      ( base * ambientLight) +
      ( base * lightDiffuse * max( 0, n_dot_l ) ) +
      ( specularLight * specularLevel * pow( max( 0, n_dot_h ), specular_power ) );
   psOutStruct.color0.a = 1.0f; //** Set the alpha component manually
 
   return psOutStruct;
 }





评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值