diff --git a/java/libraries/opengl/src/processing/opengl/FillShaderFragTex.glsl b/java/libraries/opengl/src/processing/opengl/FillShaderFragTex.glsl index 650e90355..5b4d09298 100644 --- a/java/libraries/opengl/src/processing/opengl/FillShaderFragTex.glsl +++ b/java/libraries/opengl/src/processing/opengl/FillShaderFragTex.glsl @@ -21,8 +21,6 @@ uniform sampler2D textureSampler; -uniform vec2 texcoordOffset; - varying vec4 vertColor; varying vec4 vertTexcoord; diff --git a/java/libraries/opengl/src/processing/opengl/PFramebuffer.java b/java/libraries/opengl/src/processing/opengl/PFramebuffer.java index 2da4ff88a..d0a726880 100644 --- a/java/libraries/opengl/src/processing/opengl/PFramebuffer.java +++ b/java/libraries/opengl/src/processing/opengl/PFramebuffer.java @@ -64,10 +64,8 @@ public class PFramebuffer implements PConstants { protected PTexture[] colorBufferTex; protected boolean screenFb; - protected boolean noDepth; - protected boolean fboMode; + protected boolean noDepth; - protected PTexture backupTexture; protected IntBuffer pixelBuffer; PFramebuffer(PApplet parent, int w, int h) { @@ -90,8 +88,6 @@ public class PFramebuffer implements PConstants { glStencilBufferID = 0; glDepthStencilBufferID = 0; glColorBufferMultisampleID = 0; - - fboMode = PGraphicsOpenGL.fboSupported; if (screen) { // If this framebuffer is used to represent a on-screen buffer, @@ -141,14 +137,6 @@ public class PFramebuffer implements PConstants { noDepth = false; pixelBuffer = null; - - if (!screenFb && !fboMode) { - // When FBOs are not available, rendering to texture is implemented by saving a portion of - // the screen, doing the "offscreen" rendering on this portion, copying the screen color - // buffer to the texture bound as color buffer to this PFramebuffer object and then drawing - // the backup texture back on the screen. - backupTexture = new PTexture(parent, width, height, new PTexture.Parameters(ARGB, POINT)); - } } @@ -191,27 +179,10 @@ public class PFramebuffer implements PConstants { } public void bind() { - // if context is outdated ?? - - if (screenFb) { - if (PGraphicsOpenGL.fboSupported) { pgl.glBindFramebuffer(PGL.GL_FRAMEBUFFER, 0); - } - } else if (fboMode) { - pgl.glBindFramebuffer(PGL.GL_FRAMEBUFFER, glFboID); } else { - backupScreen(); - - if (0 < numColorBuffers) { - // Drawing the current contents of the first color buffer to emulate - // front-back buffer swap. - pg.drawTexture(colorBufferTex[0].glTarget, colorBufferTex[0].glID, width, height, 0, 0, width, height, 0, 0, width, height); - } - - if (noDepth) { - pgl.glDisable(PGL.GL_DEPTH_TEST); - } + pgl.glBindFramebuffer(PGL.GL_FRAMEBUFFER, glFboID); } } @@ -228,46 +199,7 @@ public class PFramebuffer implements PConstants { pgl.glEnable(PGL.GL_DEPTH_TEST); } } - - if (!screenFb && !fboMode) { - copyToColorBuffers(); - restoreBackup(); - if (!noDepth) { - // Reading the contents of the depth buffer is not possible in OpenGL ES: - // http://www.idevgames.com/forum/archive/index.php?t-15828.html - // so if this framebuffer uses depth and is offscreen with no FBOs, then - // the depth buffer is cleared to avoid artifacts when rendering more stuff - // after this offscreen render. - // A consequence of this behavior is that all the offscreen rendering when - // no FBOs are available should be done before any onscreen drawing. - pgl.glClearColor(0, 0, 0, 0); - pgl.glClear(PGL.GL_DEPTH_BUFFER_BIT); - } - } } - - // Saves content of the screen into the backup texture. - public void backupScreen() { - if (pixelBuffer == null) createPixelBuffer(); - pixelBuffer.rewind(); - pgl.glReadPixels(0, 0, width, height, PGL.GL_RGBA, PGL.GL_UNSIGNED_BYTE, pixelBuffer); - copyToTexture(pixelBuffer, backupTexture.glID, backupTexture.glTarget); - } - - // Draws the contents of the backup texture to the screen. - public void restoreBackup() { - pg.drawTexture(backupTexture, 0, 0, width, height, 0, 0, width, height); - } - - // Copies current content of screen to color buffers. - public void copyToColorBuffers() { - if (pixelBuffer == null) createPixelBuffer(); - pixelBuffer.rewind(); - pgl.glReadPixels(0, 0, width, height, PGL.GL_RGBA, PGL.GL_UNSIGNED_BYTE, pixelBuffer); - for (int i = 0; i < numColorBuffers; i++) { - copyToTexture(pixelBuffer, colorBufferTex[i].glID, colorBufferTex[i].glTarget); - } - } public void readPixels() { if (pixelBuffer == null) createPixelBuffer(); @@ -320,23 +252,21 @@ public class PFramebuffer implements PConstants { colorBufferTex[i] = textures[i]; } - if (fboMode) { - pg.pushFramebuffer(); - pg.setFramebuffer(this); + pg.pushFramebuffer(); + pg.setFramebuffer(this); - // Making sure nothing is attached. - for (int i = 0; i < numColorBuffers; i++) { - pgl.glFramebufferTexture2D(PGL.GL_FRAMEBUFFER, PGL.GL_COLOR_ATTACHMENT0 + i, PGL.GL_TEXTURE_2D, 0, 0); - } - - for (int i = 0; i < numColorBuffers; i++) { - pgl.glFramebufferTexture2D(PGL.GL_FRAMEBUFFER, PGL.GL_COLOR_ATTACHMENT0 + i, colorBufferTex[i].glTarget, colorBufferTex[i].glID, 0); - } - - validateFbo(); - - pg.popFramebuffer(); + // Making sure nothing is attached. + for (int i = 0; i < numColorBuffers; i++) { + pgl.glFramebufferTexture2D(PGL.GL_FRAMEBUFFER, PGL.GL_COLOR_ATTACHMENT0 + i, PGL.GL_TEXTURE_2D, 0, 0); } + + for (int i = 0; i < numColorBuffers; i++) { + pgl.glFramebufferTexture2D(PGL.GL_FRAMEBUFFER, PGL.GL_COLOR_ATTACHMENT0 + i, colorBufferTex[i].glTarget, colorBufferTex[i].glID, 0); + } + + validateFbo(); + + pg.popFramebuffer(); } @@ -352,10 +282,8 @@ public class PFramebuffer implements PConstants { if (screenFb) { glFboID = 0; - } else if (fboMode) { + } else { glFboID = pg.createFrameBufferObject(); - } else { - glFboID = 0; } // create the rest of the stuff... @@ -412,8 +340,6 @@ public class PFramebuffer implements PConstants { for (int i = 0; i < numColorBuffers; i++) { colorBufferTex[i] = null; } - - backupTexture = null; } return outdated; } @@ -422,17 +348,15 @@ public class PFramebuffer implements PConstants { protected void createColorBufferMultisample() { if (screenFb) return; - if (fboMode) { - pg.pushFramebuffer(); - pg.setFramebuffer(this); + pg.pushFramebuffer(); + pg.setFramebuffer(this); - glColorBufferMultisampleID = pg.createRenderBufferObject(); - pgl.glBindRenderbuffer(PGL.GL_RENDERBUFFER, glColorBufferMultisampleID); - pgl.glRenderbufferStorageMultisample(PGL.GL_RENDERBUFFER, nsamples, PGL.GL_RGBA8, width, height); - pgl.glFramebufferRenderbuffer(PGL.GL_FRAMEBUFFER, PGL.GL_COLOR_ATTACHMENT0, PGL.GL_RENDERBUFFER, glColorBufferMultisampleID); - - pg.popFramebuffer(); - } + glColorBufferMultisampleID = pg.createRenderBufferObject(); + pgl.glBindRenderbuffer(PGL.GL_RENDERBUFFER, glColorBufferMultisampleID); + pgl.glRenderbufferStorageMultisample(PGL.GL_RENDERBUFFER, nsamples, PGL.GL_RGBA8, width, height); + pgl.glFramebufferRenderbuffer(PGL.GL_FRAMEBUFFER, PGL.GL_COLOR_ATTACHMENT0, PGL.GL_RENDERBUFFER, glColorBufferMultisampleID); + + pg.popFramebuffer(); } @@ -443,24 +367,22 @@ public class PFramebuffer implements PConstants { throw new RuntimeException("PFramebuffer: size undefined."); } - if (fboMode) { - pg.pushFramebuffer(); - pg.setFramebuffer(this); - - glDepthStencilBufferID = pg.createRenderBufferObject(); - pgl.glBindRenderbuffer(PGL.GL_RENDERBUFFER, glDepthStencilBufferID); - - if (multisample) { - pgl.glRenderbufferStorageMultisample(PGL.GL_RENDERBUFFER, nsamples, PGL.GL_DEPTH24_STENCIL8, width, height); - } else { - pgl.glRenderbufferStorage(PGL.GL_RENDERBUFFER, PGL.GL_DEPTH24_STENCIL8, width, height); - } - - pgl.glFramebufferRenderbuffer(PGL.GL_FRAMEBUFFER, PGL.GL_DEPTH_ATTACHMENT, PGL.GL_RENDERBUFFER, glDepthStencilBufferID); - pgl.glFramebufferRenderbuffer(PGL.GL_FRAMEBUFFER, PGL.GL_STENCIL_ATTACHMENT, PGL.GL_RENDERBUFFER, glDepthStencilBufferID); - - pg.popFramebuffer(); - } + pg.pushFramebuffer(); + pg.setFramebuffer(this); + + glDepthStencilBufferID = pg.createRenderBufferObject(); + pgl.glBindRenderbuffer(PGL.GL_RENDERBUFFER, glDepthStencilBufferID); + + if (multisample) { + pgl.glRenderbufferStorageMultisample(PGL.GL_RENDERBUFFER, nsamples, PGL.GL_DEPTH24_STENCIL8, width, height); + } else { + pgl.glRenderbufferStorage(PGL.GL_RENDERBUFFER, PGL.GL_DEPTH24_STENCIL8, width, height); + } + + pgl.glFramebufferRenderbuffer(PGL.GL_FRAMEBUFFER, PGL.GL_DEPTH_ATTACHMENT, PGL.GL_RENDERBUFFER, glDepthStencilBufferID); + pgl.glFramebufferRenderbuffer(PGL.GL_FRAMEBUFFER, PGL.GL_STENCIL_ATTACHMENT, PGL.GL_RENDERBUFFER, glDepthStencilBufferID); + + pg.popFramebuffer(); } @@ -471,32 +393,30 @@ public class PFramebuffer implements PConstants { throw new RuntimeException("PFramebuffer: size undefined."); } - if (fboMode) { - pg.pushFramebuffer(); - pg.setFramebuffer(this); + pg.pushFramebuffer(); + pg.setFramebuffer(this); - glDepthBufferID = pg.createRenderBufferObject(); - pgl.glBindRenderbuffer(PGL.GL_RENDERBUFFER, glDepthBufferID); + glDepthBufferID = pg.createRenderBufferObject(); + pgl.glBindRenderbuffer(PGL.GL_RENDERBUFFER, glDepthBufferID); - int glConst = PGL.GL_DEPTH_COMPONENT16; - if (depthBits == 16) { - glConst = PGL.GL_DEPTH_COMPONENT16; - } else if (depthBits == 24) { - glConst = PGL.GL_DEPTH_COMPONENT24; - } else if (depthBits == 32) { - glConst = PGL.GL_DEPTH_COMPONENT32; - } - - if (multisample) { - pgl.glRenderbufferStorageMultisample(PGL.GL_RENDERBUFFER, nsamples, glConst, width, height); - } else { - pgl.glRenderbufferStorage(PGL.GL_RENDERBUFFER, glConst, width, height); - } - - pgl.glFramebufferRenderbuffer(PGL.GL_FRAMEBUFFER, PGL.GL_DEPTH_ATTACHMENT, PGL.GL_RENDERBUFFER, glDepthBufferID); - - pg.popFramebuffer(); + int glConst = PGL.GL_DEPTH_COMPONENT16; + if (depthBits == 16) { + glConst = PGL.GL_DEPTH_COMPONENT16; + } else if (depthBits == 24) { + glConst = PGL.GL_DEPTH_COMPONENT24; + } else if (depthBits == 32) { + glConst = PGL.GL_DEPTH_COMPONENT32; } + + if (multisample) { + pgl.glRenderbufferStorageMultisample(PGL.GL_RENDERBUFFER, nsamples, glConst, width, height); + } else { + pgl.glRenderbufferStorage(PGL.GL_RENDERBUFFER, glConst, width, height); + } + + pgl.glFramebufferRenderbuffer(PGL.GL_FRAMEBUFFER, PGL.GL_DEPTH_ATTACHMENT, PGL.GL_RENDERBUFFER, glDepthBufferID); + + pg.popFramebuffer(); } @@ -507,31 +427,29 @@ public class PFramebuffer implements PConstants { throw new RuntimeException("PFramebuffer: size undefined."); } - if (fboMode) { - pg.pushFramebuffer(); - pg.setFramebuffer(this); + pg.pushFramebuffer(); + pg.setFramebuffer(this); - glStencilBufferID = pg.createRenderBufferObject(); - pgl.glBindRenderbuffer(PGL.GL_RENDERBUFFER, glStencilBufferID); + glStencilBufferID = pg.createRenderBufferObject(); + pgl.glBindRenderbuffer(PGL.GL_RENDERBUFFER, glStencilBufferID); - int glConst = PGL.GL_STENCIL_INDEX1; - if (stencilBits == 1) { - glConst = PGL.GL_STENCIL_INDEX1; - } else if (stencilBits == 4) { - glConst = PGL.GL_STENCIL_INDEX4; - } else if (stencilBits == 8) { - glConst = PGL.GL_STENCIL_INDEX8; - } - if (multisample) { - pgl.glRenderbufferStorageMultisample(PGL.GL_RENDERBUFFER, nsamples, glConst, width, height); - } else { - pgl.glRenderbufferStorage(PGL.GL_RENDERBUFFER, glConst, width, height); - } - - pgl.glFramebufferRenderbuffer(PGL.GL_FRAMEBUFFER, PGL.GL_STENCIL_ATTACHMENT, PGL.GL_RENDERBUFFER, glStencilBufferID); - - pg.popFramebuffer(); + int glConst = PGL.GL_STENCIL_INDEX1; + if (stencilBits == 1) { + glConst = PGL.GL_STENCIL_INDEX1; + } else if (stencilBits == 4) { + glConst = PGL.GL_STENCIL_INDEX4; + } else if (stencilBits == 8) { + glConst = PGL.GL_STENCIL_INDEX8; } + if (multisample) { + pgl.glRenderbufferStorageMultisample(PGL.GL_RENDERBUFFER, nsamples, glConst, width, height); + } else { + pgl.glRenderbufferStorage(PGL.GL_RENDERBUFFER, glConst, width, height); + } + + pgl.glFramebufferRenderbuffer(PGL.GL_FRAMEBUFFER, PGL.GL_STENCIL_ATTACHMENT, PGL.GL_RENDERBUFFER, glStencilBufferID); + + pg.popFramebuffer(); } diff --git a/java/libraries/opengl/src/processing/opengl/PGL.java b/java/libraries/opengl/src/processing/opengl/PGL.java index 05677a718..163d1df8f 100644 --- a/java/libraries/opengl/src/processing/opengl/PGL.java +++ b/java/libraries/opengl/src/processing/opengl/PGL.java @@ -98,6 +98,9 @@ public class PGL { /** Maximum dimension of a texture used to hold font data. **/ public static final int MAX_FONT_TEX_SIZE = 256; + public static int DEFAULT_DEPTH_BITS = 24; + public static int DEFAULT_STENCIL_BITS = 8; + /////////////////////////////////////////////////////////////////////////////////// // OpenGL constants @@ -1042,6 +1045,16 @@ public class PGL { } + // bit shifting this might be more efficient + static public int nextPowerOfTwo(int val) { + int ret = 1; + while (ret < val) { + ret <<= 1; + } + return ret; + } + + public String getShaderLog(int id) { IntBuffer val = IntBuffer.allocate(1); gl2.glGetObjectParameterivARB(id, GL2.GL_OBJECT_INFO_LOG_LENGTH_ARB, val); diff --git a/java/libraries/opengl/src/processing/opengl/PGraphicsOpenGL.java b/java/libraries/opengl/src/processing/opengl/PGraphicsOpenGL.java index 4eab6e213..083ecf6de 100644 --- a/java/libraries/opengl/src/processing/opengl/PGraphicsOpenGL.java +++ b/java/libraries/opengl/src/processing/opengl/PGraphicsOpenGL.java @@ -89,8 +89,6 @@ public class PGraphicsOpenGL extends PGraphics { /** Extensions used by Processing */ static public boolean npotTexSupported; static public boolean mipmapGeneration; - static public boolean vboSupported; - static public boolean fboSupported; static public boolean fboMultisampleSupported; static public boolean blendEqSupported; @@ -297,10 +295,6 @@ public class PGraphicsOpenGL extends PGraphics { protected PFramebuffer offscreenFramebufferMultisample; protected boolean offscreenMultisample; - /** These are public so they can be changed by advanced users. */ - public int offscreenDepthBits = 24; - public int offscreenStencilBits = 8; - // ........................................................ // Utility variables: @@ -5608,8 +5602,8 @@ public class PGraphicsOpenGL extends PGraphics { // function used in multisampled (antialiased) offscreen rendering. if (PGraphicsOpenGL.fboMultisampleSupported && 1 < antialias) { offscreenFramebufferMultisample = new PFramebuffer(parent, texture.glWidth, texture.glHeight, antialias, 0, - offscreenDepthBits, offscreenStencilBits, - offscreenDepthBits == 24 && offscreenStencilBits == 8, false); + PGL.DEFAULT_DEPTH_BITS, PGL.DEFAULT_STENCIL_BITS, + PGL.DEFAULT_DEPTH_BITS == 24 && PGL.DEFAULT_STENCIL_BITS == 8, false); offscreenFramebufferMultisample.clear(); offscreenMultisample = true; @@ -5623,8 +5617,8 @@ public class PGraphicsOpenGL extends PGraphics { } else { antialias = 0; offscreenFramebuffer = new PFramebuffer(parent, texture.glWidth, texture.glHeight, 1, 1, - offscreenDepthBits, offscreenStencilBits, - offscreenDepthBits == 24 && offscreenStencilBits == 8, false); + PGL.DEFAULT_DEPTH_BITS, PGL.DEFAULT_STENCIL_BITS, + PGL.DEFAULT_DEPTH_BITS == 24 && PGL.DEFAULT_STENCIL_BITS == 8, false); offscreenMultisample = false; } @@ -5641,8 +5635,6 @@ public class PGraphicsOpenGL extends PGraphics { npotTexSupported = -1 < OPENGL_EXTENSIONS.indexOf("texture_non_power_of_two"); mipmapGeneration = -1 < OPENGL_EXTENSIONS.indexOf("generate_mipmap"); - vboSupported = -1 < OPENGL_EXTENSIONS.indexOf("vertex_buffer_object"); - fboSupported = -1 < OPENGL_EXTENSIONS.indexOf("framebuffer_object"); fboMultisampleSupported = -1 < OPENGL_EXTENSIONS.indexOf("framebuffer_multisample"); try { diff --git a/java/libraries/opengl/src/processing/opengl/PTexture.java b/java/libraries/opengl/src/processing/opengl/PTexture.java index 957a26db8..a4f710a63 100644 --- a/java/libraries/opengl/src/processing/opengl/PTexture.java +++ b/java/libraries/opengl/src/processing/opengl/PTexture.java @@ -293,23 +293,13 @@ public class PTexture implements PConstants { tempFbo = new PFramebuffer(parent, glWidth, glHeight); } - if (PGraphicsOpenGL.fboSupported) { - // Attaching the texture to the color buffer of a FBO, binding the FBO and reading the pixels - // from the current draw buffer (which is the color buffer of the FBO). - tempFbo.setColorBuffer(this); - pg.pushFramebuffer(); - pg.setFramebuffer(tempFbo); - tempFbo.readPixels(); - pg.popFramebuffer(); - } else { - // Here we don't have FBOs, so the method above is of no use. What we do instead is - // to draw the texture to the screen framebuffer, and then grab the pixels from there. - pg.pushFramebuffer(); - pg.setFramebuffer(tempFbo); - pg.drawTexture(this, 0, 0, glWidth, glHeight, 0, 0, glWidth, glHeight); - tempFbo.readPixels(); - pg.popFramebuffer(); - } + // Attaching the texture to the color buffer of a FBO, binding the FBO and reading the pixels + // from the current draw buffer (which is the color buffer of the FBO). + tempFbo.setColorBuffer(this); + pg.pushFramebuffer(); + pg.setFramebuffer(tempFbo); + tempFbo.readPixels(); + pg.popFramebuffer(); if (tempPixels == null) { tempPixels = new int[size]; @@ -488,16 +478,7 @@ public class PTexture implements PConstants { //////////////////////////////////////////////////////////// // Utilities - - // bit shifting this might be more efficient - protected int nextPowerOfTwo(int val) { - int ret = 1; - while (ret < val) { - ret <<= 1; - } - return ret; - } - + /** * Flips intArray along the X axis. @@ -745,8 +726,8 @@ public class PTexture implements PConstants { glWidth = w; glHeight = h; } else { - glWidth = nextPowerOfTwo(w); - glHeight = nextPowerOfTwo(h); + glWidth = PGL.nextPowerOfTwo(w); + glHeight = PGL.nextPowerOfTwo(h); } if ((glWidth > PGraphicsOpenGL.maxTextureSize) || (glHeight > PGraphicsOpenGL.maxTextureSize)) {