渲染到屏幕和 FBO 给出不同的结果

Posted

技术标签:

【中文标题】渲染到屏幕和 FBO 给出不同的结果【英文标题】:Render to screen and to FBO give different result 【发布时间】:2014-06-22 22:00:20 【问题描述】:

我编写了一个程序来将带有纹理的正方形渲染到屏幕和 FBO。我相信这两种情况的渲染结果应该是相同的,只是输出目的地不同。令人惊讶的是,它给了我完全不同的结果。

对于第一张图片,我直接输出到屏幕上。这很好,没有任何问题。对于第二张图像,我将其渲染为带有纹理的 FBO,然后将该纹理渲染到屏幕上。在这种情况下,输出完全混乱,似乎输出只包含图像的左上角。

相关代码为:

def render(self):
    gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)

    gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, self._fbids[1])
    gl.glBindTexture(gl.GL_TEXTURE_2D, self._texids[0])
    gl.glUseProgram(0)
    self.drawQuad2()

    gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, 0)
    gl.glBindTexture(gl.GL_TEXTURE_2D, self._texids[1]) # This is for second, messed up output.
    # gl.glBindTexture(gl.GL_TEXTURE_2D, self._texids[0])   # This is for first, normal output.
    gl.glUseProgram(0)
    self.drawQuad2()

def drawQuad2(self):
    gl.glBegin(gl.GL_QUADS)

    gl.glTexCoord2f(0, 1)
    gl.glVertex2f(-1, 1)
    gl.glTexCoord2f(1, 1)
    gl.glVertex2f(1, 1)
    gl.glTexCoord2f(1, 0)
    gl.glVertex2f(1, -1)
    gl.glTexCoord2f(0, 0)
    gl.glVertex2f(-1, -1)

    gl.glEnd()
    gl.glFlush()

def setupTexture(self, num, rawstr, width, height):
    texids = gl.glGenTextures(num)
    for tid in texids:
        print 'texture binded %s' % tid
        gl.glBindTexture(gl.GL_TEXTURE_2D, tid)
        gl.glTexImage2D(
            gl.GL_TEXTURE_2D,
            0, gl.GL_RGBA, width, height,
            0, gl.GL_RGBA, gl.GL_UNSIGNED_BYTE,
            rawstr)
        gl.glTexParameteri(
            gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST)
        gl.glTexParameteri(
            gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST)
    gl.glEnable(gl.GL_TEXTURE_2D);

    return texids

def setupFramebuffer(self, num, texids):
    assert(len(texids) == num)
    fbids = gl.glGenFramebuffers(num)
    for i in range(len(fbids)):
        print 'framebuffer binded %s with texture %s' % (fbids[i], texids[i])
        gl.glBindFramebuffer(gl.GL_FRAMEBUFFER, fbids[i])
        gl.glFramebufferTexture2D(
            gl.GL_FRAMEBUFFER, gl.GL_COLOR_ATTACHMENT0,
            gl.GL_TEXTURE_2D, texids[i], 0)
    return fbids

def reshape(self, w, h):
    if not h:
        return
    print 'reshape. w:%s, h:%s' % (w, h)

    gl.glMatrixMode(gl.GL_PROJECTION)
    gl.glLoadIdentity()

    gl.glViewport(0, 0, w, h)
    gl.glOrtho(-1, 1, -1, 1, -1, 1)

    gl.glMatrixMode(gl.GL_MODELVIEW)
    gl.glLoadIdentity()

【问题讨论】:

【参考方案1】:

您必须使用glViewport 函数来告诉OpenGL 它应该通过其绘图操作处理的目标窗口的大小。因此,当您切换到渲染到 FBO 时,您必须调用 glViewport 并使用对目标纹理有意义的内容;通常是目标纹理本身。当切换到渲染到窗口时,您调用 glViewport 并使用目标窗口大小。

如果目标视口大于目标帧缓冲区,这将有效地导致放大。

【讨论】:

以上是关于渲染到屏幕和 FBO 给出不同的结果的主要内容,如果未能解决你的问题,请参考以下文章

将我的场景渲染到帧缓冲区对象(FBO)然后将该 FBO 渲染到屏幕所需的步骤是啥?

绘制不同尺寸的FBO

从纹理渲染到屏幕外纹理 (FBO)

GL_TEXTURE_3D 颜色和模板 FBO 附件

OpenGL:如何设置 OpenGL 只渲染到 FBO,不输出到屏幕/窗口/控件?

Android Opengl FBO 屏幕外