Jump to content
  • Advertisement
Sign in to follow this  

Vertex Shader and Animation Blending

This topic is 5194 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

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
	Vector3 position;
	Vector3 normal;
	DWORD color;
	float weight[4];
	unsigned int boneId[4];


// declaration

// values - boneweights and indices are just dummy values for testing value transfer
if(SUCCEEDED(tstvb->Lock(0, 0, (void**) &l_vertices, D3DLOCK_DISCARD)))
	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;


// shader
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 this post

Link to post
Share on other sites

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 this post

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

D3DXMATRIX skinMatrices[n]

// Set the matrices

m_Device->SetVertexShaderConstantF(firstRegisterIndex, skinMatrices, numberOfMatrices);

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

Share this post

Link to post
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 this post

Link to post
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 this post

Link to post
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 :)

Share this post

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

  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!