• Create Account

## How to debug an fx file

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

26 replies to this topic

Posted 17 March 2014 - 08:36 AM

Hi,

Can anyone tell me how to debug an fx file ? I have tried using gpu perfstudio, PIX and visual studio ultimate 2013 but all of them gives me an error when I try to debug..

### #2Tasaq  Members

Posted 17 March 2014 - 11:13 AM

Be a little bit more specific, what kind of error do you get? Which version of DirectX, 9 or newer?

For visual studio ultimate 2013, alt+f5 will start application in diagnstic mode, there you press print screen (not sure if was prt sc), close application and you get a lot of stuff. You either need to go through even list to find draw call you want to debug or pick pixel and check it's history.

Note:

What I wrote here is from memory, I mostly use built in profiler instinctively For more accurate information, check this link:

http://msdn.microsoft.com/en-us/library/hh873207.aspx#fbid=cfoh58W0Z1l

Posted 18 March 2014 - 11:37 AM

I used that graphics debugger and most recently I have noticed one thing in the output window. This message is kept showing the whole time :

1. ID3D11DeviceContext::DrawIndexed: Input Assembler - Vertex Shader linkage error: Signatures between stages are incompatible. The input stage requires Semantic/Index (WEIGHTS,0) as input, but it is not provided by the output stage.

2. ID3D11DeviceContext::DrawIndexed: Input Assembler - Vertex Shader linkage error: Signatures between stages are incompatible. The input stage requires Semantic/Index (BONEINDICES,0) as input, but it is not provided by the output stage.

My vertex structure is :

struct PosNormalTexSkin
{
XMFLOAT3 Pos;
XMFLOAT3 Normal;
XMFLOAT2 Tex;
float Weights[3];
UINT BoneIndices[4];
};


And my input layout is :

const D3D11_INPUT_ELEMENT_DESC InputLayoutDesc::PosNormalTexSkin[5] =
{
{"POSITION",     0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0,  D3D11_INPUT_PER_VERTEX_DATA, 0},
{"NORMAL",       0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0},
{"TEXCOORD",     0, DXGI_FORMAT_R32G32_FLOAT,    0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0},
{"WEIGHTS",      0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 32, D3D11_INPUT_PER_VERTEX_DATA, 0},
{"BONEINDICES",  0, DXGI_FORMAT_R32G32B32A32_UINT, 0, 44, D3D11_INPUT_PER_VERTEX_DATA, 0}
};

And my skinning code is :

# include "LightHelper.fx"

cbuffer cbPerFrame
{
DirectionalLight gDirLights[3];
float3 gEyePosW;
float gFogStart;
float gFogRange;
float4 gFogColor;
};

cbuffer cbPerObject
{
float4x4 gWorld;
float4x4 gWorldInvTranspose;
float4x4 gWorldViewProj;
float4x4 gTexTransform;
Material gMaterial;
};

cbuffer cbSkinned
{
float4x4 gBoneTransforms[96];
};

Texture2D gDiffuseMap;

SamplerState samAnisotropic
{
Filter = ANISOTROPIC;
MaxAnisotropy = 4;

};

struct VertexIn
{
float3 PosL : POSITION;
float3 NormalL : NORMAL;
float2 Tex : TEXCOORD;
};

struct SkinnedVertexIn
{
float3 PosL : POSITION;
float3 NormalL : NORMAL;
float2 Tex : TEXCOORD;
float3 Weights : WEIGHTS;
uint4 BoneIndices : BONEINDICES;
};

struct VertexOut
{
float4 PosH : SV_POSITION;
float3 PosW : POSITION;
float3 NormalW : NORMAL;
float2 Tex : TEXCOORD;
};

VertexOut VS(VertexIn vin)
{
VertexOut vout;

vout.PosW = mul(float4(vin.PosL, 1.0f), gWorld).xyz;
vout.NormalW = mul(vin.NormalL, (float3x3) gWorldInvTranspose);

vout.PosH = mul(float4(vin.PosL, 1.0f), gWorldViewProj);
vout.Tex = mul(float4(vin.Tex, 0.0f, 1.0f), gTexTransform).xy;

return vout;
}

