pixel shader
是在对每个像素进行光栅化处理期间
运行在显卡上的一段定制程序(其不会用软件运算方式来模拟)
PS实质上是取代了固定功能渲染管线中的多重纹理(multitexturing)环节
,而且赋予了我们直接操纵单个像素以及访问每个像素的纹理坐标的能力
。个人觉得PS取代了光栅化阶段中的某一个子部分
像素着色器版本检查
if(caps.PixelShaderVersion < D3DPS_VERSION(2, 0)){
}
- 1、对
多重纹理
的理解 - 2、PS的使用步骤
- 3、使用PS实现多重纹理
1、多重纹理概述
多重纹理可能是PS实现的最简单的技术
由于PS取代了固定功能渲染管线中的多重纹理环节,所以我们应该对多重纹理环节及其功能
有基本的理解
多重纹理包含的思想与融合有些关联
。我们同时启用若干层纹理,并定义这些纹理的融合方式
,以获得某种特殊效果
多重纹理的一种典型应用就是进行光照运算
光照效果的两种实现方式
:
- 1、在
顶点运算阶段
使用实时光照模型 - 2、使用
光照纹理图(light maps)
光照纹理图规定了某一表面是如何被照亮的
在固定功能的多重纹理环节,我们通过纹理绘制状态
对多重纹理的融合方式进行控制;而在PS中,我们可以在代码中以可编程方式来定义多重纹理的具体融合方式(更灵活)
通过多重纹理实现的光照运算
之于实时光照模型
的优点:
- 1、光照已预先计算好了,节省运算时间。只对
静止物体和固定光源
才可以预先进行光照计算 - 2、可以使用
更精确、更复杂的光照模型
多重纹理环节一般用于为静态物体实现一个完整的光照计算引擎
当给定场景和光源时,可以用专门的程序来生成光照纹理图
1.1、启用多重纹理
纹理用IDirect3DDevice9::SetTexture
来启用;采样状态(sampler state)可用IDirect3DDevice9::SetSamplerState
来设置
一个特定的采样器级数索引i
与第i层纹理
是关联的,即第i个采样级为第i层纹理指定了采样器状态
纹理层索引
标识了我们想要将纹理
设置成的纹理层
;采样级索引
标识了我们想要将采样器
设置成的采样级
。这样,我们就可以激活多个纹理,并通过不同的层索引来为这些纹理设置相应的采样状态
采样状态
和过滤模式
每一层纹理都有其对应的采样状态(包括其对应的多级渐进纹理采样状态
)
应用程序源代码
d3ddev->SetTexture(i, Texi);
d3ddev->SetSamplerState(i, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
d3ddev->SetSamplerState(i, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
d3ddev->SetSamplerState(i, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR); 多级纹理过滤器的设置
1.2、多重纹理坐标
在使用多重纹理时,对于定义3D三角形图元的三个顶点,我们需要在启用的每个纹理中定义相应的三角形。为此,我们可为每个顶点额外增加若干纹理坐标对——每对纹理坐标对对应于某一层被启用的纹理
该顶点结构少了顶点法线,因为多重纹理和光照可同时具有
struct MultiTexVertex{
MultiTexVertex(float x, float y, float z,
float u0, float v0,
float u1, float v1,
float u2, float v2)
{
_x = x; _y = y; _z = z;
_u0 = u0; _v0 = v0;
_u1 = u1; _v1 = v1;
_u2 = u2; _v2 = v2;
}
float _x, _y, _z;
float _u0, _v0; texture stage 0
float _u1, _v1; texture stage 1
float _u2, _v2; texture stage 2
static const DWORD FVF;
};
const DWORD MultiTexVertex::FVF = D3DFVF_XYZ | D3DFVF_TEX3;
固定功能渲染管线至多支持8层纹理
。如果要使用的纹理层数超过8,则必须使用顶点声明和VS
2、像素着色器的输入和输出
PS的输入包括每个像素的颜色和纹理坐标
每个像素的纹理坐标
其实是指定的纹理中将被映射到当前像素的纹理元的坐标
在进入PS之前,D3D先根据VS输出结构中的顶点颜色和顶点纹理坐标计算出每个像素的颜色和纹理坐标(已经是2D了),然后将计算所得每个像素的颜色和纹理坐标输入PS
输入PS的颜色
和纹理坐标对的个数
由VS输出的颜色
和纹理坐标对的个数
决定。数量关系不变,但是具体的值由D3D计算得出(应该是差值运算
)
我们需要借助语义语法来将输入的颜色和纹理坐标映射为PS程序中的变量。说的不太明白,需要通过例子说明
PS将输出计算所得的每个像素的单个颜色值
struct PS_OUTPUT
{
vector finalPixelColor : COLOR0;
};
VS和PS之间起到计算作用的是光栅化(rasterizatioin)
3、使用像素着色器的步骤
与使用VS的步骤相同,只是有些参数不同
4、HLSL采样器对象
要在PS中对纹理进行采样
,可使用专门与纹理相关的HLSL内置函数
采样
是指根据像素的纹理坐标
和采样状态
来检索某一像素所对应的纹理元
纹理坐标
来自于PS的输入;采样状态和想要检索的特定纹理
在PS中是用一个特别的HLSL对象——采样器(sampler)
来标识的
在PS的HLSL代码中定义sampler对象,然后在应用程序代码中通过常量表获取该对象,然后对该对象进行纹理和采样状态的设置
除了可以使用sampler类型
外,还可以使用更具体、类型检查更严格的相关类型