D3DXComputeTangent() Problem

Started by
1 comment, last by dave 14 years, 9 months ago
In my previous thread i was trying to work out why my tangent space normal mapping wasn't working, focussed on my shader. Well i took a step back and made sure that D3DXComputeTangent() was actually creating the tangents and binormals, it isn't. However, it returns S_OK and D3D reports no errors. Here is the code for creating thenew declaration, cloning and calculation:
	D3DXMesh	pMesh( pNewModel->GetMesh() );

	D3DVERTEXELEMENT9	EndElement = {0xFF,0,D3DDECLTYPE_UNUSED,0,0,0};

	D3DVERTEXELEMENT9 CurrentDeclaration[MAX_FVF_DECL_SIZE];

	pMesh->GetDeclaration(&CurrentDeclaration[0]);

	//	Find the end of the declaration and insert space for tangents.
	UInt32 EndIndex( 0 );

	for ( UInt32 Index( 0 ); Index < MAX_FVF_DECL_SIZE; ++Index )
	{
		if ( CurrentDeclaration[ Index ].Type == D3DDECLTYPE_UNUSED )
		{
			EndIndex = Index;
			break;
		}
	}

	CurrentDeclaration[ EndIndex + 2 ] = EndElement;

	D3DVERTEXELEMENT9& rTangentElement( CurrentDeclaration[EndIndex] );
	D3DVERTEXELEMENT9& rBiNormalElement( CurrentDeclaration[EndIndex+1] );
	D3DVERTEXELEMENT9& rPreviousElement( CurrentDeclaration[EndIndex-1] );

	rTangentElement.Offset = rPreviousElement.Offset + 12;
	rTangentElement.Method = D3DDECLMETHOD_DEFAULT;
	rTangentElement.Stream = rPreviousElement.Stream;
	rTangentElement.Type = D3DDECLTYPE_FLOAT3;
	rTangentElement.Usage = D3DDECLUSAGE_TEXCOORD;
	rTangentElement.UsageIndex = 1;

	rBiNormalElement.Offset = rTangentElement.Offset + 12;
	rBiNormalElement.Method = D3DDECLMETHOD_DEFAULT;
	rBiNormalElement.Stream = rPreviousElement.Stream;
	rBiNormalElement.Type = D3DDECLTYPE_FLOAT3;
	rBiNormalElement.Usage = D3DDECLUSAGE_TEXCOORD;
	rBiNormalElement.UsageIndex = 2;

	D3DXMesh NewMesh;

	HRESULT Result = pMesh->CloneMesh( D3DXMESH_VB_MANAGED | D3DXMESH_IB_MANAGED, &CurrentDeclaration[0], m_Device, &NewMesh );

	pNewModel->SetMesh( NewMesh );

	DWORD* pCharBuffer( new DWORD[3 * NewMesh->GetNumFaces()] );
	NewMesh->GenerateAdjacency( 0.0f, pCharBuffer );


	D3DXCleanMesh( D3DXCLEAN_BOWTIES , NewMesh, pCharBuffer, &NewMesh, pCharBuffer, NULL );
	D3DXCleanMesh( D3DXCLEAN_BACKFACING , NewMesh, pCharBuffer, &NewMesh, pCharBuffer, NULL );

	static UInt32 TexStage(0);
	static UInt32 TangentStage(0);
	static UInt32 BinormalStage(0);

	Result = D3DXComputeTangent( pNewModel->GetMesh(), TexStage, TangentStage, D3DX_DEFAULT, TRUE, pCharBuffer );
	pNewModel->SetMesh( NewMesh );

	if ( Result == D3DERR_INVALIDCALL )
		Result = Result;
	else if ( Result == D3DXERR_INVALIDDATA )
		Result = Result;

	NewMesh->GetDeclaration(&CurrentDeclaration[0]);


	void*	pData( NULL );
	NewMesh->LockVertexBuffer( 0, &pData );

	if ( pData != NULL )
	{

	}

	NewMesh->UnlockVertexBuffer();

Here is the .x file, a quad:
xof 0303txt 0032


template VertexDuplicationIndices { 
 <b8d65549-d7c9-4995-89cf-53a9a8b031e3>
 DWORD nIndices;
 DWORD nOriginalVertices;
 array DWORD indices[nIndices];
}
template XSkinMeshHeader {
 <3cf169ce-ff7c-44ab-93c0-f78f62d172e2>
 WORD nMaxSkinWeightsPerVertex;
 WORD nMaxSkinWeightsPerFace;
 WORD nBones;
}
template SkinWeights {
 <6f0d123b-bad2-4167-a0d0-80224f25fabb>
 STRING transformNodeName;
 DWORD nWeights;
 array DWORD vertexIndices[nWeights];
 array float weights[nWeights];
 Matrix4x4 matrixOffset;
}

Frame RootFrame {

  FrameTransformMatrix {
    1.000000,0.000000,0.000000,0.000000,
    0.000000,-0.000000,1.000000,0.000000,
    0.000000,1.000000,0.000000,0.000000,
    0.000000,0.000000,0.000000,1.000000;;
  }
Frame Plane {

  FrameTransformMatrix {
    1.000000,0.000000,0.000000,0.000000,
    0.000000,-0.000000,1.000000,0.000000,
    0.000000,-1.000000,-0.000000,0.000000,
    0.000000,0.000000,0.000000,1.000000;;
  }
Mesh {
4;
1.000000; 1.000000; 0.000000;,
-1.000000; 1.000000; 0.000000;,
-1.000000; -1.000000; 0.000000;,
1.000000; -1.000000; 0.000000;;
1;
4; 0, 3, 2, 1;;
  MeshMaterialList {
    0;
    1;
    0;;
    }  //End of MeshMaterialList
  MeshNormals {
4;
    0.000000; 0.000000; 1.000000;,
    0.000000; 0.000000; 1.000000;,
    0.000000; 0.000000; 1.000000;,
    0.000000; 0.000000; 1.000000;;
1;
4; 0, 3, 2, 1;;
}  //End of MeshNormals
MeshTextureCoords {
4;
1.000000;-1.000000;,
0.000000;-1.000000;,
0.000000;-0.000000;,
1.000000;-0.000000;;
}  //End of MeshTextureCoords
 }
}
}

Here is a screenshot of the pre vertex shader input from PIX: Any suggestions for why this is happening? EDIT: On posting realised this PIX output was for a more complicated model, but the same principle applies. Thanks in advance.
Advertisement
I believe that function expects that you have D3DUSAGE_BINORMAL and D3DUSAGE_TANGENT elements in your vertex declaration, but you don't. Any particular reason why you're using TEXCOORD's instead of BINORMAL and TANGENT?

D3DXComputeTangentFrameEx lets you specify what semantic you want the binormal and tangent data to be output to, and that function is recommended anyway (D3DXComputeTangent is a legacy function).
Meh, i've done a full circle of debugging. I actually had it with those originally and it wasn't working. The reason i changed to use multiple indexes of TEXCOORD was because PIX didn't seem to be picking up TANGENT and BINORMAL as the vertex shader input.

Any idea why that might be?

This topic is closed to new replies.

Advertisement