Only red channel when using FBO render to texture

Hi guys,

Im trying to write a simple example code to use FBO render to texture. Im trying to render a rotating solid sphere on to a quad. I see the sphere, but it seems i get only the red channel being used. The color of the sphere is actually pink by setting red and blue to 1 and i also cleared the framebuffer to blue, but i get black. It seems like the data written to the texture image attached to the fbo has only red channel valid.

I am using java and i have my own bindings to opengl via jni.

Here is the code that does the gl initialization to create fbo and attach a texture and depth image to the fbo:


    protected void glInitialize() {
      Gl gl = gl();

      _fboId = gl.genFramebuffer();
      gl.bindFramebuffer(Gl.DRAW_FRAMEBUFFER, _fboId);

      // Create a texture object for fbo.
      _texId = gl.genTexture();
      int texSize = WND_SIZE;
      gl.activeTexture(Gl.TEXTURE0);
      gl.bindTexture(Gl.TEXTURE_2D, _texId);
      gl.texParameterf(Gl.TEXTURE_2D, Gl.TEXTURE_MAG_FILTER, Gl.LINEAR);
      gl.texParameterf(Gl.TEXTURE_2D, Gl.TEXTURE_MIN_FILTER, Gl.LINEAR);
      gl.texParameterf(Gl.TEXTURE_2D, Gl.TEXTURE_WRAP_S, Gl.CLAMP_TO_EDGE);
      gl.texParameterf(Gl.TEXTURE_2D, Gl.TEXTURE_WRAP_T, Gl.CLAMP_TO_EDGE);
      gl.texImage2D(Gl.TEXTURE_2D, 0, Gl.RGBA8, texSize, texSize, 0, Gl.RGBA,
          Gl.UNSIGNED_BYTE, (byte[])null);
      gl.bindTexture(Gl.TEXTURE_2D, 0);

      //Create the depth renderbuffer.
      _depthRenderBufferId = gl.genRenderbuffer();
      gl.bindRenderbuffer(Gl.RENDERBUFFER, _depthRenderBufferId);
      gl.renderbufferStorage(Gl.RENDERBUFFER, Gl.DEPTH_COMPONENT, texSize,
          texSize);
      gl.bindRenderbuffer(Gl.RENDERBUFFER, 0);
      
//      //Create the stencil renderbuffer.
//      int[] stencilBuffer = new int[1];
//      gl.genRenderbuffers(1, stencilBuffer);
//      _stencilRenderBufferId = stencilBuffer[0];
//      gl.bindRenderbuffer(Gl.RENDERBUFFER, _stencilRenderBufferId);
//      gl.renderbufferStorage(Gl.RENDERBUFFER, Gl.STENCIL_INDEX, texSize, texSize);
//      gl.bindRenderbuffer(Gl.RENDERBUFFER, 0);

      gl.framebufferTexture2D(Gl.DRAW_FRAMEBUFFER, Gl.COLOR_ATTACHMENT0,
          Gl.TEXTURE_2D, _texId, 0);
      gl.framebufferRenderbuffer(Gl.DRAW_FRAMEBUFFER, Gl.DEPTH_ATTACHMENT,
          Gl.RENDERBUFFER, _depthRenderBufferId);
//      gl.framebufferRenderbuffer(Gl.FRAMEBUFFER, Gl.STENCIL_ATTACHMENT,
//          Gl.RENDERBUFFER, _stencilRenderBufferId);
      
      printFramebufferInfo(gl);
      boolean status = checkFramebufferStatus(gl);
      System.out.println("Framebuffer status: "+status);
      gl.bindFramebuffer(Gl.DRAW_FRAMEBUFFER, 0);
      
      gl.pixelStorei(Gl.UNPACK_ALIGNMENT, 4);
      gl.enable(Gl.TEXTURE_2D);
      gl.enable(Gl.DEPTH_TEST);
      gl.depthMask(true);
//      gl.clearDepth(1.f);
      gl.depthFunc(Gl.LEQUAL);
      
      checkErrors(gl);
    }

