Как передать матрицу преобразования экземпляра на вход вершинного шейдера? - PullRequest
0 голосов
/ 20 февраля 2020

Я попытался разложить свое преобразование на четыре вектора и собрать их на шейдере, но, похоже, это не сработало. Мои преобразования неверны, и мои объекты не отображаются. Пожалуйста, помогите!

Вот мой формат ввода:

D3D11_INPUT_ELEMENT_DESC inputElementDescriptor[] =
    {
        { "POSITION",   0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA,      0 },
        { "TEXCOORD",   0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA,         0 },
        { "TEXCOORD",   1, DXGI_FORMAT_R32G32_FLOAT, 0, 20, D3D11_INPUT_PER_VERTEX_DATA,         0 },
        { "NORMAL",     0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 76, D3D11_INPUT_PER_VERTEX_DATA,      0 },
        { "RowX",       0, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, 0, D3D11_INPUT_PER_INSTANCE_DATA,  1},
        { "RowY",       0, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, 16, D3D11_INPUT_PER_INSTANCE_DATA, 1},
        { "RowZ",       0, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, 32, D3D11_INPUT_PER_INSTANCE_DATA, 1 },
        { "RowW",       0, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, 48, D3D11_INPUT_PER_INSTANCE_DATA, 1}
    };

Вот мои данные экземпляра:

struct RenderableInstanceData
// This really has no business being inside D3D code.
{
    FASTVEC rowX;
    FASTVEC rowY;
    FASTVEC rowZ;
    FASTVEC rowW;
};

Вот как я буферизую их:

{
    if (this->m_pInstanceBuffer)
        delete this->m_pInstanceBuffer;

size_t numInstances     = this->m_pInstances.size ();

if (this->m_pInstanceBuff)
    delete [] this->m_pInstanceBuff;
this->m_pInstanceBuff   = (CORE_BYTE *)malloc (sizeof (RenderableInstanceData) * numInstances);
for (size_t idx         = 0; idx < numInstances; idx++)
{
    auto pInstance      = this->m_pInstances[idx];
    RenderableInstanceData data;
    pInstance->ToInstanceData(data);
    memcpy (&this->m_pInstanceBuff[idx], (const void *) &data, sizeof(data));
}
D3D11_SUBRESOURCE_DATA _instanceData;
_instanceData.pSysMem   = m_pInstanceBuff;
this->m_pInstanceBuffer = DirectX11Buffer::CreateInstanceBuffer (pDevice, (UINT) sizeof (RenderableInstanceData), numInstances, false, &_instanceData); // We only keep the transform for an instance for now.
}

Вот шейдер:

struct DirectionalLight
{
    float4 colourAmbient;
    float4 colourDiffuse;
    float pad;
    float3 direction;

};

cbuffer cbPerFrame
{
    DirectionalLight light;
    matrix CameraMatrix;
    matrix ViewProjectionMatrix;
};

StructuredBuffer<DirectionalLight> lightBuffer;
Texture2D ObjTexture;
SamplerState ObjSamplerState;

struct VS_INPUT
{
    float4 position: POSITION;
    float2 texCoord0: TEXCOORD0;
    float2 texCoord1: TEXCOORD1;
    float3 normal: NORMAL;

    float4 rowX: ROWX;
    float4 rowY: ROWY;
    float4 rowZ: ROWZ;
    float4 rowW: ROWW;
};



struct VOut
{
    float4 position : SV_POSITION;
    float2 texCoord : TEXCOORD;
    float3 normal: NORMAL;
};

VOut VShader (VS_INPUT input)
{
    VOut output;

    float4x4 world      = float4x4(input.rowX, input.rowY, input.rowZ, input.rowW);
    float4x4 MVP        = world * ViewProjectionMatrix;

    output.position     = mul (input.position, MVP);
    output.texCoord     = input.texCoord0;
    output.normal       = mul (input.normal, world);

    return output;

}

И вот как вычисляются камера и проекция вида:

this->m_FrameUniforms.Camera                = this->m_CameraView;
                this->m_FrameUniforms.ViewProjectionMatrix  = (this->m_CameraView * cameraViewProjectionMatrix);
                auto pUniformBufferPointer                      = this->m_pUniformBuffer->GetRawPointer ();
                this->m_pDeviceContext->UpdateSubresource (pUniformBufferPointer, 0, NULL, &this->m_PerObjectBuffer, 0, 0);
                this->m_pDeviceContext->VSSetConstantBuffers (0, 1, &pUniformBufferPointer);

1 Ответ

0 голосов
/ 22 февраля 2020

В итоге я сделал модификацию в шейдере. Вот окончательный код:

VOut VShader (VS_INPUT input)
{
    VOut output;

    float4x4 world      = float4x4(input.rowX, input.rowY, input.rowZ, input.rowW);
    float4x4 MVP        = mul(mul((ProjectionMatrix), transpose(CameraMatrix)), transpose(world));
    output.position     = mul (input.position, MVP);
    output.texCoord     = input.texCoord0;
    output.normal       = mul (input.normal, world);

    return output;

}

Были две вещи, которые помогли. Во-первых, я вспомнил, что HLSL имеет другой метод хранения матриц, чем математическая библиотека на стороне процессора, поэтому мне нужно было транспонировать свои матрицы. Во-вторых, кажется, что умножение двух матриц, таких как

matA * matB

, не то же самое, что умножение их, таких как

mul(matA, matB)
...