【译】XNA Shader 程序设计(二)
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();?
??? }?
}
?
?
OK,這就是漫反射!下載代碼調試一下吧。
?
Download:?Executable + Source
?
轉載于:https://www.cnblogs.com/cocoaleaves/archive/2009/04/23/1442515.html
總結
以上是生活随笔為你收集整理的【译】XNA Shader 程序设计(二)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SetProcessWorkingSet
- 下一篇: 2000错误信息:MMC创建无法管理单元