diff options
| author | yum <yum.food.vr@gmail.com> | 2026-01-14 14:31:13 -0800 |
|---|---|---|
| committer | yum <yum.food.vr@gmail.com> | 2026-01-14 14:34:28 -0800 |
| commit | 125f059267830d8f81694edb3ca83c6257f608f3 (patch) | |
| tree | cf6f040b75f0e63d45f3c4097e49d8dfc01f1c87 | |
| parent | 9f87b61fa59b5bd37d4539c8aeb6280963b7a69a (diff) | |
begin work on hemi octahedral article
| -rwxr-xr-x | index.md | 96 | ||||
| -rwxr-xr-x | make_html | 2 | ||||
| -rwxr-xr-x | template.html | 2 |
3 files changed, 99 insertions, 1 deletions
@@ -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. + + + +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: + + + +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: + + + +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: + + + +Finally, we can just project those points in the lower hemisphere onto the xz +plane: + + + +Viewed head on, we can see a very beautifully symmetric unwrapping: + + + +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: + + + +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 @@ -23,7 +23,7 @@ pandoc \ unzip -o "$OUTPUT_DIR/site.zip" -d /var/www/html/ # Remove in-page hash fragments from TOC links on the landing page so links open at page top -sed -E -i 's/(href="[^"#]+\.html)#[^"]+"/\1"/g' /var/www/html/index.html +sed -E -i 's/(href="[^"#]+\.html)#[^"]+"/\1"/g' /var/www/html/index.html || true cp -r vr_assets /var/www/html/ cp -r images /var/www/html/ diff --git a/template.html b/template.html index ae3cd6a..173fb82 100755 --- a/template.html +++ b/template.html @@ -34,6 +34,7 @@ $endif$ math { font-family: "Cambria Math", "Latin Modern Math", "STIX Two Math", serif; } + video { max-width: 100%; height: auto; } @media (prefers-color-scheme: dark) { /* Tomorrow night theme: https://github.com/chriskempson/tomorrow-theme */ :root { @@ -72,6 +73,7 @@ $endif$ html, body { background-color: var(--background-color); color: var(--foreground-color); + padding-left: 1em; } a { color: var(--foreground-color); } a:visited { color: var(--foreground-color); } |
