Files
wsg/docs/user/effects/msaa.md
T
Jérôme Bousquié d4c2d93fc5 eng doc
2026-09-25 20:06:10 +02:00

2.7 KiB

MSAA (anti-aliasing)

MSAA (Multisample Anti-Aliasing) smooths the edges of meshes by sampling each pixel multiple times at rasterization time (before the fragment shader).

Enabling

use wsg_lib::prelude::*;

let app = AppBuilder::new()
    .with_msaa(4)   // 4x MSAA
    .build()
    .await?;
  • Without with_msaa: the swapchain is used as-is (1x, no cost).
  • With with_msaa(4): the swapchain is created with sample_count = 4, and a resolve pass (multisample → swapchain) runs at the end of each frame.

Cost

  • The main pass becomes more expensive (fragment shader run sample_count times per pixel on aliased edges — in practice much less, since fully-covered pixels are only processed once).
  • One extra fullscreen resolve per frame (GPU-native, very cheap).
  • VRAM: the swapchain buffer is multiplied by sample_count (4x for 4x MSAA).

In practice: 4x MSAA is negligible on a discrete GPU and perfectly acceptable on an integrated one for scenes of this complexity.

MSAA + HDR

The two compose naturally:

Scene ──→ HDR multisample texture (sample_count = N)
              │
              ▼  resolve
          HDR texture (single sample)
              │
              ▼  (bloom?)
              ▼  tone mapping
          Swapchain (sRGB)
  • with_msaa(4) + with_hdr(…): the offscreen HDR texture becomes multisample and is resolved before tone mapping (and before bloom, which operates on the single-sample buffer).
  • with_msaa(4) without HDR: the swapchain itself is multisample, resolved at the end of the frame.

MSAA + fog

Fog is applied inside the fragment shader (per sample), so it is inherently MSAA-compatible: each sample computes its own fog factor based on its own depth. No aliasing on the fog boundaries.

What MSAA does NOT fix

  • Transparency aliasing (there is no transparency in the engine — all opaque).
  • Texture shimmering at distance: this is the domain of anisotropic filtering (already enabled: SampleFilter::AnisotropicClamped + anisotropy = 4).
  • Temporal flicker of fine details: this would be the domain of TAA (out of scope).

Limitations

  • sample_count is fixed at swapchain creation (not changeable at runtime without recreating the window/surface).
  • 2 and 4 are the useful values. 8 exists but the cost/quality ratio is bad.
  • Not all adapters support MSAA on the swapchain — if unsupported, the builder falls back to 1x with a warning.

See lib/examples/effects/msaa.rs for a full interactive demo (torus + Icosphere, with zoom/orbit, MSAA 4x by default).