diff --git a/core/src/processing/opengl/PGraphicsOpenGL.java b/core/src/processing/opengl/PGraphicsOpenGL.java index dfbe2961b..5bdab92de 100644 --- a/core/src/processing/opengl/PGraphicsOpenGL.java +++ b/core/src/processing/opengl/PGraphicsOpenGL.java @@ -231,7 +231,7 @@ public class PGraphicsOpenGL extends PGraphics { PGraphicsOpenGL.class.getResource("PointFrag.glsl"); static protected ColorShader defColorShader; - static protected TexureShader defTextureShader; + static protected TextureShader defTextureShader; static protected LightShader defLightShader; static protected TexlightShader defTexlightShader; static protected LineShader defLineShader; @@ -239,10 +239,10 @@ public class PGraphicsOpenGL extends PGraphics { static protected URL maskShaderFragURL = PGraphicsOpenGL.class.getResource("MaskFrag.glsl"); - static protected TexureShader maskShader; + static protected TextureShader maskShader; protected ColorShader colorShader; - protected TexureShader textureShader; + protected TextureShader textureShader; protected LightShader lightShader; protected TexlightShader texlightShader; protected LineShader lineShader; @@ -2355,9 +2355,8 @@ public class PGraphicsOpenGL extends PGraphics { protected void flushPolys() { - updatePolyBuffers(lights, texCache.hasTexture); + updatePolyBuffers(lights, texCache.hasTextures); - texCache.beginRender(); for (int i = 0; i < texCache.size; i++) { Texture tex = texCache.getTexture(i); @@ -2410,7 +2409,6 @@ public class PGraphicsOpenGL extends PGraphics { shader.unbind(); } - texCache.endRender(); unbindPolyBuffers(); } @@ -5370,7 +5368,7 @@ public class PGraphicsOpenGL extends PGraphics { } if (maskShader == null) { - maskShader = new TexureShader(parent, defTextureShaderVertURL, + maskShader = new TextureShader(parent, defTextureShaderVertURL, maskShaderFragURL); } maskShader.set("mask", alpha); @@ -5412,7 +5410,7 @@ public class PGraphicsOpenGL extends PGraphics { @Override public void filter(PShader shader) { - if (!(shader instanceof TexureShader)) { + if (!(shader instanceof TextureShader)) { PGraphics.showWarning(INVALID_FILTER_SHADER_ERROR); return; } @@ -5448,8 +5446,8 @@ public class PGraphicsOpenGL extends PGraphics { stroke = false; // int prevBlendMode = blendMode; // blendMode(REPLACE); - TexureShader prevTexShader = textureShader; - textureShader = (TexureShader) shader; + TextureShader prevTexShader = textureShader; + textureShader = (TextureShader) shader; beginShape(QUADS); texture(filterImage); vertex(0, 0, 0, 0); @@ -6198,7 +6196,7 @@ public class PGraphicsOpenGL extends PGraphics { shader = new LightShader(parent); shader.setVertexShader(defLightShaderVertURL); } else if (shaderType == PShader.TEXTURE) { - shader = new TexureShader(parent); + shader = new TextureShader(parent); shader.setVertexShader(defTextureShaderVertURL); } else if (shaderType == PShader.COLOR) { shader = new ColorShader(parent); @@ -6235,7 +6233,7 @@ public class PGraphicsOpenGL extends PGraphics { shader = new LightShader(parent); shader.setFragmentShader(defColorShaderFragURL); } else if (shaderType == PShader.TEXTURE) { - shader = new TexureShader(parent); + shader = new TextureShader(parent); shader.setFragmentShader(defTextureShaderFragURL); } else if (shaderType == PShader.COLOR) { shader = new ColorShader(parent); @@ -6254,7 +6252,7 @@ public class PGraphicsOpenGL extends PGraphics { } else if (shaderType == PShader.LIGHT) { shader = new LightShader(parent, vertFilename, fragFilename); } else if (shaderType == PShader.TEXTURE) { - shader = new TexureShader(parent, vertFilename, fragFilename); + shader = new TextureShader(parent, vertFilename, fragFilename); } else if (shaderType == PShader.COLOR) { shader = new ColorShader(parent, vertFilename, fragFilename); } @@ -6274,8 +6272,8 @@ public class PGraphicsOpenGL extends PGraphics { flush(); // Flushing geometry drawn with a different shader. if (kind == TRIANGLES || kind == QUADS || kind == POLYGON) { - if (shader instanceof TexureShader) { - textureShader = (TexureShader) shader; + if (shader instanceof TextureShader) { + textureShader = (TextureShader) shader; } else if (shader instanceof ColorShader) { colorShader = (ColorShader) shader; } else if (shader instanceof TexlightShader) { @@ -6403,7 +6401,7 @@ public class PGraphicsOpenGL extends PGraphics { if (tex) { if (textureShader == null) { if (defTextureShader == null) { - defTextureShader = new TexureShader(parent, + defTextureShader = new TextureShader(parent, defTextureShaderVertURL, defTextureShaderFragURL); } @@ -6514,6 +6512,7 @@ public class PGraphicsOpenGL extends PGraphics { protected int modelviewLoc; protected int projectionLoc; protected int bufferLoc; + protected int bufferUnit; protected int viewportLoc; public BaseShader(PApplet parent) { @@ -6541,7 +6540,7 @@ public class PGraphicsOpenGL extends PGraphics { public void unbind() { if (-1 < bufferLoc) { pgl.needFBOLayer(); - pgl.activeTexture(PGL.TEXTURE0 + lastTexUnit); + pgl.activeTexture(PGL.TEXTURE0 + bufferUnit); pgCurrent.unbindBackTexture(); pgl.activeTexture(PGL.TEXTURE0); } @@ -6576,9 +6575,12 @@ public class PGraphicsOpenGL extends PGraphics { } if (-1 < bufferLoc) { - setUniformValue(bufferLoc, lastTexUnit); - pgl.activeTexture(PGL.TEXTURE0 + lastTexUnit); + bufferUnit = getLastTexUnit() + 1; + setUniformValue(bufferLoc, bufferUnit); + pgl.activeTexture(PGL.TEXTURE0 + bufferUnit); pgCurrent.bindBackTexture(); + } else { + bufferUnit = -1; } } @@ -6824,7 +6826,9 @@ public class PGraphicsOpenGL extends PGraphics { } - protected class TexureShader extends ColorShader { + protected class TextureShader extends ColorShader { + protected Texture texture; + protected int texUnit; protected int texCoordLoc; protected int textureLoc; @@ -6836,16 +6840,16 @@ public class PGraphicsOpenGL extends PGraphics { protected float[] tcmat; - public TexureShader(PApplet parent) { + public TextureShader(PApplet parent) { super(parent); } - public TexureShader(PApplet parent, String vertFilename, + public TextureShader(PApplet parent, String vertFilename, String fragFilename) { super(parent, vertFilename, fragFilename); } - public TexureShader(PApplet parent, URL vertURL, URL fragURL) { + public TextureShader(PApplet parent, URL vertURL, URL fragURL) { super(parent, vertURL, fragURL); } @@ -6916,13 +6920,17 @@ public class PGraphicsOpenGL extends PGraphics { setUniformValue(texOffsetLoc, 1.0f / tex.width, 1.0f / tex.height); - setUniformValue(textureLoc, 0); + if (-1 < textureLoc) { + texUnit = bufferUnit + 1; + setUniformValue(textureLoc, texUnit); + pgl.activeTexture(PGL.TEXTURE0 + texUnit); + tex.bind(); + texture = tex; + } } @Override public void bind() { - firstTexUnit = 1; // 0 will be used by the textureSampler - super.bind(); if (-1 < texCoordLoc) pgl.enableVertexAttribArray(texCoordLoc); @@ -6939,12 +6947,21 @@ public class PGraphicsOpenGL extends PGraphics { if (-1 < texCoordLoc) pgl.disableVertexAttribArray(texCoordLoc); if (-1 < normalLoc) pgl.disableVertexAttribArray(normalLoc); + if (-1 < textureLoc && texture != null) { + pgl.activeTexture(PGL.TEXTURE0 + texUnit); + texture.unbind(); + pgl.activeTexture(PGL.TEXTURE0); + texture = null; + } + super.unbind(); } } protected class TexlightShader extends LightShader { + protected Texture texture; + protected int texUnit; protected int texCoordLoc; protected int textureLoc; @@ -7023,13 +7040,17 @@ public class PGraphicsOpenGL extends PGraphics { setUniformValue(texOffsetLoc, 1.0f / tex.width, 1.0f / tex.height); - setUniformValue(textureLoc, 0); + if (-1 < textureLoc) { + texUnit = bufferUnit + 1; + setUniformValue(textureLoc, texUnit); + pgl.activeTexture(PGL.TEXTURE0 + texUnit); + tex.bind(); + texture = tex; + } } @Override public void bind() { - firstTexUnit = 1; // 0 will be used by the textureSampler - super.bind(); if (-1 < texCoordLoc) pgl.enableVertexAttribArray(texCoordLoc); @@ -7039,6 +7060,13 @@ public class PGraphicsOpenGL extends PGraphics { public void unbind() { if (-1 < texCoordLoc) pgl.disableVertexAttribArray(texCoordLoc); + if (-1 < textureLoc && texture != null) { + pgl.activeTexture(PGL.TEXTURE0 + texUnit); + texture.unbind(); + pgl.activeTexture(PGL.TEXTURE0); + texture = null; + } + super.unbind(); } } @@ -7268,8 +7296,7 @@ public class PGraphicsOpenGL extends PGraphics { int[] lastIndex; int[] firstCache; int[] lastCache; - boolean hasTexture; - Texture tex0; + boolean hasTextures; TexCache() { allocate(); @@ -7282,17 +7309,13 @@ public class PGraphicsOpenGL extends PGraphics { firstCache = new int[PGL.DEFAULT_IN_TEXTURES]; lastCache = new int[PGL.DEFAULT_IN_TEXTURES]; size = 0; - hasTexture = false; + hasTextures = false; } void clear() { java.util.Arrays.fill(textures, 0, size, null); size = 0; - hasTexture = false; - } - - void beginRender() { - tex0 = null; + hasTextures = false; } PImage getTextureImage(int i) { @@ -7305,35 +7328,11 @@ public class PGraphicsOpenGL extends PGraphics { if (img != null) { tex = pgPrimary.getTexture(img); - if (tex != null) { - tex.bind(); - tex0 = tex; - } - } - if (tex == null && tex0 != null) { - tex0.unbind(); - pgl.disableTexturing(tex0.glTarget); } return tex; } - void endRender() { - if (hasTexture) { - // Unbinding all the textures in the cache. - for (int i = 0; i < size; i++) { - PImage img = textures[i]; - if (img != null) { - Texture tex = pgPrimary.getTexture(img); - if (tex != null) { - tex.unbind(); - pgl.disableTexturing(tex.glTarget); - } - } - } - } - } - void addTexture(PImage img, int firsti, int firstb, int lasti, int lastb) { arrayCheck(); @@ -7344,7 +7343,7 @@ public class PGraphicsOpenGL extends PGraphics { lastCache[size] = lastb; // At least one non-null texture since last reset. - hasTexture |= img != null; + hasTextures |= img != null; size++; } diff --git a/core/src/processing/opengl/PShader.java b/core/src/processing/opengl/PShader.java index 10306e53f..2abc47647 100644 --- a/core/src/processing/opengl/PShader.java +++ b/core/src/processing/opengl/PShader.java @@ -78,7 +78,8 @@ public class PShader { protected HashMap uniformValues = null; protected HashMap textures; - protected int firstTexUnit; + protected HashMap texUnits; +// protected int firstTexUnit; protected int lastTexUnit; // Direct buffers to pass shader data to GL @@ -101,7 +102,7 @@ public class PShader { glVertex = 0; glFragment = 0; - firstTexUnit = 0; +// firstTexUnit = 0; intBuffer = PGL.allocateIntBuffer(1); floatBuffer = PGL.allocateFloatBuffer(1); @@ -212,10 +213,12 @@ public class PShader { */ public void bind() { init(); - pgl.useProgram(glProgram); - bound = true; - consumeUniforms(); - bindTextures(); + if (!bound) { + pgl.useProgram(glProgram); + bound = true; + consumeUniforms(); + bindTextures(); + } } @@ -223,9 +226,11 @@ public class PShader { * Unbinds the shader program. */ public void unbind() { - unbindTextures(); - pgl.useProgram(0); - bound = false; + if (bound) { + unbindTextures(); + pgl.useProgram(0); + bound = false; + } } @@ -521,45 +526,18 @@ public class PShader { protected void setUniformTex(int loc, Texture tex) { - // get unit from last value in bindTextures ... - // pgl.activeTexture(PGL.TEXTURE0 + unit); - tex.bind(); - } - - - /* - // The individual attribute setters are not really needed, read this: - // http://stackoverflow.com/questions/7718976/what-is-glvertexattrib-versus-glvertexattribpointer-used-for - // except for setting a constant vertex attribute value. - public void set1FloatAttribute(int loc, float x) { - if (-1 < loc) { - pgl.glVertexAttrib1f(loc, x); + if (texUnits != null) { + Integer unit = texUnits.get(loc); + if (unit != null) { + pgl.activeTexture(PGL.TEXTURE0 + unit); + tex.bind(); + } else { + throw new RuntimeException("Cannot find unit for texture " + tex); + } } } - public void set2FloatAttribute(int loc, float x, float y) { - if (-1 < loc) { - pgl.glVertexAttrib2f(loc, x, y); - } - } - - - public void set3FloatAttribute(int loc, float x, float y, float z) { - if (-1 < loc) { - pgl.glVertexAttrib3f(loc, x, y, z); - } - } - - - public void set4FloatAttribute(int loc, float x, float y, float z, float w) { - if (-1 < loc) { - pgl.glVertexAttrib4f(loc, x, y, z, w); - } - } - */ - - protected void setUniformImpl(String name, int type, Object value) { int loc = getUniformLoc(name); if (-1 < loc) { @@ -576,7 +554,7 @@ public class PShader { protected void consumeUniforms() { if (uniformValues != null && 0 < uniformValues.size()) { - lastTexUnit = firstTexUnit; + lastTexUnit = 0; //firstTexUnit; for (Integer loc: uniformValues.keySet()) { UniformValue val = uniformValues.get(loc); if (val.type == UniformValue.INT1) { @@ -650,11 +628,18 @@ public class PShader { } else if (val.type == UniformValue.SAMPLER2D) { PImage img = (PImage)val.value; Texture tex = pgMain.getTexture(img); - pgl.uniform1i(loc, lastTexUnit); - if (textures == null) { - textures = new HashMap(); + + if (textures == null) textures = new HashMap(); + textures.put(loc, tex); + + if (texUnits == null) texUnits = new HashMap(); + if (texUnits.containsKey(loc)) { + lastTexUnit = texUnits.get(loc); + pgl.uniform1i(loc, lastTexUnit); + } else { + texUnits.put(loc, lastTexUnit); + pgl.uniform1i(loc, lastTexUnit); } - textures.put(lastTexUnit, tex); lastTexUnit++; } } @@ -674,28 +659,43 @@ public class PShader { protected void bindTextures() { - if (textures != null) { - for (int unit: textures.keySet()) { - Texture tex = textures.get(unit); - pgl.activeTexture(PGL.TEXTURE0 + unit); - tex.bind(); + if (textures != null && texUnits != null) { + for (int loc: textures.keySet()) { + Texture tex = textures.get(loc); + Integer unit = texUnits.get(loc); + if (unit != null) { + pgl.activeTexture(PGL.TEXTURE0 + unit); + tex.bind(); + } else { + throw new RuntimeException("Cannot find unit for texture " + tex); + } } } } protected void unbindTextures() { - if (textures != null) { - for (int unit: textures.keySet()) { - Texture tex = textures.get(unit); - pgl.activeTexture(PGL.TEXTURE0 + unit); - tex.unbind(); + if (textures != null && texUnits != null) { + for (int loc: textures.keySet()) { + Texture tex = textures.get(loc); + Integer unit = texUnits.get(loc); + if (unit != null) { + pgl.activeTexture(PGL.TEXTURE0 + unit); + tex.unbind(); + } else { + throw new RuntimeException("Cannot find unit for texture " + tex); + } } pgl.activeTexture(PGL.TEXTURE0); } } + protected int getLastTexUnit() { + if (texUnits == null) return -1; + else return texUnits.size() - 1; + } + protected void init() { if (glProgram == 0 || contextIsOutdated()) { context = pgl.getCurrentContext(); @@ -929,4 +929,36 @@ public class PShader { this.value = value; } } + + /* + // The individual attribute setters are not really needed, read this: + // http://stackoverflow.com/questions/7718976/what-is-glvertexattrib-versus-glvertexattribpointer-used-for + // except for setting a constant vertex attribute value. + public void set1FloatAttribute(int loc, float x) { + if (-1 < loc) { + pgl.glVertexAttrib1f(loc, x); + } + } + + + public void set2FloatAttribute(int loc, float x, float y) { + if (-1 < loc) { + pgl.glVertexAttrib2f(loc, x, y); + } + } + + + public void set3FloatAttribute(int loc, float x, float y, float z) { + if (-1 < loc) { + pgl.glVertexAttrib3f(loc, x, y, z); + } + } + + + public void set4FloatAttribute(int loc, float x, float y, float z, float w) { + if (-1 < loc) { + pgl.glVertexAttrib4f(loc, x, y, z, w); + } + } + */ } diff --git a/core/src/processing/opengl/PShapeOpenGL.java b/core/src/processing/opengl/PShapeOpenGL.java index 88e84c38d..9d0475a41 100644 --- a/core/src/processing/opengl/PShapeOpenGL.java +++ b/core/src/processing/opengl/PShapeOpenGL.java @@ -4124,13 +4124,7 @@ public class PShapeOpenGL extends PShape { protected void renderPolys(PGraphicsOpenGL g, PImage textureImage) { - Texture tex = null; - if (textureImage != null) { - tex = g.getTexture(textureImage); - if (tex != null) { - tex.bind(); - } - } + Texture tex = textureImage != null ? g.getTexture(textureImage) : null; boolean renderingFill = false, renderingStroke = false; BaseShader shader = null; @@ -4207,10 +4201,6 @@ public class PShapeOpenGL extends PShape { if (shader != null && shader.bound()) { shader.unbind(); } - - if (tex != null) { - tex.unbind(); - } }