You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

DirectX相机移动时三角形渲染扭曲/拉伸问题求助

平移相机/三角形时渲染扭曲问题排查

我正在开发一款简易DirectX引擎以巩固图形编程知识,目前遇到以下问题:使用仅支持平移的相机渲染简单三角形时,相机移动会导致三角形扭曲;平移三角形时也会出现扭曲,且方向相反。

无相机移动时的三角形外观:CameraNeutral
相机右移时的三角形外观:CameraRight
相机上移时的三角形外观:CameraUp

最初怀疑WorldViewProjection(WVP)矩阵存在问题,但检查后未发现异常,相关代码如下:

void Renderer::CreateViewProjectionMatrix()
{
    using namespace DirectX;

    // Create world matrix
    const XMMATRIX translation = XMMatrixTranslation(0.f, 0.f, 0.f);
    const XMMATRIX rotation = XMMatrixRotationRollPitchYaw(0.f, 0.f, 0.f);  // In radians
    const XMMATRIX scale = XMMatrixScaling(1.f, 1.f, 1.f);

    const XMMATRIX worldMatrix = scale * rotation * translation;
    XMStoreFloat4x4(&m_VertexConstantBuffer.worldMatrix, worldMatrix);

    // Create view matrix
    const XMFLOAT3 cameraForward{ 0.f, 0.f, 1.f };
    const XMFLOAT3 cameraUp{ 0.f, 1.f, 0.f };

    const XMVECTOR worldPos = XMLoadFloat3(&m_CameraPos);
    const XMVECTOR worldForward = XMLoadFloat3(&cameraForward);
    const XMVECTOR worldUp = XMLoadFloat3(&cameraUp);

    const XMMATRIX viewMatrix = XMMatrixLookToLH(worldPos, worldForward, worldUp);

    // Create projection matrix
    const float aspectRatioX = static_cast<float>(m_BackBufferDescription.Width) / m_BackBufferDescription.Height;
    const float FOV{ 45.f };
    const float nearZ{ 0.1f };
    const float farZ{ 100.f };
    const XMMATRIX projectionMatrix = XMMatrixPerspectiveFovLH(XMConvertToRadians(FOV), aspectRatioX, nearZ, farZ);

    // Store WVP matrix
    const XMMATRIX WVPMatrix = worldMatrix * viewMatrix * projectionMatrix;
    XMStoreFloat4x4(&m_VertexConstantBuffer.worldViewProjection, WVPMatrix);
}

三角形创建代码如下:

HRESULT Renderer::CreateTriangle()
{
    // Create triangle geometry
    const BaseVertexInput triangleVertices[] =
    {
        { DirectX::XMFLOAT3{ -0.5f,-0.5f, 0.0f }, DirectX::XMFLOAT3{}, DirectX::XMFLOAT2{} },
        { DirectX::XMFLOAT3{  0.5f,-0.5f, 0.0f }, DirectX::XMFLOAT3{}, DirectX::XMFLOAT2{} },
        { DirectX::XMFLOAT3{  0.0f, 0.3f, 0.0f }, DirectX::XMFLOAT3{}, DirectX::XMFLOAT2{} }
    };

    // Create vertexBuffer
    const CD3D11_BUFFER_DESC vertexDescription{ sizeof(triangleVertices), D3D11_BIND_VERTEX_BUFFER};

    D3D11_SUBRESOURCE_DATA vertexData;
    ZeroMemory(&vertexData, sizeof(D3D11_SUBRESOURCE_DATA));    // Stops writes being compiled away if it isn't being read immeadiatly
    vertexData.pSysMem = triangleVertices;                      // Initialization data
    vertexData.SysMemPitch = 0;                                 // Distance from beginning line of texture to the next line (only for 2D & 3D texture)
    vertexData.SysMemSlicePitch = 0;                            // Distance from beginning of one depth level to the next   (only for 3D texture)

    HRESULT result = m_pDevice->CreateBuffer
    (
        &vertexDescription,
        &vertexData,
        m_pVertexBuffer.GetAddressOf()
    );

    if (FAILED(result))
    {
        Logger::Log(L"ERROR - Failed to create a vertexBuffer");
        return result;
    }

    // Create indexBuffer
    const unsigned short triangleIndices[]
    {
        0,2,1
    };

    m_IndexCount = ARRAYSIZE(triangleIndices);

    const CD3D11_BUFFER_DESC indexDescription{ sizeof(triangleIndices), D3D11_BIND_INDEX_BUFFER };

    D3D11_SUBRESOURCE_DATA indexData;
    ZeroMemory(&indexData, sizeof(D3D11_SUBRESOURCE_DATA));
    indexData.pSysMem = triangleIndices;
    indexData.SysMemPitch = 0;
    indexData.SysMemSlicePitch = 0;

    result = m_pDevice->CreateBuffer
    (
        &indexDescription,
        &indexData,
        m_pIndexBuffer.GetAddressOf()
    );

    if (FAILED(result))
    {
        Logger::Log(L"ERROR - Failed to create an indexBuffer");
        return result;
    }

    // Creation success
    m_SuccesfullCreation = true;
    return result;
}

已排查WVP矩阵、顶点着色器、顶点缓冲区创建等方向,尝试过Microsoft指南中的Transpose(RightHandMatrix(...))方法,但导致三角形完全不可见。目前毫无头绪,可提供更多代码,寻求技术帮助。

补充:完整顶点着色器代码如下:

cbuffer CB_World : register(b0)    // Register for GPU access (b. for constant buffers)
{
    matrix g_WorldViewProjection;   // World to projection space
    matrix g_World;                 // World space
};

struct VS_INPUT
{
    float3 position : POSITION;
    float3 normal : NORMAL;
    float2 uv : TEXCOORD0;
};

struct VS_OUTPUT
{
    float4 position : SV_POSITION;  // System value
    float3 normal : NORMAL;
    float2 uv : TEXCOORD0;
};

VS_OUTPUT VSMain(VS_INPUT input)
{
    VS_OUTPUT output;
    
    output.position = mul(float4(input.position, 1.0), g_WorldViewProjection);
    output.normal = normalize(mul(input.normal, (float3x3) g_World));
    output.uv = input.uv;
    
    return output;
}

内容的提问来源于stack exchange,提问作者RenzoDP

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 04:19:51