diff --git a/android/core/src/processing/opengl/PGraphicsOpenGL.java b/android/core/src/processing/opengl/PGraphicsOpenGL.java index a0f3201ff..6efebc8fe 100644 --- a/android/core/src/processing/opengl/PGraphicsOpenGL.java +++ b/android/core/src/processing/opengl/PGraphicsOpenGL.java @@ -5818,6 +5818,11 @@ public class PGraphicsOpenGL extends PGraphics { } } + + public void resetShader() { + resetShader(PShader.TEXTURED); + } + public void resetShader(int kind) { flush(); // Flushing geometry drawn with a different shader. @@ -6246,6 +6251,7 @@ public class PGraphicsOpenGL extends PGraphics { protected class PolyTexShader extends PolyFlatShader { protected int inTexcoordLoc; + protected int textureSamplerLoc; protected int texcoordMatrixLoc; protected int texcoordOffsetLoc; @@ -6266,6 +6272,7 @@ public class PGraphicsOpenGL extends PGraphics { public void loadUniforms() { super.loadUniforms(); + textureSamplerLoc = getUniformLoc("textureSampler"); texcoordMatrixLoc = getUniformLoc("texcoordMatrix"); texcoordOffsetLoc = getUniformLoc("texcoordOffset"); } @@ -6313,9 +6320,13 @@ public class PGraphicsOpenGL extends PGraphics { } setUniformValue(texcoordOffsetLoc, 1.0f / tex.width, 1.0f / tex.height); + + setUniformValue(textureSamplerLoc, 0); } public void bind() { + firstTexUnit = 1; // 0 will be used by the textureSampler + super.bind(); if (-1 < inTexcoordLoc) pgl.glEnableVertexAttribArray(inTexcoordLoc); @@ -6332,6 +6343,7 @@ public class PGraphicsOpenGL extends PGraphics { protected class PolyFullShader extends PolyLightShader { protected int inTexcoordLoc; + protected int textureSamplerLoc; protected int texcoordMatrixLoc; protected int texcoordOffsetLoc; @@ -6352,6 +6364,7 @@ public class PGraphicsOpenGL extends PGraphics { public void loadUniforms() { super.loadUniforms(); + textureSamplerLoc = getUniformLoc("textureSampler"); texcoordMatrixLoc = getUniformLoc("texcoordMatrix"); texcoordOffsetLoc = getUniformLoc("texcoordOffset"); } @@ -6399,9 +6412,13 @@ public class PGraphicsOpenGL extends PGraphics { } setUniformValue(texcoordOffsetLoc, 1.0f / tex.width, 1.0f / tex.height); + + setUniformValue(textureSamplerLoc, 0); } public void bind() { + firstTexUnit = 1; // 0 will be used by the textureSampler + super.bind(); if (-1 < inTexcoordLoc) pgl.glEnableVertexAttribArray(inTexcoordLoc); diff --git a/android/core/src/processing/opengl/PShader.java b/android/core/src/processing/opengl/PShader.java index f2eb29e8b..dcb66b532 100644 --- a/android/core/src/processing/opengl/PShader.java +++ b/android/core/src/processing/opengl/PShader.java @@ -72,6 +72,10 @@ public class PShader { protected HashMap uniformValues = null; + protected HashMap textures; + protected int firstTexUnit; + + public PShader() { parent = null; pgMain = null; @@ -87,8 +91,11 @@ public class PShader { glVertex = 0; glFragment = 0; + firstTexUnit = 0; + bound = false; } + public PShader(PApplet parent) { @@ -185,6 +192,7 @@ public class PShader { pgl.glUseProgram(glProgram); bound = true; consumeUniforms(); + bindTextures(); } @@ -192,6 +200,7 @@ public class PShader { * Unbinds the shader program. */ public void unbind() { + unbindTextures(); pgl.glUseProgram(0); bound = false; } @@ -203,7 +212,7 @@ public class PShader { public boolean bound() { return bound; } - + public void set(String name, int x) { setUniformImpl(name, UniformValue.INT1, new int[] { x }); @@ -317,11 +326,17 @@ public class PShader { mat.m10, mat.m11, mat.m12, mat.m13, mat.m20, mat.m21, mat.m22, mat.m23, mat.m30, mat.m31, mat.m32, mat.m33 }; - setUniformImpl(name, UniformValue.MAT4, matv); + setUniformImpl(name, UniformValue.MAT4, matv); } } + public void set(String name, PImage tex) { + setUniformImpl(name, UniformValue.SAMPLER2D, tex); + } + + + /** * Returns the ID location of the attribute parameter given its name. * @@ -494,13 +509,14 @@ public class PShader { } uniformValues.put(loc, new UniformValue(type, value)); } else { - PGraphics.showWarning("The shader doesn't have the uniform " + name); + PGraphics.showWarning("The shader doesn't have a uniform called \"" + name + "\""); } } protected void consumeUniforms() { if (uniformValues != null && 0 < uniformValues.size()) { + int texUnit = firstTexUnit; for (Integer loc: uniformValues.keySet()) { UniformValue val = uniformValues.get(loc); if (val.type == UniformValue.INT1) { @@ -560,6 +576,15 @@ public class PShader { } else if (val.type == UniformValue.MAT4) { float[] v = ((float[])val.value); pgl.glUniformMatrix4fv(loc, 1, false, v, 0); + } else if (val.type == UniformValue.SAMPLER2D) { + PImage img = (PImage)val.value; + Texture tex = pgMain.getTexture(img); + pgl.glUniform1i(loc, texUnit); + if (textures == null) { + textures = new HashMap(); + textures.put(texUnit, tex); + } + texUnit++; } } uniformValues.clear(); @@ -567,6 +592,29 @@ public class PShader { } + protected void bindTextures() { + if (textures != null) { + for (int unit: textures.keySet()) { + Texture tex = textures.get(unit); + pgl.glActiveTexture(PGL.GL_TEXTURE0 + unit); + tex.bind(); + } + } + } + + + protected void unbindTextures() { + if (textures != null) { + for (int unit: textures.keySet()) { + Texture tex = textures.get(unit); + pgl.glActiveTexture(PGL.GL_TEXTURE0 + unit); + tex.unbind(); + } + pgl.glActiveTexture(PGL.GL_TEXTURE0); + } + } + + protected void init() { if (glProgram == 0 || contextIsOutdated()) { context = pgl.getCurrentContext(); @@ -783,6 +831,7 @@ public class PShader { static final int MAT2 = 16; static final int MAT3 = 17; static final int MAT4 = 18; + static final int SAMPLER2D = 19; int type; Object value; diff --git a/core/src/processing/opengl/PGraphicsOpenGL.java b/core/src/processing/opengl/PGraphicsOpenGL.java index a0f3201ff..6efebc8fe 100644 --- a/core/src/processing/opengl/PGraphicsOpenGL.java +++ b/core/src/processing/opengl/PGraphicsOpenGL.java @@ -5818,6 +5818,11 @@ public class PGraphicsOpenGL extends PGraphics { } } + + public void resetShader() { + resetShader(PShader.TEXTURED); + } + public void resetShader(int kind) { flush(); // Flushing geometry drawn with a different shader. @@ -6246,6 +6251,7 @@ public class PGraphicsOpenGL extends PGraphics { protected class PolyTexShader extends PolyFlatShader { protected int inTexcoordLoc; + protected int textureSamplerLoc; protected int texcoordMatrixLoc; protected int texcoordOffsetLoc; @@ -6266,6 +6272,7 @@ public class PGraphicsOpenGL extends PGraphics { public void loadUniforms() { super.loadUniforms(); + textureSamplerLoc = getUniformLoc("textureSampler"); texcoordMatrixLoc = getUniformLoc("texcoordMatrix"); texcoordOffsetLoc = getUniformLoc("texcoordOffset"); } @@ -6313,9 +6320,13 @@ public class PGraphicsOpenGL extends PGraphics { } setUniformValue(texcoordOffsetLoc, 1.0f / tex.width, 1.0f / tex.height); + + setUniformValue(textureSamplerLoc, 0); } public void bind() { + firstTexUnit = 1; // 0 will be used by the textureSampler + super.bind(); if (-1 < inTexcoordLoc) pgl.glEnableVertexAttribArray(inTexcoordLoc); @@ -6332,6 +6343,7 @@ public class PGraphicsOpenGL extends PGraphics { protected class PolyFullShader extends PolyLightShader { protected int inTexcoordLoc; + protected int textureSamplerLoc; protected int texcoordMatrixLoc; protected int texcoordOffsetLoc; @@ -6352,6 +6364,7 @@ public class PGraphicsOpenGL extends PGraphics { public void loadUniforms() { super.loadUniforms(); + textureSamplerLoc = getUniformLoc("textureSampler"); texcoordMatrixLoc = getUniformLoc("texcoordMatrix"); texcoordOffsetLoc = getUniformLoc("texcoordOffset"); } @@ -6399,9 +6412,13 @@ public class PGraphicsOpenGL extends PGraphics { } setUniformValue(texcoordOffsetLoc, 1.0f / tex.width, 1.0f / tex.height); + + setUniformValue(textureSamplerLoc, 0); } public void bind() { + firstTexUnit = 1; // 0 will be used by the textureSampler + super.bind(); if (-1 < inTexcoordLoc) pgl.glEnableVertexAttribArray(inTexcoordLoc); diff --git a/core/src/processing/opengl/PShader.java b/core/src/processing/opengl/PShader.java index 93a27d162..dcb66b532 100644 --- a/core/src/processing/opengl/PShader.java +++ b/core/src/processing/opengl/PShader.java @@ -72,6 +72,10 @@ public class PShader { protected HashMap uniformValues = null; + protected HashMap textures; + protected int firstTexUnit; + + public PShader() { parent = null; pgMain = null; @@ -87,8 +91,11 @@ public class PShader { glVertex = 0; glFragment = 0; + firstTexUnit = 0; + bound = false; } + public PShader(PApplet parent) { @@ -185,6 +192,7 @@ public class PShader { pgl.glUseProgram(glProgram); bound = true; consumeUniforms(); + bindTextures(); } @@ -192,6 +200,7 @@ public class PShader { * Unbinds the shader program. */ public void unbind() { + unbindTextures(); pgl.glUseProgram(0); bound = false; } @@ -203,18 +212,7 @@ public class PShader { public boolean bound() { return bound; } - - - public void set(String name, PImage tex) { - /* - texUnit = tu; - gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit); - gl.glBindTexture(texTarget, tex); - if (-1 < texUniform) { - gl.glUniform1iARB(texUniform, texUnit); - */ - } - + public void set(String name, int x) { setUniformImpl(name, UniformValue.INT1, new int[] { x }); @@ -328,11 +326,17 @@ public class PShader { mat.m10, mat.m11, mat.m12, mat.m13, mat.m20, mat.m21, mat.m22, mat.m23, mat.m30, mat.m31, mat.m32, mat.m33 }; - setUniformImpl(name, UniformValue.MAT4, matv); + setUniformImpl(name, UniformValue.MAT4, matv); } } + public void set(String name, PImage tex) { + setUniformImpl(name, UniformValue.SAMPLER2D, tex); + } + + + /** * Returns the ID location of the attribute parameter given its name. * @@ -505,13 +509,14 @@ public class PShader { } uniformValues.put(loc, new UniformValue(type, value)); } else { - PGraphics.showWarning("The shader doesn't have the uniform " + name); + PGraphics.showWarning("The shader doesn't have a uniform called \"" + name + "\""); } } protected void consumeUniforms() { if (uniformValues != null && 0 < uniformValues.size()) { + int texUnit = firstTexUnit; for (Integer loc: uniformValues.keySet()) { UniformValue val = uniformValues.get(loc); if (val.type == UniformValue.INT1) { @@ -571,6 +576,15 @@ public class PShader { } else if (val.type == UniformValue.MAT4) { float[] v = ((float[])val.value); pgl.glUniformMatrix4fv(loc, 1, false, v, 0); + } else if (val.type == UniformValue.SAMPLER2D) { + PImage img = (PImage)val.value; + Texture tex = pgMain.getTexture(img); + pgl.glUniform1i(loc, texUnit); + if (textures == null) { + textures = new HashMap(); + textures.put(texUnit, tex); + } + texUnit++; } } uniformValues.clear(); @@ -578,6 +592,29 @@ public class PShader { } + protected void bindTextures() { + if (textures != null) { + for (int unit: textures.keySet()) { + Texture tex = textures.get(unit); + pgl.glActiveTexture(PGL.GL_TEXTURE0 + unit); + tex.bind(); + } + } + } + + + protected void unbindTextures() { + if (textures != null) { + for (int unit: textures.keySet()) { + Texture tex = textures.get(unit); + pgl.glActiveTexture(PGL.GL_TEXTURE0 + unit); + tex.unbind(); + } + pgl.glActiveTexture(PGL.GL_TEXTURE0); + } + } + + protected void init() { if (glProgram == 0 || contextIsOutdated()) { context = pgl.getCurrentContext(); @@ -794,6 +831,7 @@ public class PShader { static final int MAT2 = 16; static final int MAT3 = 17; static final int MAT4 = 18; + static final int SAMPLER2D = 19; int type; Object value;