-
Notifications
You must be signed in to change notification settings - Fork 7
Open
Description
Hey there!
Have you considered encoding normals using octahedron mapping? It's a neat way to map a direction vector into two components and it has a more uniform distribution than storing (angle, z).
I haven't profiled it against the current implementation, but here's some sample code:
code
use glam::{Vec2, Vec3};
/// Encode a 3d direction vector to a 2d vector using octahedron mapping.
/// The output vector is in the range [-1..1]. The input vector doesn't have to be normalized.
pub fn encode_oct(dir: Vec3) -> Vec2 {
let norm = dir.x.abs() + dir.y.abs() + dir.z.abs();
let nx = dir.x / norm;
let ny = dir.y / norm;
if dir.z.is_sign_positive() {
Vec2::new(nx, ny)
} else {
// fold over negative z
Vec2::new(
(1.0 - ny.abs()) * nx.signum(),
(1.0 - nx.abs()) * ny.signum(),
)
}
}
/// Decode an octahedron mapped direction vector back to the original one.
/// The output is normalized.
pub fn decode_oct(mut oct: Vec2) -> Vec3 {
let z = 1.0 - oct.x.abs() - oct.y.abs();
oct += oct.signum() * z.min(0.0);
Vec3::new(oct.x, oct.y, z).normalize()
}If you want to, I could open a PR to compare it to the current impl.
Metadata
Metadata
Assignees
Labels
No labels