volumeMarch

Walk a ray through the medium front to back, adding up what glows and what dims.

volumeMarch(opts: {
        steps: number
        entry: Expr
        length: Expr
        /** A per-pixel offset added to each step's position along the ray, as a fraction of the ray. */
        jitter?: Expr
        /** A multiplier on every sample's `emit`. */
        emissionGain?: Expr
        hint?: string
    }, sample: (step: VolumeMarchStep) => {emit: Expr; absorb: Expr}): {color: Expr; transmittance: Expr}

Import volume from shaders/std and use volume.volumeMarch.

steps is how many samples to take (4–8 is typical; it is fixed when the shader compiles). entry and length come from interiorRay. For each step your callback returns emit, the rgb light this sample gives off, and absorb, the rgb amount it blocks. Absorption is per channel, so a medium can dim blue more than red. Returns the accumulated color and the transmittance left at the far side: multiply anything behind the medium by it. jitter is a small per-pixel offset along the ray, as a fraction of its length (a hash times 1 / steps works), that trades banding for fine grain. emissionGain scales every sample's glow; use k / steps so brightness does not change with the step count.

Parameters

NameTypeNotes
opts`{
    steps: number
    entry: Expr
    length: Expr
    /** A per-pixel offset added to each step's position along the ray, as a fraction of the ray. */
    jitter?: Expr
    /** A multiplier on every sample's `emit`. */
    emissionGain?: Expr
    hint?: string
}` |  |

| sample | (step: VolumeMarchStep) => {emit: Expr; absorb: Expr} | |

Example

const march = volumeMarch({steps: 6, entry: ray.entry, length: ray.length, jitter}, ({z, i}) => ({emit: math.mul(rgb, dens), absorb: math.splat3(math.mul(dens, u.density))}))

Tip. Fewer steps plus jitter beats more steps: the noise becomes grain instead of bands.

See also

  • interiorRay — The line of sight through a shape: where it enters, how far it travels inside, and where it is at any depth.
  • turbulentMedium — A billowing cloud density at a point inside the shape.
  • parallaxPlane — A flat layer at a fixed depth inside the shape, like scenery seen through a window.

Used by

Nebula