Skip to content

Instantly share code, notes, and snippets.

@reinsteam
Last active October 15, 2020 03:05
Show Gist options
  • Save reinsteam/9e291ed75925eb74d827 to your computer and use it in GitHub Desktop.
Save reinsteam/9e291ed75925eb74d827 to your computer and use it in GitHub Desktop.
Snippet to calculate TBN basis from quaternion in 8 instructions (seems like this one is used at Crytek: http://www.crytek.com/download/izfrey_siggraph2011.pdf)
/*----------------------------------------------------------------------------------------------------------------------
Custom cross-product: mad + mul
----------------------------------------------------------------------------------------------------------------------*/
half3 crs(half3 v0, half3 v1)
{
//return cross(v0, v1);
half3 v0_0 = v0.yzx;
half3 v0_1 = v1.zxy;
half3 v1_0 = v0.zxy;
half3 v1_1 = v1.yzx;
return v0_0 * v0_1 - (v1_0 * v1_1);
}
/*----------------------------------------------------------------------------------------------------------------------
Tangent and BiTangent computation takes 6 instructions : add, mul, mad, mad, mad, mad
Normal computation takes 2 instructions (crs prod) : mul, mad
----------------------------------------------------------------------------------------------------------------------*/
half3x3 tbn_from_quat_1(half4 quat)
{
half3x3 tbn;
half4 dquat = (quat + quat);
half4 wquat = (quat + quat) * quat.w;
half3 tbn_t_0 = (quat.xyz * dquat.xxx) + half3(-1.0, 0.0, 0.0);
half3 tbn_b_0 = (quat.xyz * dquat.yyy) + half3(0.0, -1.0, 0.0);
half3 tbn_t_1 = (wquat.wzy * half3(1.0, -1.0, 1.0)) + tbn_t_0;
half3 tbn_b_1 = (wquat.zwx * half3(1.0, 1.0, -1.0)) + tbn_b_0;
tbn[0] = tbn_t_1;
tbn[1] = tbn_b_1;
tbn[2] = crs(tbn_t_0, tbn_b_0);
return tbn;
}
/*----------------------------------------------------------------------------------------------------------------------
Tangent and BiTangent computation takes 6 instructions : add, mul, mad, mad, mad, mad
Normal computation takes 2 instructions : mad, mad
----------------------------------------------------------------------------------------------------------------------*/
half3x3 tbn_from_quat_2(half4 quat)
{
half3x3 tbn;
half4 dquat = (quat + quat);
half4 wquat = (quat + quat) * quat.w;
half3 tbn_t_0 = (quat.xyz * dquat.xxx) + half3(-1.0, 0.0, 0.0);
half3 tbn_b_0 = (quat.xyz * dquat.yyy) + half3(0.0, -1.0, 0.0);
half3 tbn_n_0 = (quat.xyz * dquat.yyy) + half3(0.0, 0.0, -1.0);
half3 tbn_t_1 = (wquat.wzy * half3(1.0, -1.0, 1.0)) + tbn_t_0;
half3 tbn_b_1 = (wquat.zwx * half3(1.0, 1.0, -1.0)) + tbn_b_0;
half3 tbn_n_1 = (wquat.yxw * half3(-1.0, 1.0, 1.0)) + tbn_n_0;
tbn[0] = tbn_t_1;
tbn[1] = tbn_b_1;
tbn[2] = tbn_n_1;
return tbn;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment