Skip to main content

hexPrismSDF: Three-Dimensional Hexagonal Prism Distance Field

Regular Hexagonal Cross-Section with Extruded Height

The hexPrismSDF function generates a signed distance field for a hexagonal prism, combining a regular hexagonal base with vertical extrusion. This primitive uses hexagonal symmetry constants to create precise geometric boundaries.

Mathematical Foundation

The hexagonal prism distance combines planar hexagonal distance with vertical extent:

dhex=max(d1,d2,0)2+min(max(d1,d2),0)d_{\text{hex}} = \sqrt{\max(d_1, d_2, 0)^2} + \min(\max(d_1, d_2), 0)

where:

  • d1=zhyd_1 = |z| - h_y represents the vertical extent constraint
  • d2=max(x32+y0.5,y)hxd_2 = \max(|x| \cdot \frac{\sqrt{3}}{2} + |y| \cdot 0.5, |y|) - h_x defines the hexagonal boundary

The constant 0.866025=320.866025 = \frac{\sqrt{3}}{2} derives from regular hexagonal geometry, representing the cosine of 30° for the hexagonal edge angles.

Function Signature

ParameterTypeDescription
pvec33D sample point position
hvec2Hexagonal prism dimensions (radius, height)

Implementation Demonstrations

Live Editor
const fragment = () => {
      const up = vec3(0, 1, 0)
      const eps = vec3(0.01, 0, 0)
      const eye = rotate3dY(iTime).mul(vec3(5))
      const args = [1.2, 0.8]
      const march = Fn(([eye, dir]: [Vec3, Vec3]) => {
              const p = eye.toVar()
              const d = hexPrismSDF(p, vec2(...args)).toVar()
              Loop(16, ({ i }) => {
                      If(d.lessThanEqual(eps.x), () => {
                              const dx = hexPrismSDF(p.add(eps.xyy), vec2(...args)).sub(d)
                              const dy = hexPrismSDF(p.add(eps.yxy), vec2(...args)).sub(d)
                              const dz = hexPrismSDF(p.add(eps.yyx), vec2(...args)).sub(d)
                              return vec4(vec3(dx, dy, dz).normalize().mul(0.5).add(0.5), 1)
                      })
                      p.addAssign(d.mul(dir))
                      d.assign(hexPrismSDF(p, vec2(...args)))
              })
              return vec4(0)
      })
      const z = eye.negate().normalize()
      const x = z.cross(up)
      const y = x.cross(z)
      const scr = vec3(uv.sub(0.5), 2)
      const dir = mat3(x, y, z).mul(scr).normalize()
      return march(eye, dir)
}