Skip to content

ComputeTangentFrame

Chuck Walbourn edited this page Jan 21, 2022 · 11 revisions
DirectXMesh

Generates per-vertex tangent and bi-tangent information

HRESULT ComputeTangentFrame(
   const uint16_t* indices, size_t nFaces,
   const XMFLOAT3* positions, const XMFLOAT3* normals,
   const XMFLOAT2* texcoords, size_t nVerts,
   XMFLOAT3* tangents, XMFLOAT3* bitangents );

HRESULT ComputeTangentFrame(
   const uint16_t* indices, size_t nFaces,
   const XMFLOAT3* positions, const XMFLOAT3* normals,
   const XMFLOAT2* texcoords, size_t nVerts,
   XMFLOAT4* tangents, XMFLOAT3* bitangents );

HRESULT ComputeTangentFrame(
   const uint16_t* indices, size_t nFaces,
   const XMFLOAT3* positions, const XMFLOAT3* normals,
   const XMFLOAT2* texcoords, size_t nVerts,
   XMFLOAT4* tangents );
HRESULT ComputeTangentFrame(
   const uint32_t* indices, size_t nFaces,
   const XMFLOAT3* positions, const XMFLOAT3* normals,
   const XMFLOAT2* texcoords, size_t nVerts,
   XMFLOAT3* tangents, XMFLOAT3* bitangents );

HRESULT ComputeTangentFrame(
   const uint32_t* indices, size_t nFaces,
   const XMFLOAT3* positions, const XMFLOAT3* normals,
   const XMFLOAT2* texcoords, size_t nVerts,
   XMFLOAT4* tangents, XMFLOAT3* bitangents );

HRESULT ComputeTangentFrame(
   const uint32_t* indices, size_t nFaces,
   const XMFLOAT3* positions, const XMFLOAT3* normals,
   const XMFLOAT2* texcoords, size_t nVerts,
   XMFLOAT4* tangents );

Parameters

The normals parameter can be computed from the mesh indices and vertex positions using ComputeNormals.

The tangents can be optionally returned as a 4-vector where the .w component indicates 'handedness' which allows for an easy reconstruction of the bi-tangent in the shader.

float3 normal : NORMAL0
float4 tangent : TANGENT0

...

float3 tan1 = tangent.xyz;
float3 tan2 = cross( normal, tangent.xyz ) * tangent.w;

In the overloads that take both tangents and bitangents, either but not both can be nullptr.

Remark

Note that bi-normal is another common term used for bi-tangent, although technically a bi-normal only applies in 2D and not 3D. The Direct3D HLSL semantic name for the bi-tangent is BINORMAL.

Due to the C++ overload resolution rules, if you want to call ComputeTangentFrame for only the binormal output and not the tangent output, you need to use an explicit cast on the nullptr parameter:

auto bitangents = std::make_unique<XMFLOAT3[]>(nVerts);

if ( FAILED( ComputeTangentFrame( mesh->indices.data(), nFaces,
   pos.get(), normals.get(), texcoords.get(), nVerts,
   static_cast<XMFLOAT3*>(nullptr), bitangents.get() ) ) )
   // Error

Example

auto mesh = std::make_unique<WaveFrontReader<uint16_t>>();

if ( FAILED( mesh->Load( L"test.obj" ) ) )
   // Error

if ( mesh->hasNormals )
   // Skip next computation

size_t nFaces = mesh->indices.size() / 3;
size_t nVerts = mesh->vertices.size();

auto pos = std::make_unique<XMFLOAT3[]>(nVerts);
for( size_t j = 0; j < nVerts; ++j )
   pos[ j ] = mesh->vertices[ j ].position;

auto normals = std::make_unique<XMFLOAT3[]>(nVerts);
if ( FAILED( ComputeNormals( mesh->indices.data(), nFaces,
   pos.get(), nVerts, CNORM_DEFAULT, normals.get() ) ) )
   // Error

if ( !mesh->hasTexcoords )
   // Skip next computation

auto texcoords = std::make_unique<XMFLOAT2[]>(nVerts);
for( size_t j = 0; j < nVerts; ++j )
   texcoords[ j ] = mesh->vertices[ j ].textureCoordinate;

auto tangents = std::make_unique<XMFLOAT3[]>(nVerts);
auto bitangents = std::make_unique<XMFLOAT3[]>(nVerts);

if ( FAILED( ComputeTangentFrame( mesh->indices.data(), nFaces,
   pos.get(), normals.get(), texcoords.get(), nVerts,
   tangents.get(), bitangents.get() ) ) )
   // Error

Further Reading

Lengyel, Eric. "7.5 Tangent Space", Foundations of Game Engine Development: Volume 2 - Rendering, Terathon Software LLC (2019) link

Mittring, Martin. "Triangle Mesh Tangent Space Calculation". Shader X^4 Advanced Rendering Techniques, 2006

For Use

  • Universal Windows Platform apps
  • Windows desktop apps
  • Windows 11
  • Windows 10
  • Windows 8.1
  • Windows 7 Service Pack 1
  • Xbox One
  • Xbox Series X|S
  • Windows Subsystem for Linux

For Development

  • Visual Studio 2022
  • Visual Studio 2019 (16.11)
  • clang/LLVM v12 - v16
  • GCC 9.4, 11.3
  • MinGW 12.2, 13.2
  • CMake 3.20

Related Projects

DirectX Tool Kit for DirectX 11

DirectX Tool Kit for DirectX 12

DirectXTex

DirectXMath

Tools

Test Suite

Content Exporter

DxCapsViewer

See also

DirectX Landing Page

Clone this wiki locally