【问题标题】:Why is the transitive closure of matrix multiplication not working in this vertex shader?为什么矩阵乘法的传递闭包在这个顶点着色器中不起作用?
【发布时间】:2013-07-23 18:37:55
【问题描述】:

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

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

// 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 是row-major struct(并且它的所有运算符都这样对待它)并且 mul(...) 将其矩阵参数解释为行专业。所以这似乎不是问题,但也许它仍然是我不理解的方式。

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

感谢您的阅读,如果您能给我任何提示,我将不胜感激。

编辑(在 cmets 中请求的附加信息): 这是我用作矩阵常量缓冲区的结构:

// 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
        );
}

【问题讨论】:

    标签: graphics matrix windows-phone-8 directx hlsl


    【解决方案1】:

    鉴于您的代码 sn-ps,它应该可以工作。

    问题的可能原因:

    • 您是否尝试过反向乘法:projection * view * model
    • 您确定在常量缓冲区中正确设置了cummulative寄存器索引 = 12,偏移量 = 192
    • eyePosition 也一样(寄存器索引 = 12,偏移量 = 256)?

    【讨论】:

    • 嗯。那么在制作 MatrixConstantBuffer 之前我给 D3D 的唯一信息是:CD3D11_BUFFER_DESC constantMatrixBufferDesc(sizeof(ModelViewProjectionConstantBuffer), D3D11_BIND_CONSTANT_BUFFER); Arg,我不小心按了进入。让我试着颠倒乘法的顺序,我会在之后更新
    • @Nico 您能否分享您在m_constantMatrixBuffer 中写入的代码(通过编辑您的帖子)。
    • 完成(写此评论以触发您的通知)
    • 哇。不要打扰阅读。反转乘法工作。我会认真思考为什么会这样。非常感谢,我自己会花很长时间才能解决这个问题。
    • @Nico 我问你是否尝试过反转乘法(第一点)!...:P
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多