VertexOut SkinnedVS(SkinnedVertexIn vin)
{
VertexOut vout;

float weights[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
weights[0] = vin.Weights.x;
weights[1] = vin.Weights.y;
weights[2] = vin.Weights.z;
weights[3] = 1.0f - vin.Weights.x - vin.Weights.y - vin.Weights.z;

float3 posL = float3(0.0f, 0.0f, 0.0f);
float3 normalL = float3(0.0f, 0.0f, 0.0f);

for (int i = 0; i < 4; i++)
{
posL += weights[i] * mul(float4(vin.PosL, 1.0f), gBoneTransforms[vin.BoneIndices[i]]).xyz;
normalL += weights[i] * mul(vin.NormalL, (float3x3)gBoneTransforms[vin.BoneIndices[i]]).xyz;
}

vout.PosW = mul(float4(posL, 1.0f), gWorld).xyz;
vout.NormalW = mul(normalL, (float3x3)gWorldInvTranspose);
vout.PosH = mul(float4(posL, 1.0f), gWorldViewProj);
vout.Tex = mul(float4(vin.Tex, 0.0f, 1.0f), gTexTransform).xy;

return vout;
}

float4 PS(VertexOut pin, uniform int gLightCount, uniform bool gUseTexure, uniform bool gAlphaClip, uniform bool gFogEnabled) : SV_Target
{
// Interpolating normal can unnormalize it, so normalize it.
pin.NormalW = normalize(pin.NormalW);

// The toEye vector is used in lighting.
float3 toEye = gEyePosW - pin.PosW;

// Cache the distance to the eye from this surface point.
float distToEye = length(toEye);

// Normalize.
toEye /= distToEye;

// Default to multiplicative identity.
float4 texColor = float4(1, 1, 1, 1);
if (gUseTexure)
{
// Sample texture.
texColor = gDiffuseMap.Sample(samAnisotropic, pin.Tex);

if (gAlphaClip)
{
// Discard pixel if texture alpha < 0.1.  Note that we do this
// test as soon as possible so that we can potentially exit the shader
// early, thereby skipping the rest of the shader code.
clip(texColor.a - 0.1f);
}
}

//
// Lighting.
//

float4 litColor = texColor;
if (gLightCount > 0)
{
float4 ambient = float4(0.0f, 0.0f, 0.0f, 0.0f);
float4 diffuse = float4(0.0f, 0.0f, 0.0f, 0.0f);
float4 spec = float4(0.0f, 0.0f, 0.0f, 0.0f);

// Sum the light contribution from each light source.
[unroll]
for (int i = 0; i < gLightCount; ++i)
{
float4 A, D, S;
ComputeDirectionalLight(gMaterial, gDirLights[i], pin.NormalW, toEye,
A, D, S);

ambient += A;
diffuse += D;
spec += S;
}

litColor = texColor*(ambient + diffuse) + spec;
}

//
// Fogging
//

if (gFogEnabled)
{
float fogLerp = saturate((distToEye - gFogStart) / gFogRange);

// Blend the fog color and the lit color.
litColor = lerp(litColor, gFogColor, fogLerp);
}

// Common to take alpha from diffuse material and texture.
litColor.a = gMaterial.Diffuse.a * texColor.a;

return litColor;
}

technique11 Light1
{
pass P0
{
}
}

technique11 Light2
{
pass P0
{
}
}

technique11 Light3
{
pass P0
{
}
}

technique11 Light0Tex
{
pass P0
{
}
}

technique11 Light1Tex
{
pass P0
{
}
}

technique11 Light2Tex
{
pass P0
{
}
}

technique11 Light3Tex
{
pass P0
{
}
}

technique11 Light0TexAlphaClip
{
pass P0
{
}
}

technique11 Light1TexAlphaClip
{
pass P0
{
}
}

technique11 Light2TexAlphaClip
{
pass P0
{
}
}

technique11 Light3TexAlphaClip
{
pass P0
{
}
}

technique11 Light1Fog
{
pass P0
{
}
}

technique11 Light2Fog
{
pass P0
{
}
}

technique11 Light3Fog
{
pass P0
{
}
}

technique11 Light0TexFog
{
pass P0
{
}
}

technique11 Light1TexFog
{
pass P0
{
}
}

technique11 Light2TexFog
{
pass P0
{
}
}

technique11 Light3TexFog
{
pass P0
{
}
}

technique11 Light0TexAlphaClipFog
{
pass P0
{
}
}

technique11 Light1TexAlphaClipFog
{
pass P0
{
}
}

technique11 Light2TexAlphaClipFog
{
pass P0
{
}
}

technique11 Light3TexAlphaClipFog
{
pass P0
{
}
}

technique11 Light1Reflect
{
pass P0
{
}
}

technique11 Light2Reflect
{
pass P0
{
}
}

technique11 Light3Reflect
{
pass P0
{
}
}

technique11 Light0TexReflect
{
pass P0
{
}
}

technique11 Light1TexReflect
{
pass P0
{
}
}

technique11 Light2TexReflect
{
pass P0
{
}
}

technique11 Light3TexReflect
{
pass P0
{
}
}

technique11 Light0TexAlphaClipReflect
{
pass P0
{
}
}

technique11 Light1TexAlphaClipReflect
{
pass P0
{
}
}

technique11 Light2TexAlphaClipReflect
{
pass P0
{
}
}

technique11 Light3TexAlphaClipReflect
{
pass P0
{
}
}

technique11 Light1FogReflect
{
pass P0
{
}
}

technique11 Light2FogReflect
{
pass P0
{
}
}

technique11 Light3FogReflect
{
pass P0
{
}
}

technique11 Light0TexFogReflect
{
pass P0
{
}
}

technique11 Light1TexFogReflect
{
pass P0
{
}
}

technique11 Light2TexFogReflect
{
pass P0
{
}
}

technique11 Light3TexFogReflect
{
pass P0
{
}
}

technique11 Light0TexAlphaClipFogReflect
{
pass P0
{
}
}

technique11 Light1TexAlphaClipFogReflect
{
pass P0
{
}
}

technique11 Light2TexAlphaClipFogReflect
{
pass P0
{
}
}

technique11 Light3TexAlphaClipFogReflect
{
pass P0
{
}
}

technique11 Light1Skinned
{
pass P0
{
}
}

technique11 Light2Skinned
{
pass P0
{
}
}

technique11 Light3Skinned
{
pass P0
{
}
}

technique11 Light0TexSkinned
{
pass P0
{
}
}

technique11 Light1TexSkinned
{
pass P0
{
}
}

technique11 Light2TexSkinned
{
pass P0
{
}
}

technique11 Light3TexSkinned
{
pass P0
{
}
}

technique11 Light0TexAlphaClipSkinned
{
pass P0
{
}
}

technique11 Light1TexAlphaClipSkinned
{
pass P0
{
}
}

technique11 Light2TexAlphaClipSkinned
{
pass P0
{
}
}

technique11 Light3TexAlphaClipSkinned
{
pass P0
{
}
}

technique11 Light1FogSkinned
{
pass P0
{
}
}

technique11 Light2FogSkinned
{
pass P0
{
}
}

technique11 Light3FogSkinned
{
pass P0
{
}
}

technique11 Light0TexFogSkinned
{
pass P0
{
}
}

technique11 Light1TexFogSkinned
{
pass P0
{
}
}

technique11 Light2TexFogSkinned
{
pass P0
{
}
}

technique11 Light3TexFogSkinned
{
pass P0
{
}
}

technique11 Light0TexAlphaClipFogSkinned
{
pass P0
{
}
}

technique11 Light1TexAlphaClipFogSkinned
{
pass P0
{
}
}

technique11 Light2TexAlphaClipFogSkinned
{
pass P0
{
}
}

technique11 Light3TexAlphaClipFogSkinned
{
pass P0
{
}
}

technique11 Light1ReflectSkinned
{
pass P0
{
}
}

technique11 Light2ReflectSkinned
{
pass P0
{
}
}

technique11 Light3ReflectSkinned
{
pass P0
{
}
}

technique11 Light0TexReflectSkinned
{
pass P0
{
}
}

technique11 Light1TexReflectSkinned
{
pass P0
{
}
}

technique11 Light2TexReflectSkinned
{
pass P0
{
}
}

technique11 Light3TexReflectSkinned
{
pass P0
{
}
}

technique11 Light0TexAlphaClipReflectSkinned
{
pass P0
{
}
}

technique11 Light1TexAlphaClipReflectSkinned
{
pass P0
{
}
}

technique11 Light2TexAlphaClipReflectSkinned
{
pass P0
{
}
}

technique11 Light3TexAlphaClipReflectSkinned
{
pass P0
{
}
}

technique11 Light1FogReflectSkinned
{
pass P0
{
}
}

technique11 Light2FogReflectSkinned
{
pass P0
{
}
}

technique11 Light3FogReflectSkinned
{
pass P0
{
}
}

technique11 Light0TexFogReflectSkinned
{
pass P0
{
}
}

technique11 Light1TexFogReflectSkinned
{
pass P0
{
}
}

technique11 Light2TexFogReflectSkinned
{
pass P0
{
}
}

technique11 Light3TexFogReflectSkinned
{
pass P0
{
}
}

technique11 Light0TexAlphaClipFogReflectSkinned
{
pass P0
{
}
}

technique11 Light1TexAlphaClipFogReflectSkinned
{
pass P0
{
}
}

technique11 Light2TexAlphaClipFogReflectSkinned
{
pass P0
{
}
}

technique11 Light3TexAlphaClipFogReflectSkinned
{
pass P0
{
}
}


I guess the problem might lie in the SkinnedVertexIn.

And one more thing : If I try to debug the shader it says failed to generate shader trace and therefore it is unable to debug shader.

Edit : I cannot see the Pixel shader stage in the graphics pipline .

Edited by Saad Manzur, 18 March 2014 - 12:08 PM.

### #4unbird  Members

Posted 19 March 2014 - 03:08 AM

These are errors, the draw call fails. I'm not surprised the graphics debugger can't work with that. I still use PIX, but I cannot remember how it reacts in such a case, since I usually fire it up only after I have fixed such pipeline errors.

Looks pretty obvious to me. You are either binding the wrong input layout or the input layout creation is at fault.

### #5Juliean  GDNet+

Posted 19 March 2014 - 03:51 AM

1. ID3D11DeviceContext::DrawIndexed: Input Assembler - Vertex Shader linkage error: Signatures between stages are incompatible. The input stage requires Semantic/Index (WEIGHTS,0) as input, but it is not provided by the output stage.

2. ID3D11DeviceContext::DrawIndexed: Input Assembler - Vertex Shader linkage error: Signatures between stages are incompatible. The input stage requires Semantic/Index (BONEINDICES,0) as input, but it is not provided by the output stage.

Since you have one vertex shader that offers those two semantics (SkinnedVS) and one that does not (VS) it is my quess that you are drawing with the wrong technique, one that uses VS. To solve this error, you need to ensure that input layout always matches VS input elements.

Posted 19 March 2014 - 10:09 AM

Since you have one vertex shader that offers those two semantics (SkinnedVS) and one that does not (VS) it is my quess that you are drawing with the wrong technique, one that uses VS. To solve this error, you need to ensure that input layout always matches VS input elements.

I am using the "Light1Skinned" technique as follows :

technique11 Light1Skinned
{
pass P0
{
}
}


But when I use the Light1 Technique all is perfect:

technique11 Light1
{
pass P0
{
}
}


Posted 19 March 2014 - 10:31 AM

@Unbird

These are errors, the draw call fails. I'm not surprised the graphics debugger can't work with that. I still use PIX, but I cannot remember how it reacts in such a case, since I usually fire it up only after I have fixed such pipeline errors.

I cannot get the PIX to work with directx 11 and windows 8.

Looks pretty obvious to me. You are either binding the wrong input layout or the input layout creation is at fault

Ok so I checked the input layout again and found this problem :

Effects::SkinFX->Light1Tech->GetPassByIndex(0)->GetDesc(&passDesc);
HR(device->CreateInputLayout(InputLayoutDesc::PosNormalTexSkin, 5, passDesc.pIAInputSignature,
passDesc.IAInputSignatureSize, &PosNormalTexSkin));


Effects::SkinFX->Light1SkinnedTech->GetPassByIndex(0)->GetDesc(&passDesc);
HR(device->CreateInputLayout(InputLayoutDesc::PosNormalTexSkin, 5, passDesc.pIAInputSignature,
passDesc.IAInputSignatureSize, &PosNormalTexSkin));

The error line seems to be gone. But the problem still persists. The bones and weights are correctly present in the vertex buffer. But I still cannot see the model on the screen. I am trying to debug the shader . But it is giving me the same error :

**Graphics Diagnostics failed to build shader trace. Therefore, it is unable to debug shader.**

What sort of problem is this ?

Posted 19 March 2014 - 11:37 AM

One thing I still can see that in the graphics pipline input assembler looks ok. But the vertex shader is blank and there is no pixel shader stage. And output merger stage is transparent.

### #9unbird  Members

Posted 19 March 2014 - 12:26 PM

Hmmm, quite stubborn

Can't help you with the graphics debugger, still using PIX here. I wonder if that thing works at all: Ever successfully tried a simpler sample ? Preferably one not using the effect framework ? I remember AMD PerfStudio never wanted to work with the D3D9 effects with my C#/SlimDX stuff or something.

If you don't get it to work that leaves only manual debugging. Unfortunately it can get quite involved:
• First double check you don't have other errors/warnings lurking.
• Reading back data with CopyResource to a staging buffer, then map and read back to CPU, to check if shader constants are set correctly (bone transformations,...)
• One can actually grab the data after the vertex shader with a special geometry shader (so-called stream output). This is not that easy to setup, though.
• Alternatively, setup special VS and PS (and vertex buffers) to visualize vertex data or shader constants (e.g. output weights as colored pixels).
• Simplify the thing. Use a Mesh with one triangle, one Bone/Weight. It sounds silly, but as soon you have some output you can usually work from there more easily.
• Since it could be a bug in the effect framework, try without. Last resort I'd say, because doing it manually even more can go wrong. Though: I still use it myself and I don't remember a related problem. But it is obsolete and could behave buggy in a new runtime/OS I guess.
I'm just brainstorming here, sorry, no idea what could be wrong. Also read the recent thread about graphics debugging.

Edit: Could you show all relevant code that goes into that draw call, please ? Or even put the whole project on github or something ? Maybe we spot something.

Posted 19 March 2014 - 02:41 PM

I tried PIX. But does it work with Directx 11 ?

Reading back data with CopyResource to a staging buffer, then map and read back to CPU, to check if shader constants are set correctly (bone transformations,...)

Silly question ... But how to do that ? I am seeing some constant buffers in the VSSetShader(). But couldn't make much from it coz the variable names in the shader files are not mentioned there. Though I can definetely see that one constant buffer object is just initialized to 0. I mean every variable inside it is 0. I have only 2 constant buffers here.

Again, my vertex shader stays blank .And if I try to debug it throws an error. So, my guess the input assembler fails to link with the shader at all, If I use the SkinnedVS() in the shader code. But if I use the VS() it works and I can debug and the vertex shader shows a wireframed model.

### #11unbird  Members

Posted 19 March 2014 - 02:52 PM

PIX works to a certain extent. One cannot debug D3D11-only features (tesselation, compute), nonetheless, inspecting buffers/textures/render output works usually fine. Your code should pose little problems. Edit: I'm running Windows 7 and vanilla D3D11, though. PIX does not run with platform update a year ago and I don't think it runs on Win 8 either.

Silly question ... But how to do that ? I am seeing some constant buffers in the VSSetShader(). But couldn't make much from it coz the variable names in the shader files are not mentioned there. Though I can definetely see that one constant buffer object is just initialized to 0. I mean every variable inside it is 0. I have only 2 constant buffers here.

Aaah, so you can inspect buffers. Well, good. In PIX one can define the structure, meaning, copy-paste from the HLSL cbuffer definition, more or less. No idea how to do that in your case.

Edited by unbird, 19 March 2014 - 03:26 PM.

Posted 19 March 2014 - 03:17 PM

Ok here goes.....

These are the function I am using to set the variables. I am not good in Effects framework. Its based on the concept of Frank D Luna. May contain huge mistakes.]

