Thanks for your input. I really appreciate the detailed response.
The beginPGL makes sense now, as does popping of the viewport. I was thinking of beginPGL as more of a constructor rather than an OpenGL call. I've also added to my code some endPGL calls since I see beginPGL followed by endPGL in the internal code, and also logically this makes sense to me.
The best I can tell from some tests the processing internal FBO is no longer interfering with your FBO code, since I am able to get things to work without using the pushFramebuffer and popFramebuffer. What is confusing me is that I am unable to get my own changes to affect the FBO, but calls to native processing routines such as background do affect the FBO. When I don't use the background() routine the FBO comes out uninitialized.
The code can be found here. Pastebin is numbered so it's just easier to talk about.
The idea is that I create an FBO in setup(), make it green, and then use it in draw() when a boolean is toggled. A key press will toggle the boolean, and the background should alter between black (no FBO) and green (FBO).
What is killing me is that line 45 correctly changes the FBO to green, but lines 48-55 do not, even though 48-55 is a copy of the code for background().... I even tried some Z translations to see if there was some depth test I was missing.
If anyone has any insight, I'd appreciate it. The full code is below just so the link is never lost.
- import processing.core.*;
- import processing.opengl.*;
- import javax.media.opengl.GL;
- import javax.media.opengl.GL2;
- public class FBOTest extends PApplet {
- GL gl;
- int myFBO;
- int fboTexture;
- boolean drawFBO = true;
- public void setup() {
- frameRate(30);
- size(800, 600, P3D);
- background(0, 0, 0);
- colorMode(RGB, 100);
- // Start the opengl context so we can do some initialisation
- PGL pgl = g.beginPGL();
- gl = pgl.gl.getGL().getGL2();
- // Check what version of OpenGL we're using
- println("This system uses OpenGL:"
- + pgl.gl.getGL().glGetString(GL.GL_VERSION));
- int[] fboAndTex = new int[2];
- // create a FBO ten times smaller than the sketch
- try {
- fboAndTex = initializeFBO(gl, width, height);
- } catch (Exception e) {
- exit();
- }
- myFBO = fboAndTex[0];
- fboTexture = fboAndTex[1];
- println("FBO created, ID: " + myFBO + ", with texture ID: " + fboTexture);
- gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, myFBO); // Bind our frame buffer
- // THIS WORKS
- //background(0, 100, 0, 100);
- // THIS DOES NOT WORK
- pushStyle();
- pushMatrix();
- resetMatrix();
- //translate(0, 0, 5); // just a double check for depth test
- fill(0, 100, 0, 100);
- rect(0, 0, width, height);
- popMatrix();
- popStyle();
- /*
- // TODO why won't this work??
- fill(50, 50, 50);
- rect(0, 0, width, height);
- fill(0, 0, 100);
- textSize(32);
- text("word", 50, 50, 0);
- */
- gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0); // Bind draw buffer
- g.endPGL();
- }
- boolean checkBufferCompletness(GL gl) {
- int fBStatus = gl.glCheckFramebufferStatus(GL.GL_FRAMEBUFFER);
- if (fBStatus != GL.GL_FRAMEBUFFER_COMPLETE) {
- switch (fBStatus) {
- case GL.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
- println("Not all framebuffer attachment points are framebuffer attachment complete.");
- break;
- case GL.GL_FRAMEBUFFER_UNSUPPORTED:
- println("The combination of internal formats of the attached images violates an implementation-dependent set of restrictions.");
- break;
- case GL.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
- println("No images are attached to the framebuffer.");
- break;
- default:
- println("Framebuffer not ready for another reason.");
- }
- return false;
- }
- return true;
- }
- /*
- * Creates a Frame Buffer Object (FBO) take can be used to render color and
- * depth offscreen. There is a texture attached to the FBO which can be used
- * like a regular texture (texturing a quad for instance). gl : the OpenGL
- * context w : the width of the FBO h: the height Returns the ids of the FBO
- * and the associated texture in an array in that order. Throws an exception
- * if the FBO could not be created
- */
- int[] initializeFBO(GL gl, int w, int h) throws Exception {
- // let's first create a texture to attach to the FBO
- int[] array = new int[1];
- gl.glGenTextures(1, array, 0); // ask OpenGL for a texture id
- int tex = array[0];
- // tell OpenGL we're going to work on this new texture
- gl.glEnable(GL.GL_TEXTURE_2D);
- gl.glBindTexture(GL.GL_TEXTURE_2D, tex);
- // Setup some properties, mipmap etc...
- gl.glTexParameteri(GL.GL_TEXTURE_2D,
- GL.GL_TEXTURE_MIN_FILTER,
- GL.GL_NEAREST);
- gl.glTexParameteri(GL.GL_TEXTURE_2D,
- GL.GL_TEXTURE_MAG_FILTER,
- GL.GL_NEAREST);
- gl.glTexParameteri(GL.GL_TEXTURE_2D,
- GL.GL_TEXTURE_WRAP_S,
- GL.GL_CLAMP_TO_EDGE);
- gl.glTexParameteri(GL.GL_TEXTURE_2D,
- GL.GL_TEXTURE_WRAP_T,
- GL.GL_CLAMP_TO_EDGE);
- // set what the format of the pixels we're using
- gl.glTexImage2D(GL.GL_TEXTURE_2D, 0,
- GL.GL_RGBA, w, h, 0,
- GL.GL_RGBA,
- GL.GL_UNSIGNED_BYTE, null);
- // Done with the texture
- gl.glBindTexture(GL.GL_TEXTURE_2D, 0);
- // Create a Frame Buffer Object
- gl.glGenFramebuffers(1, array, 0); // Ask OpenGL for a framebuffer id
- int fbo = array[0];
- // Tells OpenGL we're going to work on the fbo
- gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, fbo);
- // attach the texture to the FBO
- gl.glFramebufferTexture2D(GL.GL_FRAMEBUFFER,
- GL.GL_COLOR_ATTACHMENT0,
- GL.GL_TEXTURE_2D, tex, 0);
- // then create a render buffer
- gl.glGenRenderbuffers(1, array, 0); // Ask OpenGL for a renderbuffer id
- int rb = array[0];
- // attach the render buffer to the FBO
- gl.glBindRenderbuffer(GL.GL_RENDERBUFFER, rb);
- // this tells OpenGL that the render buffer is used for depth data and
- // that we need a buffer of dimension w by h
- gl.glRenderbufferStorage(GL.GL_RENDERBUFFER,
- GL2.GL_DEPTH_COMPONENT24,
- w, h);
- // attach it to the frame buffer
- gl.glFramebufferRenderbuffer(GL2.GL_DRAW_FRAMEBUFFER,
- GL.GL_DEPTH_ATTACHMENT,
- GL.GL_RENDERBUFFER, rb);
- // done working on the render buffer
- gl.glBindRenderbuffer(GL.GL_RENDERBUFFER, 0);
- // At this point everything is set and all that remains to do is to
- // check for completness of the FBO
- if (!checkBufferCompletness(gl)) {
- throw new Exception("Could not create the FBO.");
- }
- // done working on the frame buffer
- gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0);
- return new int[] { fbo, tex };
- }
- public void draw() {
- // Start the opengl context so we can do some initialisation
- PGL pgl = g.beginPGL();
- gl = pgl.gl.getGL().getGL2();
- background(0);
- if(drawFBO) {
- ((PGraphicsOpenGL) g).drawTexture(GL.GL_TEXTURE_2D, fboTexture,
- width, height, 0, 0, width, height);
- }
- fill(100, 0, 0);
- rect(0, 0, 50, 50);
- g.endPGL();
- }
- public void keyPressed() {
- drawFBO = !drawFBO;
- println("FBO is " + drawFBO);
- }
- }