---
title: Refraction Pipeline & Chromatic Dispersion
description: Snell's Law, SVG displacement-map filters, Smoothstep intensity mapping, and RGB chromatic dispersion models.
---

# Refraction Pipeline & Chromatic Dispersion

The `refraction` material mode of `TxBaseSurface`, with `TxGlassSurface` as its glass layer, recreates physical refraction and dispersion inside modern Web and Electron runtimes.

## Snell's Law and Physical Refraction

Light traveling across media boundaries follows Snell's Law:
$$n_1 \sin\theta_1 = n_2 \sin\theta_2$$
When viewing background elements through a card, perimeter light should bend. TuffEx applies parameterized displacement vectors to shift background pixels, mimicking optical refraction.

## RGB Chromatic Dispersion

Natural white light comprises a continuous spectrum. Inside real prisms, different wavelengths exhibit distinct refractive indexes (Cauchy's dispersion equation):
$$n(\lambda) = A + \frac{B}{\lambda^2}$$
Blue light refracts more sharply than red light ($n_{\text{Blue}} > n_{\text{Red}}$). TuffEx displaces the Red, Green and Blue channels separately, each by a slightly different amount (scales of −180, −170 and −160 by default), so the channels part and leave subtle spectral fringes along refracted contours.

:::TuffDemoWrapper{demo="ConceptRefractionRayDemo"}
:::

## Smoothstep Intensity Curve Mapping

To avoid abrupt transitions at low intensities and severe distortions at high values, `TxBaseSurface` divides `refraction-strength` (0–100, 62 by default) by 100 and passes it through a cubic `smoothstep`:
$$S(x) = 3x^2 - 2x^3 \quad (x \in [0, 1])$$
S is a $C^1$-continuous Hermite interpolation with zero slope at both ends, so strength changes slowly near the start and the end instead of jumping at the first nudge. A filmic curve follows:
$$s = 1 - \left(1 - S(x)\right)^{1.65}$$
The exponent 1.65 belongs to the default `filmic` profile; `soft` uses 1.15 and `cinematic` 2.2. Every parameter is then interpolated by s between two ends: in the `filmic` profile the displacement scale runs from −110 to −360, so a strength of 0 still keeps a scale of −110. The component uses this strength model only when one of `refraction-strength`, `refraction-angle` or `refraction-profile` is set; otherwise it uses fixed defaults (a scale of −180).

:::TuffDemoWrapper{demo="ConceptRefractionSmoothstepDemo"}
:::

## The SVG Displacement Map Pipeline

`TxGlassSurface`'s glass layer is an SVG filter, applied to what lies behind it as `backdrop-filter: url(#…)`:

:::TuffCodeBlock{lang="xml"}
---
code: |
  <!-- TxGlassSurface's filter (simplified, default parameters) -->
  <filter id="tx-glass-filter-…" color-interpolation-filters="sRGB">
    <!-- Displacement map: an SVG generated at the element's size, a horizontal red gradient,
         a vertical blue one and a blurred grey patch in the middle -->
    <feImage href="data:image/svg+xml,…" result="map" />
    <!-- One displacement per channel: scale = distortionScale + the channel's offset -->
    <feDisplacementMap in="SourceGraphic" in2="map" scale="-180" xChannelSelector="R" yChannelSelector="G" result="dispRed" />
    <feColorMatrix in="dispRed" type="matrix" values="1 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 1 0" result="red" />
    <!-- Green and blue likewise, at scales of -170 and -160 -->
    <feBlend in="red" in2="green" mode="screen" result="rg" />
    <feBlend in="rg" in2="blue" mode="screen" result="output" />
    <feGaussianBlur in="output" stdDeviation="0.5" />
  </filter>
---
:::

Inside the grey patch every point moves by the same amount, a plain shift; the bending happens in the band around the edge. The component writes the parameters onto the filter nodes with `setAttribute`, and a `ResizeObserver` regenerates the map when the element changes size. Safari and Firefox skip this filter and fall back to a `backdrop-filter` blur.
