PDA

View Full Version : Only red channel when using FBO render to texture



siddharth.cmdz
08-06-2013, 11:48 PM
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

siddharth.cmdz
08-07-2013, 08:15 AM
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.

GClements
08-07-2013, 03:16 PM
I see the sphere, but it seems i get only the red channel being used.



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


gl.color3f(0.75f, 1.f, 0.f);


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.

siddharth.cmdz
08-07-2013, 10:57 PM
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.