多重采样纹理在 horizon 处产生伪影

Multisample Texture produces artifacts at horizon

我已经实现了延迟渲染,并且正在尝试使用多重采样纹理来消除锯齿。

我将场景渲染到具有多采样纹理的 FBO 中,使用 glBlit 在第二个 FBO 中创建常规纹理,最后将纹理绑定到产生最终图像的光照着色器。

// draw to textures
mMultiGeometryFBO->bind();
glViewport(0,0,mWidth,mHeight);
glEnable(GL_DEPTH_TEST);
glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT );

// calling all modules to draw to FBO
for(auto r : mRenderer)
    r->renderMaterial(camera);

glBindFramebuffer(GL_READ_FRAMEBUFFER, mMultiGeometryFBO->fbo());
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mGeometryFBO->fbo());

glReadBuffer(GL_COLOR_ATTACHMENT0);
glDrawBuffer(GL_COLOR_ATTACHMENT0);
glBlitFramebuffer(0, 0, mWidth, mHeight,
                  0, 0, mWidth, mHeight, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_LINEAR);

glReadBuffer(GL_COLOR_ATTACHMENT1);
glDrawBuffer(GL_COLOR_ATTACHMENT1);
glBlitFramebuffer(0, 0, mWidth, mHeight,
                  0, 0, mWidth, mHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR);

glReadBuffer(GL_COLOR_ATTACHMENT2);
glDrawBuffer(GL_COLOR_ATTACHMENT2);
glBlitFramebuffer(0, 0, mWidth, mHeight,
                  0, 0, mWidth, mHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR);

// draw to screen
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClear(GL_DEPTH_BUFFER_BIT);

mSkybox->renderMaterial(camera);

mShader->use();
mShader->setTexture("tDiffuse", mDiffuseColor, 0);
mShader->setTexture("tNormal", mNormals, 1);
mShader->setTexture("tMaterial", mMaterialParams, 2);
mShader->setTexture("tDepth", mDepthBuffer, 3);
mShader->setTexture("tLights", mLightColor, 4);
mQuad->draw();

这会在 horizon 处(几何体和天空盒之间)生成一条可见线。 颜色是清澈的颜色。只有清除深度才能减少移动时的问题。在渲染几何体之前将 SkyBox 渲染到 FBO 会产生不太明显的伪像,但线条仍然存在。

编辑:忘记图片了

从概念上讲,在光照通道之前解决多重采样目标没有意义。你会得到的是你的 gbuffers 中的值将在对象的边缘进行平均。这对于法线方向尤其不利。想一想:如果你有一个包含 50% 地平面和 50% 天空的像素,你将得到一个法线方向,即 (normal_ground + normal_sky)/2。这与使用原始法线计算每个部分的最终颜色并混合结果颜色完全不同。

如果你想用延迟渲染进行多重采样,你必须为光照使用多重采样目标,并且必须启用每个样本着色并实际访问和照亮每个样本单独采样,并且只将最终结果 blit 到非多重采样目标。然而,这将非常昂贵。您尤其会失去多重采样与超级采样的优势。

我不知道是否有一些巧妙的技巧可以更有效地使用多重采样,但通常的方法是根本不使用多重采样并通过一些基于图像的方式进行抗锯齿后处理过程。