From d1aae8d4791ac4b6a85157c3e6402431b7afb380 Mon Sep 17 00:00:00 2001 From: Teencrusher Date: Wed, 6 Apr 2016 13:56:13 -0400 Subject: [PATCH 1/2] Added support to glBlendEquation for renderes implementing GL2, and material loading support --- .../java/com/jme3/material/RenderState.java | 212 +++++++++++++++++- .../java/com/jme3/renderer/RenderContext.java | 12 + .../java/com/jme3/renderer/opengl/GL2.java | 6 + .../jme3/renderer/opengl/GLDebugDesktop.java | 5 + .../com/jme3/renderer/opengl/GLRenderer.java | 47 ++++ .../com/jme3/material/plugins/J3MLoader.java | 5 + .../java/com/jme3/renderer/jogl/JoglGL.java | 5 + .../java/com/jme3/renderer/lwjgl/LwjglGL.java | 4 + .../java/com/jme3/renderer/lwjgl/LwjglGL.java | 4 + 9 files changed, 298 insertions(+), 2 deletions(-) diff --git a/jme3-core/src/main/java/com/jme3/material/RenderState.java b/jme3-core/src/main/java/com/jme3/material/RenderState.java index 7ff4a992a..ba7214e58 100644 --- a/jme3-core/src/main/java/com/jme3/material/RenderState.java +++ b/jme3-core/src/main/java/com/jme3/material/RenderState.java @@ -120,6 +120,92 @@ public class RenderState implements Cloneable, Savable { */ Always,} + /** + * BlendEquation specifies the blending equation to combine + * pixels. + */ + public enum BlendEquation { + /** + * Sets the blend equation so that the source and destination data are + * added. (Default) Clamps to [0,1] Useful for things like antialiasing + * and transparency. + */ + Add, + /** + * Sets the blend equation so that the source and destination data are + * subtracted (Src - Dest). Clamps to [0,1] Falls back to Add if + * supportsSubtract is false. + */ + Subtract, + /** + * Same as Subtract, but the order is reversed (Dst - Src). Clamps to + * [0,1] Falls back to Add if supportsSubtract is false. + */ + ReverseSubtract, + /** + * Sets the blend equation so that each component of the result color is + * the minimum of the corresponding components of the source and + * destination colors. This and Max are useful for applications that + * analyze image data (image thresholding against a constant color, for + * example). Falls back to Add if supportsMinMax is false. + */ + Min, + /** + * Sets the blend equation so that each component of the result color is + * the maximum of the corresponding components of the source and + * destination colors. This and Min are useful for applications that + * analyze image data (image thresholding against a constant color, for + * example). Falls back to Add if supportsMinMax is false. + */ + Max + } + + /** + * BlendEquationAlpha specifies the blending equation to + * combine pixels for the alpha component. + */ + public enum BlendEquationAlpha { + /** + * Sets the blend equation to be the same as the one defined by + * {@link #blendEquation}. + * + */ + InheritColor, + /** + * Sets the blend equation so that the source and destination data are + * added. (Default) Clamps to [0,1] Useful for things like antialiasing + * and transparency. + */ + Add, + /** + * Sets the blend equation so that the source and destination data are + * subtracted (Src - Dest). Clamps to [0,1] Falls back to Add if + * supportsSubtract is false. + */ + Subtract, + /** + * Same as Subtract, but the order is reversed (Dst - Src). Clamps to + * [0,1] Falls back to Add if supportsSubtract is false. + */ + ReverseSubtract, + /** + * Sets the blend equation so that the result alpha is the minimum of + * the source alpha and destination alpha. This and Max are useful for + * applications that analyze image data (image thresholding against a + * constant color, for example). Falls back to Add if supportsMinMax is + * false. + */ + Min, + /** + * sSets the blend equation so that the result alpha is the maximum of + * the source alpha and destination alpha. This and Min are useful for + * applications that analyze image data (image thresholding against a + * constant color, for example). Falls back to Add if supportsMinMax is + * false. + */ + Max + } + /** * BlendMode specifies the blending operation to use. * @@ -282,6 +368,8 @@ public class RenderState implements Cloneable, Savable { ADDITIONAL.applyDepthWrite = false; ADDITIONAL.applyDepthTest = false; ADDITIONAL.applyColorWrite = false; + ADDITIONAL.applyBlendEquation = false; + ADDITIONAL.applyBlendEquationAlpha = false; ADDITIONAL.applyBlendMode = false; ADDITIONAL.applyAlphaTest = false; ADDITIONAL.applyAlphaFallOff = false; @@ -299,6 +387,10 @@ public class RenderState implements Cloneable, Savable { boolean applyDepthTest = true; boolean colorWrite = true; boolean applyColorWrite = true; + BlendEquation blendEquation = BlendEquation.Add; + boolean applyBlendEquation = true; + BlendEquationAlpha blendEquationAlpha = BlendEquationAlpha.InheritColor; + boolean applyBlendEquationAlpha = true; BlendMode blendMode = BlendMode.Off; boolean applyBlendMode = true; boolean alphaTest = false; @@ -352,6 +444,8 @@ public class RenderState implements Cloneable, Savable { oc.write(backStencilDepthPassOperation, "backStencilDepthPassOperation", StencilOperation.Keep); oc.write(frontStencilFunction, "frontStencilFunction", TestFunction.Always); oc.write(backStencilFunction, "backStencilFunction", TestFunction.Always); + oc.write(blendEquation, "blendEquation", BlendEquation.Add); + oc.write(blendEquationAlpha, "blendEquationAlpha", BlendEquationAlpha.InheritColor); oc.write(depthFunc, "depthFunc", TestFunction.LessOrEqual); oc.write(alphaFunc, "alphaFunc", TestFunction.Greater); oc.write(lineWidth, "lineWidth", 1); @@ -363,6 +457,8 @@ public class RenderState implements Cloneable, Savable { oc.write(applyDepthWrite, "applyDepthWrite", true); oc.write(applyDepthTest, "applyDepthTest", true); oc.write(applyColorWrite, "applyColorWrite", true); + oc.write(applyBlendEquation, "applyBlendEquation", true); + oc.write(applyBlendEquationAlpha, "applyBlendEquationAlpha", true); oc.write(applyBlendMode, "applyBlendMode", true); oc.write(applyAlphaTest, "applyAlphaTest", true); oc.write(applyAlphaFallOff, "applyAlphaFallOff", true); @@ -396,6 +492,8 @@ public class RenderState implements Cloneable, Savable { backStencilDepthPassOperation = ic.readEnum("backStencilDepthPassOperation", StencilOperation.class, StencilOperation.Keep); frontStencilFunction = ic.readEnum("frontStencilFunction", TestFunction.class, TestFunction.Always); backStencilFunction = ic.readEnum("backStencilFunction", TestFunction.class, TestFunction.Always); + blendEquation = ic.readEnum("blendEquation", BlendEquation.class, BlendEquation.Add); + blendEquationAlpha = ic.readEnum("blendEquationAlpha", BlendEquationAlpha.class, BlendEquationAlpha.InheritColor); depthFunc = ic.readEnum("depthFunc", TestFunction.class, TestFunction.LessOrEqual); alphaFunc = ic.readEnum("alphaFunc", TestFunction.class, TestFunction.Greater); lineWidth = ic.readFloat("lineWidth", 1); @@ -407,6 +505,8 @@ public class RenderState implements Cloneable, Savable { applyDepthWrite = ic.readBoolean("applyDepthWrite", true); applyDepthTest = ic.readBoolean("applyDepthTest", true); applyColorWrite = ic.readBoolean("applyColorWrite", true); + applyBlendEquation = ic.readBoolean("applyBlendEquation", true); + applyBlendEquationAlpha = ic.readBoolean("applyBlendEquationAlpha", true); applyBlendMode = ic.readBoolean("applyBlendMode", true); applyAlphaTest = ic.readBoolean("applyAlphaTest", true); applyAlphaFallOff = ic.readBoolean("applyAlphaFallOff", true); @@ -433,8 +533,8 @@ public class RenderState implements Cloneable, Savable { } /** - * returns true if the given renderState is equall to this one - * @param o the renderState to compate to + * returns true if the given renderState is equal to this one + * @param o the renderState to compare to * @return true if the renderStates are equal */ @Override @@ -475,6 +575,14 @@ public class RenderState implements Cloneable, Savable { return false; } + if (blendEquation != rs.blendEquation) { + return false; + } + + if (blendEquationAlpha != rs.blendEquationAlpha) { + return false; + } + if (blendMode != rs.blendMode) { return false; } @@ -663,6 +771,61 @@ public class RenderState implements Cloneable, Savable { cachedHashCode = -1; } + /** + * Set the blending equation. + *

+ * When blending is enabled, (blendMode is not + * {@link BlendMode#Off}) the input pixel will be blended with the pixel + * already in the color buffer. The blending equation is determined by the + * {@link BlendEquation}. For example, the mode {@link BlendMode#Additive} + * and {@link BlendEquation#Add} will add the input pixel's color to the + * color already in the color buffer: + *
+ * Result = Source Color + Destination Color + *
+ * However, the mode {@link BlendMode#Additive} + * and {@link BlendEquation#Subtract} will subtract the input pixel's color to the + * color already in the color buffer: + *
+ * Result = Source Color - Destination Color + * + * @param blendEquation The blend equation to use. + */ + public void setBlendEquation(BlendEquation blendEquation) { + applyBlendEquation = true; + this.blendEquation = blendEquation; + cachedHashCode = -1; + } + + /** + * Set the blending equation for the alpha component. + *

+ * When blending is enabled, (blendMode is not + * {@link BlendMode#Off}) the input pixel will be blended with the pixel + * already in the color buffer. The blending equation is determined by the + * {@link BlendEquation} and can be overrode for the alpha component using + * the {@link BlendEquationAlpha} . For example, the mode + * {@link BlendMode#Additive} and {@link BlendEquationAlpha#Add} will add + * the input pixel's alpha to the alpha component already in the color + * buffer: + *
+ * Result = Source Alpha + Destination Alpha + *
+ * However, the mode {@link BlendMode#Additive} and + * {@link BlendEquationAlpha#Subtract} will subtract the input pixel's alpha + * to the alpha component already in the color buffer: + *
+ * Result = Source Alpha - Destination Alpha + * + * @param blendEquationAlpha The blend equation to use for the alpha + * component. + */ + public void setBlendEquationAlpha(BlendEquationAlpha blendEquationAlpha) { + applyBlendEquationAlpha = true; + this.blendEquationAlpha = blendEquationAlpha; + cachedHashCode = -1; + } + /** * Enable depth testing. * @@ -991,6 +1154,24 @@ public class RenderState implements Cloneable, Savable { return backStencilFunction; } + /** + * Retrieve the blend equation. + * + * @return the blend equation. + */ + public BlendEquation getBlendEquation() { + return blendEquation; + } + + /** + * Retrieve the blend equation used for the alpha component. + * + * @return the blend equation for the alpha component. + */ + public BlendEquationAlpha getBlendEquationAlpha() { + return blendEquationAlpha; + } + /** * Retrieve the blend mode. * @@ -1165,6 +1346,14 @@ public class RenderState implements Cloneable, Savable { return applyBlendMode; } + public boolean isApplyBlendEquation() { + return applyBlendEquation; + } + + public boolean isApplyBlendEquationAlpha() { + return applyBlendEquationAlpha; + } + public boolean isApplyColorWrite() { return applyColorWrite; } @@ -1219,6 +1408,8 @@ public class RenderState implements Cloneable, Savable { hash = 79 * hash + (this.depthFunc != null ? this.depthFunc.hashCode() : 0); hash = 79 * hash + (this.colorWrite ? 1 : 0); hash = 79 * hash + (this.blendMode != null ? this.blendMode.hashCode() : 0); + hash = 79 * hash + (this.blendEquation != null ? this.blendEquation.hashCode() : 0); + hash = 79 * hash + (this.blendEquationAlpha != null ? this.blendEquationAlpha.hashCode() : 0); hash = 79 * hash + (this.alphaTest ? 1 : 0); hash = 79 * hash + (this.alphaFunc != null ? this.alphaFunc.hashCode() : 0); hash = 79 * hash + Float.floatToIntBits(this.alphaFallOff); @@ -1302,6 +1493,16 @@ public class RenderState implements Cloneable, Savable { } else { state.colorWrite = colorWrite; } + if (additionalState.applyBlendEquation) { + state.blendEquation = additionalState.blendEquation; + } else { + state.blendEquation = blendEquation; + } + if (additionalState.applyBlendEquationAlpha) { + state.blendEquationAlpha = additionalState.blendEquationAlpha; + } else { + state.blendEquation = blendEquation; + } if (additionalState.applyBlendMode) { state.blendMode = additionalState.blendMode; } else { @@ -1389,6 +1590,8 @@ public class RenderState implements Cloneable, Savable { backStencilDepthPassOperation = state.backStencilDepthPassOperation; frontStencilFunction = state.frontStencilFunction; backStencilFunction = state.backStencilFunction; + blendEquationAlpha = state.blendEquationAlpha; + blendEquation = state.blendEquation; depthFunc = state.depthFunc; alphaFunc = state.alphaFunc; lineWidth = state.lineWidth; @@ -1399,6 +1602,8 @@ public class RenderState implements Cloneable, Savable { applyDepthWrite = true; applyDepthTest = true; applyColorWrite = true; + applyBlendEquation = true; + applyBlendEquationAlpha = true; applyBlendMode = true; applyAlphaTest = true; applyAlphaFallOff = true; @@ -1424,6 +1629,9 @@ public class RenderState implements Cloneable, Savable { + "\napplyDepthTest=" + applyDepthTest + "\ncolorWrite=" + colorWrite + "\napplyColorWrite=" + applyColorWrite + + "\nblendEquation=" + blendEquation + + "\napplyBlendEquation=" + applyBlendEquation + + "\napplyBlendEquationAlpha=" + applyBlendEquationAlpha + "\nblendMode=" + blendMode + "\napplyBlendMode=" + applyBlendMode + "\nalphaTest=" + alphaTest diff --git a/jme3-core/src/main/java/com/jme3/renderer/RenderContext.java b/jme3-core/src/main/java/com/jme3/renderer/RenderContext.java index 5be184c94..ac44e438d 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/RenderContext.java +++ b/jme3-core/src/main/java/com/jme3/renderer/RenderContext.java @@ -110,6 +110,16 @@ public class RenderContext { */ public RenderState.BlendMode blendMode = RenderState.BlendMode.Off; + /** + * @see RenderState#setBlendEquation(com.jme3.material.RenderState.BlendEquation) + */ + public RenderState.BlendEquation blendEquation = RenderState.BlendEquation.Add; + + /** + * @see RenderState#setBlendEquationAlpha(com.jme3.material.RenderState.BlendEquationAlpha) + */ + public RenderState.BlendEquationAlpha blendEquationAlpha = RenderState.BlendEquationAlpha.InheritColor; + /** * @see RenderState#setWireframe(boolean) */ @@ -270,6 +280,8 @@ public class RenderContext { polyOffsetUnits = 0; pointSize = 1; blendMode = RenderState.BlendMode.Off; + blendEquation = RenderState.BlendEquation.Add; + blendEquationAlpha = RenderState.BlendEquationAlpha.InheritColor; wireframe = false; boundShaderProgram = 0; boundShader = null; diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GL2.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GL2.java index abf6a77d7..d6e53b14d 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GL2.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GL2.java @@ -71,8 +71,14 @@ public interface GL2 extends GL { public static final int GL_TEXTURE_WRAP_R = 0x8072; public static final int GL_VERTEX_PROGRAM_POINT_SIZE = 0x8642; public static final int GL_UNSIGNED_INT_8_8_8_8 = 0x8035; + public static final int GL_FUNC_ADD = 0x8006; + public static final int GL_FUNC_SUBTRACT = 0x800A; + public static final int GL_FUNC_REVERSE_SUBTRACT = 0x800B; + public static final int GL_MIN = 0x8007; + public static final int GL_MAX = 0x8008; public void glAlphaFunc(int func, float ref); + public void glBlendEquationSeparate(int colorMode, int alphaMode); public void glPointSize(float size); public void glPolygonMode(int face, int mode); public void glDrawBuffer(int mode); diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebugDesktop.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebugDesktop.java index fd18cc7ff..3c39c8036 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebugDesktop.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebugDesktop.java @@ -100,4 +100,9 @@ public class GLDebugDesktop extends GLDebugES implements GL2, GL3, GL4 { gl3.glFramebufferTextureLayer(param1, param2, param3, param4, param5); checkError(); } + + public void glBlendEquationSeparate(int colorMode, int alphaMode) { + gl2.glBlendEquationSeparate(colorMode, alphaMode); + checkError(); + } } diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java index 7ef77a2b6..73e55b0e2 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java @@ -746,6 +746,18 @@ public final class GLRenderer implements Renderer { throw new UnsupportedOperationException("Unrecognized blend mode: " + state.getBlendMode()); } + + if (gl2 != null && (state.getBlendEquation() != context.blendEquation || state.getBlendEquationAlpha() != context.blendEquationAlpha)) { + int colorMode = convertBlendEquation(state.getBlendEquation()); + int alphaMode; + if (state.getBlendEquationAlpha() == RenderState.BlendEquationAlpha.InheritColor) { + alphaMode = colorMode; + } else { + alphaMode = convertBlendEquationAlpha(state.getBlendEquationAlpha()); + } + gl2.glBlendEquationSeparate(colorMode, alphaMode); + context.blendEquation = state.getBlendEquation(); + } } context.blendMode = state.getBlendMode(); @@ -796,6 +808,41 @@ public final class GLRenderer implements Renderer { } } + private int convertBlendEquation(RenderState.BlendEquation blendEquation) { + switch (blendEquation) { + case Add: + return GL2.GL_FUNC_ADD; + case Subtract: + return GL2.GL_FUNC_SUBTRACT; + case ReverseSubtract: + return GL2.GL_FUNC_REVERSE_SUBTRACT; + case Min: + return GL2.GL_MIN; + case Max: + return GL2.GL_MAX; + default: + throw new UnsupportedOperationException("Unrecognized blend operation: " + blendEquation); + } + } + + private int convertBlendEquationAlpha(RenderState.BlendEquationAlpha blendEquationAlpha) { + //Note: InheritColor mode should already be handled, that is why it does not belong the the switch case. + switch (blendEquationAlpha) { + case Add: + return GL2.GL_FUNC_ADD; + case Subtract: + return GL2.GL_FUNC_SUBTRACT; + case ReverseSubtract: + return GL2.GL_FUNC_REVERSE_SUBTRACT; + case Min: + return GL2.GL_MIN; + case Max: + return GL2.GL_MAX; + default: + throw new UnsupportedOperationException("Unrecognized alpha blend operation: " + blendEquationAlpha); + } + } + private int convertStencilOperation(StencilOperation stencilOp) { switch (stencilOp) { case Keep: diff --git a/jme3-core/src/plugins/java/com/jme3/material/plugins/J3MLoader.java b/jme3-core/src/plugins/java/com/jme3/material/plugins/J3MLoader.java index 8b0f831c5..9657df3f2 100644 --- a/jme3-core/src/plugins/java/com/jme3/material/plugins/J3MLoader.java +++ b/jme3-core/src/plugins/java/com/jme3/material/plugins/J3MLoader.java @@ -36,6 +36,7 @@ import com.jme3.material.logic.SinglePassLightingLogic; import com.jme3.material.logic.DefaultTechniqueDefLogic; import com.jme3.asset.*; import com.jme3.material.*; +import com.jme3.material.RenderState.BlendEquation; import com.jme3.material.RenderState.BlendMode; import com.jme3.material.RenderState.FaceCullMode; import com.jme3.material.TechniqueDef.LightMode; @@ -452,6 +453,10 @@ public class J3MLoader implements AssetLoader { renderState.setDepthTest(parseBoolean(split[1])); }else if (split[0].equals("Blend")){ renderState.setBlendMode(BlendMode.valueOf(split[1])); + }else if (split[0].equals("BlendEquation")){ + renderState.setBlendEquation(BlendEquation.valueOf(split[1])); + }else if (split[0].equals("BlendEquationAlpha")){ + renderState.setBlendEquationAlpha(RenderState.BlendEquationAlpha.valueOf(split[1])); }else if (split[0].equals("AlphaTestFalloff")){ renderState.setAlphaTest(true); renderState.setAlphaFallOff(Float.parseFloat(split[1])); diff --git a/jme3-jogl/src/main/java/com/jme3/renderer/jogl/JoglGL.java b/jme3-jogl/src/main/java/com/jme3/renderer/jogl/JoglGL.java index 2ca2fb266..8b222d751 100644 --- a/jme3-jogl/src/main/java/com/jme3/renderer/jogl/JoglGL.java +++ b/jme3-jogl/src/main/java/com/jme3/renderer/jogl/JoglGL.java @@ -78,6 +78,11 @@ public class JoglGL implements GL, GL2, GL3, GL4 { GLContext.getCurrentGL().glBindTexture(param1, param2); } + @Override + public void glBlendEquationSeparate(int colorMode, int alphaMode){ + GLContext.getCurrentGL().glBlendEquationSeparate(colorMode, alphaMode); + } + @Override public void glBlendFunc(int param1, int param2) { GLContext.getCurrentGL().glBlendFunc(param1, param2); diff --git a/jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java b/jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java index 6f640042f..abc419c41 100644 --- a/jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java +++ b/jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java @@ -50,6 +50,10 @@ public final class LwjglGL implements GL, GL2, GL3, GL4 { GL11.glBindTexture(param1, param2); } + public void glBlendEquationSeparate(int colorMode, int alphaMode){ + GL20.glBlendEquationSeparate(colorMode,alphaMode); + } + public void glBlendFunc(int param1, int param2) { GL11.glBlendFunc(param1, param2); } diff --git a/jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java b/jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java index 25de6b148..10358c009 100644 --- a/jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java +++ b/jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java @@ -79,6 +79,10 @@ public class LwjglGL implements GL, GL2, GL3, GL4 { GL11.glBindTexture(param1, param2); } + public void glBlendEquationSeparate(int colorMode, int alphaMode){ + GL20.glBlendEquationSeparate(colorMode,alphaMode); + } + public void glBlendFunc(int param1, int param2) { GL11.glBlendFunc(param1, param2); } From bffa2191e5753b7013c5224e45ccf8f749a7ef83 Mon Sep 17 00:00:00 2001 From: Teencrusher Date: Thu, 7 Apr 2016 10:06:34 -0400 Subject: [PATCH 2/2] Moved glBlendEquationSeparate from GL2 interface to GL interface. Added an example of the feature. Minors issues. --- .../com/jme3/renderer/android/AndroidGL.java | 5 + .../java/com/jme3/material/RenderState.java | 2 +- .../java/com/jme3/renderer/opengl/GL.java | 6 + .../java/com/jme3/renderer/opengl/GL2.java | 6 - .../jme3/renderer/opengl/GLDebugDesktop.java | 2 +- .../com/jme3/renderer/opengl/GLDebugES.java | 5 + .../com/jme3/renderer/opengl/GLRenderer.java | 5 +- .../jme3test/renderer/TestBlendEquations.java | 110 ++++++++++++++++++ .../java/com/jme3/renderer/ios/IosGL.java | 5 + .../com/jme3/renderer/ios/JmeIosGLES.java | 1 + 10 files changed, 137 insertions(+), 10 deletions(-) create mode 100644 jme3-examples/src/main/java/jme3test/renderer/TestBlendEquations.java diff --git a/jme3-android/src/main/java/com/jme3/renderer/android/AndroidGL.java b/jme3-android/src/main/java/com/jme3/renderer/android/AndroidGL.java index b77c4a36d..8aeb883e0 100644 --- a/jme3-android/src/main/java/com/jme3/renderer/android/AndroidGL.java +++ b/jme3-android/src/main/java/com/jme3/renderer/android/AndroidGL.java @@ -523,4 +523,9 @@ public class AndroidGL implements GL, GLExt, GLFbo { public Object glFenceSync(int condition, int flags) { throw new UnsupportedOperationException("OpenGL ES 2 does not support sync fences"); } + + @Override + public void glBlendEquationSeparate(int colorMode, int alphaMode) { + GLES20.glBlendEquationSeparate(colorMode, alphaMode); + } } diff --git a/jme3-core/src/main/java/com/jme3/material/RenderState.java b/jme3-core/src/main/java/com/jme3/material/RenderState.java index ba7214e58..e7db36f77 100644 --- a/jme3-core/src/main/java/com/jme3/material/RenderState.java +++ b/jme3-core/src/main/java/com/jme3/material/RenderState.java @@ -1501,7 +1501,7 @@ public class RenderState implements Cloneable, Savable { if (additionalState.applyBlendEquationAlpha) { state.blendEquationAlpha = additionalState.blendEquationAlpha; } else { - state.blendEquation = blendEquation; + state.blendEquationAlpha = blendEquationAlpha; } if (additionalState.applyBlendMode) { state.blendMode = additionalState.blendMode; diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GL.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GL.java index 1b9c3f94d..9abe23b8e 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GL.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GL.java @@ -69,6 +69,9 @@ public interface GL { public static final int GL_EXTENSIONS = 0x1F03; public static final int GL_FALSE = 0x0; public static final int GL_FLOAT = 0x1406; + public static final int GL_FUNC_ADD = 0x8006; + public static final int GL_FUNC_SUBTRACT = 0x800A; + public static final int GL_FUNC_REVERSE_SUBTRACT = 0x800B; public static final int GL_FRAGMENT_SHADER = 0x8B30; public static final int GL_FRONT = 0x404; public static final int GL_FRONT_AND_BACK = 0x408; @@ -95,6 +98,7 @@ public interface GL { public static final int GL_LINK_STATUS = 0x8B82; public static final int GL_LUMINANCE = 0x1909; public static final int GL_LUMINANCE_ALPHA = 0x190A; + public static final int GL_MAX = 0x8008; public static final int GL_MAX_CUBE_MAP_TEXTURE_SIZE = 0x851C; public static final int GL_MAX_TEXTURE_IMAGE_UNITS = 0x8872; public static final int GL_MAX_TEXTURE_SIZE = 0xD33; @@ -103,6 +107,7 @@ public interface GL { public static final int GL_MAX_VERTEX_UNIFORM_COMPONENTS = 0x8B4A; public static final int GL_MAX_VERTEX_UNIFORM_VECTORS = 0x8DFB; public static final int GL_MIRRORED_REPEAT = 0x8370; + public static final int GL_MIN = 0x8007; public static final int GL_NEAREST = 0x2600; public static final int GL_NEAREST_MIPMAP_LINEAR = 0x2702; public static final int GL_NEAREST_MIPMAP_NEAREST = 0x2700; @@ -188,6 +193,7 @@ public interface GL { public void glAttachShader(int program, int shader); public void glBindBuffer(int target, int buffer); public void glBindTexture(int target, int texture); + public void glBlendEquationSeparate(int colorMode, int alphaMode); public void glBlendFunc(int sfactor, int dfactor); public void glBufferData(int target, long data_size, int usage); public void glBufferData(int target, FloatBuffer data, int usage); diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GL2.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GL2.java index d6e53b14d..abf6a77d7 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GL2.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GL2.java @@ -71,14 +71,8 @@ public interface GL2 extends GL { public static final int GL_TEXTURE_WRAP_R = 0x8072; public static final int GL_VERTEX_PROGRAM_POINT_SIZE = 0x8642; public static final int GL_UNSIGNED_INT_8_8_8_8 = 0x8035; - public static final int GL_FUNC_ADD = 0x8006; - public static final int GL_FUNC_SUBTRACT = 0x800A; - public static final int GL_FUNC_REVERSE_SUBTRACT = 0x800B; - public static final int GL_MIN = 0x8007; - public static final int GL_MAX = 0x8008; public void glAlphaFunc(int func, float ref); - public void glBlendEquationSeparate(int colorMode, int alphaMode); public void glPointSize(float size); public void glPolygonMode(int face, int mode); public void glDrawBuffer(int mode); diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebugDesktop.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebugDesktop.java index 3c39c8036..44dc3687a 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebugDesktop.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebugDesktop.java @@ -102,7 +102,7 @@ public class GLDebugDesktop extends GLDebugES implements GL2, GL3, GL4 { } public void glBlendEquationSeparate(int colorMode, int alphaMode) { - gl2.glBlendEquationSeparate(colorMode, alphaMode); + gl.glBlendEquationSeparate(colorMode, alphaMode); checkError(); } } diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebugES.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebugES.java index 2348bd3cd..ed6b336f8 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebugES.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLDebugES.java @@ -560,4 +560,9 @@ public class GLDebugES extends GLDebug implements GL, GLFbo, GLExt { checkError(); return sync; } + + public void glBlendEquationSeparate(int colorMode, int alphaMode) { + gl.glBlendEquationSeparate(colorMode, alphaMode); + checkError(); + } } diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java index 73e55b0e2..5a6f4ea40 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java @@ -747,7 +747,7 @@ public final class GLRenderer implements Renderer { + state.getBlendMode()); } - if (gl2 != null && (state.getBlendEquation() != context.blendEquation || state.getBlendEquationAlpha() != context.blendEquationAlpha)) { + if (state.getBlendEquation() != context.blendEquation || state.getBlendEquationAlpha() != context.blendEquationAlpha) { int colorMode = convertBlendEquation(state.getBlendEquation()); int alphaMode; if (state.getBlendEquationAlpha() == RenderState.BlendEquationAlpha.InheritColor) { @@ -755,8 +755,9 @@ public final class GLRenderer implements Renderer { } else { alphaMode = convertBlendEquationAlpha(state.getBlendEquationAlpha()); } - gl2.glBlendEquationSeparate(colorMode, alphaMode); + gl.glBlendEquationSeparate(colorMode, alphaMode); context.blendEquation = state.getBlendEquation(); + context.blendEquationAlpha = state.getBlendEquationAlpha(); } } diff --git a/jme3-examples/src/main/java/jme3test/renderer/TestBlendEquations.java b/jme3-examples/src/main/java/jme3test/renderer/TestBlendEquations.java new file mode 100644 index 000000000..9335912b6 --- /dev/null +++ b/jme3-examples/src/main/java/jme3test/renderer/TestBlendEquations.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2009-2016 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package jme3test.renderer; + +import com.jme3.app.SimpleApplication; +import com.jme3.light.DirectionalLight; +import com.jme3.material.Material; +import com.jme3.material.RenderState; +import com.jme3.math.ColorRGBA; +import com.jme3.math.Vector3f; +import com.jme3.renderer.queue.RenderQueue; +import com.jme3.scene.Geometry; +import com.jme3.scene.shape.Quad; + +public class TestBlendEquations extends SimpleApplication { + + public static void main(String[] args) { + TestBlendEquations app = new TestBlendEquations(); + app.start(); + } + + public void simpleInitApp() { + Geometry teaGeom = (Geometry) assetManager.loadModel("Models/Teapot/Teapot.obj"); + teaGeom.scale(6); + teaGeom.getMaterial().getAdditionalRenderState().setBlendEquation(RenderState.BlendEquation.Add); + teaGeom.move(0, -2f, 0); + + DirectionalLight dl = new DirectionalLight(); + dl.setColor(ColorRGBA.Red); + dl.setDirection(Vector3f.UNIT_XYZ.negate()); + + rootNode.addLight(dl); + rootNode.attachChild(teaGeom); + + Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); + mat.setColor("Color", new ColorRGBA(0.5f, 0f, 1f, 0.3f)); + mat.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Color); + mat.getAdditionalRenderState().setBlendEquation(RenderState.BlendEquation.Subtract); + + Geometry geo = new Geometry("BottomLeft", new Quad(guiViewPort.getCamera().getWidth() / 2, guiViewPort.getCamera().getHeight() / 2)); + geo.setMaterial(mat); + geo.setQueueBucket(RenderQueue.Bucket.Gui); + geo.setLocalTranslation(0, 0, 1); + + guiNode.attachChild(geo); + + Material m = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); + m.getAdditionalRenderState().setBlendEquation(RenderState.BlendEquation.ReverseSubtract); + m.setColor("Color", new ColorRGBA(0.0f, 1f, 1.f, 1f)); + m.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.AlphaAdditive); + + geo = new Geometry("BottomRight", new Quad(guiViewPort.getCamera().getWidth() / 2, guiViewPort.getCamera().getHeight() / 2)); + geo.setMaterial(m); + geo.setQueueBucket(RenderQueue.Bucket.Gui); + geo.setLocalTranslation(guiViewPort.getCamera().getWidth() / 2, 0, 1); + + guiNode.attachChild(geo); + + m = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); + m.getAdditionalRenderState().setBlendEquation(RenderState.BlendEquation.Min); + m.setColor("Color", new ColorRGBA(0.3f, 0f, 0.1f, 0.3f)); + m.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Additive); + + geo = new Geometry("TopRight", new Quad(guiViewPort.getCamera().getWidth() / 2, guiViewPort.getCamera().getHeight() / 2)); + geo.setMaterial(m); + geo.setQueueBucket(RenderQueue.Bucket.Gui); + geo.setLocalTranslation(guiViewPort.getCamera().getWidth() / 2, guiViewPort.getCamera().getHeight() / 2, 1); + + guiNode.attachChild(geo); + + geo = new Geometry("OverTeaPot", new Quad(guiViewPort.getCamera().getWidth() / 2, guiViewPort.getCamera().getHeight() / 2)); + geo.setMaterial(mat); + geo.setQueueBucket(RenderQueue.Bucket.Transparent); + geo.setLocalTranslation(0, -100, 5); + + rootNode.attachChild(geo); + + } + + +} diff --git a/jme3-ios/src/main/java/com/jme3/renderer/ios/IosGL.java b/jme3-ios/src/main/java/com/jme3/renderer/ios/IosGL.java index a9398f159..958163596 100644 --- a/jme3-ios/src/main/java/com/jme3/renderer/ios/IosGL.java +++ b/jme3-ios/src/main/java/com/jme3/renderer/ios/IosGL.java @@ -78,6 +78,11 @@ public class IosGL implements GL, GLExt, GLFbo { checkLimit(buffer); return buffer.limit() / elementSize; } + + @Override + public void glBlendEquationSeparate(int colorMode, int alphaMode) { + JmeIosGLES.glBlendEquationSeparate(colorMode, alphaMode); + } private int toArray(IntBuffer buffer) { int remain = buffer.remaining(); diff --git a/jme3-ios/src/main/java/com/jme3/renderer/ios/JmeIosGLES.java b/jme3-ios/src/main/java/com/jme3/renderer/ios/JmeIosGLES.java index 0811dc422..b8ec75a77 100644 --- a/jme3-ios/src/main/java/com/jme3/renderer/ios/JmeIosGLES.java +++ b/jme3-ios/src/main/java/com/jme3/renderer/ios/JmeIosGLES.java @@ -142,6 +142,7 @@ public class JmeIosGLES { public static native void glBindRenderbuffer(int target, int renderbuffer); public static native void glBindTexture(int target, int texture); // public static native void glBindVertexArray // TODO: Investigate this + public static native void glBlendEquationSeparate(int colorMode, int alphaMode); public static native void glBlendFunc(int sfactor, int dfactor); public static native void glBufferData(int target, int size, Buffer data, int usage); public static native void glBufferData2(int target, int size, byte[] data, int offset, int usage);