メインコンテンツまでスキップ

displace: Parallax Occlusion Mapping Function

Heightmap Surface Displacement with Ray Intersection

The displace function implements parallax occlusion mapping through iterative raymarching. Given a heightmap texture and viewing parameters, it computes surface intersection points by stepping along ray directions until depth discontinuities are detected.

Mathematical Foundation

For a ray originating at position ro\mathbf{r_o} with direction rd\mathbf{r_d}, the displacement algorithm samples heightmap values h(u,v)h(u,v) along the parametric line:

p(t)=ro+trd\mathbf{p}(t) = \mathbf{r_o} + t \cdot \mathbf{r_d}

The intersection condition is satisfied when:

pz(t)h(px(t),py(t))Dp_z(t) \leq h(p_x(t), p_y(t)) \cdot D

where DD is the displacement depth scale factor.

Function Variants

FunctionInputOutputPurpose
displace(tex, ro, rd)texture, vec3, vec3vec3Ray-based displacement
displaceUV(tex, ro, uv)texture, vec3, vec2vec3UV-based displacement

Implementation Details

The function performs binary refinement when depth intersection occurs. The final position interpolates between the last two sample points using distance-based weighting:

pfinal=pprev+dprevdcurr+dprev(pcurrpprev)\mathbf{p_{final}} = \mathbf{p_{prev}} + \frac{d_{prev}}{|d_{curr}| + d_{prev}} \cdot (\mathbf{p_{curr}} - \mathbf{p_{prev}})

where dprevd_{prev} and dcurrd_{curr} represent signed distances to the heightmap surface.

ライブエディター
const fragment = () => {
      const heightTex = uniform('https://avatars.githubusercontent.com/u/40712342')
      const viewPos = vec3(iTime.cos(), iTime.sin(), 0.5)
      const surface = displaceUV(heightTex, viewPos, uv)
      return vec4(surface, 1)
}