983 字
5 分钟
DirectX 11 图元装配、相机原理与视口

一、 输入装配:索引缓冲区 (Index Buffer) 的意义#

在代码中创建 Mesh(如球体)时,我们发现总是会有两个数组:Vertices(顶点)和 Indices(索引)。

1. 为什么要用索引?#

假设我们要画一个正方形(由两个三角形组成):

  • 不使用索引:我们需要 6 个顶点。虽然正方形只有 4 个角,但因为两个三角形共用一条对角线,那两个公共点的数据(位置、法线、UV)必须在内存里存两份。
  • 使用索引:我们只需要存 4 个顶点。然后用一个整数数组(索引)来告诉 GPU:“画第一个三角形用第 0,1,2 号点;画第二个用 2,1,3 号点”。

核心优势

  • 复用顶点:减少显存占用(顶点数据通常很大,索引只是整数)。
  • 顶点缓存(Vertex Cache)优化:显卡硬件会缓存最近处理过的顶点。通过索引复用,显卡可以跳过重复顶点的着色器计算,显著提升性能。

2. 图元拓扑 (Primitive Topology)#

IASetPrimitiveTopology 中,我们通常使用 D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST

  • Triangle List:每 3 个索引构成一个独立的三角形(0,1,2 是一个,3,4,5 是另一个)。
  • Triangle Strip:更紧凑的格式。每增加 1 个索引就多画一个三角形(0,1,2 是第一个,1,2,3 是第二个…)。这在地形渲染中很常见。

二、 摄像机原理:UVN 系统与 LookAt 矩阵#

我们在代码中经常调用 XMMatrixLookAtLH(eye, focus, up) 来获取观察矩阵(View Matrix)。这个函数内部其实是在构建一个摄像机坐标系

1. 摄像机的本质#

摄像机本身并没有“动”。在渲染管线中,移动摄像机 = 把整个世界反向移动

  • 摄像机向左移动 5 米 = 所有物体向右移动 5 米。
  • 摄像机向右旋转 30 度 = 所有物体绕摄像机向左旋转 30 度。

2. UVN 坐标系构建#

为了把世界坐标转换到摄像机视角的坐标,我们需要构建三个基向量:

  • N (Look/Forward):摄像机看向的方向()。
  • U (Right):摄像机的右方向。它通过 上方向 (Up)N 进行向量叉乘 (Cross Product) 得到。
  • V (Up):摄像机真实的头顶方向。通过 NU 再次叉乘得到(修正后的 Up)。

3. 观察矩阵 (View Matrix)#

一旦有了 U、V、N 这三个轴,我们就可以构造一个矩阵,将世界空间中的点“投影”到这三个轴上。这就是观察矩阵的数学本质——它是一个基变换(Change of Basis)矩阵加上一个位移(Translation)矩阵的组合。


三、 光栅化前夜:视口 (Viewport) 与 裁剪#

当顶点着色器算出了位置(Clip Space),在像素着色器运行之前,硬件还默默做了两件事。

1. 透视除法 (Perspective Divide)#

顶点着色器输出的是 float4(x, y, z, w)。硬件会自动执行 x/w, y/w, z/w。 这一步让近大远小成为现实,并将坐标归一化到 NDC 空间(Normalized Device Coordinates),即所有可见物体的坐标都在 到 的立方体内。

2. 视口变换 (Viewport Transform)#

我们在初始化时填写的 D3D11_VIEWPORT 结构体:

viewport.Width = 1920.0f;
viewport.Height = 1080.0f;

它的作用是将 NDC 空间(-1 到 1)的数学点,拉伸映射到具体的像素坐标(0 到 1920, 0 到 1080)。

  • 如果在游戏中做“画中画”效果(比如后视镜),其实就是绑定了另一个较小的 Viewport,让渲染结果只画在屏幕的一小块区域。

总结#

这三个概念填补了图形管线的“首”和“尾”:

  • 索引缓冲区决定了 GPU 如何高效地读取几何体。
  • 摄像机矩阵决定了我们如何从数学上定义观察视角。
  • 视口变换决定了数学计算结果最终如何在显示器像素上。
DirectX 11 图元装配、相机原理与视口
https://www.m4doka.xyz/posts/dx11/dx11-4/
作者
m4doka
发布于
2026-02-01
许可协议
CC BY-NC-SA 4.0