Skip to content

Anti-Aliasing — MSAA, FXAA, TAA and Supersampling

DodaTech Updated 2026-06-21 7 min read

In this tutorial, you'll learn about Anti. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.

Anti-aliasing eliminates jagged edges (aliasing artifacts) in rendered images by smoothing the transition between pixel colors, using techniques ranging from hardware multisampling to temporal accumulation.

What You'll Learn & Why It Matters

In this tutorial, you will learn the main anti-aliasing techniques — SSAA (supersampling), MSAA (multisample), FXAA (post-Process), and TAA (temporal). You will understand the quality-performance trade-off of each approach.

Real-world use: Every game and 3D application uses some form of anti-aliasing. The security camera feeds in Durga Antivirus Pro use FXAA for smooth edges at minimal performance cost.

Prerequisites

  • Rendering Pipeline (previous)
  • Post-Processing (previous)
  • Understanding of pixel sampling

Learning Path

flowchart LR
  A[Post-Processing] --> B[Anti-Aliasing]
  B --> C[Compute Shaders]
  B --> D[GPU Architecture]
  B --> E[Real-Time GI]
  B:::current

  classDef current fill:#f90,color:#fff,stroke:#333,stroke-width:2px

What Causes Aliasing?

Aliasing occurs because a pixel samples only one color at its center. When a triangle edge passes through a pixel, the pixel is either fully inside or fully outside, creating a staircase pattern.

import numpy as np

def render_without_aa(width, height, triangle):
    """Render a triangle without anti-aliasing."""
    image = np.zeros((height, width))
    for y in range(height):
        for x in range(width):
            cx, cy = x + 0.5, y + 0.5
            if point_in_triangle(cx, cy, triangle):
                image[y, x] = 1.0
    return image
flowchart TD
  A[Scene Geometry] --> B[Pixel Grid]
  B --> C[Single Sample Per Pixel]
  C --> D[Jagged Edges (Aliased)]
  B --> E[Multiple Samples Per Pixel]
  E --> F[Smooth Edges (Anti-Aliased)]

SSAA (Supersampling Anti-Aliasing)

SSAA renders the scene at a higher resolution (e.g., 2x or 4x) and downsamples to the display resolution. It produces the highest quality but costs the most performance.

// SSAA resolve shader - averages 4 samples
uniform sampler2D superSampledImage;
uniform vec2 texelSize;

void main()
{
    vec3 color = vec3(0.0);
    color += texture(superSampledImage, TexCoords + vec2(-0.25, -0.25) * texelSize).rgb;
    color += texture(superSampledImage, TexCoords + vec2( 0.25, -0.25) * texelSize).rgb;
    color += texture(superSampledImage, TexCoords + vec2(-0.25,  0.25) * texelSize).rgb;
    color += texture(superSampledImage, TexCoords + vec2( 0.25,  0.25) * texelSize).rgb;
    FragColor = vec4(color * 0.25, 1.0);
}

MSAA (Multisample Anti-Aliasing)

MSAA is more efficient than SSAA. It evaluates the fragment shader once per pixel but evaluates depth/stencil at multiple sub-sample positions:

// Enable MSAA in OpenGL
glEnable(GL_MULTISAMPLE);
glfwWindowHint(GLFW_SAMPLES, 4);  // Request 4x MSAA

// Create multisample framebuffer
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGB, width, height, GL_TRUE);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, tex, 0);
flowchart LR
  subgraph SSAA
    A1[4x pixels] --> A2[4x shader] --> A3[Downsample]
  end
  subgraph MSAA
    B1[1x pixels] --> B2[1x shader + 4x depth] --> B3[Resolve]
  end

MSAA Resolve

#version 330 core
uniform sampler2DMS msaaTexture;
uniform int sampleCount;

void main()
{
    vec3 color = vec3(0.0);
    ivec2 texel = ivec2(gl_FragCoord.xy);
    for (int i = 0; i < sampleCount; i++)
    {
        color += texelFetch(msaaTexture, texel, i).rgb;
    }
    FragColor = vec4(color / sampleCount, 1.0);
}

FXAA (Fast Approximate Anti-Aliasing)

FXAA is a post-Process technique that detects edges in the final image and applies blur along them:

uniform sampler2D sceneTexture;
uniform vec2 texelSize;

void main()
{
    vec3 colorCenter = texture(sceneTexture, TexCoords).rgb;

    // Edge detection using luminance
    float lumaCenter = dot(colorCenter, vec3(0.299, 0.587, 0.114));
    float lumaNorth = dot(texture(sceneTexture, TexCoords + vec2(0, 1) * texelSize).rgb, vec3(0.299, 0.587, 0.114));
    float lumaSouth = dot(texture(sceneTexture, TexCoords + vec2(0, -1) * texelSize).rgb, vec3(0.299, 0.587, 0.114));
    float lumaEast  = dot(texture(sceneTexture, TexCoords + vec2(1, 0) * texelSize).rgb, vec3(0.299, 0.587, 0.114));
    float lumaWest  = dot(texture(sceneTexture, TexCoords + vec2(-1, 0) * texelSize).rgb, vec3(0.299, 0.587, 0.114));

    // Check if this is an edge
    float edgeX = abs(lumaEast + lumaWest - 2.0 * lumaCenter);
    float edgeY = abs(lumaNorth + lumaSouth - 2.0 * lumaCenter);

    if (edgeX > 0.1 || edgeY > 0.1)
    {
        vec2 blurDir = vec2(edgeX, edgeY);
        // Blend with neighboring pixels along the edge direction
        colorCenter = (texture(sceneTexture, TexCoords + blurDir * texelSize).rgb +
                       texture(sceneTexture, TexCoords - blurDir * texelSize).rgb +
                       colorCenter * 2.0) * 0.25;
    }

    FragColor = vec4(colorCenter, 1.0);
}

