KO7*_*O70 2 opengl fbo multisampling antialiasing
这是我第一次尝试使用opengl进行多重采样(用于抗锯齿).基本上,我正在为屏幕绘制一个背景(不应该得到消除锯齿),然后我绘制应该消除锯齿的顶点.到目前为止我做了什么:
//create the framebuffer:
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
//Generate color buffer:
glGenRenderbuffers(1, &cb);
glBindRenderbuffer(GL_RENDERBUFFER, cb);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_RGBA8, x_size, y_size);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, cb);
//Generate depth buffer:
glGenRenderbuffers(1, &db);
glBindRenderbuffer(GL_RENDERBUFFER, db);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_DEPTH_COMPONENT, x_size, y_size);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, db);
...
glBindFramebuffer(GL_FRAMEBUFFER, 0);
//draw background ... ...
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
//draw things that should get anti-aliased ... ...
//finally:
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glBlitFramebuffer(0, 0, x_size, y_size, 0, 0, x_size, y_size, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);
Run Code Online (Sandbox Code Playgroud)
问题是:当我调用glBlitFramebuffer(...)时,整个背景变黑,我只看到消除锯齿的顶点.
有什么建议?
通常,如果要在图像中考虑透明度的同时在现有渲染上渲染新图像/纹理,则混合是最明显的选项.将渲染到多重采样的帧缓冲区视为具有透明度的图像,这正是您所拥有的情况.
在这种情况下,有一些挑战使得混合的使用比平常更困难.首先,glBlitFramebuffer()不适用混合.从规格:
Blit操作绕过片段管道.影响blit的唯一片段操作是像素所有权测试和剪刀测试.
如果没有多重采样,这很容易克服.glBlitFramebuffer()您可以通过绘制屏幕大小的纹理四边形来执行blit,而不是使用它.由于现在所有片段操作都在使用,您可以使用混合.
Howerver,"绘制纹理四边形"部分变得更加棘手,因为您的内容是多重采样的.我想到了一些选择.
您可以将背景渲染到多重采样FBO而不是主帧缓冲区.然后你可以glBlitFramebuffer()像现在一样使用.
你可能会想:"但我不希望我的背景被反锯齿!" 这不是一个真正的问题.您只需在绘制背景时禁用多重采样:
glDisable(GL_MULTISAMPLE);
Run Code Online (Sandbox Code Playgroud)
我认为应该给你你想要的东西.如果确实如此,它是迄今为止最简单的选择.
OpenGL 3.2及更高版本支持多重采样纹理.为此,您将使用纹理而不是渲染缓冲区作为FBO的颜色缓冲区.纹理分配:
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8,
xsize, ysize, GL_FALSE);
Run Code Online (Sandbox Code Playgroud)
还有其他方面我不能在这里涵盖.如果您想探索此选项,可以阅读规范或其他来源中的所有详细信息.例如,着色器代码中纹理的采样工作方式不同,采样器类型不同,采样功能只允许您一次读取一个采样.
您可以使用混合glBlitFramebuffer()来解析多重采样内容,使用"手动"blit将内容混合到默认帧缓冲区中:
glBlitFramebuffer()从第一个FBO中的多重采样渲染缓冲区复制到第二个FBO中的纹理.虽然这看起来有些尴尬,并且需要一个对性能不利的额外副本,但它相当简单.
为此,您可以完成您现在正在执行的操作,将多重采样的FBO内容复制到默认的帧缓冲区glBlitFramebuffer().但你这样做第一,并呈现背景之后.
您可能认为这不起作用,因为它将背景放在其他内容的前面,这使得它不是很多背景.
但这里是混合再次发挥作用的地方.虽然在混合其他内容上面的内容是使用混合的最常见的方式,你也可以用它来呈现的东西背后现有内容.要做到这一点,你需要一些东西:
正确的混合功能.对于前后混合,您通常使用:
glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ONE);
Run Code Online (Sandbox Code Playgroud)
这会添加以前未呈现任何内容的新渲染(即目标中的alpha为0),并且在已经渲染(即目标alpha为1)的情况下将保持先前渲染不变.
如果渲染涉及部分透明度,则混合设置会变得有点棘手.
这看起来有点复杂,但是一旦你了解混合功能的工作方式,它就会非常直观.而且我认为它总体上是一个优雅而有效的解决方案,可以解决您的整体问题.
| 归档时间: |
|
| 查看次数: |
2850 次 |
| 最近记录: |