Sign in to follow this  
8up tuotlo

Help with Skinned Mesh shader

Recommended Posts

I am use this HLSL D3DXEFFECT shader to draw my animated model in my application.

Shader model 3.0.

 

[source]

 

//-- Lighting ------
struct Direct
{
float3 pos;
float3 col;
};
Direct Dl[2];
float3 Al;
//------------------
 
float3 eye;
 
float Sp;
 
float4x4 BM[60];
 
float4x4 Gm;
float4x4 Wm;
 
struct VS_in
{
float4 Pos  : POSITION;
float3 Norm : NORMAL;
float2 Tex  : TEXCOORD0;
float4 bi   : BLENDINDICES0;
float4 bw : BLENDWEIGHT0;
};
 
struct VS_out
{
float4 Pos  : POSITION;
float3 Norm : TEXCOORD1;
float2 Tex  : TEXCOORD0;
float3 wPos : TEXCOORD2;
float3 v    : TEXCOORD3;
};
 
VS_out vs(VS_in In)
{
VS_out Out;
 
float4x4 blend = BM[In.bi.x]*In.bw.x + BM[In.bi.y]*In.bw.y + BM[In.bi.z]*In.bw.z + BM[In.bi.w]*In.bw.w;
 
float4 SkinPos, SkinNorm;
 
SkinPos.x = (In.Pos.x * blend._11)+(In.Pos.z * blend._21)+(In.Pos.y * blend._31)+(blend._41);
SkinPos.z = (In.Pos.x * blend._12)+(In.Pos.z * blend._22)+(In.Pos.y * blend._32)+(blend._42);
SkinPos.y = (In.Pos.x * blend._13)+(In.Pos.z * blend._23)+(In.Pos.y * blend._33)+(blend._43);
SkinPos.w = 1.0f;
 
SkinNorm.x = (In.Norm.x * blend._11)+(In.Norm.z * blend._21)+(In.Norm.y * blend._31);
SkinNorm.z = (In.Norm.x * blend._12)+(In.Norm.z * blend._22)+(In.Norm.y * blend._32);
SkinNorm.y = (In.Norm.x * blend._13)+(In.Norm.z * blend._23)+(In.Norm.y * blend._33);
SkinNorm.w = 1.0f;
 
Out.Pos = mul(SkinPos, Gm);
Out.Tex = In.Tex;
Out.Norm = normalize(mul(SkinNorm, (float3x3)Wm));
Out.wPos = mul(SkinPos, Wm);
Out.v = eye.xyz - Out.wPos;
 
return Out;
}
 
float3 light(float3 n, float3 v)
{
float  nDotL[2];
 
nDotL[0] = saturate(dot(n, normalize(Dl[0].pos)));
nDotL[1] = saturate(dot(n, normalize(Dl[1].pos)));
 
float3 ret = Dl[0].col * nDotL[0] + Dl[1].col * nDotL[1] + Al;
/*+ (Dl[0].col * ((nDotL[0] == 0.0f) ? 0.0f : pow((saturate(dot(n, normalize(Dl[0].pos + v)))), Sp)));*/
 
return ret;
}
 
float4 ps(VS_out In) : COLOR0
{
return float4(light(normalize(In.Norm), normalize(In.v)), 1);
}
 
technique Standart
    pass P0
    {          
        VertexShader = compile vs_3_0 vs();
PixelShader  = compile ps_3_0 ps();
    }
}
 

[/source]

 

it is maximum of 60 bones by:

 

float4x4 BM[60];

 

when i try to set it to:

 

float4x4 BM[120];

 

shader not works.

 

Who knows why?

Can it be set to 120, and how if it is possible?

Edited by 8up tuotlo

Share this post


Link to post
Share on other sites

You're limited to 256 registers (float4) for constants. 60 * 4 = 240, which is okay. 120 * 4 > 256.

 

EDIT: For clarity - float4x4 is float4 times 4 = 4 registers. Also, beware, with 60 matrices taking up 240 registers, you're limited to just 16 additional constants.

 

float3 eye; // 1 register
float Sp; // 1 register
float4x4 BM[60]; // 240 registers
float4x4 Gm; // 4 registers
float4x4 Wm; // 4 registers

 

for 250 registers (of 256 available).

Edited by Buckeye

Share this post


Link to post
Share on other sites

Yup, up to 1024 bones if you do it naively. "Limitless" if you're doing it smart wink.png

 

But since you use SM3 you could use vertex texture fetch: Using a texture to hold your bone matrices and use several tex2Dlod in the vertex shader to load them.

 

There are other ways to address this limit: Split the mesh, use affine transformations (3x4 matrices), quaternions... Here's a recent discussion.

 

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this