diff --git a/core/src/processing/opengl/PGraphicsOpenGL.java b/core/src/processing/opengl/PGraphicsOpenGL.java index 876345526..ef7f30235 100644 --- a/core/src/processing/opengl/PGraphicsOpenGL.java +++ b/core/src/processing/opengl/PGraphicsOpenGL.java @@ -84,12 +84,6 @@ public class PGraphicsOpenGL extends PGraphics { "shader() called with a wrong shader"; static final String UNKNOWN_SHADER_KIND_ERROR = "Unknown shader kind"; - static final String LIGHT_SHADER_ERROR = - "The shader expects lights but it is beging used to draw an unlit scene, " + - "this might lead to unexpected rendering errors."; - static final String TEXTURE_SHADER_ERROR = - "The shader expects textures but it is being used to draw an untextured scene, " + - "this might lead to unexpected rendering errors."; static final String TOO_LONG_STROKE_PATH_ERROR = "Stroke path is too long, some bevel triangles won't be added"; static final String TESSELLATION_ERROR = @@ -1294,7 +1288,8 @@ public class PGraphicsOpenGL extends PGraphics { } - protected void updatePolyBuffers(boolean lit, boolean tex) { + protected void updatePolyBuffers(boolean lit, boolean tex, + boolean needNormals, boolean needTexCoords) { createPolyBuffers(); int size = tessGeo.polyVertexCount; @@ -1312,11 +1307,6 @@ public class PGraphicsOpenGL extends PGraphics { tessGeo.polyColorsBuffer, PGL.STATIC_DRAW); if (lit) { - tessGeo.updatePolyNormalsBuffer(); - pgl.bindBuffer(PGL.ARRAY_BUFFER, glPolyNormal); - pgl.bufferData(PGL.ARRAY_BUFFER, 3 * sizef, - tessGeo.polyNormalsBuffer, PGL.STATIC_DRAW); - tessGeo.updatePolyAmbientBuffer(); pgl.bindBuffer(PGL.ARRAY_BUFFER, glPolyAmbient); pgl.bufferData(PGL.ARRAY_BUFFER, sizei, @@ -1337,8 +1327,14 @@ public class PGraphicsOpenGL extends PGraphics { pgl.bufferData(PGL.ARRAY_BUFFER, sizef, tessGeo.polyShininessBuffer, PGL.STATIC_DRAW); } + if (lit || needNormals) { + tessGeo.updatePolyNormalsBuffer(); + pgl.bindBuffer(PGL.ARRAY_BUFFER, glPolyNormal); + pgl.bufferData(PGL.ARRAY_BUFFER, 3 * sizef, + tessGeo.polyNormalsBuffer, PGL.STATIC_DRAW); + } - if (tex) { + if (tex || needTexCoords) { tessGeo.updatePolyTexCoordsBuffer(); pgl.bindBuffer(PGL.ARRAY_BUFFER, glPolyTexcoord); pgl.bufferData(PGL.ARRAY_BUFFER, 2 * sizef, @@ -2381,7 +2377,11 @@ public class PGraphicsOpenGL extends PGraphics { protected void flushPolys() { - updatePolyBuffers(lights, texCache.hasTextures); + boolean customShader = polyShader != null; + boolean needNormals = customShader ? polyShader.accessNormals() : false; + boolean needTexCoords = customShader ? polyShader.accessTexCoords() : false; + + updatePolyBuffers(lights, texCache.hasTextures, needNormals, needTexCoords); for (int i = 0; i < texCache.size; i++) { Texture tex = texCache.getTexture(i); @@ -2405,10 +2405,6 @@ public class PGraphicsOpenGL extends PGraphics { 4 * voffset * PGL.SIZEOF_FLOAT); shader.setColorAttribute(glPolyColor, 4, PGL.UNSIGNED_BYTE, 0, 4 * voffset * PGL.SIZEOF_BYTE); - shader.setNormalAttribute(glPolyNormal, 3, PGL.FLOAT, 0, - 3 * voffset * PGL.SIZEOF_FLOAT); - shader.setTexcoordAttribute(glPolyTexcoord, 2, PGL.FLOAT, 0, - 2 * voffset * PGL.SIZEOF_FLOAT); if (lights) { shader.setNormalAttribute(glPolyNormal, 3, PGL.FLOAT, 0, @@ -2421,14 +2417,17 @@ public class PGraphicsOpenGL extends PGraphics { 4 * voffset * PGL.SIZEOF_BYTE); shader.setShininessAttribute(glPolyShininess, 1, PGL.FLOAT, 0, voffset * PGL.SIZEOF_FLOAT); - } else if (shader.supportLighting()) { - PGraphics.showWarning(LIGHT_SHADER_ERROR); } - if (tex != null) { + if (lights || needNormals) { + shader.setNormalAttribute(glPolyNormal, 3, PGL.FLOAT, 0, + 3 * voffset * PGL.SIZEOF_FLOAT); + } + + if (tex != null || needTexCoords) { + shader.setTexcoordAttribute(glPolyTexcoord, 2, PGL.FLOAT, 0, + 2 * voffset * PGL.SIZEOF_FLOAT); shader.setTexture(tex); - } else if (shader.supportsTexturing()) { - PGraphics.showWarning(TEXTURE_SHADER_ERROR); } pgl.bindBuffer(PGL.ELEMENT_ARRAY_BUFFER, glPolyIndex); @@ -5539,7 +5538,8 @@ public class PGraphicsOpenGL extends PGraphics { @Override public void filter(PShader shader) { - if (!(shader instanceof PolyShader) || !((PolyShader)shader).supportsTexturing()) { + if (!(shader instanceof PolyShader) || + !((PolyShader)shader).supportsTexturing()) { PGraphics.showWarning(INVALID_FILTER_SHADER_ERROR); return; } @@ -5671,7 +5671,7 @@ public class PGraphicsOpenGL extends PGraphics { * Allows to set custom blend modes for the entire scene, using openGL. * Reference article about blending modes: * http://www.pegtop.net/delphi/articles/blendmodes/ - * HARD_LIGHT, SOFT_LIGHT, OVERLAY, DODGE, BURN modes cannot be + * DIFFERENCE, HARD_LIGHT, SOFT_LIGHT, OVERLAY, DODGE, BURN modes cannot be * implemented in fixed-function pipeline because they require * conditional blending and non-linear blending equations. */ @@ -5726,12 +5726,6 @@ public class PGraphicsOpenGL extends PGraphics { PGraphics.showWarning(BLEND_DRIVER_ERROR, "DARKEST"); } - } else if (blendMode == DIFFERENCE) { - if (blendEqSupported) { - pgl.blendEquation(PGL.FUNC_ADD); - } - pgl.blendFunc(PGL.ONE_MINUS_DST_COLOR, PGL.ZERO); - } else if (blendMode == EXCLUSION) { if (blendEqSupported) { pgl.blendEquation(PGL.FUNC_ADD); @@ -5750,6 +5744,9 @@ public class PGraphicsOpenGL extends PGraphics { } pgl.blendFunc(PGL.ONE_MINUS_DST_COLOR, PGL.ONE); + } else if (blendMode == DIFFERENCE) { + PGraphics.showWarning(BLEND_RENDERER_ERROR, "DIFFERENCE"); + } else if (blendMode == OVERLAY) { PGraphics.showWarning(BLEND_RENDERER_ERROR, "OVERLAY"); @@ -6645,7 +6642,7 @@ public class PGraphicsOpenGL extends PGraphics { } if (-1 < bufferLoc) { - bufferUnit = getLastTexUnit() + 1; + bufferUnit = super.getLastTexUnit() + 1; setUniformValue(bufferLoc, bufferUnit); pgl.activeTexture(PGL.TEXTURE0 + bufferUnit); pgCurrent.bindFrontTexture(); @@ -6654,6 +6651,11 @@ public class PGraphicsOpenGL extends PGraphics { } } + @Override + public int getLastTexUnit() { + return -1 < bufferUnit ? bufferUnit : super.getLastTexUnit(); + } + public boolean supportsTexturing() { return false; } @@ -6662,6 +6664,14 @@ public class PGraphicsOpenGL extends PGraphics { return false; } + public boolean accessTexCoords() { + return false; + } + + public boolean accessNormals() { + return false; + } + public void setVertexAttribute(int vboId, int size, int type, int stride, int offset) { } public void setColorAttribute(int vboId, int size, int type, @@ -6760,32 +6770,40 @@ public class PGraphicsOpenGL extends PGraphics { texOffsetLoc = getUniformLoc("texOffset"); } -// @Override -// public int getLastTexUnit() { -// return -1 < bufferUnit ? bufferUnit : super.getLastTexUnit(); -// } - @Override public void setTexture(Texture tex) { + texture = tex; + float scaleu = 1; float scalev = 1; float dispu = 0; float dispv = 0; - if (tex.invertedX()) { - scaleu = -1; - dispu = 1; - } + if (tex != null) { + if (tex.invertedX()) { + scaleu = -1; + dispu = 1; + } - if (tex.invertedY()) { - scalev = -1; - dispv = 1; - } + if (tex.invertedY()) { + scalev = -1; + dispv = 1; + } - scaleu *= tex.maxTexcoordU(); - dispu *= tex.maxTexcoordU(); - scalev *= tex.maxTexcoordV(); - dispv *= tex.maxTexcoordV(); + scaleu *= tex.maxTexcoordU(); + dispu *= tex.maxTexcoordU(); + scalev *= tex.maxTexcoordV(); + dispv *= tex.maxTexcoordV(); + + setUniformValue(texOffsetLoc, 1.0f / tex.width, 1.0f / tex.height); + + if (-1 < textureLoc) { + texUnit = getLastTexUnit() + 1; + setUniformValue(textureLoc, texUnit); + pgl.activeTexture(PGL.TEXTURE0 + texUnit); + tex.bind(); + } + } if (-1 < texMatrixLoc) { if (tcmat == null) { @@ -6797,16 +6815,6 @@ public class PGraphicsOpenGL extends PGraphics { tcmat[3] = 0; tcmat[7] = 0; tcmat[11] = 0; tcmat[15] = 0; setUniformMatrix(texMatrixLoc, tcmat); } - - setUniformValue(texOffsetLoc, 1.0f / tex.width, 1.0f / tex.height); - - if (-1 < textureLoc) { - texUnit = getLastTexUnit() + 1; - setUniformValue(textureLoc, texUnit); - pgl.activeTexture(PGL.TEXTURE0 + texUnit); - tex.bind(); - texture = tex; - } } @Override @@ -6819,6 +6827,16 @@ public class PGraphicsOpenGL extends PGraphics { return -1 < lightCountLoc || -1 < lightPositionLoc || -1 < lightNormalLoc; } + @Override + public boolean accessTexCoords() { + return -1 < texCoordLoc; + } + + @Override + public boolean accessNormals() { + return -1 < normalLoc; + } + @Override public void setVertexAttribute(int vboId, int size, int type, int stride, int offset) { @@ -6894,14 +6912,16 @@ public class PGraphicsOpenGL extends PGraphics { int count = pgCurrent.lightCount; setUniformValue(lightCountLoc, count); - setUniformVector(lightPositionLoc, pgCurrent.lightPosition, 4, count); - setUniformVector(lightNormalLoc, pgCurrent.lightNormal, 3, count); - setUniformVector(lightAmbientLoc, pgCurrent.lightAmbient, 3, count); - setUniformVector(lightDiffuseLoc, pgCurrent.lightDiffuse, 3, count); - setUniformVector(lightSpecularLoc, pgCurrent.lightSpecular, 3, count); - setUniformVector(lightFalloffLoc, pgCurrent.lightFalloffCoefficients, - 3, count); - setUniformVector(lightSpotLoc, pgCurrent.lightSpotParameters, 2, count); + if (0 < count) { + setUniformVector(lightPositionLoc, pgCurrent.lightPosition, 4, count); + setUniformVector(lightNormalLoc, pgCurrent.lightNormal, 3, count); + setUniformVector(lightAmbientLoc, pgCurrent.lightAmbient, 3, count); + setUniformVector(lightDiffuseLoc, pgCurrent.lightDiffuse, 3, count); + setUniformVector(lightSpecularLoc, pgCurrent.lightSpecular, 3, count); + setUniformVector(lightFalloffLoc, pgCurrent.lightFalloffCoefficients, + 3, count); + setUniformVector(lightSpotLoc, pgCurrent.lightSpotParameters, 2, count); + } } @Override @@ -8008,24 +8028,6 @@ public class PGraphicsOpenGL extends PGraphics { vert[SA] = ((strokeColors[i] >> 24) & 0xFF) / 255.0f; vert[SW] = strokeWeights[i]; - - /* - // Android doesn't have these: - vert[AR] = ((ambient[i] >> 16) & 0xFF) / 255.0f; - vert[AG] = ((ambient[i] >> 8) & 0xFF) / 255.0f; - vert[AB] = ((ambient[i] >> 0) & 0xFF) / 255.0f; - - vert[SPR] = ((specular[i] >> 16) & 0xFF) / 255.0f; - vert[SPG] = ((specular[i] >> 8) & 0xFF) / 255.0f; - vert[SPB] = ((specular[i] >> 0) & 0xFF) / 255.0f; - - vert[ER] = ((emissive[i] >> 16) & 0xFF) / 255.0f; - vert[EG] = ((emissive[i] >> 8) & 0xFF) / 255.0f; - vert[EB] = ((emissive[i] >> 0) & 0xFF) / 255.0f; - - vert[SHINE] = shininess[i]; - */ - } return data; diff --git a/core/src/processing/opengl/PShader.java b/core/src/processing/opengl/PShader.java index 5c390a55d..0bc608368 100644 --- a/core/src/processing/opengl/PShader.java +++ b/core/src/processing/opengl/PShader.java @@ -265,7 +265,7 @@ public class PShader { * @param w fourth component of the variable to modify. The variable has to be declared with an array/vector type in the shader (i.e.: int[4], vec4) */ public void set(String name, int x, int y, int z, int w) { - setUniformImpl(name, UniformValue.INT4, new int[] { x, y, z }); + setUniformImpl(name, UniformValue.INT4, new int[] { x, y, z, w }); } diff --git a/core/src/processing/opengl/PShapeOpenGL.java b/core/src/processing/opengl/PShapeOpenGL.java index b2bdceacd..bd33f666f 100644 --- a/core/src/processing/opengl/PShapeOpenGL.java +++ b/core/src/processing/opengl/PShapeOpenGL.java @@ -33,9 +33,9 @@ import processing.core.PShape; import processing.core.PVector; import processing.opengl.PGraphicsOpenGL.LineShader; import processing.opengl.PGraphicsOpenGL.PointShader; -import processing.opengl.PGraphicsOpenGL.BaseShader; import processing.opengl.PGraphicsOpenGL.IndexCache; import processing.opengl.PGraphicsOpenGL.InGeometry; +import processing.opengl.PGraphicsOpenGL.PolyShader; import processing.opengl.PGraphicsOpenGL.TessGeometry; import processing.opengl.PGraphicsOpenGL.Tessellator; @@ -4432,10 +4432,14 @@ public class PShapeOpenGL extends PShape { protected void renderPolys(PGraphicsOpenGL g, PImage textureImage) { + boolean customShader = g.polyShader != null; + boolean needNormals = customShader ? g.polyShader.accessNormals() : false; + boolean needTexCoords = customShader ? g.polyShader.accessTexCoords() : false; + Texture tex = textureImage != null ? g.getTexture(textureImage) : null; boolean renderingFill = false, renderingStroke = false; - BaseShader shader = null; + PolyShader shader = null; IndexCache cache = tessGeo.polyIndexCache; for (int n = firstPolyIndexCache; n <= lastPolyIndexCache; n++) { if (is3D() || (tex != null && (firstLineIndexCache == -1 || @@ -4478,10 +4482,6 @@ public class PShapeOpenGL extends PShape { 0, 4 * voffset * PGL.SIZEOF_FLOAT); shader.setColorAttribute(root.glPolyColor, 4, PGL.UNSIGNED_BYTE, 0, 4 * voffset * PGL.SIZEOF_BYTE); - shader.setNormalAttribute(root.glPolyNormal, 3, PGL.FLOAT, - 0, 3 * voffset * PGL.SIZEOF_FLOAT); - shader.setTexcoordAttribute(root.glPolyTexcoord, 2, PGL.FLOAT, - 0, 2 * voffset * PGL.SIZEOF_FLOAT); if (g.lights) { shader.setNormalAttribute(root.glPolyNormal, 3, PGL.FLOAT, @@ -4494,14 +4494,16 @@ public class PShapeOpenGL extends PShape { 0, 4 * voffset * PGL.SIZEOF_BYTE); shader.setShininessAttribute(root.glPolyShininess, 1, PGL.FLOAT, 0, voffset * PGL.SIZEOF_FLOAT); - } else if (shader.supportLighting()) { - PGraphics.showWarning(PGraphicsOpenGL.LIGHT_SHADER_ERROR); + } + if (g.lights || needNormals) { + shader.setNormalAttribute(root.glPolyNormal, 3, PGL.FLOAT, + 0, 3 * voffset * PGL.SIZEOF_FLOAT); } - if (tex != null) { + if (tex != null || needTexCoords) { + shader.setTexcoordAttribute(root.glPolyTexcoord, 2, PGL.FLOAT, + 0, 2 * voffset * PGL.SIZEOF_FLOAT); shader.setTexture(tex); - } else if (shader.supportsTexturing()) { - PGraphics.showWarning(PGraphicsOpenGL.TEXTURE_SHADER_ERROR); } pgl.bindBuffer(PGL.ELEMENT_ARRAY_BUFFER, root.glPolyIndex); diff --git a/core/src/processing/opengl/TextureVert.glsl b/core/src/processing/opengl/TextureVert.glsl index cbbb361b1..87f101536 100644 --- a/core/src/processing/opengl/TextureVert.glsl +++ b/core/src/processing/opengl/TextureVert.glsl @@ -18,7 +18,7 @@ Boston, MA 02111-1307 USA */ -//#define PROCESSING_TEXTURE_SHADER +#define PROCESSING_TEXTURE_SHADER uniform mat4 transformMatrix; uniform mat4 texMatrix;