视区和剪裁 (Direct3D 9)

从概念上讲,视区是投影 3D 场景的二维 (2D) 矩形。 在 Direct3D 中,矩形在系统作为渲染目标使用的 Direct3D 表面内作为坐标存在。 投影转换将顶点转换为用于视区的坐标系统。 视区还用于指定渲染目标表面(场景将渲染到其中)的深度值范围(通常为 0.0 至 1.0)。

视锥

视锥是场景中相对于视区的相机放置的 3D 体。 体的形状影响模型从相机空间投影到屏幕上的方式。 最常见投影类型是透视投影,它负责让靠近相机的对象显得比远处的对象大。 对于透视视见,可以用金字塔直观地显示视锥,其中相机位于下图中显示的尖部。 此金字塔与前后剪裁平面相交。 金字塔中的前后剪裁平面之间的体就是视锥。 对象仅在位于此体中时才可见。

带前后剪裁平面的视锥的图示

假设你站在昏暗的房间内通过一个正方形窗户向外看,你就直观地显示了视锥。 在这个类比中,近的剪裁平面是窗户,后剪裁平面是最终挡住你的视线的任何物体 - 跨过街道的摩天跨街景、远处的山峰或什么都没有。 你可以看到从窗户开始并以挡住你的视线的任何物体结尾的被截断的金字塔内的一切,并且看不到任何其他东西。z

视锥由 fov(视场)和前后剪裁平面之间的距离(以 z 坐标指定)定义,如下图所示。

视锥的图示

在此图中,变量 D 是从相机到在几何图形管道的最后部分中定义的空间的原点的距离 - 视见变换。 这是你安排视锥的限制围绕的空间。 有关如何使用此 D 变量生成投影矩阵的信息,请参阅 投影转换 (Direct3D 9)

视区矩形

使用 D3DVIEWPORT9 结构在 C++ 中定义视区矩形。 D3DVIEWPORT9 结构与 IDirect3DDevice9 接口公开的以下视区操作方法一起使用。

D3DVIEWPORT9 结构包含四个成员(X、Y、Width、Height),用于定义呈现场景的目标图面的区域。 这些值对应于目标矩形(即视区矩形),如下图所示。

视区矩形的图示

为 X 成员、Y 成员、Width 成员和 Height 成员指定的值是相对于呈现目标图面的左上角的屏幕坐标。 该结构定义了两个其他成员(MinZ 和 MaxZ),指示将场景呈现到的深度范围。

Direct3D 假定视区剪裁体范围在 X 方向为 -1.0 - 1.0,在 Y 方向为 1.0 - -1.0。这些是应用程序在过去最常使用的设置。 你可以在剪裁之前使用投影转换调整视区纵横比。

注意

MinZ 和 MaxZ 指示将呈现场景的深度范围,并且不用于剪辑。 大多数应用程序会将这些成员设置为 0.0 和 1.0,使系统能够呈现到深度缓冲区中的整个深度值范围。 在某些情况下,你可以通过使用其他深度范围来实现特殊效果。 例如,要在游戏中呈现抬头显示,你可以将这两个值都设置为 0.0 以强制系统在前台呈现场景中的对象,或者也可以将它们都设置为 1.0 以呈现应始终位于后台的对象。

 

视区 D3DVIEWPORT9 结构的 X、Y、Width、Height 成员中使用的尺寸定义呈现目标图面上视区的位置和尺寸。 这些值位于屏幕坐标中,相对于图面的左上角。

Direct3D 使用视区位置和尺寸来缩放顶点,以便将呈现的场景放在目标图面上的合适位置。 在内部,Direct3D 将这些值插入应用于每个顶点的以下矩阵。

应用于每个顶点的矩阵的方程

此矩阵根据视区尺寸和所需的深度范围缩放顶点,并将它们转换到平移目标图面上的合适位置。 此矩阵还将翻转 y 坐标以在左上角反射屏幕原点,同时让 y 向下增大。 应用此矩阵后,顶点仍然是同类的(即,它们仍作为 [x,y,z,w] 顶点存在),并且它们在发送到光栅器之前必须平移到非同类坐标。

注意

视区缩放矩阵将 D3DVIEWPORT9 结构的 MinZ 和 MaxZ 成员合并为缩放顶点以适应深度范围 [MinZ, MaxZ]。 这表示与以前版本的 DirectX 不同的语义,在这些版本中,这些成员用于剪辑。

 

注意

应用程序通常分别将 MinZ 和 MaxZ 设置为 0.0 和 1.0,使系统呈现到整个深度范围。 但是,你可以使用其他值实现某些效果。 例如,你可以将这两个值都设置为 0.0 以强制所有对象位于前台,或将这两个值设置为 1.0 以将所有对象呈现到后台。

 

清除视区

清除视区将重置呈现目标图面上的视区矩形的内容。 它还可以清除深度和模具缓冲区图面中的矩形。

