Graphics 是否有使用深度缓冲区的伪造抗锯齿算法?

Graphics 是否有使用深度缓冲区的伪造抗锯齿算法?,graphics,3d,antialiasing,fxaa,deferred-shading,Graphics,3d,Antialiasing,Fxaa,Deferred Shading,最近,我在OpenGL应用程序中实现了FXAA算法。我现在还没有完全理解这个算法,但我知道它使用最终图像的对比度数据来选择性地应用模糊。作为一种有意义的后处理效果。B因为我在应用程序中使用了延迟着色,所以我已经有了场景的深度纹理。使用该选项,可以更轻松、更精确地找到用于在那里应用模糊的边 那么,是否有已知的抗锯齿算法使用深度纹理而不是最终图像来查找边缘?“伪”是指基于像素而非顶点的抗锯齿算法。经过一些研究,我发现我的想法已经广泛应用于延迟渲染器。我决定发布这个答案,因为我提出了我自己的实现,我想

最近,我在OpenGL应用程序中实现了FXAA算法。我现在还没有完全理解这个算法,但我知道它使用最终图像的对比度数据来选择性地应用模糊。作为一种有意义的后处理效果。B因为我在应用程序中使用了延迟着色,所以我已经有了场景的深度纹理。使用该选项,可以更轻松、更精确地找到用于在那里应用模糊的边


那么,是否有已知的抗锯齿算法使用深度纹理而不是最终图像来查找边缘?“伪”是指基于像素而非顶点的抗锯齿算法。

经过一些研究,我发现我的想法已经广泛应用于延迟渲染器。我决定发布这个答案,因为我提出了我自己的实现,我想与社区分享

基于深度的梯度变化和法线的角度变化,对像素应用模糊

// 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);
}
//GLSL片段着色器
#330版
在vec2坐标中;
输出vec4图像;
均匀采样二维图像;
均匀取样器2D位置_tex;
均匀取样器2D法线_tex;
统一的vec2框架尺寸;
空隙深度(向外浮动值,以vec2偏移为单位)
{
值=纹理2d(位置坐标+偏移量/帧大小)。z/1000.0f;
}
无效法线(向外vec3值,向内vec2偏移)
{
值=纹理2d(正常纹理,坐标+偏移量/帧大小).xyz;
}
void main()
{
//深度
浮点数dc、dn、ds、de、dw;
深度(dc,vec2(0,0));
深度(dn,vec2(0,+1));
深度(ds,vec2(0,-1));
深度(de,vec2(+1,0));
深度(dw,vec2(-1,0));
浮动dvertical=abs(dc-((dn+ds)/2));
浮动水平=abs(dc-((de+dw)/2));
浮点数=1000*(数字+水平);
//常态
vec3北纬、北纬、北纬、东北、西北;
正常(nc,vec2(0,0));
正常(nn,vec2(0,+1));
正常(ns,vec2(0,-1));
正常(ne,vec2(+1,0));
正常(nw,vec2(-1,0));
float nvertical=dot(vec3(1),abs(nc-((nn+ns)/2.0));
浮动水平=点(vec3(1),abs(nc-((ne+nw)/2.0));
浮点数=50*(非垂直+水平);
//模糊
常数int半径=1;
vec3模糊=vec3(0);
int n=0;

对于(float u=-radius;u),我们已经这样做了。它确实允许对边缘进行早期分类以进行后期处理,但它在非常精细的几何体中发现边缘时存在问题,因为深度变化不够。我没有直接的参考,我们只是应用了我们的常规方法,但使用深度缓冲作为输入(我们可能已经在GDC上展示了这一点,但我手头没有链接).@JasonD.谢谢,这是一个开始。我将在接下来的几天里自己实现类似的操作。有没有关于使用和不使用着色器时的屏幕截图?@SAKrisT这是绘制距离。我建议统一传递该参数。@SAKrisT位置纹理在视图空间中,因此深度值在近平面和t之间远平面。因为我们只想找到深度上的不连续性,除以远平面就足够了。精确的方法是将近平面考虑进去
。除此之外,获取深度的最佳方法是读取深度缓冲区并在线性空间中转换其值。@danijar感谢您的解释!我有问题,也许您可以帮助。您能看看吗?找到了FXAA的实现。也许对您有用。