Heres the code where i use the framebuffer :


    @Override
    public void glPaint() {
      
      final Gl gl = gl();
      final Glu glu = glu();
      
      gl.pushClientAttrib(Gl.CLIENT_ALL_ATTRIB_BITS);
      gl.pushAttrib(Gl.ALL_ATTRIB_BITS);
      
      gl.colorMask(true, true, true, true);
      gl.activeTexture(Gl.TEXTURE0);
      gl.disable(Gl.TEXTURE_2D);
      gl.bindTexture(Gl.TEXTURE_2D, 0);
      gl.bindFramebuffer(Gl.DRAW_FRAMEBUFFER, _fboId);
      
      gl.viewport(0, 0, WND_SIZE, WND_SIZE);
      gl.matrixMode(Gl.PROJECTION);
      gl.loadIdentity();
      glu.perspective(60.f, 1.f, 1.f, 100.f);
      
      gl.matrixMode(Gl.MODELVIEW);
      gl.loadIdentity();
      gl.translatef(0, 0, -2f);
      _sphereRotateX+= 0.1;
      gl.rotate(_sphereRotateX % 360, 1.0, 0.0, 0.0);
      
      //clear blue for sphere rendering 
      gl.clearColor(0.f, 0.f, 1.f, 1.f);
      gl.clear(Gl.COLOR_BUFFER_BIT | Gl.DEPTH_BUFFER_BIT);

      _sphere.glDraw(gl);
      gl.bindFramebuffer(Gl.DRAW_FRAMEBUFFER, 0);
      gl.popAttrib();
      gl.popClientAttrib();
        
      gl.pushClientAttrib(Gl.CLIENT_ALL_ATTRIB_BITS);
      gl.pushAttrib(Gl.ALL_ATTRIB_BITS);
      
      getTextureParameters(gl, _texId);

      //draw cube normally.
      gl.activeTexture(Gl.TEXTURE0);
      gl.enable(Gl.TEXTURE_2D);
     
      int width = getWidth();
      int height = getHeight();
      gl.viewport(0, 0, width, height);
      gl.matrixMode(Gl.PROJECTION);
      gl.loadIdentity();
      glu.perspective(60.f, (float)width/(float)height, 1.f, 100.f);
      
      gl.matrixMode(Gl.MODELVIEW);
      gl.loadIdentity();
      gl.translatef(0, 0, -2);
      gl.rotatef(_cameraAngleX, 1, 0, 0);
      gl.rotatef(_cameraAngleY, 0, 1, 0);
      
      gl.clearColor(1.f, 0.8f, 0.f, 1.f);
      gl.clear(Gl.COLOR_BUFFER_BIT | Gl.DEPTH_BUFFER_BIT );
      
      drawTexturedQuad(gl);
//      drawSolidQuad(gl);

      gl.popAttrib();
      gl.popClientAttrib();
      
      checkErrors(gl);
      
      repaint();
    }

Here is the code to draw the quad with the texture from the framebuffer object:


    private void drawTexturedQuad(final Gl gl) {
      gl.bindTexture(Gl.TEXTURE_2D, _texId);
      gl.frontFace(Gl.CW);
      gl.begin(Gl.QUADS);
      // front face
       gl.color3f(0.75f, 1.f, 0.f);
//      gl.normal3f(0f, -1f, 0f);
      
      gl.texCoord2f(0.f, 0.f);
      gl.vertex3f(-1.f, 0.f, -1.f);
      
      gl.texCoord2f(1.f, 0.f);
      gl.vertex3f(1.f, 0.f, -1.f);
      
      gl.texCoord2f(1.f, 1.f);
      gl.vertex3f(1.f, 0.f, 1.f);
      
      gl.texCoord2f(0.f, 1.f);
      gl.vertex3f(-1.f, 0.f, 1.f);
      gl.end();
      gl.bindTexture(Gl.TEXTURE_2D, 0);
    }


…and heres the code to draw a sphere:


    public void glDraw(final Gl gl) {
      
      gl.pushClientAttrib(Gl.CLIENT_ALL_ATTRIB_BITS);
      gl.pushAttrib(Gl.ALL_ATTRIB_BITS);
      
      Gl.color3f(1.0f, 0f, 1f);
      Gl.polygonMode(Gl.FRONT_AND_BACK, Gl.FILL);
      gl.vertexArray(3, _verts);
      Gl.enableClientState(Gl.VERTEX_ARRAY);
      for (int i = 0; i < _strips.length; i++) {
        gl.drawElements(Gl.QUAD_STRIP, _strips[i].length, _strips[i]);
      }
      for (int i = 0; i < _caps.length; i++) {
        gl.drawElements(Gl.TRIANGLE_FAN, _caps[i].length, _caps[i]);
      }

      gl.polygonMode(Gl.FRONT_AND_BACK, Gl.LINE);
      Gl.color3f(0.0f, 0.0f, 0f);
      for (int i = 0; i < _strips.length; i++) {
        gl.drawElements(Gl.QUAD_STRIP, _strips[i].length, _strips[i]);
      }
      for (int i = 0; i < _caps.length; i++) {
        gl.drawElements(Gl.TRIANGLE_FAN, _caps[i].length, _caps[i]);
      }

      gl.popAttrib();
      gl.popClientAttrib();
      
    }


The image i get currently is this: http://s21.postimg.org/472o42d5j/FBO_incorrect.jpg

However if i simply render the sphere without fbo (and what i expect should be a texture from the fbo is) : http://s21.postimg.org/j78sx4y6v/sphere_correct.png

Could someone let me know what im doing wrong here? Any suggestion would be appreciated…

thanks

Any suggestion on how to debug? or perhaps try something out that would give me a hint would be great…this is using fixed function pipeline…I verified there were no gl errors as well.

The default glTexEnv() setting for GL_TEXTURE_ENV_MODE is GL_MODULATE, so the texture colours are multiplied by the current colour. Setting the current colour to (0.75,1,0) scales the red channel by 0.75 and sets the blue channel to zero, so (1,0,1) = magenta becomes (0.75,0,0) = red and (0,0,1) = blue becomes (0,0,0) = black.

Set the current colour to white or GL_TEXTURE_ENV_MODE to GL_REPLACE if you want the texture colours to be reproduced correctly.

Thanks GClements!! i actually figured this folly a little earlier…its one of those moments where i wasnt thinking it through…but thanks a lot.