1
\$\begingroup\$

I am learning HLSL and having trouble understanding how to pass matrices into the shaders to be able to perform the necessary operations within the shader to have the position values sent to the shaders placed in the correct place according to the view and projection matrices. I was going to place the viewMatrix and projMatrix data into the INPUT_ELEMENT_DESC array but then found that there is not a DXGI_FORMAT value to support a 4x4 float matrix. What is the correct way to pass the values of projMatrix and viewMatrix into the shader?

Thanks in advance

windowSource.cpp

    void BuildD3D(HWND hWnd){

    // create a struct to hold information about the swap chain
    DXGI_SWAP_CHAIN_DESC scd;

    // clear out the struct for use
    ZeroMemory(&scd, sizeof(DXGI_SWAP_CHAIN_DESC));

    // fill the swap chain description struct
    scd.BufferCount = 1;                                    // one back buffer
    scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;     // use 32-bit color
    scd.BufferDesc.Width = 800;
    scd.BufferDesc.Height = 600;
    scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;      // how swap chain is to be used
    scd.OutputWindow = hWnd;                                // the window to be used
    scd.SampleDesc.Count = 4;                               // how many multisamples
    scd.Windowed = TRUE;                                    // windowed/full-screen mode
    scd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;

    // create a device, device context and swap chain using the information in the scd struct
    D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, NULL, NULL, NULL, D3D11_SDK_VERSION, &scd, &swapchain, &dev, NULL, &devContext);

    // Get Back Buffer information
    ID3D11Texture2D *pBackbuffer;
    swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackbuffer);

    // Target rendering to the backbuffer that was just defined
    dev->CreateRenderTargetView(pBackbuffer, NULL, &backbuffer);

    // Release the data that was rendered to the backbuffer.
    pBackbuffer->Release();

    // Define the backbuffer as the rendering target
    devContext->OMSetRenderTargets(1, &backbuffer, NULL);

    // Define Viewport
    D3D11_VIEWPORT viewport;
    ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT));
    viewport.TopLeftX = 0;
    viewport.TopLeftY = 0;
    viewport.Width = 800;
    viewport.Height = 600;

    devContext->RSSetViewports(1, &viewport);

    // Set Up Projection Matrix
    projMatrix = DirectX::XMMatrixPerspectiveFovLH(DirectX::XMConvertToRadians(45.0f), 1920.0f, 1.0f, 200.0f);

    // Set Up View Matrix
    DirectX::XMVECTOR eyePos = {0.0f, 10.0f, 0.0f};
    DirectX::XMVECTOR focusPos = {0.0f, 0.0f, 0.0f};
    DirectX::XMVECTOR upPos = { 0.0f, 1.0f, 0.0f };

    // Bind LookAt matrix to viewmatrix
    viewMatrix = DirectX::XMMatrixLookAtLH(eyePos, focusPos, upPos);



    BuildPipeline();
    ParseGraphics();
}

void RenderFrame(void) {

    // Clear BackBuffer to a color
    devContext->ClearRenderTargetView(backbuffer, D3DXCOLOR(0.0f, 0.2f, 0.4f, 1.0f));

    // select which vertex buffer to display
    UINT stride = sizeof(Vertex);
    UINT offset = 0;
    devContext->IASetVertexBuffers(0, 1, &pVBuffer, &stride, &offset);

    // select which primtive type we are using
    devContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

    // draw the vertex buffer to the back buffer
    devContext->Draw(6, 0);

    // swap buffers
    swapchain->Present(0, 0);
}

void ParseGraphics() {

    // Create Vertex Buffer
    D3D11_BUFFER_DESC bd;
    ZeroMemory(&bd, sizeof(bd));

    bd.Usage = D3D11_USAGE_DYNAMIC;
    bd.ByteWidth = sizeof(Vertex) * 6;
    bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
    bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;

    dev->CreateBuffer(&bd, NULL, &pVBuffer);

    // copy vertices into buffer
    D3D11_MAPPED_SUBRESOURCE msr;
    devContext->Map(pVBuffer, NULL, D3D11_MAP_WRITE_DISCARD, NULL, &msr);
    memcpy(msr.pData, square, sizeof(square));
    devContext->Unmap(pVBuffer, NULL);

}

void BuildPipeline() {
    // Load and Compile Shaders
    ID3D10Blob *VS, *PS;
    D3DX11CompileFromFile(L"shaders.shader", 0, 0, "VShader", "vs_5_0", 0, 0, 0, &VS, 0, 0);
    D3DX11CompileFromFile(L"shaders.shader", 0, 0, "PShader", "ps_5_0", 0, 0, 0, &PS, 0, 0);

    // Create shaders from the data in the Blobs Buffer
    dev->CreateVertexShader(VS->GetBufferPointer(), VS->GetBufferSize(), NULL, &pVS);
    dev->CreatePixelShader(PS->GetBufferPointer(), PS->GetBufferSize(), NULL, &pPS);

    // Apply Shaders to the device context
    devContext->VSSetShader(pVS, 0, 0);
    devContext->PSSetShader(pPS, 0, 0);

    // Define the layout of the input given to the shaders
    D3D11_INPUT_ELEMENT_DESC ied[] =
    {
        {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
        {"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 3 * sizeof(float), D3D11_INPUT_PER_VERTEX_DATA, 0},
        // Maybe pass projection matrix into shader here???

    };

    dev->CreateInputLayout(ied, 2, VS->GetBufferPointer(), VS->GetBufferSize(), &pLayout);
    devContext->IASetInputLayout(pLayout);

}

shader.shaders

    struct VOut
{
    float4 position : SV_POSITION;
    float4 color : COLOR;
    float4x4 fMatrix;
};

VOut VShader(float4 position : POSITION, float4 color : COLOR)
{
    VOut output;

    output.position = position;
    output.color = color;

    return output;
}


float4 PShader(float4 position : SV_POSITION, float4 color : COLOR) : SV_TARGET
{
    return color;
}
\$\endgroup\$
  • 1
    \$\begingroup\$ As you are new to DirectX, I recommend you take a look at DirectX Tool Kit and it's tutorials in particular. \$\endgroup\$ – Chuck Walbourn Dec 1 '16 at 18:09
2
\$\begingroup\$

Yes, there is no way to pass a float4x4 to an input description. By doing that you'd be passing a matrix for every vertex to your vertex shader. This is bad practice unless you need to bind a different matrix for every vertex that you input. It's a better idea to create and bind a constant buffer that has that matrix. You only have to bind that constant buffer once per frame and it will be a lot faster since you'll be reusing that matrix.

Here's a straightforward example from Microsoft on creating and using a constant buffer: https://msdn.microsoft.com/en-us/library/windows/desktop/ff476896%28v=vs.85%29.aspx

Here's some more advanced reading on buffers in DX11 in general: https://msdn.microsoft.com/en-us/library/windows/desktop/ff476898%28v=vs.85%29.aspx

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.