采样状态对象
1. 采用状态对象有什么用?
采样状态描述用于描述纹理贴图的采样方式。一个采样状态对象允许我们访问一个纹理的采样状态信息。后面我们看采样状态描述结构体就知道有哪些内容可以描述了。
2. 采样状态可以描述哪些内容?
我们来看采样状态描述结构体D3D11_SAMPLER_DESC有哪些成员:
- Filter,它指定被采样的纹理怎样过滤。纹理过滤描述从源数据怎样被读取和联合,使得用于着色器。过滤能够提升画质但是在纹理采样时会有更多的性能开销,因为一些过滤类型是由于读取和结合多个纹理元素值来产生一个在着色器中看到的单一的颜色值。下面会详细介绍。
- AddressU,纹理寻址模式。下面会详细介绍。
- AddressU,纹理寻址模式。下面会详细介绍。
- AddressW,纹理寻址模式。下面会详细介绍。
- MipLODBias,用于 MIP 的级别细节(level-of-detail,简称 LOD)偏移。该值是一个通过 Direct3D 使用的 MIP 级别机制的偏移量。例如,如果 Direct3D 指定使用第 2 级别的 MIP 并且偏移量为 3,则实际上 MIP 使用的是第 5 级别。
- MaxAnisotropy,最大各向异性值,用于各向异性过滤和比较函数。该值范围是 1-16 之间的整数,它不用于点和双线性过滤。
- ComparisonFunc, COMPARISON函数的返回值用于判定贴图过滤标识的比较。比较标识在D3D11_COMPARISON_FUNC 中指定,其比较状态的本质是比较两个值之间的等于,大于小于关系。
- BorderColor,如果贴图地址模式使用了D3D11_TEXTURE_ADDRESS_BORDER,这个成员就可以指定颜色值(RGBA值必须在0~1)。
- MinLOD,指定Mip最小级别。
- MinLOD,指定Mip最大级别。例如,如果最大值指定为 1,那么级别为 0 的 MIP纹理就不会被访问到(注意级别为 0 的 MIP 就是分辨率最高的纹理)。
3. Filter成员如何填充?
在 Direct3D 11 中可用的过滤类型如下:
typedef enum D3D11_FILTER {
D3D11_FILTER_MIN_MAG_MIP_POINT
D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR
D3D11_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT
D3D11_FILTER_MIN_POINT_MAG_MIP_LINEAR
D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT
D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR
D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT
D3D11_FILTER_MIN_MAG_MIP_LINEAR
D3D11_FILTER_ANISOTROPIC
D3D11_FILTER_COMPARISON_MIN_MAG_MIP_POINT
D3D11_FILTER_COMPARISON_MIN_MAG_POINT_MIP_LINEAR
D3D11_FILTER_COMPARISON_MIN_POINT_MAG_LINEAR_MIP_POINT
D3D11_FILTER_COMPARISON_MIN_POINT_MAG_MIP_LINEAR
D3D11_FILTER_COMPARISON_MIN_LINEAR_MAG_MIP_POINT
D3D11_FILTER_COMPARISON_MIN_LINEAR_MAG_POINT_MIP_LINEAR
D3D11_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT
D3D11_FILTER_COMPARISON_MIN_MAG_MIP_LINEAR
D3D11_FILTER_COMPARISON_ANISOTROPIC
D3D11_FILTER_TEXT_1BIT
} D3D11_FILTER;我们看到上面一堆东西先不要慌乱,其实上面这么多内容都是组合出来的,我们把它们拆开一个个小的组合子,就只有下面几种:
- POINT,点采样,也就是最邻近采样,是用于过滤的一种最快的采样方式。它直接从纹理中取得单一的值作为采样结果,而不进行修改。
- LINEAR,线性采样。
(1)用于Mip(下面会谈到)时,即为双线性采样, 在被采样点的纹理坐标处进行双线性内插值,除了包围采样的边框附件的那些采样点。这些内插值(已经双线性采样后的结果)将是在着色器中可见。选择此采样方式是通过过滤(双线性组合)在像素中心周围的最接近的四个纹理元素完成。这种组合多个附近的纹理元素的方式能够使得结果更加的平滑,该采样方式能够有效减少在渲染中的锯齿效果。
(2)用于MIN和MAG时,即为三线性采样,通过在最接近的 MIP 分级纹理中分别进行双线性采样,然后再内插值完成。 当一个网格表面从使用一个 MIP 等级到另一个等级时,该物体表表面将会出现一些明显的变化。而在最邻近的 MIP 等级之间使用插值,在两个等级之间使用双线性过滤后,能够很大的减少渲染的人工痕迹(译者注:就是使用三线性采样在物体远离或靠近时,表面纹理能够平滑过渡)。- ANISOTROPIC,各向异性。各向异性过滤,使用三线性采样在不等边四边形上来代替正方形区域。双线性和三线性过滤(采样)能够在当视线方向垂直于表面时工作得很好,因为是符合正方形采样,但是斜视物体表面时(视线与物体表面夹角为一个锐角),例如在观察 3D 游戏中的天花板或地面时,将会出现明显的模糊和渲染痕迹。各向异性过滤在用于不同形状的区域的贴图采样时会将角度考虑进去。
4. Mip、MIN、MAG是什么意思?
- Mip:当物体越来越远离观察者,在屏幕上被着色的像素随着观察者的远离也越来越少。这意味着,为了表现高品质的画质,我们需要在近处的物体使用高分辨率的图像,但是当对象越来越远离观察者时,高分辨率的图像不必传递给渲染管线,代替的是使用较低分辨率的图像。这一点很是重要,因为我们只需要很少的数据进行移动,其渲染性能能够很好的得到提升。如果有许多物体远离照相机,使用合适的分辨率贴图与使用最高级的分辨率贴图在外观上是没有太大的差别的,而且这是提升性能的一个关键部分。这个出来过程就是著名的 Mip 映射,使用 D3DX11CreateTextureFromFile 将默认会创建全部的 MIP 分级链。使用 Mip 分级机制的另一个好处是能够有效的减少混淆走样。
- MIN:Minification(缩小系数)发生在已经贴图的物体表面远离观察者时,当表面越来越远离时,越来越多的纹理元素结合为屏幕上的单个颜色,这是因为来自远离物体的多个纹理元素渲染时使用屏幕
- MAG:Magnification(放大系数)现象发生在当已经贴图的物体表面越来越靠近照相机时,因为屏幕上的多个像素被渲染为物体表面的同一个纹理元素上的同一个像素的原因。
5. 纹理寻址模式是什么?
纹理坐标值被指定范围 0.0-1.0 在纹理的各个尺寸。纹理寻址模式告诉 Direct3D 怎样处理超出该范围的坐标值。纹理寻址模式可以使用如下值:
- D3D11_TEXTURE_ADDRESS_WRAP,重复(WRAP)纹理地址将导致贴图重复用于周围。例如,如果你有一个方形区域,你想一张贴图在区域的水平方向重复显示两次,只需要指定最右边的顶点的 U 贴图坐标分量为 2.0 即可。这能够使贴图像瓦片一样覆盖一个单一的表面,它的好处就是只需要使用很少量的数据就可以达到整个覆盖的效果。(如下图)
- D3D11_TEXTURE_ADDRESS_CLAMP,UV范围超出[0,1]将取UV为0或1(即边界)的颜色。
- D3D11_TEXTURE_ADDRESS_MIRROR,镜像(MIRROR)纹理地址将导致贴图以镜像形式重复(见下图)。
- D3D11_TEXTURE_ADDRESS_MIRROR_ONCE将会使得贴图的镜像形式出现一次,对负的u,v坐标取绝对值,所以左,上是镜像的效果。对超过[0,1]范围的正的坐标,使用clamp方式。
- D3D11_TEXTURE_ADDRESS_BORDER寻址模式将会设置任何在 0.0-1.0 范围之外的像素一个指定的边界颜色。边界颜色通过 D3D11_SAMPLER_DESC 的另一个叫做 BorderColor 的成员来指定,它是一个有四个浮点值得数组。
6. 如何根据采样状态描述创建采样对象?
为了创建一个采样状态对象,我们使用 Direct3D 设备的 CreateSamplerState 函数,它使用采样描述作为参数并且输出所创建的采样状态对象的地址。
7. 创建采样状态对象示例代码
//创建采样状态对象
D3D11_SAMPLER_DESC colorMapDesc;
ZeroMemory( &colorMapDesc, sizeof( colorMapDesc ) );
colorMapDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
colorMapDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
colorMapDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
colorMapDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
colorMapDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
colorMapDesc.MaxLOD = D3D11_FLOAT32_MAX;
d3dResult = d3dDevice_->CreateSamplerState( &colorMapDesc, &colorMapSampler_ );
if( FAILED( d3dResult ) )
{
DXTRACE_MSG( "Failed to create color map sampler state!" );
return false;
}