D3D11坐标系

时间:2014-08-27 11:00:42

标签: c++ matrix direct3d direct3d11

我的一些旧代码最终出现了一堆令人讨厌的黑客,以便让事情正常工作,#34;就移动物体和相机而言,例如必须采取"的std :: SIN(-yaw)"而不是" std :: sin(yaw)"当实现在网上其他地方发现的方程式时,这种方法通常只会让所有事情在许多情况下都变得混乱和错误。

  1. 使用D3D11和DirectXMath东西(左手坐标和行主要?),究竟是什么样的坐标系,例如:假设相机位于原点并沿着图像中的黄色矢量看而没有旋转,标签是否正确?。

    enter image description here

    然后给出了一个由(x,y,z)和音高(y轴鼠标/控制),偏航(x轴鼠标/控制)描述的相机,并假设没有其他方式我甚至应该这样做......

  2. 获取视图矩阵的正确函数是什么(目前我正在乘以平移和2个旋转​​矩阵,乘以投影,然后是所讨论对象的任何世界矩阵,并将结果转置为用作单个着色器常量)。

  3. 获取相机所在矢量的等式是什么(当前将(0,0,1)矢量乘以2中的矩阵)。

  4. ......以及" up"和"对"向量(因为即使不使用外观矩阵视图函数,似乎截头剔除需要知道那些)。目前再次与2中的矩阵相乘。
  5. 从方向矢量计算正确的俯仰和偏航标量/分量(例如,对于具有单独俯仰/偏航关节的炮塔)。
  6. 编辑:代码示例:

    //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?其中一些功能我最终用跟踪和错误来做到这一点,在线样本没有使用负面。

2 个答案:

答案 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;
}