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