getOrthogonalBasis
#正規直交基底 #ベクトル #幾何学 #回転 #数学 #シェーダー
getOrthogonalBasis orthBas は、3次元のベクトル1本から3次元の正規直交基底を生成する関数
即ち、normalを渡すとbinormalとtangentを適当に決めて mat3 を作ってくれるやつ
WrighterのCyclic Noiseの座標系回転で初めて見た
https://www.shadertoy.com/view/3tcyD7
その他、カメラの回転・レイ方向の決定・重点サンプリングでの方向ベクトルの生成など色々使えます
”orthogonal” が「直交基底」を表すのに対して、「正規直交基底」は "orthonormal" なので、この関数もgetOrthonormalBasisと呼ぶほうがより正確
でも、正規直交基底 ⊂ 直交基底なので、間違っちゃいないのでいいよ別に
2026年4月、nimitz先生が2D版のサンプルコードを公開してくれたよ
https://www.shadertoy.com/view/fcjXzh
以下の論文で議論されている
Hughes-Möller 1999: Building an Orthonormal Basis from a Unit Vector
Frisvad 2012: Building an Orthonormal Basis from a 3D Unit Vector Without Normalization
Duff 2017: Building an Orthonormal Basis, Revisited
実装
GLSLでのナイーブな実装例
いわゆるグラム・シュミットの正規直交化法
code:glsl
mat3 getOrthogonalBasis(vec3 z) {
z = normalize(z);
vec3 up = abs(z.y) < 0.99 ? vec3(0.0, 1.0, 0.0) : vec3(0.0, 0.0, 1.0);
vec3 x = normalize(cross(up, z));
return mat3(x, cross(z, x), z);
}
入力となるベクトルとは別にもう一本ベクトルを用意しなきゃいけないが、いろいろ択がある
Frisvad 2012で挙げられているナイーブな手法では、 x > 0.9 ? (0, 1, 0) : (1, 0, 0) https://www.desmos.com/3d/ilkwpvbnzw
Wrighterのコードでは特異点の処理を行っていない https://www.desmos.com/3d/vy0sypm1mv
Hughes-Möller 1999では、 abs(x) > abs(z) ? (-y, x, 0) : (0, -z, y) https://www.desmos.com/3d/hor6j8gz2a
Frisvad 2012では、クォータニオンによる任意軸の回転を利用して軸を決めている。正規化いらず https://www.desmos.com/3d/x0j1xovycx
Duff 2017は、Frisvadの手法が極付近で誤差がひどくなるのを改善している https://www.desmos.com/3d/7t9bkhp7th