TAA (Temporal Anti-Aliasing)

TAA accumulates samples across multiple frames using sub-pixel jitter:

// Per-frame jitter (Halton sequence)
float halton(int index, int base)
{
    float result = 0.0;
    float f = 1.0;
    while (index > 0)
    {
        f /= base;
        result += f * (index % base);
        index /= base;
    }
    return result;
}

// Generate jitter for current frame
int frame = 0;
vec2 jitter = vec2(halton(frame, 2) - 0.5, halton(frame, 3) - 0.5);
jitter /= vec2(screenWidth, screenHeight);

// Apply to projection matrix
projection[2].x += jitter.x;
projection[2].y += jitter.y;
// TAA resolve with history
uniform sampler2D currentFrame;
uniform sampler2D historyBuffer;
uniform vec2 velocity;

void main()
{
    vec3 current = texture(currentFrame, TexCoords).rgb;
    vec3 history = texture(historyBuffer, TexCoords - velocity).rgb;

    // Clamp history to current frame neighborhood
    vec3 neighborhoodMin = min(min(current, ...), ...);
    vec3 neighborhoodMax = max(max(current, ...), ...);
    history = clamp(history, neighborhoodMin, neighborhoodMax);

    // Blend
    float blendFactor = 0.05;
    vec3 result = mix(current, history, blendFactor);
    FragColor = vec4(result, 1.0);
}

Quality Comparison

Method Quality Cost Artifacts
None Poor 0% Jagged edges
SSAA 4x Excellent +300% None
MSAA 4x Good +50% Alpha-test edges
FXAA Fair +5% Blurred text
TAA Very Good +10% Ghosting

Common Errors & Mistakes

1. MSAA Disabled After Framebuffer Creation

Mistake: Enabling GL_MULTISAMPLE but not using a multisample framebuffer, so MSAA has no effect.

Fix: Use glTexImage2DMultisample and glFramebufferTexture2D(GL_FRAMEBUFFER, ..., GL_TEXTURE_2D_MULTISAMPLE, ...) for the FBO.

2. TAA Ghosting

Mistake: Moving objects leave trails because the history buffer contains outdated pixel data.

Fix: Apply motion vectors and neighborhood clamping to reject invalid history. Reduce blend factor for fast-moving objects.

3. FXAA Blurring Fine Details

Mistake: FXAA blurs text, UI elements, and fine textures because it cannot distinguish aliasing from detail.

Fix: Use MSAA or TAA for scenes with text or fine patterns. Apply FXAA only to the 3D scene layer, not the UI.

4. Incorrect Sample Pattern

Mistake: Using the same sub-pixel offset every frame for TAA, failing to accumulate new information.

Fix: Use a deterministic low-discrepancy sequence (Halton, Hammersley) that covers the pixel evenly over time.

Practice Questions

Question 1

Why is SSAA more expensive than MSAA?

Show answer SSAA runs the fragment shader N times per pixel (N = sample count). MSAA runs the fragment shader once per pixel but computes depth/stencil at N positions, sharing the shader result.

Question 2

What causes TAA ghosting and how do you fix it?

Show answer Ghosting occurs when the history buffer contains outdated pixel data that is blended with the current frame. Fix by using motion vectors, neighborhood clamping to reject invalid history, and reducing blend factor for moving objects.

Question 3

What is the main disadvantage of FXAA?

Show answer FXAA blurs the entire image, especially affecting text, UI elements, and fine texture details. It cannot distinguish between intended detail and aliasing artifacts.

Question 4

What are sub-pixel samples in MSAA?

Show answer Sub-pixel samples are multiple depth/stencil test locations within each pixel. The pixel color is determined by averaging the covered sub-samples. Typical configurations are 2x, 4x, or 8x samples.

Challenge

Implement a TAA system with motion vector generation, history buffer management, neighborhood clamping, and a per-frame Halton jitter sequence. Compare the quality against 4x MSAA and FXAA.

FAQ

Does anti-aliasing affect performance?

Yes, but the impact varies. FXAA costs about 1-2% performance. MSAA 4x costs about 30-50%. SSAA 4x costs about 300% (rendering 4x the pixels). TAA costs about 10-15% including motion vector rendering.

Can I use multiple AA methods together?

Yes. Some games combine TAA with MSAA, or use MSAA for geometry and FXAA for alpha-test transparency. Each combination has different quality and cost trade-offs.

Is anti-aliasing needed at 4K resolution?

At 4K, individual pixels are very small, making aliasing less noticeable. 4K with no AA often looks better than 1080p with 4x MSAA. However, shimmering on fine geometry may still be visible.

What is DLSS and is it anti-aliasing?

NVIDIA DLSS (Deep Learning Super Sampling) uses AI to reconstruct a higher-resolution image from lower-resolution input. It provides both upscaling and anti-aliasing. DLSS 3.5 includes ray reconstruction for ray-traced scenes.


Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.

Author: DodaTech | Last updated: June 21, 2026

DodaTech tutorials are built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro — security tools used by millions worldwide.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro