3

最近、FXAAアルゴリズムをOpenGLアプリケーションに実装しました。このアルゴリズムは今のところ完全には理解していませんが、最終的な画像のコントラストデータを使用して選択的にぼかしを適用していることは知っています。意味のある後処理効果として。Bアプリケーションで遅延シェーディングを使用しているため、シーンの奥行きテクスチャがすでにあります。これを使用すると、そこにブラーを適用するためのエッジを見つけるのがはるかに簡単で正確になる可能性があります。

では、エッジを見つけるために最終画像の代わりに深度テクスチャを使用する既知のアンチエイリアスアルゴリズムはありますか?偽物とは、頂点ベースではなくピクセルベースに基づくアンチエイリアスアルゴリズムを意味します。

4

1 に答える 1

3

いくつかの調査の結果、私のアイデアはすでに遅延レンダラーで広く使用されていることがわかりました。コミュニティと共有したい独自の実装を思いついたので、この回答を投稿することにしました。

深さの勾配の変化と法線の角度の変化に基づいて、ピクセルにぼかしが適用されます。

// 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);
}

比較のために、これはアンチエイリアシングのないシーンです。

アンチエイリアシングのないシーン

これは、アンチエイリアシングを適用した結果です。

アンチエイリアシングのあるシーン

効果を判断するには、画像をフル解像度で表示する必要がある場合があります。私の見解では、結果は単純な実装には十分です。最良の点は、カメラが動いたときにギザギザのアーティファクトがほとんどないことです。

于 2013-03-08T22:51:41.720 に答える