像素着色器(pixel shader)是在对每个像素进行光栅化处理期间运行在图形卡GPU上的一段程序(不同与顶点着色器,Direct3D不会以软件方式来模拟像素着色器),它实质上是取代了固定功能流水线中的多重纹理环节,而且赋予了我们直接操纵单个像素以及访问每个像素的纹理坐标的能力。使得可以获得多重纹理、景深、云彩模拟、火焰模拟等效果。
可以通过检查D3DCAPS9结构的成员PixelShaderVersion,并与宏D3DPS_VERSION进行比较,来测试图形卡是否支持某个像素着色器版本
cpp
if(cap.PixelShaderVersion < D3DPS_VERSION(2,0))
多重纹理
多重纹理涵含的思想与与融合有些关联,我们了解了如何将正在进行光栅化的像素与先前已写入后台缓存中的像素进行融合,以获得某种特殊效果,我们将这种思想沿用到多重纹理中,即我们同事启用若干层纹理,并定义这些纹理的融合方式,以获得某种特殊效果,一种典型应用就是进行光照运算。在顶点运算阶段我们不打算使用Direct3D的光照模型,而是使用一种特殊的纹理图--光照纹理图,它规定了某一表面是如何被照亮。例如我们希望在一个板条箱上投射一个聚光灯,可用D3DLIGHT9来定义该聚光灯,可以将代表板条箱的纹理图与代表聚光灯的纹理图进行融合。
在固定功能多重纹理环节,是通过纹理绘制状态对融合方程进行控制的,而借助像素像素着色器,可以在代码中以可编程方式将融合函数写为一个简单表达式,这样就可以以任何方式对多个纹理进行融合运算。多重纹理环节一般用于为静态物体实现一个完整的光照计算引擎。
多个纹理进行进行融合与Direct3D光照计算模型对比
1.光照已预先计算好,并保存在聚光灯光照纹理图中,这样程序运行时就不需要对光照进行计算了,节省运算时间,只有对于静止的物体和固定固定光源方可预先进行光照计算
2.由于光照纹理涂是预先计算号的,我们可采用比Direct3D更精确、更复杂的光照模型
启用多重纹理
纹理可用方法SetTexture来启用,采样器状态(sampler state)可用方法SetSamplerState来设置,一个特定采样器的级数索引i与第i层纹理是关联的,即第i个采样级为第i层纹理指定了采样器状态。之前总是将层索引定为0(表示第一层索引),这是因为我们那是只需要使用一层纹理就够了,如果需要3层纹理,可用序号0、1、2来分别表示每层纹理。
cpp
Device->SetTexture(0,Tex1);
Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
Device->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
Device->SetTexture(1,Tex2);
Device->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
Device->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
Device->SetSamplerState(1, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
Device->SetTexture(2,Tex3);
Device->SetSamplerState(2, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
Device->SetSamplerState(2, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
Device->SetSamplerState(2, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
多重纹理坐标
对于三角形而言,使用多重纹理时可为每个顶点额外增加若干纹理坐标对,每对纹理坐标对应于某一层被启用的纹理,例如将3层纹理进行融合,则每个顶点都必须有3对分别与这3层纹理对应的纹理坐标。