void SetWorldViewProj(CXMMATRIX M) { WorldViewProj->SetMatrix(reinterpret_cast<const float*>(&M)); }
void SetWorld(CXMMATRIX M) { World->SetMatrix(reinterpret_cast<const float*>(&M)); }
void SetWorldInvTranspose(CXMMATRIX M) { WorldInvTranspose->SetMatrix(reinterpret_cast<const float *> (&M)); }
void SetBoneTransforms(const XMFLOAT4X4 *M, int cnt) { BoneTransforms->SetMatrixArray(reinterpret_cast<const float*>(M), 0, sizeof(M)*cnt); }
void SetTexTransform(CXMMATRIX M) { TexTransform->SetMatrix(reinterpret_cast<const float *> (&M)); }
void SetEyePosW(const XMFLOAT3 &v) { EyePosW->SetRawValue(&v,0,sizeof(XMFLOAT3)); }
void SetFogColor(const FXMVECTOR v) { FogColor->SetFloatVector(reinterpret_cast<const float *>(&v)); }
void SetFogStart(float f) { FogStart->SetFloat(f); }
void SetFogRange(float f) { FogRange->SetFloat(f); }
void SetDirLights(const DirectionalLight* lights)   { DirLights->SetRawValue(lights, 0, 3 * sizeof(DirectionalLight)); }
void SetMaterial(const Material& mat)               { Mat->SetRawValue(&mat, 0, sizeof(Material)); }
void SetDiffuseMap(ID3D11ShaderResourceView *tex) { DiffuseMap->SetResource(tex); }


