Build an orthonormal basis (tangent, bitangent) around `n`. Branchless method from Frisvad 2012 — more stable than cross(n, up) when n is close to the up vector.
(n: Vec3)
| 1170 | /// Branchless method from Frisvad 2012 — more stable than cross(n, up) |
| 1171 | /// when n is close to the up vector. |
| 1172 | fn build_tbn(n: Vec3) -> (Vec3, Vec3) { |
| 1173 | if n.z < -0.9999999 { |
| 1174 | return (Vec3::new(0.0, -1.0, 0.0), Vec3::new(-1.0, 0.0, 0.0)); |
| 1175 | } |
| 1176 | let a = 1.0 / (1.0 + n.z); |
| 1177 | let b = -n.x * n.y * a; |
| 1178 | let t = Vec3::new(1.0 - n.x * n.x * a, b, -n.x); |
| 1179 | let bt = Vec3::new(b, 1.0 - n.y * n.y * a, -n.y); |
| 1180 | (t, bt) |
| 1181 | } |
| 1182 | |
| 1183 | /// Cosine-weighted hemisphere sample, used for diffuse direction |
| 1184 | /// sampling. `rand` is two uniform samples in [0, 1)². |