TGEA中材质的使用(三)

3.CustomMaterial对象


前面已经介绍过,CustomMaterial是用于使用程序员自己开发的shader,首先看一下如何指定要使用的shader。

仍旧以box为例:
new CustomMaterial(Two)

{

   mapTo = six;

   version = 2.0;

   shader = Waves;

   texture[0] = "two";

   texture[2] = "~/data/interiors/test/metalcrate_bump";

   specular[0] = "1.0 1.0 1.0 1.0";

   specularPower[0] = 16;

   fallback = TwoFallback;

};

其中shader = Waves;就指定了使用Waves这个ShaderData渲染这个面。

再打开example\demo\client\scripts下的shaders.cs文件,其中有如下代码:

new ShaderData(Waves)

{

   DXVertexShaderFile   = "shaders/wavesV.hlsl";

   DXPixelShaderFile    = "shaders/wavesP.hlsl";

   pixVersion = 2.0;

};

这里有一个新的对象ShaderData,是TGEA新引入的,用于指定材质使用的顶点着色器和像素着色器。具体的vertex shader和pix shader的代码位于目录example\shaders中。

3.1. 修改相应的shader

使用CustomMaterial较Material复杂,需根据TGEA的要求对相应的shader做一些修改。

以TGEA1.0.3中的DEMO为例。

example\demo\data\shapes\test\materials.cs中,有如下的材质定义,这是box的一个面的材质:

new CustomMaterial(SixBump)

{

    mapTo = two;

    texture[0] = "~/data/interiors/test/metalcrate_bump";

    texture[1] = "six";

    texture[3] = "$cubemap";

    cubemap = Garage;

    shader = BumpCubeDiff;

    specular = "1.0 1.0 1.0 0.0";

    specularPower = 20.0;

    version = 2.0;

    fallback = SixBumpFallback;

};

相应的ShaderDate定义位于example\demo\client\scripts\shaders.cs中:

new ShaderData( BumpCubeDiff )

{

    DXVertexShaderFile   = "shaders/bumpCubeDiffuseV.hlsl";

    DXPixelShaderFile    = "shaders/bumpCubeDiffuseP.hlsl";

    pixVersion = 2.0;

};

这两个HLSL文件位于example\shaders\中,首先来看bumpCubeDiffuseV.hlsl

3.1.1.  bumpCubeDiffuseV.hlsl (vertex shader)

相应的代码如下:

#define IN_HLSL
#include "shdrConsts.h"

struct Appdata
{
    float4 position   : POSITION;
    float4 normal     : NORMAL;
    float4 baseTex    : TEXCOORD0;
    float4 lmTex      : TEXCOORD1;
    float3 T          : TEXCOORD2;
    float3 B          : TEXCOORD3;
    float3 N          : TEXCOORD4;
};

struct Conn

{
   float4 HPOS             : POSITION;
   float4 TEX0             : TEXCOORD0;
   float4 tangentToCube0   : TEXCOORD1;
   float4 tangentToCube1   : TEXCOORD2;
   float4 tangentToCube2   : TEXCOORD3;
   float4 outLightVec      : TEXCOORD4;
   float3 pos              : TEXCOORD5;
   float3 outEyePos        : TEXCOORD6;
};

Conn main( Appdata In, 
           uniform float4x4 modelview : register(VC_WORLD_PROJ),
           uniform float3x3 cubeTrans : register(VC_CUBE_TRANS),
           uniform float4   cubeEyePos : register(VC_CUBE_EYE_POS),
           uniform float3   inLightVec : register(VC_LIGHT_DIR1),
           uniform float3   eyePos     : register(VC_EYE_POS)
){
   Conn Out;
   。。。。。。   
  
return Out;
}

开头是vertex shader的输入输出结构的定义。

输入结构(Appdata)即vertex declaration,注意,TGEA中的顶点声明是有规则的。如那纹理坐标寄存器,TEXCOORD2~4指定的即是纹理空间的三个基向量T,B,N,用于bump mapping(bump mapping可以参考《The Cg Tutorial》,《OpenGL Shading Language》等书籍)。具体的顶点声明可以参考引擎源码中的GFXVertexPNTTBN结构的定义,位于engine\gfx\gfxStructs.h,另在engin\ts\tsMesh.h中,GFXVertexPNTTBN也被typedefMeshVertex(网格的顶点格式)。

输出结构(Conn)则无特殊的限制。

接下来的是VS的main函数,与普通的并无多大的差别,但是要注意main函数的参数。

Vertex Shader必须要与应用程序(引擎)交互,传递相应的数据,如变换矩阵,光源位置,摄像机位置等,DX使用常量表来往VS中传递数据。TGEA在此基础上封装好了大部分的操作,见main函数的参数:

uniform float4x4 modelview  : register(VC_WORLD_PROJ)

uniform float3x3 cubeTrans  : register(VC_CUBE_TRANS)

uniform float4   cubeEyePos : register(VC_CUBE_EYE_POS)

uniform float3   inLightVec : register(VC_LIGHT_DIR1)

uniform float3   eyePos     : register(VC_EYE_POS)

类型符后的modelview指定了变量名,在“:”号后指定了它使用的顶点寄存器, VC_WORLD_PROJ是一个宏,参example\shaders\shdrConsts.h: 

#define VC_WORLD_PROJ      C0

这里指定C0用于存储世界投影变换矩阵,不管是对于应用程序(引擎)还是你自己开发的shader而言,所以如果你要使用引擎中当前的世界投影变换矩阵,只需声明变量时指定相应的寄存器号(: register(VC_WORLD_PROJ))。shdrConsts.h中还有大量的寄存器宏定义,可以参考。

3.1.2. bumpCubeDiffuseP.hlsl (pixel shader)

PS与VS大部分相似。不同的是PS需要使用纹理,因此需要将相应纹理信息传递至PS中。

首先看一下CustomMaterial(SixBump)的定义,有如下语句:

   texture[0] = "~/data/interiors/test/metalcrate_bump";

   texture[1] = "six";

   texture[3] = "$cubemap";

可以看出它使用了三张纹理。

再在bumpCubeDiffuseP.hlsl的main函数的参数中有如下语句:

uniform sampler2D    bumpMap  : register(S0)

uniform sampler2D    diffMap  : register(S1)

uniform samplerCUBE  cubeMap  : register(S3)

可见它指定的三个纹理寄存器,寄存器号正好与texture的下标一致。TGEA就是用这种方式来传递纹理信息的。注意此处它没有使用2号寄存器,并不意味着2号寄存器不可用。可以随意使用,只是不要超过shader model指定的最大纹理寄存器数。


3.2. CustomMaterial的其他注意事项

(1 mapTo

在Material中,如果不指定mapto属性,则将材质自动mapTo至baseTex的那张纹理,但是CustomMaterial一定要指定mapTo属性。

(2) 在CustomMaterial可以使用来自SceneGraph的一些纹理,如:

$lightmap          内景的光照贴图

$fog scenegraph  生成的表示雾的纹理

$cubemap           立方体贴图

$backbuff          后缓冲区(用于制作折射效果)

例如:

CustomMaterial(SixBump)

“texture[3] = "$cubemap";”这条语句就指定了将在PS中使用SceneGraph生成的立方体贴图。

posted on 2009-02-01 22:28  chsaov  阅读(479)  评论(0编辑  收藏  举报

导航