使用光栅器阶段入门
本部分介绍如何设置视区、剪刀矩形、光栅器状态和多重采样。
设置视区
视区将剪辑空间中的顶点位置 () 映射到呈现目标位置。 此步骤将 3D 位置缩放为 2D 空间。 呈现目标的方向为 Y 轴向下指向;这要求在视区缩放期间翻转 Y 坐标。 此外,根据以下公式调整 x 和 y 范围 (x 和 y 值范围) 以适合视区大小:
X = (X + 1) * Viewport.Width * 0.5 + Viewport.TopLeftX
Y = (1 - Y) * Viewport.Height * 0.5 + Viewport.TopLeftY
Z = Viewport.MinDepth + Z * (Viewport.MaxDepth - Viewport.MinDepth)
教程 1 使用 D3D11_VIEWPORT 和调用 ID3D11DeviceContext::RSSetViewports 创建 640 × 480 视区。
D3D11_VIEWPORT vp[1];
vp[0].Width = 640.0f;
vp[0].Height = 480.0f;
vp[0].MinDepth = 0;
vp[0].MaxDepth = 1;
vp[0].TopLeftX = 0;
vp[0].TopLeftY = 0;
g_pd3dContext->RSSetViewports( 1, vp );
视区说明指定视区的大小、使用 MinDepth 和 MaxDepth) 将深度映射到 (的范围,以及视区左上角的位置。 MinDepth 必须小于或等于 MaxDepth; MinDepth 和 MaxDepth 的范围介于 0.0 和 1.0 之间,包括 0.0 和 1.0。 视区通常映射到呈现器目标,但没有必要;此外,视区不必具有与呈现器目标相同的大小或位置。
可以创建一个视区数组,但只能将一个对象应用于几何着色器的基元输出。 一次只能设置一个处于活动状态的视区。 管道使用默认视区 (和剪刀矩形,将在光栅化过程中的下一节) 进行讨论。 默认值始终是数组中) (或剪刀矩形的第一个视区。 若要在几何着色器中按基元选择视区,请在 GS 输出签名声明中的相应 GS 输出组件上指定 ViewportArrayIndex 语义。
任何时间可以绑定到光栅器阶段 (和剪刀矩形) 的最大视区数为 16 个 (D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE) 。
设置剪刀矩形
剪刀矩形提供了另一个减少将发送到输出合并阶段的像素数的机会。 剪刀矩形外部的像素将被丢弃。 剪刀矩形的大小以整数指定。 光栅化期间,在系统值语义 () 中,只能将一个基于 ViewportArrayIndex 的剪刀矩形应用于三角形。
若要启用剪刀矩形,请使用 D3D11_RASTERIZER_DESC1 ) 中的ScissorEnable 成员 (。 默认剪刀矩形为空矩形;也就是说,所有 rect 值都为 0。 换句话说,如果未设置剪刀矩形并且启用了剪刀,则不会将任何像素发送到输出合并阶段。 最常见的设置是将剪刀矩形初始化为视区的大小。
若要为设备设置剪刀矩形数组,请使用 D3D11_RECT调用 ID3D11DeviceContext::RSSetScissorRects。
D3D11_RECT rects[1];
rects[0].left = 0;
rects[0].right = 640;
rects[0].top = 0;
rects[0].bottom = 480;
g_pd3dContext->RSSetScissorRects( 1, rects );
此方法采用两个参数: (1) 数组中的矩形数, (2) 矩形数组。
管道在光栅化期间使用默认剪刀矩形索引, (默认为零大小的矩形,) 禁用剪裁。 若要替代此值,请在 GS 输出签名声明中指定 GS 输出组件的SV_ViewportArrayIndex语义。 这将导致 GS 阶段使用此语义将此 GS 输出组件标记为系统生成的组件。 光栅器阶段识别此语义,并将其附加到的参数用作剪刀矩形索引来访问剪刀矩形数组。 在创建光栅器对象之前,不要忘记告知光栅器阶段使用通过启用光栅器说明中的 ScissorEnable 值来定义的剪刀矩形。
设置光栅器状态
从 Direct3D 10 开始,光栅器状态封装在光栅器状态对象中。 最多可以创建 4096 个光栅器状态对象,然后可以通过向状态对象传递句柄将其设置为设备。
使用 ID3D11Device1::CreateRasterizerState1 根据光栅器说明创建光栅器状态对象, (请参阅 D3D11_RASTERIZER_DESC1) 。
ID3D11RasterizerState1 * g_pRasterState;
D3D11_RASTERIZER_DESC1 rasterizerState;
rasterizerState.FillMode = D3D11_FILL_SOLID;
rasterizerState.CullMode = D3D11_CULL_FRONT;
rasterizerState.FrontCounterClockwise = true;
rasterizerState.DepthBias = false;
rasterizerState.DepthBiasClamp = 0;
rasterizerState.SlopeScaledDepthBias = 0;
rasterizerState.DepthClipEnable = true;
rasterizerState.ScissorEnable = true;
rasterizerState.MultisampleEnable = false;
rasterizerState.AntialiasedLineEnable = false;
rasterizerState.ForcedSampleCount = 0;
g_pd3dDevice->CreateRasterizerState1( &rasterizerState, &g_pRasterState );
此示例状态集可能完成最基本的光栅器设置:
- 实心填充模式
- 剔除或移除背面人脸;假设基元的逆时针缠绕顺序
- 关闭深度偏差,但启用深度缓冲并启用剪刀矩形
- 关闭多重采样和行抗锯齿
此外,基本光栅器操作始终包括以下内容:剪裁 (到视图视锥) 、透视除法和视区比例。 成功创建光栅器状态对象后,将其设置为设备,如下所示:
g_pd3dContext->RSSetState(g_pRasterState);
多重采样
多重采样以更高分辨率 (对图像的一些或所有组件进行采样,然后向下采样到原始分辨率) 以减少绘制多边形边缘引起的最明显的锯齿形式。 尽管多重采样需要子像素样本,但新式 GPU 实现多重采样,以便像素着色器每个像素运行一次。 这在性能 (之间提供了可接受的权衡,尤其是在 GPU 绑定应用程序中,) 和最终映像的抗锯齿。
若要使用多重采样,请在光栅化说明中设置 enable 字段,创建多重采样呈现目标,然后使用着色器读取呈现器目标以将样本解析为单像素颜色,或者调用 ID3D11DeviceContext::ResolveSubresource 以使用视频卡解析样本。 最常见的方案是绘制到一个或多个多重采样呈现目标。
多重采样与是否使用样本掩码、是否启用 alpha 覆盖 ,还是始终按样本) 执行的模具操作 (无关。
深度测试受多重采样的影响:
- 启用多重采样后,深度按样本内插,深度/模具测试按样本执行;对于所有传递的样本,像素着色器输出颜色重复。 如果像素着色器输出深度,则所有样本的深度值 (重复,尽管此方案将失去多重采样) 的优势。
- 禁用多重采样后,仍按样本执行深度/模具测试,但不会按样本内插深度。
在单个呈现目标中混合多重采样和非多重采样呈现没有限制。 如果启用多重采样并绘制到非多重采样呈现器目标,则会生成与未启用多重采样相同的结果;采样是通过每个像素的单个样本完成的。
相关主题