struct TangentFrame { normal: vec3, tangent: vec3 }; // https://knarkowicz.wordpress.com/2014/04/16/octahedron-normal-vector-encoding/?like_comment=12 fn oct_norm_wrap(v: vec2) -> vec2 { return (1.0 - abs(v.yx)) * select(vec2(-1.0), vec2(1.0), v.xy >= vec2(0.0)); } fn oct_norm_encode(n: vec3) -> vec2 { let ml = (abs(n.x) + abs(n.y) + abs(n.z)); // ml = manhattan length let n = n / ml; let v = select(oct_norm_wrap(n.xy), n.xy, n.z >= 0.0); return fma(v, vec2(0.5), vec2(0.5)); } fn oct_norm_decode(f: vec2) -> vec3 { let f = fma(f, vec2(2.0), vec2(-1.0)); let n = vec3(f.xy, 1.0 - abs(f.x) - abs(f.y)); let t = vec2(clamp(-n.z, 0.0, 1.0)); let nxy = n.xy + select(t, -t, n.xy >= vec2(0.0)); return normalize(vec3(nxy, n.z)); } fn tan_frame_encode(tf: TangentFrame) -> u32 { return u32(0); // TODO } fn tan_frame_decode(i: u32) -> TangentFrame { let n = i & u32(0xffff); let nx = n >> u32(8); let ny = n & u32(0xff); let n = vec2(f32(nx), f32(ny)) / 255.0; let t = i >> u32(16); let tx = t >> u32(8); let ty = t & u32(0xff); let t = vec2(f32(tx), f32(ty)) / 255.0; var tf: TangentFrame; tf.normal = oct_norm_decode(n); tf.tangent = oct_norm_decode(n); return tf; } fn tan_frame_transform(i: u32, transform: mat4x4) -> u32 { var tf = tan_frame_decode(i); tf.normal = (transform * vec4(tf.normal, 0.0)).xyz; tf.tangent = (transform * vec4(tf.tangent, 0.0)).xyz; return tan_frame_encode(tf); }