And this is how I store variables in SkinEffect class.

        WorldViewProj = mFX->GetVariableByName("gWorldViewProj")->AsMatrix();
World = mFX->GetVariableByName("gWorld")->AsMatrix();
WorldInvTranspose = mFX->GetVariableByName("gWorldInvTranspose")->AsMatrix();
TexTransform = mFX->GetVariableByName("gTexTransform")->AsMatrix();
EyePosW = mFX->GetVariableByName("gEyePosW")->AsVector();
FogColor = mFX->GetVariableByName("gFogColor")->AsVector();
FogStart = mFX->GetVariableByName("gFogStart")->AsScalar();
FogRange = mFX->GetVariableByName("gFogRange")->AsScalar();
DirLights = mFX->GetVariableByName("gDirLights");
Mat = mFX->GetVariableByName("gMaterial");
BoneTransforms = mFX->GetVariableByName("gBoneTransforms")->AsMatrix();


My main concern would be BoneTransforms. Am I setting it right ? I am setting the variables before rendering in this way :

        Effects::SkinFX->SetEyePosW(mCam.GetPosition());
Effects::SkinFX->SetWorld(World);
Effects::SkinFX->SetWorldInvTranspose(worldInvTranspose);
Effects::SkinFX->SetWorldViewProj(worldViewProj);
Effects::SkinFX->SetTexTransform(XMMatrixScaling(1.0f, 1.0f, 1.0f));
Effects::SkinFX->SetDirLights(&dirLight[0]);

