我需要澄清一下 "Spaces"(世界 space、视图 space、投影 space、本地 space 和屏幕 space 的概念s) (C++, direct3d 11)

I need some clarification with the concept of "Spaces" (world space, view space, projection spaces, local spaces and screen spaces) (c++, direct3d 11)

到目前为止,我对这些 space 的理解是它们定义了游戏 3d 世界的某个方面。视图 space 实际上只是相机,我们通过创建包含相机位置、相机目标和相机的 "up" 方向的矩阵来定义它。

这一切都是在代码中完成的,如下...

XMMATRIX CameraView;
XMVECTOR CameraPosition;                        
XMVECTOR CameraTarget;
XMVECTOR CameraUp;

/* Describing the matrix */
CameraPosition = XMVectorSet(0.0f, 0.0f, -0.5f, 0.0f);      
CameraTarget = XMVectorSet(0.0f, 0.0f, 0.0f, 0.0f);         
CameraUp = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);

/*  Creating the matrix*/
CameraView = XMMatrixLookAtLH(CameraPosition, CameraTarget, CameraUp);  

我很难在脑海中想象这一点。所以简单来说.. 我只是 "enabling" 玩家可以通过创建 CameraView 来随意移动吗? (假设 3d 世界已经创建)

谁能给我解释一下这里到底发生了什么

第一个建议:由于您是 DirectXMath 和 Direct3D 的新手,因此您应该特别查看 DirectX Tool Kit and the SimpleMath 包装器。它会让你在这里分心很多。

当您渲染一个对象时,实际上只进行了一次转换。它从它定义的任何坐标系(称为 'local' 或 'model' 坐标 spaces)获取对象,最终结果是一个 x,y 像素位置和一个 z深度。

然而,对于人类来说,通常更容易将这种转换视为分阶段发生——实际上,由于齐次坐标的强大功能和乘法串联,实际上它只是一个向量矩阵乘法。这通常被认为是 world -> view -> projection.

  1. 'world'矩阵将局部坐标中定义的点放置到'world'坐标中。这允许所有模型都在它们自己的本地坐标中,然后相对于另一个放置在场景中。世界坐标系也是您规范地定义光源所在位置的地方。这通常是通过 XMMatrixTranslationXMMatrixRototation*XMMatrixScaling 函数相乘的组合创建的(还有许多其他方法可以在库中创建转换矩阵,包括使用四元数旋转)。
  2. 'view' 矩阵将世界坐标 space 中的点移动到视图坐标 space 中,这通常被认为是相机如何看待事物。这就是您显示的代码片段正在计算的内容。给定世界坐标中的相机位置、世界坐标中的相机目标位置和任意 'up' 向量,该函数计算 'view' 矩阵需要使用 'left-handed' 观察坐标(因此 "LH").
  3. 'projection' 矩阵将点从视图系统移动到定义 'projection' 的通用标准化框,包括应用透视投影或正交投影。对于 DirectXMath,这是通过 XMMatrixPerspectiveFovLHXMMatrixOrthographicLH 相关函数完成的。

3D projection

回复:惯用手

'left-handed' 与 'right-handed' 查看系统的选择纯粹是一个品味问题以及您的内容是如何定义的。历史上,Direct3D 使用左手坐标,而 OpenGL 使用右手坐标。在现代可编程着色器中,系统中没有内置任何东西。你只需要保持一致。 XNA Game Studio 和 SimpleMath 使用 'right-handed' 系统。 DirectXMath 在 99% 的情况下都使用其中之一。

Right-hand rule

将对象转换为 "view space" 基本上是根据相机的位置和 orientation/rotation.

相对于相机重新定位它们

视图或相机矩阵本身是使用相机的参考系制作的:想象一个 x、y 和 z 向量从相机出来,跟随相机的任何旋转,这样它们总是从相机的顶部出来,右边和前面。通常分别称为上、右、视向量。

视图矢量是使用观察点和位置导出的,即

视图向量 = lookAt - 位置。

然后使用新计算的视图向量与您提供的向上向量的叉积创建相机的右向量。

右向量 = 视图向量 X 上向量

最后 "real" 使用新视图和右向量创建相机的向上向量

上向量=右向量X视图向量

作为一个非常重要的注意事项,您要确保三个向量是正交归一化的。这听起来很技术性,但这只是意味着所有三个都具有一个的长度并且彼此真正成 90 度,否则模型可能会发生一些有趣的事情,例如拉伸和扭曲。

如何在视图矩阵中使用这些向量来创建矩阵的左上角 3 x 3 部分。然后,根据您使用的是行向量还是列向量,最底部的行或最右侧的列使用相机的位置。

现在,真正的技巧是存储的值实际上是 position/rotation 的倒数。想想看。如果您有一个相机并将其向右移动到位置 (2,0,0),您将必须将所有对象 -2.0 向左平移以获得移动相机所期望的效果。同样对于旋转 - 向右旋转相机,物体应该相对于相机向左移动

因此,对于位于 (4,5,3) 且未旋转的相机,在视图矩阵中使用列向量应如下所示:

[1 0 0 -4]
[0 1 0 -5]
[0 0 1 -3]
[0 0 0  1]

正如 Chuck Walbourn 所说,很多时候,许多对象的变换是使用由世界、视图、投影矩阵一起生成的矩阵的一次乘法,但在某些情况下,您可能希望使用视图 space 模型视图矩阵(没有投影)在着色器中的坐标,如照明,具体取决于您的方法。