我需要澄清"Spaces"的概念(世界空间,视图空间,投影空间,局部空间和屏幕空间)(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)

本文关键字:空间 投影 direct3d 局部 视图 屏幕 世界 Spaces      更新时间:2023-10-16

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

这些都是在代码中完成的,如下所示…

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);  

我很难在脑子里想象这个。简单来说…我是否只是通过创造CameraView来"允许"玩家随意移动?(假设3d世界已经创建)

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

第一个建议:因为你对DirectXMath和Direct3D完全陌生,你应该看看directxtool Kit和SimpleMath包装器。这会为你节省很多精力。

当你渲染一个对象时,实际上只有一个变换。它从定义对象的坐标系统(称为"局部"或"模型"坐标空间)中获取对象,最终结果是x,y像素位置和z深度。

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

  1. "世界"矩阵将本地坐标中定义的点放置到"世界"坐标中。这允许所有的模型在他们自己的本地坐标,然后放置相对于另一个场景。世界坐标系统也是你通常定义光源位置的地方。这通常是通过XMMatrixTranslation, XMMatrixRototation*XMMatrixScaling函数相乘的组合来创建的(在库中还有许多其他方法来创建变换矩阵,包括使用四元数进行旋转)。
  2. "视图"矩阵将世界坐标空间中的点移动到视图坐标空间中,这通常被认为是相机看到事物的方式。这就是您所展示的代码片段所计算的内容。给定世界坐标中的相机位置和世界坐标中的相机目标位置,以及任意的"向上"向量,该函数计算"视图"矩阵需要使用"左手"观看坐标(因此称为"LH")。
  3. "投影"矩阵将视图系统中的点移动到一个通用的规范化方框中,该方框定义了"投影",包括应用透视图或正交投影。对于DirectXMath,这是通过XMMatrixPerspectiveFovLH, XMMatrixOrthographicLH,相关函数完成的。

参见3D投影

RE:偏手性

左撇子的选择vs。"右撇子"观看系统纯粹是一个品味问题,以及如何定义你的内容。过去Direct3D使用左手坐标,而OpenGL使用右手坐标。在现代可编程着色器中,没有什么内置到系统中。你只需要保持一致。XNA Game Studio和SimpleMath使用"右手"系统。DirectXMath在99%的情况下使用。

参见右手定则

将对象转换为"视图空间"基本上是根据相机的位置和方向/旋转来重新定位它们相对于相机的位置。

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

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

视图向量= lookAt - Position.

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

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

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

上矢量=右矢量X视图矢量

作为一个非常重要的注意事项,您要确保这三个向量是正交标准化的。这听起来很专业,但只是意味着这三个模型的长度都是一个,并且彼此成90度,或者有趣的事情会发生在模型上,比如拉伸和扭曲。

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

现在,真正的技巧是存储的值实际上是位置/旋转的逆。想想看。如果你有一个相机并将其右移到位置(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所说,很多时候,许多对象的变换是使用由世界,视图,投影矩阵产生的矩阵进行乘法运算,但在某些情况下,您可能想要使用来自模型-视图矩阵(没有投影)的视图空间坐标在着色器中,如照明,这取决于您的方法。