多重采样纹理在地平线上产生伪影

时间:2015-08-03 15:51:20

标签: opengl deferred-rendering

我实现了延迟渲染,并尝试使用多重采样纹理进行抗锯齿。

我将场景渲染为具有多重采样纹理的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();

这会在地平线(几何体和天空盒之间)产生可见线。 颜色是清晰的颜色。只有清除深度才能减少移动时的问题。在渲染几何体之前将SkyBox渲染到FBO会产生较少的可见伪像,但该线仍然存在。

编辑:忘了图片 enter image description here

1 个答案:

答案 0 :(得分:1)

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

如果您希望使用延迟渲染进行多重采样,则必须使用多重采样目标进行照明,并且必须启用每个样本着色并实际访问并单独点亮每个样本,并且仅将最终结果blit到非多重采样目标。然而,这将是昂贵的。您尤其失去了多重采样与超级采样的优势。

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