百度空间 | 百度首页 
 
查看文章
 
XNA Shader 程序设计(二)
2009-05-25 16:39
XNA Shader 程序设计
教程2 - 漫反射



大家好,今天我们将在教程一的基础上继续学习,在光照算式中加上漫反射光。

漫反射光

环境光计算等式为:
I = Aintensity * Acolor

漫反射基于这个等式,添加了一道有方向的光线:
I = Aintensity x Acolor + Dintensity x Dcolor x N.L (2.1)

通过计算式,你可以看到我们仍然使用了环境光,但添加了两个变量,分别表示漫反射光的光强和颜色,还添加了两个向量N和L,L表示光照方向,N表示表面法线。

我们可以认为漫反射表现了一个表面如何反射光线。法线方向N和光线方向L的夹角越小,表面反射的光就越强。




当L和N平行,反射光最强,当L与物体表面平行,反射光最弱。

我们可以通过计算向量的点积(或叫数量积)来得到L与N的夹角。这条计算向量夹角的法则定义如下:N.L = |N| x |L| x cos(a)。|N|是向量N的长度,|L|是向量L的长度,cos(a)表示两向量的夹角。

实现shader
我们需要三个全局变量

float4x4     matWorldViewProj;
float4x4     matInverseWorld;
float4       vLightDirection;

我们仍然需要教程一中介绍的worldviewprojection矩阵,同时需要添加InverseWorld矩阵来变换法线,添加vLightDirection表示光线方向。

我们仍需为顶点着色器定义OUT结构体,从而把数据传给像素着色器:
struct OUT
{
     float4 Pos: POSITION;
     float3 L:     TEXCOORD0;
     float3 N:     TEXCOORD1;
};

我们把位置Pos,光线方向L,法线N存在不同的寄存器中。TEXCOORDn可以用来表示任意值,在我们没有使用贴图的情况下,我们用它来存储向量。

OK,下面是顶点着色器:
OUT VertexShader( float4 Pos: POSITION, float3 N: NORMAL )
{
     OUT Out = (OUT) 0;
     Out.Pos = mul(Pos, matWorldViewProj);
     Out.L = normalize(vLightDirection);
     Out.N = normalize(mul(matInverseWorld, N));
     return Out;
}

我们从模型文件中获得顶点和法线的数据然后传递给shader,然后变换位置坐标,归一化光线方向,变换并归一化物体表面的法线。

然后,在像素着色器中,把TEXCOORD0的值给L,TEXCOORD1的值给N,寄存器的值来自顶点着色器。下面在像素着色器中实现算式2.1:

float4 PixelShader(float3 L: TEXCOORD0, float3 N: TEXCOORD1) : COLOR
{  
     float Ai = 0.8f;
     float4 Ac = float4(0.075, 0.075, 0.2, 1.0);
     float Di = 1.0f;
     float4 Dc = float4(1.0, 1.0, 1.0, 1.0);
     return Ai * Ac + Di * Dc * saturate(dot(L, N));
}


下面是这个shader的technique
technique DiffuseLight
{
     pass P0
     {
         VertexShader = compile vs_1_1 VertexShader();
         PixelShader = compile ps_1_1 PixelShader();
     }
}

类别:三维方面知识 | 添加到搜藏 | 浏览() | 评论 (0)
 
最近读者:
 
网友评论:
发表评论:
姓 名:
网址或邮箱: (选填)
内 容:
验证码: 请点击后输入四位验证码,字母不区分大小写
      

     

©2009 Baidu