Skip to main content

cylinderSDF: Cylindrical Distance Field Variations

Versatile Tube Geometry with Multiple Parameterization Methods​

The cylinderSDF function family generates signed distance fields for cylindrical geometries with various parameterization options. These functions support standard cylinders, uniform height cylinders, height-radius specification, and arbitrary orientation with caps.

Mathematical Foundation​

The basic cylinder distance function operates on radial and axial components:

dcylinder=min⁡(max⁡(dx,dy),0)+∣max⁡(d⃗,0)∣d_{\text{cylinder}} = \min(\max(d_x, d_y), 0) + |\max(\vec{d}, 0)|

where d⃗=∣q⃗∣−h⃗\vec{d} = |\vec{q}| - \vec{h} and q⃗=(∣p⃗xz∣,py)\vec{q} = (|\vec{p}_{xz}|, p_y) represents the radial-axial projection.

For arbitrary orientation cylinders with caps, the distance involves projection calculations:

x=∣pa⃗⋅baba−ba⃗⋅paba∣−r⋅babax = |\vec{pa} \cdot ba_{ba} - \vec{ba} \cdot pa_{ba}| - r \cdot ba_{ba} y=∣paba−baba2∣−baba2y = |pa_{ba} - \frac{ba_{ba}}{2}| - \frac{ba_{ba}}{2}

Function Variants​

FunctionParametersDescription
cylinderSDFp, hVector height parameter (radius, height)
cylinderSDFHeightp, hUniform radius with height specification
cylinderSDFHeightRadiusp, h, rExplicit height and radius parameters
cylinderSDFCapsp, a, b, rArbitrary orientation with endpoint caps

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.5, 0.8]
      const march = Fn(([eye, dir]: [Vec3, Vec3]) => {
              const p = eye.toVar()
              const d = cylinderSDFHeightRadius(p, ...args).toVar()
              Loop(16, ({ i }) => {
                      If(d.lessThanEqual(eps.x), () => {
                              const dx = cylinderSDFHeightRadius(p.add(eps.xyy), ...args).sub(d)
                              const dy = cylinderSDFHeightRadius(p.add(eps.yxy), ...args).sub(d)
                              const dz = cylinderSDFHeightRadius(p.add(eps.yyx), ...args).sub(d)
                              return vec4(vec3(dx, dy, dz).normalize().mul(0.5).add(0.5), 1)
                      })
                      p.addAssign(d.mul(dir))
                      d.assign(cylinderSDFHeightRadius(p, ...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)
}
Result
Loading...