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

Recommended Posts

I need some help on Animation Blending with vertexshaders. I have chosen to write my own shader, and I have now been studying the (few!) texts out there on them, the last 4-5 days. So I began tinkering with a shader, to test how I transferred parameters to it, and more specifically arrayed parameters in the form of weights and indices. Here is what I got:
// vertex structure
struct TSTVERTEX
{
Vector3 position;
Vector3 normal;
DWORD color;
float weight[4];
unsigned int boneId[4];
};

|
|

// declaration
D3DVERTEXELEMENT9 decl[] =
{
{0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},		// 3*4=12
{0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},			// 3*4=12
{0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},		// 1*4=4
{0, 28, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDWEIGHT, 0},	// 4*4=16
{0, 44, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDINDICES, 0},	// 4*4=16
D3DDECL_END()
};

// values - boneweights and indices are just dummy values for testing value transfer
{
l_vertices[0].position = Vector3(-400.0f, -200.0f, 200.0f);
l_vertices[1].position = Vector3(-400.0f, 200.0f, 200.0f);
l_vertices[2].position = Vector3(0.0f, -200.0f, 200.0f);

l_vertices[0].normal = Vector3(0.0f, 0.0f, -1.0f);
l_vertices[1].normal = Vector3(0.0f, 0.0f, -1.0f);
l_vertices[2].normal = Vector3(0.0f, 0.0f, -1.0f);

l_vertices[0].color = D3DCOLOR_XRGB(0,0,255);
l_vertices[1].color = D3DCOLOR_XRGB(0,255,0);
l_vertices[2].color = D3DCOLOR_XRGB(255,0,0);

l_vertices[0].weight[0] = 0.1f;
l_vertices[0].weight[1] = 0.2f;
l_vertices[0].weight[2] = 0.3f;
l_vertices[0].weight[3] = 0.4f;

l_vertices[1].weight[0] = 0.5f;
l_vertices[1].weight[1] = 0.6f;
l_vertices[1].weight[2] = 0.7f;
l_vertices[1].weight[3] = 0.8f;

l_vertices[2].weight[0] = 0.9f;
l_vertices[2].weight[1] = 0.11f;
l_vertices[2].weight[2] = 0.22f;
l_vertices[2].weight[3] = 0.33f;

l_vertices[0].boneId[0] = 2;
l_vertices[0].boneId[1] = 3;
l_vertices[0].boneId[2] = 4;
l_vertices[0].boneId[3] = 4;

l_vertices[1].boneId[0] = 5;
l_vertices[1].boneId[1] = 6;
l_vertices[1].boneId[2] = 7;
l_vertices[1].boneId[3] = 8;

l_vertices[2].boneId[0] = 9;
l_vertices[2].boneId[1] = 11;
l_vertices[2].boneId[2] = 22;
l_vertices[2].boneId[3] = 33;

tstvb->Unlock();
}

VS_OUTPUT VS(float4 Pos : POSITION, float3 Normal : NORMAL, float4 Weight : BLENDWEIGHT, int4 Index : BLENDINDICES)
{
VS_OUTPUT Out = (VS_OUTPUT)0;
Out.Pos = mul(Pos, matWorldViewProj);				// transform Position
Out.Light = vecLightDir;							// L
//    float3 PosWorld = normalize(mul(Pos, matWorld));
Out.View = vecEye; // - PosWorld;						// V
Out.Norm = mul(Normal, matWorld);					// N

//
// testing purpose alone: I see if the right values go in
Out.Pos[0] = Weight[0];
Out.Pos[1] = Weight[1];
Out.Pos[2] = Weight[2];

Out.Pos[0] = Index[0];
Out.Pos[1] = Index[1];
Out.Pos[2] = Index[2];
// /end testing purpose
//

return Out;
}


Almost everything works perfectly! All the weights are good, but when I get to the indices, I get a problem: Only the first index works, all successive indices will just be zero, no matter what their value is (even the same value as the first index). How come? Does the array coming in from the application not match the int4 type? I was looking for a BYTE type to match the declaration, but could find none... Can that be the answer? ------------------------------------------------------------------- Btw, if you have been through skinning on a shader, do you know the best way to transfer all the bone matrices? Would you just transfer them to a global array of matrices in the shader? Do you have any sample code to do this? Sorry if I sound a bit newbie on this, it IS pretty new to me, and I could find absolutely no resources on shader skinning in HLSL... ------------------------------------------------------------------- PS: Just so you know: In my skinning, I do *not* use D3DX functionality (like the D3DXMESH) - I have built my own mesh and animation system, that runs in software atm, and now I want to put it in hardware. [Edited by - Mercenarey on July 30, 2005 4:25:52 AM]

Share on other sites
Hi,

UBYTE4 = 1 DWORD containing all 4 indices, you are using unsigned int[4] that means 4 DWORDs... Make it a unsigned char[4] and it should work.

Share on other sites
For your second question, have something like:

D3DXMATRIX skinMatrices[n]

// Set the matrices

You should try to send them all at once to reduce the number of SetVertexShaderConstant*.

Share on other sites
thanx alot aldenar. i will test it tomorrow when Im home again.

One last question:
What does the array of matrices look like on the shaderside?
Will I have to hardcode a max-size?
And then maybe have a matrixcount?

As far as I know, there is no dynamic array allocations in shaders, right?

Share on other sites
In HLSL, you'll probably have something like:

uniform float4x4 g_mSkinMatrices[MAX_BONES];

From what I remember, you must specify the size of the array (makes sense since the compiler will have to know how many constant register to allocate for that variable).

It doesn't mean that you have to upload all matrices if you know you only need a few. Also, if you make sure the compiler didn't make use of the registers following the last matrix, then you could probably use more than the maximum you specified, but that's not always a safe thing to do.

Share on other sites
Thanx alot. Everything works like a charm!

I would strongly advice against exceeding the memory that you ordered. Just on general principle :)

• 10
• 13
• 14
• 18
• 15