关于Shader的原理笔者始终不能在实际程序中产生联想,以至于每次做DEMO时,都会时不时把例程代码翻来看看流程。
先说下我对Shader的理解,结合DX的API来说,当你调用DrawPrimitives的时候,图形显示卡的固定渲染管线就开始工作
了,它要做些什么呢?先从顶点缓存里把数据提出来,然后确定你创造的模型的位置(世界),以及我们怎么才能看到他
(视图),并且让他从窗口中显示出来(投影),同时,在进行光照处理,之后其实还有像素级的处理,这样,一个3D的
对象就在窗口中出来了。而Shader呢,取代的就是上面三个括号中所作的事情,同时在顶点着色器中你还可以对顶点做一
些自定义的处理(比如如何计算顶点的颜色,是用D3D应用程序设置的颜色,还是通过光照&材质的计算等等)。就像书上
说的那样,Shader增加了程序员的自由度,我们可以做更多事了。
Shader Code :
// File name : shader_diffuse.txt
//
// Author : Dormy.ET.C
//
// Description :
//
//
// 需要在 D3D 应用程序中对以下常量初始化.
matrix viewMat;
matrix viewProjMat;
vector lightDir;
vector ambientMtrl;
vector diffuseMtrl;
// 已经被初始化的常量(环境光 & 散射光 强度).
vector ambientIntensity = {0.0f, 0.0f, 0.0f, 1.0f};
vector diffuseIntensity = {1.0f, 1.0f, 1.0f, 1.0f};
// Structure name : 顶点输入结构
// Description : 接收顶点包括 位置信息、法线信息.
struct VS_INPUT
{
vector position : POSITION;
vector normal : NORMAL;
};
// Structure name : 顶点输出结构
// Description : 输出顶点包括 经过视图投影变换的位置,
// 经过光照处理后的顶点颜色信息.
struct VS_OUTPUT
{
vector position : POSITION;
vector color : COLOR;
};
// Function name : main 顶点着色器主函数
// Description : main 中处理顶点信息,输入参数为输入顶点结构对象,
// 返回值为输入顶点结构对象.
VS_OUTPUT main(VS_INPUT input)
{
VS_OUTPUT output = (VS_OUTPUT)0;
output.position = mul(input.position, viewProjMat);
lightDir.w = 0.0f;
input.normal.w = 0.0f;
// Description : 光线入射角与法线的夹角大于90度时,即
// 光线入射方向与法线点乘结果小于0,则光
// 线强度为0.
float theta = dot(lightDir, input.normal);
if( theta < 0.0f )
theta = 0.0f;
output.color = (ambientMtrl * ambientIntensity) +
(diffuseMtrl * diffuseIntensity) * theta;
return output;
}