Course outline
Anti-Aliasing
In one line
Slanted edges on a pixel grid look like steps. MSAA smooths them while drawing, FXAA and SMAA smooth the finished picture. The catch: the canvas's MSAA does not reach a composer's pictures unless you ask for it.
Think of it like this
Draw a diagonal line on squared paper by colouring whole squares. It looks like a staircase. Now colour the squares along the line a pale grey instead of all-or-nothing: from far away the stairs vanish. Anti-aliasing is deciding that pale grey for every edge pixel.
Words you'll meet
New words in this topic, in plain English. Come back here whenever one feels fuzzy.
- aliasing
- The stair-step look of slanted edges on a pixel grid.
- MSAA
- Multisample anti-aliasing: several sample points per pixel while drawing triangles.
- FXAA
- Fast approximate anti-aliasing: one pass that blurs detected edges in the finished picture.
- SMAA
- Subpixel morphological anti-aliasing: finds edge shapes in the finished picture and blends along them.
- samples
- How many points per pixel MSAA tests. 4 is the usual choice.
Step by step
01Draw a white wedge on black
Every edge is slanted: the hardest case. A "soft pixel" is one that is neither black nor white (red between 10 and 245). More soft pixels along the edge means smoother edges.
02Compare the canvas with and without MSAA
antialias: false gives 0 soft pixels: pure staircase. antialias: true gives 450.
03Add a composer
The same renderer, with antialias: true, drawing through a plain EffectComposer gives 0 again. The flag still says true, but the picture the canvas receives was made in targets with no samples.
04Bring the smoothing back
samples: 4 on the composer's target gives 450. SMAAPass after OutputPass gives 595 (after its lookup pictures load). The FXAA ShaderPass gives 759: the most soft pixels, because it blurs a wide band.
Try it yourself
- 1
More samples
In the first example change
samples: 4tosamples: 8inside thenew THREE.WebGLRenderTarget(300, 150, { ... })line (the label text still says 4). It still printssoft edge pixels 450, because the software GPU used for these runs allows 4 samples at most (renderer.capabilities.maxSamplesprinted 4 here) and a larger request is clamped without an error. On your GPU that number says what you can ask for. - 2
No samples
Change
samples: 4tosamples: 0in the same line. The line labelledcomposer, samples: 4:(the label is only text) now printssoft edge pixels 0: no samples, no smoothing.
Code & diagrams
The counts come from this software GPU: another GPU's MSAA pattern gives a different number, but 0 stays 0. The pause lets SMAA's lookup pictures load.
Console
Run the scene to see its console.Expected console output
no anti-aliasing: soft edge pixels 0
antialias: true: soft edge pixels 450
same renderer + composer: soft edge pixels 0
composer, samples: 4: soft edge pixels 450
composer + SMAA: first frame: 0
composer + SMAA: soft edge pixels 595
composer + FXAA: soft edge pixels 759Sharpness is the average jump between neighbouring pixels on one row: 128 for 1-pixel white lines, 3 black pixels apart.
Console
Run the scene to see its console.Expected console output
no pass sharpness 128
SMAA sharpness 128
FXAA sharpness 58Break it on purpose
Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.
Break #1
antialias: true and a composer
In the first example read the line same renderer + composer:.
Break #2
SMAA on the first frame
In the first example read the line composer + SMAA: first frame:.
Myth vs fact
Myth
antialias: true smooths everything the canvas shows.
Fact
It smooths only what the renderer draws onto the canvas directly. A composer, a render target or a shader effect does its own thing.
Pro corner
Extra depth for experienced readers. New to this? Skip it for now and come back later.
- ▸
MSAA memory grows with the samples: a half-float target at 1920 × 1080 with 4 samples holds 1920 × 1080 × 8 × 4 = 66,355,200 bytes (about 63 MB) of colour, plus the resolved copy. That is why phones often skip MSAA for SMAA, or nothing.
- ▸
In the WebGPU node pipeline
pass(scene, camera)copiesrenderer.samplesinto its target (it printed 4 withantialias: trueon a real WebGPU adapter and in the WebGL 2 fallback), so MSAA survives post-processing there without extra code. The third example of Topic 15.2 prints it.
Remember this
- 1
The problem this solves: a pixel is either inside a shape or outside it, so edges at an angle show steps ("jaggies"), and they crawl when the camera moves. The fix is to estimate how much of each edge pixel the shape covers and blend the colours.
- 2
MSAA (multisample anti-aliasing) asks the GPU to test several points inside each pixel while drawing triangle edges. It is exact for geometry edges, cheap on the GPU, and costs memory in proportion to the samples.
new WebGLRenderer({ antialias: true })asks the browser for an anti-aliased canvas (browsers commonly give 4 samples, but the number is the browser's choice and some browsers or GPUs refuse). - 3
The catch with a composer. The canvas is MSAA, but a composer's pictures are plain render targets with no samples. Everything is drawn into them first, so the smooth edges are gone before the canvas sees the picture. The first example: a wedge has 450 soft edge pixels with
antialias: true, and 0 once the same renderer draws through anEffectComposer. (The counts come from the software GPU these examples run on; another GPU gives other counts, but 0 stays 0.) - 4
Three fixes. (1) Give the composer's target samples:
new WebGLRenderTarget(w, h, { type: HalfFloatType, samples: 4 }). The composer clones it for its second target. 450 soft pixels again. (2)SMAAPass, a post-process that finds edges in the finished picture: 595 soft pixels. (3) FXAA, a one-pass blur of detected edges: 759. - 5
What each costs and misses. MSAA costs memory (4 × the colour data) and cannot smooth edges made by shaders or textures. SMAA is a few full-screen passes and keeps fine detail. FXAA is one pass, the cheapest, but it blurs everything that looks like an edge, textures too: in the second example a line pattern drops from sharpness 128 to 58 under FXAA, while SMAA leaves it at 128.
- 6
SMAA starts a moment late.
SMAAPassloads two lookup pictures from embedded image data, and image decoding is asynchronous. In the first example SMAA's first frame has 0 soft pixels. Later frames have 595.
Explain it without notes
Why do edges become jagged when you add a composer to a renderer created with antialias: true?
Compare MSAA, SMAA and FXAA for a showroom page for phones.
Practice
Create a composer whose pictures keep 4-sample MSAA.
Add FXAA at the right place in the chain Render, Bloom, Output.
Done when you can
Explain why a composer loses the canvas's MSAA
Restore smooth edges with target samples, SMAA or FXAA
Place SMAA and FXAA after OutputPass
Name what each method costs and what it blurs