我需要用非常精细的细节来增强一些机械部件的视觉感知,所以我现在正在玩 screen.space 环境光遮蔽的不同实现。
到现在为止,我一直在前向渲染中将我的几何图形直接绘制到屏幕上,方法是使用gl.TRIANGLES
双倍的画布分辨率和抗锯齿功能,例如,假设我的画布样式是 800x600 像素,然后我的画布宽度/高度设置为 1600x1200 . 只有将屏幕抗锯齿与如此高分辨率一起使用,我才能获得所需的视觉质量。
通过使用渲染缓冲区,由于缺少抗锯齿,即使以双倍分辨率渲染,我也无法接近所需的质量。我尝试在额外的后处理步骤中实现许多不同的抗锯齿技术,但无论如何我无法获得干净、流畅的线条。这是我的意思的一个示例:查看图像底部的长而略微旋转的部分。
有什么方法可以通过在屏幕空间后处理期间绘制后缓冲区来获得干净、抗锯齿的线条?任何关于其他策略/技术的额外提示将不胜感激。
是否有人成功实施——仅举一个例子——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 );
}
编辑:
下面我将使用 John Chapman 在这个伟大的SSAO 教程中描述的 SSAO 技术。
左边是四倍分辨率,右边是全分辨率,带有分离的高斯模糊。
请注意,使用一些经典的更“有机”或“弯曲”的模型(例如茶壶、斯坦福龙或快乐佛陀)不会令人不安。这些人工制品在规则的几何长物体、典型的机械或建筑形状中很明显。
有没有什么方法可以增强深度感知,通过保持质量和保留高频细节,而不使用四倍的画布分辨率?
编辑2:
最终结果在视网膜显示器上的全画布尺寸下看起来非常好,例如在 iPad 上,它的分辨率为每英寸 264 像素。但是,锯齿状线条在桌面显示器上清晰可见且令人不安,通常为 70 或 92 DPI。
我发现了这篇文章:来自 Íñigo Quílez 的多分辨率环境光遮蔽,其中还包含一些关于高频遮蔽的提示 - 程序遮蔽以增强微小细节,但我无法理解这是否也适用于直线几何形状。有人已经对此进行了实验吗?
编辑3:
这是迄今为止我找到的关于这个主题的最有用的参考资料:GPU Gems 2中的Fast Prefiltered Lines。有人已经将这里描述的技术与 SSAO 一起实现了吗?