Anteru's blog
  • Consulting
  • Research
    • Assisted environment probe placement
    • Assisted texture assignment
    • Edge-Friend: Fast and Deterministic Catmull-Clark Subdivision Surfaces
    • Error Metrics for Smart Image Refinement
    • High-Quality Shadows for Streaming Terrain Rendering
    • Hybrid Sample-based Surface Rendering
    • Interactive rendering of Giga-Particle Fluid Simulations
    • Quantitative Analysis of Voxel Raytracing Acceleration Structures
    • Real-time Hybrid Hair Rendering
    • Real-Time Procedural Generation with GPU Work Graphs
    • Scalable rendering for very large meshes
    • Spatiotemporal Variance-Guided Filtering for Motion Blur
    • Subpixel Reconstruction Antialiasing
    • Tiled light trees
    • Towards Practical Meshlet Compression
  • About
  • Archive

Subpixel Reconstruction Antialiasing

Matthäus G. Chajdas1,3, Morgan McGuire3,2, David Luebke3

1Technische Universität München, 2Williams College, 3NVIDIA

3-way split image showing the input scene, 16x anti-aliasing applied, and 4x SRAA with comparable quality.
From left to right, SRAA input, 16x anti-aliasing, 4x SRAA (Scene courtesy of DICE from the Frostbite 2 gameengine

Accepted to ACM SIGGRAPH Symposium on Interactive 3D Graphics and Games 2011

Abstract

Subpixel Reconstruction Antialiasing (SRAA) combines singlepixel (1x) shading with subpixel visibility to create antialiased images without increasing the shading cost. SRAA targets deferred shading renderers, which cannot use multisample antialiasing. SRAA operates as a post-process on a rendered image with super-resolution depth and normal buffers, so it can be incorporated into an existing renderer without modifying the shaders. In this way SRAA resembles Morphological Antialiasing (MLAA), but the new algorithm can better respect geometric boundaries and has fixed runtime independent of scene and image complexity. SRAA benefits shading-bound applications. For example, our implementation evaluates SRAA in 1.8 ms (1280x720) to yield antialiasing quality comparable to 4-16x shading. Thus SRAA would produce a net speedup over supersampling for applications that spend 1 ms or more on shading; for comparison, most modern games spend 5-10 ms shading. We also describe simplifications that increase performance by reducing quality.

Download

  • Paper
  • Subpixel reconstruction anti-aliasing video (updated, see below for details)

Bibtex

@InProceedings{CML11,
    author       = "Chajdas, Matth{\"a}us G. and Mc{G}uire, Morgan and Luebke, David",
    title        = "Subpixel Reconstruction Antialiasing",
    booktitle    = "Proceedings of the ACM SIGGRAPH Symposium on Interactive 3D Graphics and Games",
    year         = "2011",
    publisher    = "ACM Press"
}

Kernel source

float3 normal(int x, int y)
{
    return normalBuffer.Get(x, y) * 2.0 -
        make_float3(1, 1, 1);
}

float depth(int x, int y)
{
    return depthBuffer.Get(x, y);
}

float bilateral(float3 centerN, float centerZ,
                float3 tapN, float tapZ)
{
    return exp(-scale * max((1.0 - dot(centerN, tapN)),
        depthScale * abs(centerZ - tapZ)));
}

// Iterate the "center" (cx, cy) of the filter
// over the samples in the pixel at (x, y)
float weights[9] = {0};
for (int cy = y; cy < (y + 2); ++cy) {
    for (int cx = x; cx < (x + 2); ++cx) {
        float3 N = normal(cx, cy);
        float Z = depth(cx, cy);
        float tmpWeights[9] = {0};
        float sum = 0.0f;

        // Iterate over the neighboring samples
        for (int j = 0; j < 3; ++j) {
            for (int i = 0; i < 3; ++i) {
                // If inside filter support
                if ((abs(i - 1 - cx) <= 1) && (abs(j - 1 - cy) <= 1)) {
                    int tapX = x + i - 1;
                    int tapY = y + j - 1;
                    // Compute the filter weight
                    float w = bilateral (N, Z,
                        normal(tapX, tapY), depth(tapX, tapY));
                    tmpWeights[i + j * 3] = w;
                    sum += w;
                }
            }
        }

        for (int t = 0; t < 9; ++t) {
            weights[t] += tmpWeights[t] / sum;
        }
    }
}

// Apply the filter
float3 result = make_float3 (0, 0, 0);
for (int j = 0; j < 3; ++j) {
    for (int i = 0; i < 3; ++i) {
        result += weights[i + j * 3] * 0.25 *
        colorBuffer.Get(x + i - 1, y + j - 1);
    }
}

Updates

  • 1.3.2011, 8:30 UTC: Added full-resolution screenshots.
  • 1.3.2011, 10:20 UTC: Updated video, re-encoded with twice the bit-rate.
  • 7.3.2011, 7:00 UTC: Added fixed kernel source. Bilateral call was incorrect.
  • 28.03.2011, 8:00 UTC: Updated video again, the 4-up part is now compressed from new source material with higher quality.
  • 23.10.2012, 8:00 UTC: Updated the paper link, should work again.

Recent posts

  • Data formats: Why CSV and JSON aren't the best
    Posted on 2024-12-29
  • Replacing cron with systemd-timers
    Posted on 2024-04-21
  • Open Source Maintenance
    Posted on 2024-04-02
  • Angular, Caddy, Gunicorn and Django
    Posted on 2023-10-21
  • Effective meetings
    Posted on 2022-09-12
  • Older posts

Find me on the web

  • GitHub
  • GPU database
  • Projects

Follow me

Anteru NIV_Anteru
Contents © 2005-2025
Anteru
Imprint/Impressum
Privacy policy/Datenschutz
Made with Liara