功能级别 9 硬件上的用户剪辑平面
从 Windows 8 开始,Microsoft高级着色器语言(HLSL)支持可用于 Microsoft Direct3D 11 API 的语法,以指定 功能级别 9_x 及更高级别的用户剪辑平面。 可以使用此剪辑平面语法编写着色器,然后将该着色器对象与 Direct3D 11 API 一起使用,以在所有 Direct3D 功能级别上运行。
背景
可以通过 IDirect3DDevice9::SetClipPlane 和 IDirect3DDevice9::GetClipPlane 方法访问 Microsoft Direct3D 9 API 中的用户剪辑平面。 在 Microsoft Direct3D 10 及更高版本中,可以通过 SV_ClipDistance 语义访问用户剪辑平面。 但在 Windows 8 之前,SV_ClipDistance不适用于 Direct3D 10 或 Direct3D 11 API 中的 功能级别 9_x 硬件。 因此,在 Windows 8 之前,访问具有功能级别9_x硬件的用户剪辑平面的唯一方法是通过 Direct3D 9 API。 Direct3D Windows 应用商店应用无法使用 Direct3D 9 API。 下面介绍可用于通过 Direct3D 11 API 访问功能级别9_x及更高版本的用户剪辑平面的语法。
应用使用剪辑平面在 3D 世界中定义一组不可见平面,这些平面会剪辑(丢弃)所有绘制基元。 Windows 不会绘制任何剪辑平面的负端的任何像素。 然后,应用可以使用剪裁平面呈现平面反射。
语法
使用此语法将剪辑平面声明为 函数声明中的函数属性。 例如,此处我们在顶点着色器片段上使用语法:
cbuffer ClipPlaneConstantBuffer
{
float4 clipPlane1;
float4 clipPlane2;
};
[clipplanes(clipPlane1,clipPlane2)]
VertexShaderOutput main(VertexShaderInput input)
{
// the rest of the vertex shader doesn't refer to the clip plane
…
return output;
}
顶点着色器片段的此示例表示两个剪辑平面。 它显示,需要在顶点着色器的返回值前立即将新的 剪裁平面 属性放在方括号内。 在 剪辑平面 属性之后的括号内,提供最多 6 float4 常量的列表,这些常量定义每个活动剪辑平面的平面系数。 该示例还显示,需要使每个平面的系数驻留在常量缓冲区中。
注意
没有可用于动态禁用剪辑平面的语法。 必须重新编译不带 剪裁平面 属性的相同着色器,或者应用可以将常量缓冲区中的系数设置为零,以便平面不再影响任何几何图形。
此语法适用于任何 4.0 或更高版本的顶点着色器目标,其中包括vs_4_0_level_9_1和vs_4_0_level_9_3。
在功能级别 9 及更高级别的剪辑空间中创建剪辑平面
下面介绍如何在 功能级别 9_x 及更高级别的剪辑空间中创建剪辑平面。
背景阅读
Frank D. Luna 的“DirectX 10 游戏编程简介”介绍了所需的图形数学背景(第 1 章、第 2 章和第 3 章),以及顶点着色器(第 5.6 和 5.8 节)中发生的各种空间和空间转换。
10Level9 功能级别
在 Direct3D 10 及更高版本中,可以在任何有意义的空间中剪辑,通常在世界空间或查看空间中。 但 Direct3D 9 使用剪辑空间,这是预先透视划分投影空间。 当顶点着色器将矢量传递到 图形管道中的阶段时,矢量处于剪辑空间中。
编写 Windows 应用商店应用时,必须使用 10Level9 功能级别(功能级别 9_x),以便应用可以在功能级别9_x和更高硬件上运行。 由于应用支持功能级别9_x及更高,因此还必须使用在剪辑空间中应用剪辑平面的常见功能。
使用 vs_4_0_level_9_1 或更高版本编译顶点着色器时,该顶点着色器可以使用 剪辑平面 属性。 Direct3D 10 或更高版本的对象具有所发出的顶点积,其中包含属性中指定的每个 float4 全局常量。 Direct3D 9 对象有足够的元数据,导致 10Level9 运行时发出对 IDirect3DDevice9::SetClipPlane的相应调用。
剪裁平面数学
剪辑平面由具有 4 个组件的向量定义。 前三个组件定义一个 x、y、 z 向量,该矢量从我们想要剪辑的空间中的原点产生。 此向量表示一个平面,垂直于向量,并通过原点运行。 Windows 将所有像素保留在平面的向量端,并剪裁平面后面的所有像素。 第四个 w 组件将平面推回,并导致 Windows 沿向量线剪辑较少(负 w 导致 Windows 剪裁更多)。 如果 x、y、z 组件构成单元(规范化)矢量,则 w 将平面推回单位。
图形处理单元(GPU)执行的用于确定剪辑的数学是顶点向量(x、y、z、1)和剪裁平面向量之间的简单点积。 此数学运算在剪辑平面向量上创建投影长度。 负点积显示要位于平面的剪裁端的顶点。
在视图空间中剪辑
下面是视图空间中的顶点:
视图空间中的
下面是视图空间中的剪辑平面:
在视图空间剪辑平面
下面是视图空间中顶点平面和剪辑平面的点积:
ClipDistance = v •C = vₓCₓ +vyCy + vzcz + Cw
此数学运算适用于 Direct3D 10 或更高版本的对象,但不适用于 Direct3D 9 对象。 对于 Direct3D 9,必须首先通过投影转换进入剪辑空间。
投影矩阵
投影矩阵将视图空间中的顶点(原点为查看器的眼睛,+x 位于右侧,+y 向上,+z 直接向前)转换为剪辑空间。 投影矩阵读取硬件剪辑的顶点和 光栅化阶段。 下面是标准透视矩阵(其他投影需要不同的数学):
- *r* 窗口宽度/高度 *α* 视角 *f* 从查看器到远平面 *n* 距离,从查看器到近平面
下一个矩阵是上一个矩阵的简化版本。 我们演示了简化的矩阵,以便稍后在矩阵乘法运算中使用它。
现在,我们将视图空间顶点转换为带矩阵相乘的剪辑空间:
在矩阵乘法运算中,x 和 y 分量仅略有调整,但 z 和 w 分量相当混乱。 我们的剪辑平面不会给我们更多的希望。
剪辑空间剪辑平面
在这里,我们希望创建一个剪辑空间剪辑平面,其点产品与剪辑空间顶点给了我们与 v 相同的值。视图空间 部分中 剪辑中的 C。
v ·C = v P ·CP
vₓCₓ +vyCy + vzCz + cw = vₓPₓCPₓ +vyPyCPy + vzAyCPz + BCPz + vzCPw
现在,可以通过顶点分量将前面的数学运算分解为四个单独的公式:
剪辑平面产品的
剪辑平面产品的
剪辑平面产品的
剪辑平面产品的
我们的视图空间剪辑平面和投影矩阵派生并给我们剪辑空间剪辑平面。
相关主题