0

I wrote a program to render a square with texture to screen and to a FBO. I believe the rendering result should be the same for both case, only the output destination is different. Surprisingly, it gives me completely different result.

For the first image, I directly output it to screen. It is good, without any problems. For the second image, I rendered it to a FBO with a texture, and then render that texture to screen. In this case, the output is totally messed up, it seems the output only contain the up-left corner of the image.

First image. Directly render to screen

Second image. Render to a texture and render that texture to screen

Related code is:

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()
Lingfeng Xiong
  • 1,131
  • 2
  • 9
  • 25

1 Answers1

3

You must use the glViewport function to tell OpenGL the size of the target window it shall address with its drawing operations. So when you switch to render to FBO, you must call glViewport with something that makes sense for the target texture; usually the target texture itself. When switching to render to the window you call glViewport with the target window size.

If destination viewport is larger than the destination framebuffer this effectively results in a zoom-in.

datenwolf
  • 159,371
  • 13
  • 185
  • 298