5-t*_*o-9 3 c# directx matrix directx-11 sharpdx
我开始使用DirectX(和SharpDX,因此仅在C#/ hlsl中编程)并且我正在尝试构建自己的相机类.它应该是可旋转的,允许向前和向后移动以及"侧向"运动(经典的第一人称运动通常映射到A和D,在我的情况下加上和向下).为了方便bugfixing模型和世界空间是在我的情况一样,透视投影尚未实现,如旋转的摄像头,和我的相机应该是正Z轴看(到屏幕).我的错误修正模型是一个简单的四边形,宽度和高度为1.f,z = 0并且在屏幕上居中.
为了便于使用,我找到了DirectX Matrix.LookAtLH()并使用它构建我的矩阵,用于从世界到视图坐标的平移,基于我的相机在世界坐标中的位置,向上矢量(现在 - 没有旋转 - 总是正Y轴)和世界坐标中的目标点.
我的(顶点)着色器使用与此矩阵的简单乘法:
output.position = mul(position, worldToView);
LookAt-Matrix计算如下:
Matrix.LookAtLH(vec3(0, 0, -1), vec3(0, 0, 0.5f), vec3(0, 1, 0))
得到这张图片:

现在我想将相机移到右边,在这种情况下,将1.f添加到它的X坐标.我的预期结果与之前的四元组相同,向左移动了一点.
我构建了一个新的LootAt矩阵,通过相同的向量移动眼睛坐标和目标坐标:
Matrix.LookAtLH(vec3(1, 0, -1), vec3(1, 0, 0.5f), vec3(0, 1, 0))
结果如下:

我移动相机越多越好,但屏幕中心仍保持四边形的中心.这与我对潜在的误解有关Matrix.LookAtLH吗?
当您使用D3DX函数时,您必须在将矩阵发送到着色器之前转置矩阵.
从这里更深入的解释:
在线性代数中,使用标准矩阵乘法算法将向量和矩阵相乘.因此,有一些关于操作顺序和所涉及的矩阵"形状"的规则.数学家通常将向量视为包含单列元素的矩阵,其转换乘法看起来像这样:
[ 0, 0, 0, tx] [ x]
[ 0, 0, 0, ty] *[ y]
[ 0, 0, 0, tz] [ z]
[ 0, 0, 0, 1] [ 1]
Run Code Online (Sandbox Code Playgroud)
首先请注意,矩阵乘法会根据此简单规则生成特定行/列配置的结果:
AxB*BxC = AxC.
换句话说,大小为A行和B列的矩阵乘以B行和C列的矩阵将产生A行和C列的矩阵.而且,为了正确地相乘,B对于两者必须相等.在这种情况下,我们有4x4*4x1,它产生4x1或另一个列向量.如果我们改变了乘法的顺序,它将是4x1*4x4,这将是非法的.
然而,计算机科学家经常将向量视为具有单行的矩阵.这有几个原因,但通常是因为单行代表单个线性内存块或单维数组,因为数组通常被称为数组[row] [column].为了避免在代码中使用二维数组,人们简单地使用"行向量".因此,为了使用矩阵乘法获得所需的结果,我们将顺序交换为1x4*4x4 = 1x4或vector*矩阵:
[ x, y, z, 1] * [ 0, 0, 0, 0]
[ 0, 0, 0, 0]
[ 0, 0, 0, 0]
[ x, y, z, 1]
Run Code Online (Sandbox Code Playgroud)
注意如何移动平移矩阵的x,y,z元素以保留适当的乘法结果(在这种情况下,它是转置的).
使用列向量时,典型的操作转换顺序为P*V*W*v,因为列向量必须最后才能产生正确的结果.请记住,矩阵乘法是相关的,而不是可交换的,所以为了实现由世界变换的矢量的适当结果,转换成视图空间,转换成同质的屏幕空间,我们必须按顺序相乘.这给了我们(使用关联性)P*(V*(W*v)),因此从内部parens到外部parens,世界变换首先,下一个观察,下一个投影.
如果我们用行向量,则乘法如下:V*W*V*P.使用的相关性,我们意识到它只是相同的操作顺序为:((V*w)*V)*P.还是世界第一,然后查看,然后投影.
两种形式的乘法同样有效,DX库选择使用后者,因为它匹配内存布局模式,并允许您从左到右读取转换顺序.
HLSL支持两种操作顺序."*"运算符通过元素缩放执行简单的元素,它不执行矩阵乘法.这是使用"mul()"内在操作执行的.如果将4元素向量作为第一个参数传递给mul()内部函数,则假定您希望将其视为"行向量".因此,您必须提供已按正确顺序相乘的矩阵,并使用正确的行/列格式提供.这是使用DX效果参数从DX库传递矩阵时的默认行为.如果将4元素向量作为第二个参数提供给mul()内在函数,则会将其视为列向量,并且必须为列向量提供正确形成和相乘的矩阵.
| 归档时间: |
|
| 查看次数: |
2269 次 |
| 最近记录: |