3

Lately I implemented the FXAA algorithm into my OpenGL application. I haven't understand this algorithm completely by now but I know that it uses contrast data of the final image to selectively apply blurring. As a post processing effect that makes sense. B since I use deferred shading in my application I already have a depth texture of the scene. Using that it might be much easier and more precise to find edges for applying blur there.

So is there a known antialiasing algorithm using the depth texture instead of the final image to find the edges? By fakes I mean an antialiasing algorithm based on a pixel basis instead of a vertex basis.

danijar
  • 27,743
  • 34
  • 143
  • 257
  • We've done this. It does allow early classification of edges for post-processing, but it has issues spotting edges in very fine geometry, where the depth does not vary enough. I have no immediate reference, we just applied our normal method but with the depth buffer as an input (we may have presented this at GDC, but I don't have a link to hand). – JasonD Jan 28 '13 at 20:07
  • @JasonD. Thanks, thats a start. I will implement something like that myself the next days. – danijar Jan 30 '13 at 14:51

1 Answers1

3

After some research I found out that my idea is widely used already in deferred renderers. I decided to post this answer because I came up with my own implementation which I want to share with the community.

Based on the gradient changes of the depth and the angle changes of the normals, there is blurring applied to the pixel.

// GLSL fragment shader

#version 330

in vec2 coord;
out vec4 image;

uniform sampler2D image_tex;
uniform sampler2D position_tex;
uniform sampler2D normal_tex;
uniform vec2 frameBufSize;

void depth(out float value, in vec2 offset)
{
    value = texture2D(position_tex, coord + offset / frameBufSize).z / 1000.0f;
}

void normal(out vec3 value, in vec2 offset)
{
    value = texture2D(normal_tex, coord + offset / frameBufSize).xyz;
}

void main()
{
    // depth

    float dc, dn, ds, de, dw;
    depth(dc, vec2( 0,  0));
    depth(dn, vec2( 0, +1));
    depth(ds, vec2( 0, -1));
    depth(de, vec2(+1,  0));
    depth(dw, vec2(-1,  0));

    float dvertical   = abs(dc - ((dn + ds) / 2));
    float dhorizontal = abs(dc - ((de + dw) / 2));
    float damount = 1000 * (dvertical + dhorizontal);

    // normals

    vec3 nc, nn, ns, ne, nw;
    normal(nc, vec2( 0,  0));
    normal(nn, vec2( 0, +1));
    normal(ns, vec2( 0, -1));
    normal(ne, vec2(+1,  0));
    normal(nw, vec2(-1,  0));

    float nvertical   = dot(vec3(1), abs(nc - ((nn + ns) / 2.0)));
    float nhorizontal = dot(vec3(1), abs(nc - ((ne + nw) / 2.0)));
    float namount = 50 * (nvertical + nhorizontal);

    // blur

    const int radius = 1;
    vec3 blur = vec3(0);
    int n = 0;
    for(float u = -radius; u <= +radius; ++u)
    for(float v = -radius; v <= +radius; ++v)
    {
        blur += texture2D(image_tex, coord + vec2(u, v) / frameBufSize).rgb;
        n++;
    }
    blur /= n;

    // result

    float amount = mix(damount, namount, 0.5);
    vec3 color = texture2D(image_tex, coord).rgb;
    image = vec4(mix(color, blur, min(amount, 0.75)), 1.0);
}

For comparison, this is the scene without any anti-aliasing.

scene without anti-aliasing

This is the result with anti-aliasing applied.

scene with anti-aliasing

You may need to view the images at their full resolution to judge the effect. In my view the result is adequate for the simple implementation. The best thing is that there are nearly no jagged artifacts when the camera moves.

danijar
  • 27,743
  • 34
  • 143
  • 257
  • got any screen shots of what this looks like with and without the shader? – Alnitak Mar 08 '13 at 22:56
  • @SAKrisT It is the draw distance. I suggest passing that parameter as uniform though. – danijar Dec 01 '13 at 14:20
  • @SAKrisT The position texture is in view space, so the depth values are between the near plane and the far plane. Since we just want to find discontinuities in depth, dividing by the far plane is sufficient. Exact would be to take the near plane into account `(x - near) / (far - near)`. Besides this, the best way for fetching depth would be reading the depth buffer and converting its values in linear space. – danijar Dec 01 '13 at 14:32
  • @danijar thanks for your explanation! I have question on [stack](http://stackoverflow.com/questions/20198855/anti-aliasing-issue-with-supersample-drawing-csg-with-depth-and-fbo) , maybe you can help. Could you have look please? – Volodymyr B. Dec 02 '13 at 10:34
  • Found [this](https://gist.github.com/sakrist/7912905) implementation of FXAA. Maybe will be useful for you. – Volodymyr B. Dec 11 '13 at 15:57
  • Can you provide me the complete code base? AA implementation along with the test program which generates the given image. I work in the field of randomized algorithms. My current results may be useful in sampling-based techniques of AA. I want to test it. Without going into much detail of openGL. Thats why I am asking for it. TIA – manmatha Jun 24 '19 at 07:32