我的一些旧代码最终出现了一堆令人讨厌的黑客,以便让事情正常工作,#34;就移动物体和相机而言,例如必须采取"的std :: SIN(-yaw)"而不是" std :: sin(yaw)"当实现在网上其他地方发现的方程式时,这种方法通常只会让所有事情在许多情况下都变得混乱和错误。
使用D3D11和DirectXMath东西(左手坐标和行主要?),究竟是什么样的坐标系,例如:假设相机位于原点并沿着图像中的黄色矢量看而没有旋转,标签是否正确?。
然后给出了一个由(x,y,z)和音高(y轴鼠标/控制),偏航(x轴鼠标/控制)描述的相机,并假设没有其他方式我甚至应该这样做......
获取视图矩阵的正确函数是什么(目前我正在乘以平移和2个旋转矩阵,乘以投影,然后是所讨论对象的任何世界矩阵,并将结果转置为用作单个着色器常量)。
获取相机所在矢量的等式是什么(当前将(0,0,1)矢量乘以2中的矩阵)。
编辑:代码示例:
//Moving a floating object with only yaw forwards (moveX,moveY,moveZ).
//Negative yaw seems wrong?
auto c = std::cosf(-yaw);
auto s = std::sinf(-yaw);
pos.x += moveX * c - moveZ * s;
pos.y += moveY;
pos.z += moveX * s + moveZ * c;
//Gets the vector the camera is looking along
//This time yaw is positive, but pitch is negative?
float c = std::cos(-pitch);
Vector3F facing(
c * std::sinf(yaw),
std::sinf(-pitch),
c * std::cosf(yaw));
//Creating the view transform matrix, everything is negative
XMMATRIX xmviewrot;
xmviewrot = XMMatrixRotationY(-yaw);
xmviewrot*= XMMatrixRotationX(-pitch);
XMMATRIX xmview;
xmview = XMMatrixTranslation(-x, -y, -z);
xmview *= xmviewrot;
XMStoreFloat4x4A(&view, xmview);
//Other vectors needed for frustum culling
XMVECTOR xmup = XMVector3Transform(XMLoadFloat4A(&UP), xmview);
XMVECTOR xmright = XMVector3Transform(XMLoadFloat4A(&RIGHT), xmview);
//Matrix for stuff that is already in world space (e.g. terrain)
XMMATRIX xmviewProj = xmview * xmproj;
//Apparently needs transposing before use on the GPU...
XMStoreFloat4x4A(&constants.transform, XMMatrixTranspose(xmviewProj));
//In the shaders
output.pos = mul(input.pos, transform);
//vertex positions for an upwards facing square with triangle strip
v0 = (x1, y, z1);
v1 = (x1, y, z2);
v2 = (x2, y, z2);
v3 = (x2, y, z1);
在我看来,我在这里做了一些根本错误的事情需要在不同的地方需要-yaw和+ yaw,-pitch和+ pitch?其中一些功能我最终用跟踪和错误来做到这一点,在线样本没有使用负面。
答案 0 :(得分:3)
Direct3D 11没有预期的坐标系,你可以随意使用。来自Getting Started with Direct3D 11的Chuck Walbourn博客文章:
数学:由于Direct3D 11没有“固定功能”图形 Direct3D 9的管道,图形数学惯例的选择 (左手与右手,行主要与列主要矩阵, 等)完全取决于开发人员。 DirectXMath可以用来 创建Direct3D风格的“左手坐标”转换为 以及使用a的OpenGL风格的“右手坐标”转换 行主矩阵约定,可以直接与行主要使用 着色器或转置以使用列主要着色器。
您的着色器确定他们期望的坐标系。最终,它们必须在齐次剪辑空间中为光栅化器阶段提供顶点,Direct3D 11 defines为:
进入光栅化器阶段的顶点(x,y,z,w)被假定为 在均匀的剪辑空间中。在此坐标空间中,X轴指向 对,Y点,Z点远离相机。
因此,您对其他问题的答案取决于您为项目选择的坐标系。 DirectXMath库有许多函数可以为您计算适当的矩阵。旧的D3DX库文档显示了用于计算这些矩阵的数学运算。
您的其他问题不是很清楚,但它们似乎无法理解矩阵如何用于变换顶点。您可能希望查看old Direct3D 9 documentation,其中描述了在固定功能管道中使用顶点的方式和原因,并对这些主题进行了很好的介绍。
答案 1 :(得分:0)
在离开Microsoft开发环境很长时间之后,我最近又重新将自己重新引入DirectX(版本12)。
我注意到,尽管我已经正确设置了所有东西,但是在执行几何变换时却得到了奇怪且不可预测的结果。就像您自己一样,我正在使用常量缓冲区将“模型视图透视”矩阵发送到顶点着色器。
为了纠正该问题,我必须对每个“模型视图透视图”矩阵使用XMMatrixTranspose()。这样...
m_constantBufferData.world = XMMatrixTranspose(worldMatrix);
m_constantBufferData.view = XMMatrixTranspose(viewMatrix);
m_constantBufferData.projection = XMMatrixTranspose(projectionMatrix);
似乎着色器使用与DirectXMath库函数相反的列主(或行主?)形式。
最初我很惊讶地了解到这一点。
为完整起见,这是我的着色器代码...
cbuffer SceneConstantBuffer : register(b0)
{
float4 offset;
matrix world;
matrix view;
matrix projection;
};
struct VS_INPUT
{
float4 Pos : POSITION;
float4 Color : COLOR;
};
struct PS_INPUT
{
float4 Pos : SV_POSITION;
float4 Color : COLOR;
};
PS_INPUT VSMain(VS_INPUT input)
{
PS_INPUT output;
output.Pos = mul(input.Pos, world);
output.Pos = mul(output.Pos, view);
output.Pos = mul(output.Pos, projection);
output.Color = input.Color;
return output;
}
float4 PSMain(PS_INPUT input) : SV_TARGET
{
return input.Color;
}