Effects::SkinFX->SetBoneTransforms(&mBones.mBoneTransforms[0], mBones.mBoneTransforms.size());

Effects::SkinFX->SetMaterial(Materials[i]);
Effects::SkinFX->SetDiffuseMap(DiffuseMapSRV[i]);


There is huge possiblity that I am setting them in a wrong way. mBoneTransforms is a vector of type XMFLOAT4X4.mCam.GetPosition() returns XMFLOAT3 value.

### #13unbird  Members

Posted 19 March 2014 - 03:44 PM


void SetBoneTransforms(const XMFLOAT4X4 *M, int cnt) { BoneTransforms->SetMatrixArray(reinterpret_cast<const float*>(M), 0, sizeof(M)*cnt); }

sizeof(M) is the size in bytes, times how many matrices gives ... a lot. Edit: My C++ reading skills at fault. M is a pointer, so this is probably 4 or 8. Still wrong though.

The doc for this function is a bit confusing (not sure if 'elements' means array or matrix elements). Luna uses it like so:


void SetBoneTransforms(const XMFLOAT4X4* M, int cnt){ BoneTransforms->SetMatrixArray(reinterpret_cast<const float*>(M), 0, cnt); }

Worth a shot. Also check (or compare to Luna's) the other calls.

Edited by unbird, 19 March 2014 - 03:48 PM.

Posted 20 March 2014 - 01:02 PM

Unbird,

I can kiss you. I owe you a drink buddy....    . This stupid mistake made me waste 3 weeks . An average catastrophe in the life of a programmer.

I imported it. But it does not seem perfect. Mesh is somewhat distorted. I used only 4 weights where my model contained 6 weights at some vertices . May be that's the reason. Do you know any DXGI format to take 6 input in the input layout. Here is what it looks like now.

### #15unbird  Members

Posted 20 March 2014 - 01:54 PM

Devil's in the details. Three weeks sounds really frustrating, glad it (somehow) works now.

Just one question: Can you now debug the shaders ?

6 components ? Nope, but no need to. You can distribute it across a 4- and a 2-component. Or use 6 one-component (scalars). Probably need to play around a bit to find out which is most convenient (or even works) and what performance implications arise.

One can go even further and pack more info with some bit-hackery. Only do this if you do have a bottleneck in the vertex size. Just one hint: bone indices probably don't need full 32 bit ints.

Posted 20 March 2014 - 04:05 PM

Again, thanks unbird. Now debugger works. But it seems when I try to use the default offset matrix provided by the model, it gets more distorted. Guess I have got some more matrix multiplication to do. Just one question is it necessary to multiply each offset matrix with its parent matrix and global inverse transform ?

Fact about 6 weights. Yes I guess I can use 2 separate format to store 6 weights . Do I have to change the semantic index in the input layout then ?

About the integer part, I think 8 bit is sufficient. DXGI_FORMAT_R8G8B8A8_UINT.

### #17Buckeye  GDNet+

Posted 20 March 2014 - 04:31 PM

is it necessary to multiply each offset matrix with its parent matrix and global inverse transform ?

Not sure what you mean by "parent" matrix and "global inverse" transform. Can you describe?

Also, take another look at my skinned mesh article. The names I use for various matrix arrays aren't the same as you seem to be using, but you should be able to find your equivalents.

You mention that your mesh uses 6 weights, but you're only inputting 4. How do you do that? You can't simply ignore the other two. Can you explain a little?

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

Posted 20 March 2014 - 05:18 PM

You mention that your mesh uses 6 weights, but you're only inputting 4. How do you do that? You can't simply ignore the other two

Guess gotta fix that first . But identity matrix shows something now that's a relief even if it is some what distorted.

Not sure what you mean by "parent" matrix and "global inverse" transform.

I am not so sure about assimp myself . This is what I did :

1. Got the offset matrix for each bone stored in the model. [I am not sure if it is really offset matrix you meant, but Assimp is referring to it as offset matrix in the aiBone structure. (http://assimp.sourceforge.net/lib_html/structai_bone.html

2. Now got the scene root node's global transformation matrix and inversed it. According to Ogglev's tutorial(http://ogldev.atspace.co.uk/www/tutorial38/tutorial38.html)

3. Then I traversed the whole scene to find the bones. I used this technique according to the above tutorial.

•      Pass parent's transformation matrix and child in the function.
•      Multiply it by child's offset
•      Multiply the above product with child's offset again and global inverse transform to get child transform (confused)
•      Recursively called the function

I am really confused about this whole thing. Can you tell me what is the mOffsetMatrix in Assimp. And which matrix it represents in your article. That would be really helpful.

### #19Buckeye  GDNet+

Posted 20 March 2014 - 07:29 PM

I'm not familiar with Assimp's implementation but it appears the ReadNodeHierarchy function is the combined equivalent of the CalulateTransformationMatrices, CalcCombinedMatrix and CalculateFinalMatrix functions in my tutorial. Although I looked at the link you posted (labeled Tutorial 38) I don't see the steps you outline.

The NodeTransformation is the bone's to-Parent animation matrix. That's multiplied by the parent's animation matrix to form the bone's to-Root animation matrix. That's multiplied by the bone's offset matrix. The role of the "global inverse transform" isn't quite clear to me, I'm afraid.

FYI, it appears that the author of that tutorial doesn't quite understand the code he provides. He describes it as starting with a child and "traveling" to it's parent. The code itself, however, clearly indicates that ReadNodeHierarchy is first called [ ReadNodeHeirarchy(AnimationTime, m_pScene->mRootNode, Identity);] with a root node (the "ultimate" parent) argument, the node's transforms are calculated, and ReadNodeHierarchy is called for each child - working it's way from parent to child, not the other way 'round. The code is straightforward but the author's description is very misleading.

Edited by Buckeye, 20 March 2014 - 07:34 PM.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.