From 125f059267830d8f81694edb3ca83c6257f608f3 Mon Sep 17 00:00:00 2001 From: yum Date: Wed, 14 Jan 2026 14:31:13 -0800 Subject: begin work on hemi octahedral article --- index.md | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) (limited to 'index.md') diff --git a/index.md b/index.md index 1164d51..592b993 100755 --- a/index.md +++ b/index.md @@ -2,6 +2,102 @@ pagetitle: yummers lang: en --- +# hemi-octahedral impostors +14 Jan 2026 + +Ryan Brucks published [an +article](https://shaderbits.com/blog/octahedral-impostors) describing +"octahedral impostors" in 2018. The basic idea is to to take photos of some +subject at octahedral lattice points, record them to an atlas, then reconstruct +those photos in a particle. + +![Octahedral lattice points around some object.](./images/2026_01_14/Screenshot from 2026-01-14 +13-35-40.png) + +Why octahedrons? The octahedral mapping is simply one way to convert between a +flat coordinate system and a spherical coordinate system. It is notable because +it does not use any trig functions, making it suitable for use in realtime +graphics. + +This is what an octahedron looks like: + +![Unit octahedron.](./images/2026_01_14/Screenshot from 2026-01-14 +13-54-05.png) + +It is a polyhedron with 8 triangular faces and 6 vertices. The equator is a +square. + +Let's work out how we'd convert this octahedron to a plane. +First, we project the upper hemisphere onto the xz plane: + +![Octahedron with upper hemisphere projected onto xz +plane.](./images/2026_01_14/Screenshot from 2026-01-14 13-50-27.png) + +Next, we effectively need to "rotate" the triangles in the lower half around +those diagonal edges. We can cheat by first *reflecting* the bottom vertex of each +triangle about its diagonal edge: + +![Octahedron with reflected lower hemisphere.](./images/2026_01_14/Screenshot from 2026-01-14 13-58-18.png) + +Finally, we can just project those points in the lower hemisphere onto the xz +plane: + +![Fully unwrapped octahedron.](./images/2026_01_14/Screenshot from 2026-01-14 13-59-24.png) + +Viewed head on, we can see a very beautifully symmetric unwrapping: + +![Unwrapped octahedron, head on.](./images/2026_01_14/Screenshot from 2026-01-14 14-00-16.png) + +Note that we never actually did any rotations, so there's no trig! Here's the +same procedure in code: + +```c +// Convert unit octahedron to a [-1,1] x [-1,1] patch on xz plane. +float3 octahedron_to_plane(float3 p) { + if (p.y >= 0) { + // Project upper hemispher onto xz plane. + p.y = 0; + return p; + } + // First, reflect the lower hemisphere's points about their diagonal. + p.x = sign(p.x) * (1 - abs(p.x)); + p.z = sign(p.z) * (1 - abs(p.z)); + // Then project onto the xz plane. + p.y = 0; + return p; +} +``` + +We can generalize this procedure to unwrap *any* spherical object by just +switching norms: + +```c +// Convert unit sphere to a [-1,1] x [-1,1] patch on xz plane. +float3 octahedron_to_plane(float3 p) { + // Switch from L2 to L1 norm. This basically bends a sphere to an octahedron. + float l1_norm = abs(p.x) + abs(p.y) + abs(p.z); + p /= l1_norm; + // Then unwrap. + if (p.y >= 0) { + // Project upper hemispher onto xz plane. + p.y = 0; + return p; + } + // First, reflect the lower hemisphere's points about their diagonal. + p.x = sign(p.x) * (1 - abs(p.x)); + p.z = sign(p.z) * (1 - abs(p.z)); + // Then project onto the xz plane. + p.y = 0; + return p; +} +``` + +Here's a quick demo showing what that norm conversion does to a unit sphere: + +![Converting a sphere to an octahedron via norm conversion.](./images/2026_01_14/hemi_octahedral_04.mp4) + +If you'd like more discussion on this topic, I recommend the spherical geometry section in [the PBR book](https://www.pbr-book.org/4ed/Geometry_and_Transformations/Spherical_Geometry#x3-OctahedralEncoding).) + # 6 wave dispersion relations with derivatives 21 Sep 2025 -- cgit v1.2.3