我需要用非常精细的细节增强某些机械零件的视觉感知,因此我现在正在使用screen.space环境光遮挡的不同实现方式进行游戏。

到目前为止,我是通过使用gl.TRIANGLES以两倍于画布分辨率将抗锯齿功能直接在正向渲染中将几何图形绘制到屏幕上的,例如,假设我的画布样式为800x600 px,那么我的画布宽度/高度为设置为1600x1200。只有将屏幕抗锯齿与如此高分辨率结合使用,我才能获得所需的视觉质量。

通过使用渲染缓冲区,由于缺少抗锯齿,即使通过两倍的分辨率进行渲染,也无法达到所需的质量。我试图在一个额外的后处理步骤中实现许多不同的抗锯齿技术,但是无论如何我都无法获得干净,流畅的线条。这是我的意思的一个示例:在图像底部看到长而略微旋转的部分。

opengl-es - SSAO深度后处理期间的抗锯齿-LMLPHP

在屏幕空间后处理过程中,是否有任何方法可以通过在后缓冲区中绘制来获得干净的抗锯齿线条?关于其他策略/技术的任何其他提示将不胜感激。

是否有人成功地实施了FXAA(仅举一个例子)或FXAA,在SSAO传递过程中获得了平滑的抗锯齿长对角线,而不会造成锯齿?



这是与上图相关的片段着色器:

float compareDepths(in float depth1,in float depth2, in float aoMultiplier) {
    float aoCap = 1.0;
    float diff = sqrt( clamp(1.0-(depth1-depth2) / (u_aoRange/(u_zFar-u_zNear)),0.0,1.0) );
    float ao = min(aoCap,max(0.0, depth1 - depth2 - u_depthTolerance) * aoMultiplier) * diff;
    return ao;
}
void main(void) {
    vec2 UV = v_texCoord.st;
    float depth = readDepth(UV);
    float d;
    float pw = 1.0 / u_resolution.x;
    float ph = 1.0 / u_resolution.y;
    float aoCap = 1.0;
    float ao = 0.0;
    float aoMultiplier = u_aoMultiplier;

    // 4 samples w/out loop
    float aoscale=1.0;
    d=readDepth( vec2(UV.x+pw,UV.y+ph));
    ao+=compareDepths(depth, d, aoMultiplier)/aoscale;
    d=readDepth( vec2(UV.x-pw,UV.y+ph));
    ao+=compareDepths(depth, d, aoMultiplier)/aoscale;
    d=readDepth( vec2(UV.x+pw,UV.y-ph));
    ao+=compareDepths(depth, d, aoMultiplier)/aoscale;
    d=readDepth( vec2(UV.x-pw,UV.y-ph));
    ao+=compareDepths(depth, d, aoMultiplier)/aoscale;

    pw*=2.0;
    ph*=2.0;
    aoMultiplier/=2.0;
    aoscale*=1.2;
    d=readDepth( vec2(UV.x+pw,UV.y+ph));
    ao+=compareDepths(depth, d, aoMultiplier)/aoscale;
    d=readDepth( vec2(UV.x-pw,UV.y+ph));
    ao+=compareDepths(depth, d, aoMultiplier)/aoscale;
    d=readDepth( vec2(UV.x+pw,UV.y-ph));
    ao+=compareDepths(depth, d, aoMultiplier)/aoscale;
    d=readDepth( vec2(UV.x-pw,UV.y-ph));
    ao+=compareDepths(depth, d, aoMultiplier)/aoscale;

    pw*=2.0;
    ph*=2.0;
    aoMultiplier/=2.0;
    aoscale*=1.2;
    d=readDepth( vec2(UV.x+pw,UV.y+ph));
    ao+=compareDepths(depth, d, aoMultiplier)/aoscale;
    d=readDepth( vec2(UV.x-pw,UV.y+ph));
    ao+=compareDepths(depth, d, aoMultiplier)/aoscale;
    d=readDepth( vec2(UV.x+pw,UV.y-ph));
    ao+=compareDepths(depth, d, aoMultiplier)/aoscale;
    d=readDepth( vec2(UV.x-pw,UV.y-ph));
    ao+=compareDepths(depth, d, aoMultiplier)/aoscale;

    pw*=2.0;
    ph*=2.0;
    aoMultiplier/=2.0;
    aoscale*=1.2;
    d=readDepth( vec2(UV.x+pw,UV.y+ph));
    ao+=compareDepths(depth, d, aoMultiplier)/aoscale;
    d=readDepth( vec2(UV.x-pw,UV.y+ph));
    ao+=compareDepths(depth, d, aoMultiplier)/aoscale;
    d=readDepth( vec2(UV.x+pw,UV.y-ph));
    ao+=compareDepths(depth, d, aoMultiplier)/aoscale;
    d=readDepth( vec2(UV.x-pw,UV.y-ph));
    ao+=compareDepths(depth, d, aoMultiplier)/aoscale;

    ao/=16.0;',
    gl_FragColor = vec4( vec3(1.0-ao), 1.0 );
}


编辑:

下面,我在此很棒的SSAO Tutorial中使用John Chapman描述的SSAO技术。

左为四倍分辨率,右为全分辨率,具有分离的高斯模糊。

opengl-es - SSAO深度后处理期间的抗锯齿-LMLPHP

请注意,使用一些经典的更“有机”或“弯曲”的模型(例如茶壶,斯坦福巨龙或佛陀)不会干扰这些文物。这些伪影在规则的几何长物体,典型的机械或建筑形状中很明显。

是否有任何方法可以通过保持画质并保留高频细节而不使用四倍的画布分辨率来增强深度感?

编辑2:

最终结果在视网膜显示屏上的完整画布尺寸下看起来非常好,例如在iPad上,每英寸分辨率为264像素。但是,锯齿线清晰可见,并且在台式机显示器上通常为70或92 DPI。

我在ÍñigoQuílez上找到了这篇文章:multiresolution ambient occlusion,其中也包含一些有关高频遮挡的提示-程序性遮挡以增强微小的细节,但是我无法理解这是否也适用于直的几何形状。有人已经尝试过了吗?

编辑3:

这是到目前为止我找到的关于该主题的最有用的参考:GPU Gems 2中的Fast Prefiltered Lines
有人已经与SSAO一起实施了此处描述的技术?

最佳答案

Screen Space Ambient Occlusion捕获低频照明。它不会捕获锐利的阴影,漫反射或镜面照明。因此,SSAO通常与“漫反射”和“镜面反射”照明结合使用以创建完整的照明解决方案。

SSAO在3D渲染的场景中显示全局灯光效果作为后期效果。它可以快速近似昂贵的光线跟踪的全局照明。因此,在某些情况下(例如您的情况)可能会出现伪影。

SSAO很少能立即使用,但需要进行一些调整。设置过程涉及调整Kernel RadiusNumber Of Samples以获得所需的效果。 Kernel Radius取决于场景的自然scale。最初似乎根本没有SSAO。此时Kernel Radius太小或太大,必须找到工作值。请记住:SSAO在CPU上非常慢,但在GPU上性能要好得多。

解:
将多个SSAO渲染通道与不同的Kernel Radii组合在一起可以产生更好的效果。

看图片的右下角:

(三张相乘的图像会生成具有特定细节的最终图像)

opengl-es - SSAO深度后处理期间的抗锯齿-LMLPHP

09-25 16:31