使用光栅器阶段入门

本部分介绍如何设置视区、剪刀矩形、光栅器状态和多重采样。

设置视区

视区将剪辑空间中的顶点位置 () 映射到呈现目标位置。 此步骤将 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 );

视区说明指定视区的大小、使用 MinDepthMaxDepth) 将深度映射到 (的范围,以及视区左上角的位置。 MinDepth 必须小于或等于 MaxDepth; MinDepthMaxDepth 的范围介于 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 覆盖 ,还是始终按样本) 执行的模具操作 (无关。

深度测试受多重采样的影响:

  • 启用多重采样后,深度按样本内插,深度/模具测试按样本执行;对于所有传递的样本,像素着色器输出颜色重复。 如果像素着色器输出深度,则所有样本的深度值 (重复,尽管此方案将失去多重采样) 的优势。
  • 禁用多重采样后,仍按样本执行深度/模具测试,但不会按样本内插深度。

在单个呈现目标中混合多重采样和非多重采样呈现没有限制。 如果启用多重采样并绘制到非多重采样呈现器目标,则会生成与未启用多重采样相同的结果;采样是通过每个像素的单个样本完成的。

光栅器阶段