diff --git a/android/core/src/processing/core/PConstants.java b/android/core/src/processing/core/PConstants.java index c6175d98a..8f9121421 100644 --- a/android/core/src/processing/core/PConstants.java +++ b/android/core/src/processing/core/PConstants.java @@ -367,12 +367,12 @@ public interface PConstants { // text alignment modes - // are inherited from LEFT, CENTER, RIGHT + // are inherited from LEFT, CENTER, RIGHT // PTexture /** This constant identifies the texture target GL_TEXTURE_2D, that is, textures with normalized coordinates */ - public static final int NORMAL_TEXTURE = 0; + public static final int TEXTURE2D = 0; /** This constant identifies the nearest texture filter */ public static final int NEAREST = 0; diff --git a/android/core/src/processing/core/PFont.java b/android/core/src/processing/core/PFont.java index 77f645fba..31376bb32 100644 --- a/android/core/src/processing/core/PFont.java +++ b/android/core/src/processing/core/PFont.java @@ -698,7 +698,7 @@ public class PFont implements PConstants { public int addTexture(GL10 gl) { int[] textures = new int[1]; - // We assume GL10.GL_TEXTURE_2D is enabled at this point. + // We assume GL10.GL_TEXTURE_2D is enabled at this point (shoud be called by PGraphicsAndroid3D.textLineImpl()). gl.glGenTextures(1, textures, 0); gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]); @@ -714,7 +714,7 @@ public class PFont implements PConstants { gl.glTexImage2D(GL10.GL_TEXTURE_2D, 0, GL10.GL_RGBA, texWidth, texHeight, 0, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, null); gl.glBindTexture(GL10.GL_TEXTURE_2D, 0); - currentTexID = -1; // No texture is bound. + currentTexID = -1; // No texture is currently bound. if (texIDList == null) { texIDList = new int[1]; diff --git a/android/core/src/processing/core/PGraphicsAndroid3D.java b/android/core/src/processing/core/PGraphicsAndroid3D.java index 90dc8d7cd..370272f1d 100644 --- a/android/core/src/processing/core/PGraphicsAndroid3D.java +++ b/android/core/src/processing/core/PGraphicsAndroid3D.java @@ -38,7 +38,6 @@ import android.opengl.GLSurfaceView.EGLConfigChooser; import android.opengl.GLSurfaceView.Renderer; import javax.microedition.khronos.opengles.*; -import javax.microedition.khronos.egl.EGL11; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.egl.EGL10; import javax.microedition.khronos.egl.EGLContext; @@ -117,6 +116,7 @@ public class PGraphicsAndroid3D extends PGraphics { */ public static final int MAX_LIGHTS = 8; + public boolean lights; public int lightCount = 0; /** Light types */ @@ -291,13 +291,14 @@ public class PGraphicsAndroid3D extends PGraphics { // ....................................................... - protected Stack fbStack; - protected PFramebuffer screenFramebuffer; + static protected Stack fbStack; + static protected PFramebuffer screenFramebuffer; + static protected PFramebuffer currentFramebuffer; + protected PFramebuffer drawFramebuffer; protected PImage[] drawImages; protected PTexture[] drawTextures; protected int drawIndex; - protected PFramebuffer currentFramebuffer; protected int[] drawTexCrop; // ........................................................ @@ -313,7 +314,12 @@ public class PGraphicsAndroid3D extends PGraphics { boolean clear = true; // ........................................................ + + boolean blend; + int blendMode; + // ........................................................ + public String OPENGL_VENDOR; public String OPENGL_RENDERER; public String OPENGL_VERSION; @@ -552,16 +558,16 @@ public class PGraphicsAndroid3D extends PGraphics { public void renderDrawTexture(int idx) { PTexture tex = drawTextures[idx]; - gl.glEnable(GL10.GL_TEXTURE_2D); - gl.glBindTexture(GL10.GL_TEXTURE_2D, tex.getGLTextureID()); + gl.glEnable(tex.getGLTarget()); + gl.glBindTexture(tex.getGLTarget(), tex.getGLTextureID()); gl.glDepthMask(false); gl.glDisable(GL10.GL_BLEND); gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE, GL10.GL_REPLACE); - gl11.glTexParameteriv(GL10.GL_TEXTURE_2D, GL11Ext.GL_TEXTURE_CROP_RECT_OES, drawTexCrop, 0); + gl11.glTexParameteriv(tex.getGLTarget(), GL11Ext.GL_TEXTURE_CROP_RECT_OES, drawTexCrop, 0); gl11x.glDrawTexiOES(0, 0, 0, width, height); - gl.glDisable(GL10.GL_TEXTURE_2D); + gl.glDisable(tex.getGLTarget()); gl.glDepthMask(true); gl.glEnable(GL10.GL_BLEND); } @@ -570,10 +576,92 @@ public class PGraphicsAndroid3D extends PGraphics { drawIndex = (drawIndex + 1) % 2; } - public PImage getBackground() { + public PImage getLastFrame() { return drawImages[(drawIndex + 1) % 2]; } + protected void saveGLState() { + gl.glMatrixMode(GL10.GL_PROJECTION); + gl.glPushMatrix(); + gl.glMatrixMode(GL10.GL_MODELVIEW); + gl.glPushMatrix(); + } + + protected void restoreGLState() { + // Restoring blending. + if (blend) { + blend(blendMode); + } else { + noBlend(); + } + + // Restoring viewport. + gl.glViewport(0, 0, width, height); + + // Restoring hints. + if (hints[DISABLE_DEPTH_TEST]) { + gl.glDisable(GL10.GL_DEPTH_TEST); + gl.glClear(GL10.GL_DEPTH_BUFFER_BIT); + } else { + gl.glEnable(GL10.GL_DEPTH_TEST); + } + + // Restoring fill + if (fill) { + fillFromCalc(); + } + + // Restoring material properties. + ambientFromCalc(); + specularFromCalc(); + shininess(shininess); + emissiveFromCalc(); + + // Restoring lights. + if (lights) { + for (int i = 0; i < lightCount; i++) { + glLightEnable(i); + if (lightType[i] == AMBIENT) { + glLightAmbient(i); + glLightPosition(i); + glLightFalloff(i); + glLightNoSpot(i); + } else if (lightType[i] == DIRECTIONAL) { + glLightNoAmbient(i); + glLightDirection(i); + glLightDiffuse(i); + glLightSpecular(i); + glLightFalloff(i); + glLightNoSpot(i); + } else if (lightType[i] == POINT) { + glLightNoAmbient(i); + glLightPosition(i); + glLightDiffuse(i); + glLightSpecular(i); + glLightFalloff(i); + glLightNoSpot(i); + } else if (lightType[i] == SPOT) { + glLightNoAmbient(i); + glLightPosition(i); + glLightDirection(i); + glLightDiffuse(i); + glLightSpecular(i); + glLightFalloff(i); + glLightSpotAngle(i); + glLightSpotConcentration(i); + } + } + } else { + noLights(); + } + + // Restoring matrices. + gl.glMatrixMode(GL10.GL_PROJECTION); + gl.glPopMatrix(); + gl.glMatrixMode(GL10.GL_MODELVIEW); + gl.glPopMatrix(); + } + // //////////////////////////////////////////////////////////// // FRAME @@ -599,6 +687,18 @@ public class PGraphicsAndroid3D extends PGraphics { TRIANGLECOUNT = 0; FACECOUNT = 0; + if (!primarySurface) { + PGraphicsAndroid3D a3d = (PGraphicsAndroid3D)parent.g; + a3d.saveGLState(); + + // Disabling all lights, so the offscreen renderer can set completely + // new light configuration (otherwise some light config from the + // primary renderer might stay). + for (int i = 0; i < a3d.lightCount; i++) { + a3d.glLightDisable(i); + } + } + if (!settingsInited) defaultSettings(); @@ -614,9 +714,8 @@ public class PGraphicsAndroid3D extends PGraphics { textureImage = null; textureImagePrev = null; - // these are necessary for alpha (i.e. fonts) to work - gl.glEnable(GL10.GL_BLEND); - gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA); + // Blend is needed for alpha (i.e. fonts) to work. + blend(BLEND); // this is necessary for 3D drawing if (hints[DISABLE_DEPTH_TEST]) { @@ -667,6 +766,7 @@ public class PGraphicsAndroid3D extends PGraphics { setFramebuffer(screenFramebuffer); } + // TODO: rework logic depending on whether this renderer is primarySurface, etc. if (clear) { gl.glClearColor(0, 0, 0, 0); gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); @@ -700,7 +800,6 @@ public class PGraphicsAndroid3D extends PGraphics { pushFramebuffer(); setFramebuffer(drawFramebuffer); drawFramebuffer.addColorBuffer(drawTextures[drawIndex]); - drawFramebuffer.validFbo(); gl.glClearColor(0, 0, 0, 0); gl.glClear(GL10.GL_DEPTH_BUFFER_BIT); @@ -742,6 +841,10 @@ public class PGraphicsAndroid3D extends PGraphics { gl.glFlush(); + if (!primarySurface) { + ((PGraphicsAndroid3D)parent.g).restoreGLState(); + } + report("top endDraw()"); /* * if (hints[ENABLE_DEPTH_SORT]) { flush(); } @@ -2282,11 +2385,15 @@ public class PGraphicsAndroid3D extends PGraphics { /** * Implementation of actual drawing for a line of text. */ - protected void textLineImpl(char buffer[], int start, int stop, float x, - float y) { + protected void textLineImpl(char buffer[], int start, int stop, float x, float y) { // Init opengl state for text rendering... gl.glEnable(GL10.GL_TEXTURE_2D); + if (!blend || blendMode != BLEND) { + gl.glEnable(GL10.GL_BLEND); + gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA); + } + if (textFont.texIDList == null) { textFont.initTexture(gl, maxTextureSize, maxTextureSize); // Add all the current glyphs to the texture. @@ -2300,6 +2407,13 @@ public class PGraphicsAndroid3D extends PGraphics { gl.glColor4f(colorFloats[0], colorFloats[1], colorFloats[2], colorFloats[3]); super.textLineImpl(buffer, start, stop, x, y); + + // Restoring current blend mode. + if (blend) { + blend(blendMode); + } else { + noBlend(); + } gl.glDisable(GL10.GL_TEXTURE_2D); } @@ -3562,6 +3676,7 @@ public class PGraphicsAndroid3D extends PGraphics { * */ public void lights() { + lights = true; gl.glEnable(GL10.GL_LIGHTING); // need to make sure colorMode is RGB 255 here @@ -3572,8 +3687,7 @@ public class PGraphicsAndroid3D extends PGraphics { lightSpecular(0, 0, 0); ambientLight(colorModeX * 0.5f, colorModeY * 0.5f, colorModeZ * 0.5f); - directionalLight(colorModeX * 0.5f, colorModeY * 0.5f, colorModeZ * 0.5f, - 0, 0, -1); + directionalLight(colorModeX * 0.5f, colorModeY * 0.5f, colorModeZ * 0.5f, 0, 0, -1); colorMode = colorModeSaved; } @@ -3583,8 +3697,9 @@ public class PGraphicsAndroid3D extends PGraphics { * method is needed. */ public void resetLights() { - for (int i = 0; i < lightCount; i++) + for (int i = 0; i < lightCount; i++) { glLightDisable(i); + } lightCount = 0; } @@ -3592,6 +3707,7 @@ public class PGraphicsAndroid3D extends PGraphics { * Disables lighting. */ public void noLights() { + lights = false; gl.glDisable(GL10.GL_LIGHTING); lightCount = 0; } @@ -4482,15 +4598,18 @@ public class PGraphicsAndroid3D extends PGraphics { /** * Allows to set custom blend modes for the entire scene, using openGL. */ - public void setBlend(int mode) { + public void blend(int mode) { + blend = true; + blendMode = mode; + gl.glEnable(GL10.GL_BLEND); if (mode == BLEND) - gl.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA); else if (mode == ADD) - gl.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE); + gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE); else if (mode == MULTIPLY) - gl.glBlendFunc(GL11.GL_DST_COLOR, GL11.GL_SRC_COLOR); + gl.glBlendFunc(GL10.GL_DST_COLOR, GL10.GL_SRC_COLOR); else if (mode == SUBTRACT) - gl.glBlendFunc(GL11.GL_ONE_MINUS_DST_COLOR, GL11.GL_ZERO); + gl.glBlendFunc(GL10.GL_ONE_MINUS_DST_COLOR, GL10.GL_ZERO); // TODO: implement all these other blending modes: // else if (blendMode == LIGHTEST) // else if (blendMode == DIFFERENCE) @@ -4503,13 +4622,11 @@ public class PGraphicsAndroid3D extends PGraphics { // else if (blendMode == BURN) } - /** - * Sets Processing's default blending mode. - */ - public void defaultBlend() { - gl.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + public void noBlend() { + blend = false; + gl.glDisable(GL10.GL_BLEND); } - + // //////////////////////////////////////////////////////////// // SAVE diff --git a/android/core/src/processing/core/PTexture.java b/android/core/src/processing/core/PTexture.java index 1e78769e3..3626eae66 100644 --- a/android/core/src/processing/core/PTexture.java +++ b/android/core/src/processing/core/PTexture.java @@ -281,6 +281,7 @@ public class PTexture implements PConstants { int[] convArray = convertToRGBA(intArray, arrayFormat); + gl.glEnable(glTarget); gl.glBindTexture(glTarget, glTextureID[0]); if (usingMipmaps) { @@ -293,7 +294,7 @@ public class PTexture implements PConstants { } gl.glTexSubImage2D(glTarget, 0, 0, 0, glWidth, glHeight, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, IntBuffer.wrap(convArray)); - gl.glBindTexture(glTarget, 0); + gl.glDisable(glTarget); } @@ -719,7 +720,8 @@ public class PTexture implements PConstants { (glMinFilter == GL10.GL_LINEAR_MIPMAP_NEAREST) || (glMinFilter == GL10.GL_NEAREST_MIPMAP_LINEAR) || (glMinFilter == GL10.GL_LINEAR_MIPMAP_LINEAR)); - + + gl.glEnable(glTarget); gl.glGenTextures(1, glTextureID, 0); gl.glBindTexture(glTarget, glTextureID[0]); gl.glTexParameterf(glTarget, GL10.GL_TEXTURE_MIN_FILTER, glMinFilter); @@ -727,13 +729,10 @@ public class PTexture implements PConstants { gl.glTexParameterf(glTarget, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE); gl.glTexParameterf(glTarget, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE); gl.glTexImage2D(glTarget, 0, glInternalFormat, glWidth, glHeight, 0, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, null); - - // TODO: check what is the correct way of unbind textures, the following or glDisable(glTarget); - gl.glBindTexture(glTarget, 0); + gl.glDisable(glTarget); flippedX = false; - flippedY = false; - + flippedY = false; // If non-power-of-two textures are not supported, and the specified width or height // is non-power-of-two, then glWidth (glHeight) will be greater than w (h) because it @@ -769,7 +768,7 @@ public class PTexture implements PConstants { Parameters res = new Parameters(); if ( glTarget == GL10.GL_TEXTURE_2D ) { - res.target = NORMAL_TEXTURE; + res.target = TEXTURE2D; } if (glInternalFormat == GL10.GL_RGB) { @@ -810,7 +809,7 @@ public class PTexture implements PConstants { * @param params GLTextureParameters */ protected void setParameters(Parameters params) { - if (params.target == NORMAL_TEXTURE) { + if (params.target == TEXTURE2D) { glTarget = GL10.GL_TEXTURE_2D; } else { throw new RuntimeException("GTexture: Unknown texture target"); @@ -901,21 +900,21 @@ public class PTexture implements PConstants { * Creates an instance of GLTextureParameters, setting all the parameters to default values. */ public Parameters() { - target = PTexture.NORMAL_TEXTURE; + target = PTexture.TEXTURE2D; format = PTexture.ARGB; minFilter = PTexture.LINEAR; magFilter = PTexture.LINEAR; } public Parameters(int format) { - target = PTexture.NORMAL_TEXTURE; + target = PTexture.TEXTURE2D; this.format = format; minFilter = PTexture.LINEAR; magFilter = PTexture.LINEAR; } public Parameters(int format, int filter) { - target = PTexture.NORMAL_TEXTURE; + target = PTexture.TEXTURE2D; this.format = format; minFilter = filter; magFilter = filter;