使用 IDirect3DDevice9::Clear 清除视区。 方法接受一个或多个矩形,这些矩形定义要清除的图面上的区域。 将 Count 参数设置为 1,将 pRects 参数设置为覆盖整个视区区域的单个矩形的地址将清除整个视区。 清除整个视区的另一种方法是将 pRects 参数设置为 NULL ,将 Count 参数设置为 0。

IDirect3DDevice9::Clear 可用于清除深度缓冲区中的模具位。 只需设置 Flags 参数即可确定 IDirect3DDevice9::Clear 如何处理呈现器目标和任何关联的深度或模具缓冲区。 D3DCLEAR_TARGET标志将使用 Color 参数中提供的任意 RGBA 颜色清除视区, (这不是材料颜色) 。 D3DCLEAR_ZBUFFER标志会将深度缓冲区清除为在 Z 中指定的任意深度:0.0 是最近距离,1.0 是最远的距离。 D3DCLEAR_STENCIL标志会将模具位重置为在模具参数中提供的值。 可以使用范围为 0 到 2n-1 的整数,其中 n 是模具缓冲区位深度。

在某些情况下,可能只呈现到呈现目标和深度缓冲区图面的一小部分。 使用 clear 方法还可以在单个调用中清除图面的多个区域。 为此,请将 Count 参数设置为要清除的矩形数,并在 pRects 参数的矩形数组中指定第一个矩形的地址。

设置要剪裁的视区

投影矩阵的结果将确定投影空间中的剪裁体,如下所示:

-wc<= xc<= wc

-wc<= yc<= wc

0 <= zc<= wc

其中:x、y、z 和 w 表示应用投影转换后顶点坐标。 如果启用了剪裁,那么位于这些范围之外的具有 x、y 或 z 分量的所有顶点都会被剪裁掉。

除顶点缓冲区外,应用程序通过 D3DRS_CLIPPING 呈现状态启用或禁用剪辑。 顶点缓冲区的剪裁信息是在处理过程中生成的。 有关详细信息,请参阅 固定函数顶点处理 (Direct3D 9) 可编程顶点处理 (Direct3D 9)

Direct3D 不会从顶点缓冲区剪辑基元的转换顶点,除非它来自 IDirect3DDevice9::P rocessVertices。 如果要执行自己的转换,并且需要 Direct3D 来执行剪辑,则不应使用顶点缓冲区。 在这种情况下,应用程序会遍历数据以对其进行转换。 Direct3D 会第二次遍历数据以对其进行剪辑,然后驱动程序会呈现数据,这效率低下。 因此,如果应用程序转换数据,还应剪切数据。

当设备收到需要剪裁的 T&L 顶点 (预转换和发光顶点) 时,为了执行剪裁操作,将使用顶点的倒数同质 w (RHW) 和视区信息将顶点反转换到剪裁空间。 然后执行剪裁。 并非所有设备都能够执行此反向转换,以便剪裁 T&L 顶点。

D3DPMISCCAPS_CLIPTLVERTS设备功能指示设备是否能够剪裁 T&L 顶点。 如果未设置此功能,则应用程序负责剪裁要发送到要呈现的设备的 T&L 顶点。 无论设备是在软件顶点处理模式下创建的,还是) 切换到软件顶点处理模式,设备始终能够在软件顶点处理模式下剪切 T&L 顶点 (。

为呈现设备配置视区参数的唯一要求是设置视区剪辑量。 为此,需要初始化并设置剪裁卷和呈现目标图面的剪裁值。 通常将视区设置为呈现到呈现目标图面的整个区域,但这不是要求。

对于 D3DVIEWPORT9 结构的成员,可以使用以下设置在 C++ 中实现此目的。

D3DVIEWPORT9 viewData = { 0, 0, width, height, 0.0f, 1.0f };

D3DVIEWPORT9 结构中设置值后,通过调用设备的 IDirect3DDevice9::SetViewport 方法将视区参数应用于设备。 下面的代码示例演示此调用可能的外观。

HRESULT hr;

hr = pd3dDevice->SetViewport(&viewData);
if(FAILED(hr))
    return hr;

如果调用成功,则设置视区参数,并在下次调用呈现方法时生效。 若要更改视区参数,只需更新 D3DVIEWPORT9 结构中的值,然后再次调用 IDirect3DDevice9::SetViewport

注意

D3DVIEWPORT9 结构成员 MinZ 和 MaxZ 指示渲染场景的深度范围,并且不用于剪辑。 大多数应用程序将这些成员设置为 0.0 和 1.0,以使系统能够在深度缓冲区中呈现到整个深度值范围。 在某些情况下,你可以通过使用其他深度范围来实现特殊效果。 例如,要在游戏中呈现抬头显示,你可以将这两个值都设置为 0.0 以强制系统在前台呈现场景中的对象,或者也可以将它们都设置为 1.0 以呈现应始终位于后台的对象。

 

入门