2
0
Эх сурвалжийг харах

Added support to glBlendEquation for renderes implementing GL2, and material loading support

Teencrusher 9 жил өмнө
parent
commit
d1aae8d479

+ 210 - 2
jme3-core/src/main/java/com/jme3/material/RenderState.java

@@ -120,6 +120,92 @@ public class RenderState implements Cloneable, Savable {
          */
         Always,}
 
+    /**
+     * <code>BlendEquation</code> 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
+    }
+    
+    /**
+     * <code>BlendEquationAlpha</code> 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
+    }
+
     /**
      * <code>BlendMode</code> 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.
+     * <p>
+     * When blending is enabled, (<code>blendMode</code> 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:
+     * <br/>
+     * <code>Result = Source Color + Destination Color</code>
+     * <br/>
+     * 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:
+     * <br/>
+     * <code>Result = Source Color - Destination Color</code>
+     *
+     * @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.
+     * <p>
+     * When blending is enabled, (<code>blendMode</code> 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:
+     * <br/>
+     * <code>Result = Source Alpha + Destination Alpha</code>
+     * <br/>
+     * 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:
+     * <br/>
+     * <code>Result = Source Alpha - Destination Alpha</code>
+     *
+     * @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

+ 12 - 0
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;

+ 6 - 0
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);

+ 5 - 0
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();
+    }
 }

+ 47 - 0
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:

+ 5 - 0
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]));

+ 5 - 0
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);

+ 4 - 0
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);
     }

+ 4 - 0
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);
     }