HLSL: Setting matrices

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

Recommended Posts

Hello,

I want to implement Skeletal animation with skinning on the GPU. I have my own Mesh class, which is subdivided into several SubMeshes (each SubMesh is a part of the geometry). The Mesh has a skeleton, which is just a hierarchy of bones/matrices. Only the SubMeshes are renderable.

Now if I want to render the Mesh, I put all SubMeshes into my RenderQueue. Each SubMesh is kinda like a render package and they do not know each other. Thus each SubMesh has to send its own Matrices to the Shader. For example lets say my Mesh has 5 Bones/Matrices and I have 2 Submeshes. SubMesh0 uses Matrices 0,1, and 3 and Submesh1 uses matrices 2 and 4.
Thus in the HLSL shader I have an array:
float4x4 mat[5];

and if I render SubMesh0 I just have to update mat[0], mat[1] and mat[3] (because the vertices of SubMesh0) will only index these 3 matrices.

First of all: Is my design ok?

Second: How can I set individual matrices in an HLSL array? I know there is the method ID3DXConstantTable::SetMatrixArray, but this only allows me to update a consecutive array of matrices. Is there a way to only update some matrices in the array?

Share on other sites

Hello,

I want to implement Skeletal animation with skinning on the GPU. I have my own Mesh class, which is subdivided into several SubMeshes (each SubMesh is a part of the geometry). The Mesh has a skeleton, which is just a hierarchy of bones/matrices. Only the SubMeshes are renderable.

Now if I want to render the Mesh, I put all SubMeshes into my RenderQueue. Each SubMesh is kinda like a render package and they do not know each other. Thus each SubMesh has to send its own Matrices to the Shader. For example lets say my Mesh has 5 Bones/Matrices and I have 2 Submeshes. SubMesh0 uses Matrices 0,1, and 3 and Submesh1 uses matrices 2 and 4.
Thus in the HLSL shader I have an array:
float4x4 mat[5];

and if I render SubMesh0 I just have to update mat[0], mat[1] and mat[3] (because the vertices of SubMesh0) will only index these 3 matrices.

First of all: Is my design ok?

Second: How can I set individual matrices in an HLSL array? I know there is the method ID3DXConstantTable::SetMatrixArray, but this only allows me to update a consecutive array of matrices. Is there a way to only update some matrices in the array?

- In D3D11 terms you matrices could be in constant buffers and in D3D11 terms you would update the whole constant buffer. Practically it is more efficient to update all the matrices at once.

I am using a system per "submesh" where I reindex all the bones, so that they are always starting from 0 and are consequentive. Since they are in sequence, they can be updated as an array. This way the mesh can have altogether a lot more bones than can fit in the shader constants, but the maximum bones is limit for each submesh, not for the mesh.

I hope you understand.

Cheers!

Share on other sites
Yes, I think I know what you mean. But for my first version (this is the first time ever I make something with animations) I want to stay with the "global" indices into the Mesh skeleton.

I forget to mention I am using DX9, so I do not have constant buffers. All I have is a float4x4 mats[10] in my HLSL shader.

Share on other sites

Yes, I think I know what you mean. But for my first version (this is the first time ever I make something with animations) I want to stay with the "global" indices into the Mesh skeleton.

I forget to mention I am using DX9, so I do not have constant buffers. All I have is a float4x4 mats[10] in my HLSL shader.

Yeah I figured that you are using D3D9, so you don't have constant buffers. My point is also that some day "float4x4 mats[10]" may not be enough.

You may use [color=#1C2837][size=2]SetMatrixArray to update only 1 matrix too.

Share on other sites

You may use [color=#1C2837][size=2]SetMatrixArray to update only 1 matrix too.

How should this work? The function only wants the name of the shader matrix and a number of matrices. It doesn't have a start offset, so I can't say "Update matrix 3 of the array", can I?

Share on other sites

[quote name='kauna' timestamp='1313493667' post='4849799']
You may use [color="#1C2837"]SetMatrixArray to update only 1 matrix too.

How should this work? The function only wants the name of the shader matrix and a number of matrices. It doesn't have a start offset, so I can't say "Update matrix 3 of the array", can I?
[/quote]

Good point. Well, to use SetMatrix[color=#1C2837][size=2], you'll need the handles to the individual matrices.
[color=#1C2837][size=2]

[color=#1C2837][size=2]Cheers!

Share on other sites

[quote name='schupf' timestamp='1313495877' post='4849810']
[quote name='kauna' timestamp='1313493667' post='4849799']
You may use [color="#1C2837"]SetMatrixArray to update only 1 matrix too.

How should this work? The function only wants the name of the shader matrix and a number of matrices. It doesn't have a start offset, so I can't say "Update matrix 3 of the array", can I?
[/quote]

Good point. Well, to use SetMatrix[color=#1C2837][size=2], you'll need the handles to the individual matrices.
[color=#1C2837][size=2]

[color=#1C2837][size=2]Cheers!
[/quote]
I have the feeling that its impossible to get the handle to an individual element inside an HLSL array. I guess there is no other way then just updating the whole matrix array for every SubMesh. Even though this means I update some matrices multiple times.

Share on other sites

I have the feeling that its impossible to get the handle to an individual element inside an HLSL array. I guess there is no other way then just updating the whole matrix array for every SubMesh. Even though this means I update some matrices multiple times.

Actually it isn't impossible.

[font=arial, sans-serif][size=2]pEffect->GetParameterByName(0, "[/font][color=#1C2837][size=2]mats[0][font=arial, sans-serif][size=2]");[/font]
[font=arial, sans-serif][size=2]pEffect->GetParameterByName(0, "[/font][color=#1C2837][size=2]mats[1][font=arial, sans-serif][size=2]");[/font]
[font="arial, sans-serif"]...[/font]
[font="arial, sans-serif"]
[/font]
[font="arial, sans-serif"]should give you the correct handles.[/font]
[font="arial, sans-serif"]
[/font]
[font="arial, sans-serif"]Best regards![/font]
[font="arial, sans-serif"]
[/font]

Share on other sites
Ah cool, sounds good, thanks!

Do you think updating individual matrices is worth the effort it? Or would it be faster to just update all bone matrices for every SubMesh?
In other words:
 // This SubMesh only needs bone matrices 0, 2 and 5 constantTable->SetMatrix("mat0", mat0); constantTable->SetMatrix("mat2", mat2); constantTable->SetMatrix("mat5", mat5); 
vs
 // Just update all! constantTable->SetMatrixArray("mats", mats, 10); 
What is faster?

Share on other sites

Ah cool, sounds good, thanks!

Do you think updating individual matrices is worth the effort it? Or would it be faster to just update all bone matrices for every SubMesh?
In other words:
 // This SubMesh only needs bone matrices 0, 2 and 5 constantTable->SetMatrix("mat0", mat0); constantTable->SetMatrix("mat2", mat2); constantTable->SetMatrix("mat5", mat5); 
vs
 // Just update all! constantTable->SetMatrixArray("mats", mats, 10); 
What is faster?

Which is faster depends on many factors. I'd say that you won't see a difference whichever method you'll decide to use. In general it is good to reduce D3D API calls (although here it is question of the effect api which is a bit different). Perhaps the code will scale up a bit better with the setmatrixarray.

Cheers!

1. 1
2. 2
3. 3
4. 4
frob
13
5. 5

• 16
• 13
• 20
• 12
• 19
• Forum Statistics

• Total Topics
632170
• Total Posts
3004547

×