PAJAMA / LEARN
← Course overview

See how pixels are made / 02 OF 12

Why a Gaussian is a soft brush

After this lessonBuild the Gaussian weight from subtraction, division, squaring and an exponential; then understand covariance.

A brush is strongest at its center and gradually fades outward. We need a rule that is smooth, symmetric, and easy to stretch or rotate.

Build the idea, one step at a time

Need a math refresher?

Open only the tool you need; return here to use it in the next step.

Exponentials & logarithmsMatrices & covariance

STEP 1 / 5

Measure distance in brush widths

Subtract the center μ from a location x. Divide by scale s: now the distance has no unit. At x = μ + s, the normalized distance is 1, regardless of whether the brush is one centimeter or one meter wide. Square it so the left and right sides receive the same value.

d=x−μs,d2=(x−μs)2d=\frac{x-\mu}{s},\qquad d^2=\left(\frac{x-\mu}{s}\right)^2

PUT NUMBERS IN

At x − μ = 2, scale 2 gives G = exp(−0.5) ≈ 0.6065. Scale 1 gives exp(−2) ≈ 0.1353. With opacity 0.8, their uncapped alphas are 0.4852 and 0.1083.

FORMULA → RUNNING CODE

Find the same operation in the code

These excerpts are read from the current repository when the site is built. Expand one to inspect it; the full snapshot opens in a separate tab.

public/learn/models.mjsL3–3

The exact arithmetic behind this lesson’s controls and worked example.

export function kernel(x,scale,opacity=1){return opacity*Math.exp(-0.5*(x/scale)**2);}
Open the deployed source snapshot ↗
src/splat.wgslL65–73

Exponentials, opacity and normalized rotation are evaluated before projection.

  let temporal_scale = max(exp(splat.r1.x), 0.000001);
  let temporal_opacity = exp(-pow(dt / temporal_scale, 2.0));
  let opacity = (1.0 / (1.0 + exp(-splat.r5.x))) * temporal_opacity;
  let scales = exp(splat.r5.yzw);
  let quaternion = normalize(splat.r6 + dt * splat.r7);
  let w = quaternion.x;
  let x = quaternion.y;
  let y = quaternion.z;
  let z = quaternion.w;
Open the deployed source snapshot ↗
src/splat.wgslL77–93

Scaled rotation axes encode the covariance without a general matrix inverse.

  let axis0 = scales.x * vec3<f32>(
    1.0 - 2.0 * (y * y + z * z),
    2.0 * (x * y + w * z),
    2.0 * (x * z - w * y)
  );
  let axis1 = scales.y * vec3<f32>(
    2.0 * (x * y - w * z),
    1.0 - 2.0 * (x * x + z * z),
    2.0 * (y * z + w * x)
  );
  let axis2 = scales.z * vec3<f32>(
    2.0 * (x * z + w * y),
    2.0 * (y * z - w * x),
    1.0 - 2.0 * (x * x + y * y)
  );

  let center_clip = camera.view_proj * vec4<f32>(center, 1.0);
Open the deployed source snapshot ↗

CHECK YOUR UNDERSTANDING

Can you predict the result?

At the center, what is G before multiplying by opacity?

This is your own review mark. You can remove it at any time.

Go deeper with primary sources

3D Gaussian Splatting · paper & implementation ↗Full mathematical derivation ↗