• Advertisement
Sign in to follow this  

Problem passing matrices to shader

This topic is 2157 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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.

Share this post


Link to post
Share on other sites
Advertisement
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?

Share this post


Link to post
Share on other sites

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?

Share this post


Link to post
Share on other sites
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!

Share this post


Link to post
Share on other sites

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!

Share this post


Link to post
Share on other sites
Yay! thanks everyone. Transposing the matrices before passing them to the video card did the trick!

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement