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 8aeb883e0..12e743810 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 @@ -103,6 +103,10 @@ public class AndroidGL implements GL, GLExt, GLFbo { public void glBlendFunc(int sfactor, int dfactor) { GLES20.glBlendFunc(sfactor, dfactor); } + + public void glBlendFuncSeparate(int sfactorRGB, int dfactorRGB, int sfactorAlpha, int dfactorAlpha) { + GLES20.glBlendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha); + } public void glBufferData(int target, FloatBuffer data, int usage) { GLES20.glBufferData(target, getLimitBytes(data), data, usage); 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 1fb33a079..f6236efd0 100644 --- a/jme3-core/src/main/java/com/jme3/material/RenderState.java +++ b/jme3-core/src/main/java/com/jme3/material/RenderState.java @@ -33,7 +33,6 @@ package com.jme3.material; import com.jme3.export.*; import com.jme3.scene.Mesh; -import com.jme3.scene.Mesh.Mode; import java.io.IOException; /** @@ -205,7 +204,60 @@ public class RenderState implements Cloneable, Savable { */ Max } - + + /** + * BlendFunc defines the blending functions for use with + * BlendMode.Custom. + * Source color components are referred to as (R_s0, G_s0, B_s0, A_s0). + * Destination color components are referred to as (R_d, G_d, B_d, A_d). + */ + public enum BlendFunc { + /** + * RGB Factor (0, 0, 0), Alpha Factor (0) + */ + Zero, + /** + * RGB Factor (1, 1, 1), Alpha Factor (1) + */ + One, + /** + * RGB Factor (R_s0, G_s0, B_s0), Alpha Factor (A_s0) + */ + Src_Color, + /** + * RGB Factor (1-R_s0, 1-G_s0, 1-B_s0), Alpha Factor (1-A_s0) + */ + One_Minus_Src_Color, + /** + * RGB Factor (R_d, G_d, B_d), Alpha Factor (A_d) + */ + Dst_Color, + /** + * RGB Factor (1-R_d, 1-G_d, 1-B_d), Alpha Factor (1-A_d) + */ + One_Minus_Dst_Color, + /** + * RGB Factor (A_s0, A_s0, A_s0), Alpha Factor (A_s0) + */ + Src_Alpha, + /** + * RGB Factor (1-A_s0, 1-A_s0, 1-A_s0), Alpha Factor (1-A_s0) + */ + One_Minus_Src_Alpha, + /** + * RGB Factor (A_d, A_d, A_d), Alpha Factor (A_d) + */ + Dst_Alpha, + /** + * RGB Factor (1-A_d, 1-A_d, 1-A_d), Alpha Factor (1-A_d) + */ + One_Minus_Dst_Alpha, + /** + * RGB Factor (i, i, i), Alpha Factor (1) + */ + Src_Alpha_Saturate; + } + /** * BlendMode specifies the blending operation to use. * @@ -277,7 +329,13 @@ public class RenderState implements Cloneable, Savable { * Result = (Source Color * (1 - Dest Color)) + (Dest Color * (1 - Source Color)) * -> (GL_ONE_MINUS_DST_COLOR, GL_ONE_MINUS_SRC_COLOR) */ - Exclusion + Exclusion, + /** + * Allows for custom blending by using glBlendFuncSeparate. + *

+ * + */ + Custom } /** @@ -408,7 +466,11 @@ public class RenderState implements Cloneable, Savable { TestFunction frontStencilFunction = TestFunction.Always; TestFunction backStencilFunction = TestFunction.Always; int cachedHashCode = -1; - + BlendFunc sfactorRGB=BlendFunc.One; + BlendFunc dfactorRGB=BlendFunc.Zero; + BlendFunc sfactorAlpha=BlendFunc.One; + BlendFunc dfactorAlpha=BlendFunc.Zero; + public void write(JmeExporter ex) throws IOException { OutputCapsule oc = ex.getCapsule(this); oc.write(true, "pointSprite", false); @@ -434,6 +496,10 @@ public class RenderState implements Cloneable, Savable { oc.write(blendEquationAlpha, "blendEquationAlpha", BlendEquationAlpha.InheritColor); oc.write(depthFunc, "depthFunc", TestFunction.LessOrEqual); oc.write(lineWidth, "lineWidth", 1); + oc.write(sfactorRGB, "sfactorRGB", sfactorRGB); + oc.write(dfactorRGB, "dfactorRGB", dfactorRGB); + oc.write(sfactorAlpha, "sfactorAlpha", sfactorAlpha); + oc.write(dfactorAlpha, "dfactorAlpha", dfactorAlpha); // Only "additional render state" has them set to false by default oc.write(applyWireFrame, "applyWireFrame", true); @@ -474,6 +540,10 @@ public class RenderState implements Cloneable, Savable { blendEquationAlpha = ic.readEnum("blendEquationAlpha", BlendEquationAlpha.class, BlendEquationAlpha.InheritColor); depthFunc = ic.readEnum("depthFunc", TestFunction.class, TestFunction.LessOrEqual); lineWidth = ic.readFloat("lineWidth", 1); + sfactorRGB = ic.readEnum("sfactorRGB", BlendFunc.class, BlendFunc.One); + dfactorAlpha = ic.readEnum("dfactorRGB", BlendFunc.class, BlendFunc.Zero); + sfactorRGB = ic.readEnum("sfactorAlpha", BlendFunc.class, BlendFunc.One); + dfactorAlpha = ic.readEnum("dfactorAlpha", BlendFunc.class, BlendFunc.Zero); applyWireFrame = ic.readBoolean("applyWireFrame", true); @@ -605,6 +675,14 @@ public class RenderState implements Cloneable, Savable { if(lineWidth != rs.lineWidth){ return false; } + + if (blendMode.equals(BlendMode.Custom)) { + return sfactorRGB==rs.getCustomSfactorRGB() + && dfactorRGB==rs.getCustomDfactorRGB() + && sfactorAlpha==rs.getCustomSfactorAlpha() + && dfactorAlpha==rs.getCustomDfactorAlpha(); + + } return true; } @@ -744,6 +822,26 @@ public class RenderState implements Cloneable, Savable { cachedHashCode = -1; } + + /** + * Sets the custom blend factors for BlendMode.Custom as + * defined by the appropriate BlendFunc. + * + * @param sfactorRGB The source blend factor for RGB components. + * @param dfactorRGB The destination blend factor for RGB components. + * @param sfactorAlpha The source blend factor for the alpha component. + * @param dfactorAlpha The destination blend factor for the alpha component. + */ + public void setCustomBlendFactors(BlendFunc sfactorRGB, BlendFunc dfactorRGB, BlendFunc sfactorAlpha, BlendFunc dfactorAlpha) + { + this.sfactorRGB = sfactorRGB; + this.dfactorRGB = dfactorRGB; + this.sfactorAlpha = sfactorAlpha; + this.dfactorAlpha = dfactorAlpha; + cachedHashCode = -1; + } + + /** * Enable depth testing. * @@ -1084,7 +1182,47 @@ public class RenderState implements Cloneable, Savable { public BlendMode getBlendMode() { return blendMode; } - + + /** + * Provides the source factor for the RGB components in + * BlendMode.Custom. + * + * @return the custom source factor for RGB components. + */ + public BlendFunc getCustomSfactorRGB() { + return sfactorRGB; + } + + /** + * Provides the destination factor for the RGB components in + * BlendMode.Custom. + * + * @return the custom destination factor for RGB components. + */ + public BlendFunc getCustomDfactorRGB() { + return dfactorRGB; + } + + /** + * Provides the source factor for the alpha component in + * BlendMode.Custom. + * + * @return the custom destination factor for alpha component. + */ + public BlendFunc getCustomSfactorAlpha() { + return sfactorAlpha; + } + + /** + * Provides the destination factor for the alpha component in + * BlendMode.Custom. + * + * @return the custom destination factor for alpha component. + */ + public BlendFunc getCustomDfactorAlpha() { + return dfactorAlpha; + } + /** * @return true * @deprecated Always returns true since point sprite is always enabled. @@ -1306,6 +1444,11 @@ public class RenderState implements Cloneable, Savable { hash = 79 * hash + (this.frontStencilFunction != null ? this.frontStencilFunction.hashCode() : 0); hash = 79 * hash + (this.backStencilFunction != null ? this.backStencilFunction.hashCode() : 0); hash = 79 * hash + Float.floatToIntBits(this.lineWidth); + + hash = 79 * hash + this.sfactorRGB.hashCode(); + hash = 79 * hash + this.dfactorRGB.hashCode(); + hash = 79 * hash + this.sfactorAlpha.hashCode(); + hash = 79 * hash + this.dfactorAlpha.hashCode(); cachedHashCode = hash; } return cachedHashCode; @@ -1380,6 +1523,13 @@ public class RenderState implements Cloneable, Savable { } if (additionalState.applyBlendMode) { state.blendMode = additionalState.blendMode; + if (additionalState.getBlendMode().equals(BlendMode.Custom)) { + state.setCustomBlendFactors( + additionalState.getCustomSfactorRGB(), + additionalState.getCustomDfactorRGB(), + additionalState.getCustomSfactorAlpha(), + additionalState.getCustomDfactorAlpha()); + } } else { state.blendMode = blendMode; } @@ -1464,6 +1614,11 @@ public class RenderState implements Cloneable, Savable { applyPolyOffset = true; applyDepthFunc = true; applyLineWidth = true; + + sfactorRGB = state.sfactorRGB; + dfactorRGB = state.dfactorRGB; + sfactorAlpha = state.sfactorAlpha; + dfactorAlpha = state.dfactorAlpha; } @Override @@ -1490,6 +1645,7 @@ public class RenderState implements Cloneable, Savable { + "\noffsetFactor=" + offsetFactor + "\noffsetUnits=" + offsetUnits + "\nlineWidth=" + lineWidth - + "\n]"; + + (blendMode.equals(BlendMode.Custom)? "\ncustomBlendFactors=("+sfactorRGB+", "+dfactorRGB+", "+sfactorAlpha+", "+dfactorAlpha+")":"") + +"\n]"; } } 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 a4a738152..136442f77 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 @@ -62,6 +62,7 @@ public interface GL { public static final int GL_DEPTH_COMPONENT16 = 0x81A5; public static final int GL_DEPTH_TEST = 0xB71; public static final int GL_DOUBLE = 0x140A; + public static final int GL_DST_ALPHA = 0x0304; public static final int GL_DST_COLOR = 0x306; public static final int GL_DYNAMIC_DRAW = 0x88E8; public static final int GL_ELEMENT_ARRAY_BUFFER = 0x8893; @@ -118,6 +119,7 @@ public interface GL { public static final int GL_NONE = 0x0; public static final int GL_NOTEQUAL = 0x205; public static final int GL_ONE = 0x1; + public static final int GL_ONE_MINUS_DST_ALPHA = 0x0305; public static final int GL_ONE_MINUS_DST_COLOR = 0x307; public static final int GL_ONE_MINUS_SRC_ALPHA = 0x303; public static final int GL_ONE_MINUS_SRC_COLOR = 0x301; @@ -137,6 +139,7 @@ public interface GL { public static final int GL_SHADING_LANGUAGE_VERSION = 0x8B8C; public static final int GL_SHORT = 0x1402; public static final int GL_SRC_ALPHA = 0x302; + public static final int GL_SRC_ALPHA_SATURATE = 0x0308; public static final int GL_SRC_COLOR = 0x300; public static final int GL_STATIC_DRAW = 0x88E4; public static final int GL_STENCIL_BUFFER_BIT = 0x400; @@ -197,6 +200,7 @@ public interface GL { public void glBindTexture(int target, int texture); public void glBlendEquationSeparate(int colorMode, int alphaMode); public void glBlendFunc(int sfactor, int dfactor); + public void glBlendFuncSeparate(int sfactorRGB, int dfactorRGB, int sfactorAlpha, int dfactorAlpha); public void glBufferData(int target, long data_size, int usage); public void glBufferData(int target, FloatBuffer data, int usage); public void glBufferData(int target, ShortBuffer data, int usage); 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 ed6b336f8..6b15bb967 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 @@ -44,6 +44,12 @@ public class GLDebugES extends GLDebug implements GL, GLFbo, GLExt { gl.glBlendFunc(sfactor, dfactor); checkError(); } + + public void glBlendFuncSeparate(int sfactorRGB, int dfactorRGB, int sfactorAlpha, int dFactorAlpha) + { + gl.glBlendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dFactorAlpha); + checkError(); + } public void glBufferData(int target, FloatBuffer data, int usage) { gl.glBufferData(target, data, usage); 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 18dde97c7..943d3ab40 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 @@ -32,6 +32,7 @@ package com.jme3.renderer.opengl; import com.jme3.material.RenderState; +import com.jme3.material.RenderState.BlendFunc; import com.jme3.material.RenderState.StencilOperation; import com.jme3.material.RenderState.TestFunction; import com.jme3.math.*; @@ -752,6 +753,13 @@ public final class GLRenderer implements Renderer { case Exclusion: gl.glBlendFunc(GL.GL_ONE_MINUS_DST_COLOR, GL.GL_ONE_MINUS_SRC_COLOR); break; + case Custom: + gl.glBlendFuncSeparate( + convertBlendFunc(state.getCustomSfactorRGB()), + convertBlendFunc(state.getCustomDfactorRGB()), + convertBlendFunc(state.getCustomSfactorAlpha()), + convertBlendFunc(state.getCustomDfactorAlpha())); + break; default: throw new UnsupportedOperationException("Unrecognized blend mode: " + state.getBlendMode()); @@ -853,6 +861,35 @@ public final class GLRenderer implements Renderer { throw new UnsupportedOperationException("Unrecognized alpha blend operation: " + blendEquationAlpha); } } + + private int convertBlendFunc(BlendFunc blendFunc) { + switch (blendFunc) { + case Zero: + return GL.GL_ZERO; + case One: + return GL.GL_ONE; + case Src_Color: + return GL.GL_SRC_COLOR; + case One_Minus_Src_Color: + return GL.GL_ONE_MINUS_SRC_COLOR; + case Dst_Color: + return GL.GL_DST_COLOR; + case One_Minus_Dst_Color: + return GL.GL_ONE_MINUS_DST_COLOR; + case Src_Alpha: + return GL.GL_SRC_ALPHA; + case One_Minus_Src_Alpha: + return GL.GL_ONE_MINUS_SRC_ALPHA; + case Dst_Alpha: + return GL.GL_DST_ALPHA; + case One_Minus_Dst_Alpha: + return GL.GL_ONE_MINUS_DST_ALPHA; + case Src_Alpha_Saturate: + return GL.GL_SRC_ALPHA_SATURATE; + default: + throw new UnsupportedOperationException("Unrecognized blend function operation: " + blendFunc); + } + } private int convertStencilOperation(StencilOperation stencilOp) { switch (stencilOp) { 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 958163596..d73c5158a 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 @@ -135,6 +135,11 @@ public class IosGL implements GL, GLExt, GLFbo { public void glBlendFunc(int sfactor, int dfactor) { JmeIosGLES.glBlendFunc(sfactor, dfactor); } + + public void glBlendFuncSeparate(int sfactorRGB, int dfactorRGB, int sfactorAlpha, int dfactorAlpha) { + JmeIosGLES.glBlendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha); + } + public void glBufferData(int target, FloatBuffer data, int usage) { JmeIosGLES.glBufferData(target, getLimitBytes(data), data, usage); 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 b8ec75a77..b5cde6721 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 @@ -144,6 +144,7 @@ public class JmeIosGLES { // 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 glBlendFuncSeparate(int sfactorRGB, int dfactorRGB, int sfactorAlpha, int dfactorAlpha); 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); public static native void glBufferSubData(int target, int offset, int size, Buffer data); 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 8b222d751..bbd1b24f9 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 @@ -88,6 +88,11 @@ public class JoglGL implements GL, GL2, GL3, GL4 { GLContext.getCurrentGL().glBlendFunc(param1, param2); } + @Override + public void glBlendFuncSeparate(int sfactorRGB, int dfactorRGB, int sfactorAlpha, int dfactorAlpha) { + GLContext.getCurrentGL().glBlendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha); + } + @Override public void glBufferData(int param1, long param2, int param3) { GLContext.getCurrentGL().glBufferData(param1, param2, null, param3); @@ -610,4 +615,5 @@ public class JoglGL implements GL, GL2, GL3, GL4 { public void glFramebufferTextureLayer(int param1, int param2, int param3, int param4, int param5) { GLContext.getCurrentGL().getGL3().glFramebufferTextureLayer(param1, param2, param3, param4, param5); } + } 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 abc419c41..59e50e3f7 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 @@ -58,6 +58,10 @@ public final class LwjglGL implements GL, GL2, GL3, GL4 { GL11.glBlendFunc(param1, param2); } + public void glBlendFuncSeparate(int param1, int param2, int param3, int param4) { + GL14.glBlendFuncSeparate(param1, param2, param3, param4); + } + public void glBufferData(int param1, long param2, int param3) { GL15.glBufferData(param1, param2, param3); } 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 10358c009..f5f6a7b1a 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 @@ -86,6 +86,10 @@ public class LwjglGL implements GL, GL2, GL3, GL4 { public void glBlendFunc(int param1, int param2) { GL11.glBlendFunc(param1, param2); } + + public void glBlendFuncSeparate(int param1, int param2, int param3, int param4) { + GL14.glBlendFuncSeparate(param1, param2, param3, param4); + } public void glBufferData(int param1, long param2, int param3) { GL15.glBufferData(param1, param2, param3); diff --git a/jme3-plugins/src/main/java/com/jme3/material/plugin/export/material/J3MOutputCapsule.java b/jme3-plugins/src/main/java/com/jme3/material/plugin/export/material/J3MOutputCapsule.java index 7dd6a2a59..01ae2b915 100644 --- a/jme3-plugins/src/main/java/com/jme3/material/plugin/export/material/J3MOutputCapsule.java +++ b/jme3-plugins/src/main/java/com/jme3/material/plugin/export/material/J3MOutputCapsule.java @@ -367,7 +367,11 @@ public class J3MOutputCapsule implements OutputCapsule { @Override public void write(int value, String name, int defVal) throws IOException { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + if (value == defVal) { + return; + } + + putParameter(name, Integer.toString(value)); } @Override