Skip to main content
GameDev.net gamedev.net
🔒 Locked

Problem passing matrices to shader

Started by Joakitex Feb 27, 2012 at 7:03 AM 5 replies 7.9k views
Original Post
Joakitex
Joakitex
Hello there. I recently decided to port my engine from D3D10 to D3D11 and I am having serious problems when trying to pass the world, view and projection matrices to the GPU. I had been using the ID3D10Effect until now, which allowed me to easily set variables in the shader. Now I am using constant buffers and I am not able to pass the matrices to the video card. I've read a lot of tutorials but I don't seem to find what's wrong with my code.

This is the function where I set the buffer:
[spoiler]
bool CShader::CreateConstantBuffers(ID3D11Device *pDev)
{
D3D11_BUFFER_DESC matrixDesc;

matrixDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
matrixDesc.ByteWidth = sizeof(MatrixType);
matrixDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
matrixDesc.MiscFlags = 0;
matrixDesc.Usage = D3D11_USAGE_DYNAMIC;
matrixDesc.StructureByteStride = 0;

if ( FAILED(pDev->CreateBuffer(&matrixDesc, 0, &pMatrixBuffer)) ) return
::Error(L"Unable to create constant buffer");

return true;
}
[/spoiler]


This two functions do the rendering (the last one is the problem):
[spoiler]
bool CShader::RenderObject(ID3D11DeviceContext *pDevCon, ID3D11Device *pDev,
CModel *model, CCamera *camera, unsigned int stride, unsigned int offset)
{
// Send information to the video card
pDevCon->IASetVertexBuffers(0, 1, model->ppGetVertexBuffer(), &stride, &offset);
pDevCon->IASetIndexBuffer(model->pGetIndexBuffer(), DXGI_FORMAT_R32_UINT, 0);
pDevCon->IASetInputLayout(pInputLayout);

if (! SetShaderVariables(pDevCon, model, 0, camera, RENDER_MODE_MODEL) ) return false;

pDevCon->DrawIndexed(model->GetNumIndices(), 0, 0);
return true;
}



bool CShader::SetShaderVariables(ID3D11DeviceContext *pDevCon, CModel *model, CSprite *sprite, CCamera *camera, unsigned int renderMode)
{
D3D11_MAPPED_SUBRESOURCE mappedSubResource;
if ( FAILED(pDevCon->Map(pMatrixBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedSubResource)) )
return ::Error(L"Could not lock the buffer");

MatrixType *pData = (MatrixType*)mappedSubResource.pData;

pData->World = model->worldMatrix;
pData->View = camera->viewMatrix;
pData->Projection = camera->projectionMatrix;

pDevCon->Unmap(pMatrixBuffer, 0);

pDevCon->VSSetConstantBuffers(0, 1, &pMatrixBuffer);
pDevCon->VSSetShader(pVertexShader, 0, 0);
pDevCon->PSSetShader(pPixelShader, 0, 0);
return true;
}
[/spoiler]

This is my matrix struct:
[spoiler]
struct MatrixType
{
D3DXMATRIX World;
D3DXMATRIX View;
D3DXMATRIX Projection;
};
[/spoiler]

And this is my shader:
[spoiler]

cbuffer cbPerObj : register ( b0 )
{
matrix World : packoffset ( c0 );
matrix View : packoffset ( c4 );
matrix Projection : packoffset ( c8 );
}
struct VS_INPUT
{
float4 Pos : POSITION;
float3 Normal : NORMAL;
float2 TexCoord : TEXCOORD;
};
struct PS_INPUT
{
float4 Pos : SV_POSITION;
float2 TexCoord : TEXCOORD0;
float3 Normal : NORMAL;
float4 Color : COLOR0;
};
PS_INPUT VS( VS_INPUT input )
{
input.Pos.w = 1.0f;
PS_INPUT output = (PS_INPUT)0;
output.Pos = mul( input.Pos, World );
output.Pos = mul( output.Pos, View );
output.Pos = mul( output.Pos, Projection );
output.TexCoord = input.TexCoord;
return output;
}
float4 PS( PS_INPUT input ) : SV_TARGET
{
return float4(1.0f, 0.0f, 0.0f, 1.0f);
}
[/spoiler]


Here's some PIX info
[spoiler]
nlQaS.jpg
V4Qcc.jpgMNvFh.jpg[/spoiler]

Thanks in advance.
relaxok
relaxok
I do something similar, in D3D11 - differences are:

-- using XMFLOAT4X4 for the matrix variable format
-- loading to XMMATRIX and transposing with XMMatrixTranspose before storing back to XMFLOAT4X4 and mapping to cbuffer
-- not using packoffset in the cbuffer declaration
-- register(cb0) instead of register(b0) for the cbuffer

I'll look closer at what you did later, but those are differences I've found and mine works fine..

Also, your PIX doesn't exactly show the problem, for me - are those cbuffer variables in the debugger not reasonable? they're definitely not zeroed out or something.. in what way are they wrong?
Joakitex
Joakitex

I do something similar, in D3D11 - differences are:

-- using XMFLOAT4X4 for the matrix variable format
-- loading to XMMATRIX and transposing with XMMatrixTranspose before storing back to XMFLOAT4X4 and mapping to cbuffer
-- not using packoffset in the cbuffer declaration
-- register(cb0) instead of register(b0) for the cbuffer

I'll look closer at what you did later, but those are differences I've found and mine works fine..

Also, your PIX doesn't exactly show the problem, for me - are those cbuffer variables in the debugger not reasonable? they're definitely not zeroed out or something.. in what way are they wrong?


Thanks, I'll try that out.

About the PIX thing, I am concerned about the pre and post Vertex shader thing, shouldn't the post Vertex shader output be equal or at least similar to the pre Vertex shader output?
kauna
kauna
Hi,

In my opinion the PIX screenshot tells exactly the problem. Your matrices aren't transposed. You should transpose the matrices you pass to the constant buffer.
The PIX shows that the vertex shaders input geometry is correct. Otherwise, relaxok has made good points about the code.

Cheers!
kauna
kauna

About the PIX thing, I am concerned about the pre and post Vertex shader thing, shouldn't the post Vertex shader output be equal or at least similar to the pre Vertex shader output?


The post vertex shader output is the position which has gone through world-view-projection transforms but not yet divided by w. If the post-vs box is empty it means that nothing will get drawn to the screen. The view port box contains the position divided by w which puts the mesh in perspective.

Best regards!
Joakitex
Joakitex
Yay! thanks everyone. Transposing the matrices before passing them to the video card did the trick!
MJP
MJP
Just so you know, you need to transpose because by default HLSL shaders will expect column-major matrices while most math libraries will use row-major matrices. You can change this behavior by declaring your matrices with the "row_major" modifier in your constant buffer, or by passing D3D10_SHADER_PACK_MATRIX_ROW_MAJOR when compiling your shader.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.