0

这可能会在过早优化下提交,但由于顶点着色器在每一帧的每个顶点上执行,这似乎是值得做的事情(在进入像素着色器之前我需要乘以很多变量)。

本质上,顶点着色器执行此操作以将向量转换为投影空间,如下所示:

// Transform the vertex position into projected space.
pos = mul(pos, model);
pos = mul(pos, view);
pos = mul(pos, projection);
output.pos = pos;

由于我正在对着色器中的多个向量执行此操作,因此将这些矩阵组合成 CPU 上的累积矩阵然后将其刷新到 GPU 进行计算是有意义的,如下所示:

// VertexShader.hlsl
cbuffer ModelViewProjectionConstantBuffer : register (b0)
{
    matrix model;
    matrix view;
    matrix projection;
    matrix cummulative;
    float3 eyePosition;
};

...

// Transform the vertex position into projected space.
pos = mul(pos, cummulative);
output.pos = pos;

在 CPU 上:

// Renderer.cpp
// now is also the time to update the cummulative matrix
m_constantMatrixBufferData->cummulative = 
    m_constantMatrixBufferData->model * 
    m_constantMatrixBufferData->view *
    m_constantMatrixBufferData->projection;
// NOTE: each of the above vars is an XMMATRIX

我的直觉是行优先/列优先存在一些不匹配,但是 XMMATRIX 是一个行优先结构(并且它的所有运算符都这样对待它)并且 mul(...) 将其矩阵参数解释为行-重大的。所以这似乎不是问题,但也许它仍然是我不理解的方式。

我还检查了累积矩阵的内容,它们看起来是正确的,这进一步增加了混乱。

感谢您的阅读,我将非常感谢您能给我的任何提示。

编辑(评论中要求的其他信息):这是我用作矩阵常量缓冲区的结构:

// a constant buffer that contains the 3 matrices needed to
// transform points so that they're rendered correctly
struct ModelViewProjectionConstantBuffer
{
    DirectX::XMMATRIX model;
    DirectX::XMMATRIX view; 
    DirectX::XMMATRIX projection;
    DirectX::XMMATRIX cummulative;
    DirectX::XMFLOAT3 eyePosition;

    // and padding to make the size divisible by 16
    float padding;
};

我在 CreateDeviceResources(连同我的其他常量缓冲区)中创建矩阵堆栈,如下所示:

void ModelRenderer::CreateDeviceResources()
{
    Direct3DBase::CreateDeviceResources();

    // Let's take this moment to create some constant buffers

    ... // creation of other constant buffers

    // and lastly, the all mighty matrix buffer
    CD3D11_BUFFER_DESC constantMatrixBufferDesc(sizeof(ModelViewProjectionConstantBuffer), D3D11_BIND_CONSTANT_BUFFER);
    DX::ThrowIfFailed(
        m_d3dDevice->CreateBuffer(
        &constantMatrixBufferDesc,
        nullptr,
        &m_constantMatrixBuffer
        )
        );

    ... // and the rest of the initialization (reading in the shaders, loading assets, etc)

}

我在我创建的矩阵堆栈类中写入矩阵缓冲区。类的客户端在完成修改矩阵后调用 Update():

void MatrixStack::Update()
{
    // then update the buffers
    m_constantMatrixBufferData->model = model.front();
    m_constantMatrixBufferData->view = view.front();
    m_constantMatrixBufferData->projection = projection.front();
    // NOTE: the eye position has no stack, as it's kept updated by the trackball

    // now is also the time to update the cummulative matrix
    m_constantMatrixBufferData->cummulative = 
        m_constantMatrixBufferData->model * 
        m_constantMatrixBufferData->view *
        m_constantMatrixBufferData->projection;

    // and flush
    m_d3dContext->UpdateSubresource(
        m_constantMatrixBuffer.Get(),
        0,
        NULL,
        m_constantMatrixBufferData,
        0,
        0
        );
}
4

1 回答 1

1

给定您的代码片段,它应该可以工作。

您的问题的可能原因:

  • 您是否尝试过反向乘法:projection * view * model
  • 您确定在常量缓冲区中正确设置了cummulative( register index = 12, offset = 192 )
  • 相同的eyePosition寄存器索引= 12,偏移量= 256)?
于 2013-07-23T18:54:14.263 回答