gpt4 book ai didi

c# - DirectX:世界观察矩阵——我的误解在哪里?

转载 作者:行者123 更新时间:2023-11-30 14:57:12 29 4
gpt4 key购买 nike

我开始使用 DirectX(和 SharpDX,因此只能在 C#/hlsl 中编程)并尝试构建我自己的相机类。它应该是可旋转的,允许向前和向后移动以及“横向”移动(经典的第一人称移动通常映射到 A 和 D,在我的例子中加上上下)。为了更容易修复错误模型和世界空间在我的例子中是相同的,透视投影尚未实现,旋转相机也是如此,我的相机应该在正 Z 轴(进入屏幕)中看。我的错误修复模型是一个简单的四边形,其宽度和高度为 1.f,z = 0 并且位于屏幕中央。
为了便于使用,我找到了 DirectX 的 Matrix.LookAtLH() 并使用它来构建我的矩阵,用于从世界坐标到 View 坐标的转换,基于我的相机在世界坐标中的定位,一个向上矢量(现在 - 没有旋转 - 总是正 Y 轴)和世界坐标中的目标点。
我的(顶点)着色器使用与该矩阵的简单乘法:
output.position = mul(position, worldToView);
LookAt-Matrix 的计算方式如下:
Matrix.LookAtLH(vec3(0, 0, -1), vec3(0, 0, 0.5f), vec3(0, 1, 0))
导致这张图片:
Camera at (0, 0, -1) looking at (0, 0, 0.5f
现在我想将相机向右移动,在本例中是将 1.f 添加到它的 X 坐标。 我的预期结果与之前的四边形相同,向左移动了一点。
我构建了一个新的 LootAt 矩阵,通过相同的向量移动眼睛坐标和目标坐标:
/>Matrix.LookAtLH(vec3(1, 0, -1), vec3(1, 0, 0.5f), vec3(0, 1, 0))
结果是:
Camera at (1, 0, -1) lookint at (1, 0, 0.5f

我移动相机越多,这种情况就越严重,但屏幕的中心仍然保持四边形的中心。这是否与我对 Matrix.LookAtLH 的潜在误解有关?

最佳答案

当您使用 D3DX 函数时,您必须先转置矩阵,然后再将它们发送到着色器。

来自 here 的更深入的解释:

在线性代数中,向量和矩阵使用标准矩阵乘法算法相乘。因此,有一些关于运算顺序和所涉及矩阵“形状”的规则。数学家通常将向量视为包含单列元素的矩阵,平移乘法看起来像这样:

[ 0, 0, 0, tx]  [ x]
[ 0, 0, 0, ty] *[ y]
[ 0, 0, 0, tz] [ z]
[ 0, 0, 0, 1] [ 1]

首先请注意,矩阵乘法根据以下简单规则产生特定行/列配置的结果:

AxB * BxC = AxC.

换句话说,A 行 B 列大小的矩阵乘以 B 行 C 列大小的矩阵将产生 A 行 C 列大小的矩阵。此外,为了正确相乘,两者的 B 必须相等。在这种情况下,我们有 4x4 * 4x1,它产生一个 4x1 或另一个列向量。如果我们改变乘法的顺序,就是 4x1 * 4x4,这是不合法的。

但是,计算机科学家通常将向量视为具有单行的矩阵。这有几个原因,但通常是因为单行代表单个线性内存块或一维数组,因为数组通常被寻址为数组[行][列]。为了避免在代码中使用二维数组,人们简单地使用“行向量”来代替。因此,为了使用矩阵乘法获得所需的结果,我们将顺序交换为 1x4 * 4x4 = 1x4,或 vector * matrix:

[ x, y, z, 1] * [ 0, 0, 0, 0]
[ 0, 0, 0, 0]
[ 0, 0, 0, 0]
[ x, y, z, 1]

请注意必须如何移动平移矩阵的 x、y、z 元素以保留正确的乘法结果(在本例中,它是转置的)。

使用列向量时,典型的变换操作顺序是 P* V * W * v,因为列向量必须排在最后才能产生正确的结果。请记住,矩阵乘法是关联的,而不是可交换的,因此为了获得向量经过世界变换、变换到 View 空间、变换到同质屏幕空间的适当结果,我们必须按此顺序进行乘法。这给了我们(使用关联性)P * (V * (W * v)),因此从内括号工作到外括号,首先是世界转换,然后是 View ,然后是投影。

如果我们使用行向量,则乘法如下:v * W * V * P。使用结合律,我们意识到它只是相同的运算顺序:((v * W) * V) * P。或者世界优先,然后是 View ,然后是投影。

这两种乘法形式同样有效,DX 库选择使用后者,因为它符合内存布局模式,并且允许您从左到右读取转换顺序。

HLSL 支持两种操作顺序。 “*”运算符按元素缩放执行简单的元素,它不执行矩阵乘法。这是使用“mul()”内部操作执行的。如果将一个 4 元素向量作为第一个参数传递给 mul() 内部函数,它会假定您希望将其视为“行向量”。因此,您必须提供以正确顺序相乘并使用正确行/列格式提供的矩阵。这是使用 DX 效果参数从 DX 库传入矩阵时的默认行为。如果您将 4 元素向量作为第二个参数提供给 mul() 内在函数,它会将其视为列向量,并且您必须为列向量提供正确形成和相乘的矩阵。

关于c# - DirectX:世界观察矩阵——我的误解在哪里?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21215930/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com