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 f6236efd0..d2a557c65 100644 --- a/jme3-core/src/main/java/com/jme3/material/RenderState.java +++ b/jme3-core/src/main/java/com/jme3/material/RenderState.java @@ -331,9 +331,17 @@ public class RenderState implements Cloneable, Savable { */ Exclusion, /** - * Allows for custom blending by using glBlendFuncSeparate. + * Uses the blend equations and blend factors defined by the render state. *
- * + * These attributes can be set by using the following methods: + *
+ * Result.RGB = BlendEquation( sfactorRGB * Source.RGB , dfactorRGB * Destination.RGB )
+ * Result.A = BlendEquationAlpha( sfactorAlpha * Source.A , dfactorAlpha * Destination.A )
*/
Custom
}
@@ -425,8 +433,6 @@ 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.applyPolyOffset = false;
}
@@ -441,9 +447,7 @@ public class RenderState implements Cloneable, Savable {
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;
float offsetFactor = 0;
@@ -466,10 +470,10 @@ 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;
+ BlendFunc sfactorRGB = BlendFunc.One;
+ BlendFunc dfactorRGB = BlendFunc.One;
+ BlendFunc sfactorAlpha = BlendFunc.One;
+ BlendFunc dfactorAlpha = BlendFunc.One;
public void write(JmeExporter ex) throws IOException {
OutputCapsule oc = ex.getCapsule(this);
@@ -507,8 +511,6 @@ 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(applyPolyOffset, "applyPolyOffset", true);
oc.write(applyDepthFunc, "applyDepthFunc", true);
@@ -541,9 +543,9 @@ public class RenderState implements Cloneable, Savable {
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);
+ dfactorAlpha = ic.readEnum("dfactorRGB", BlendFunc.class, BlendFunc.One);
sfactorRGB = ic.readEnum("sfactorAlpha", BlendFunc.class, BlendFunc.One);
- dfactorAlpha = ic.readEnum("dfactorAlpha", BlendFunc.class, BlendFunc.Zero);
+ dfactorAlpha = ic.readEnum("dfactorAlpha", BlendFunc.class, BlendFunc.One);
applyWireFrame = ic.readBoolean("applyWireFrame", true);
@@ -551,14 +553,11 @@ 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);
applyPolyOffset = ic.readBoolean("applyPolyOffset", true);
applyDepthFunc = ic.readBoolean("applyDepthFunc", true);
applyLineWidth = ic.readBoolean("applyLineWidth", true);
-
}
/**
@@ -615,19 +614,32 @@ public class RenderState implements Cloneable, Savable {
return false;
}
- if (blendEquation != rs.blendEquation) {
+ if (blendMode != rs.blendMode) {
return false;
}
- if (blendEquationAlpha != rs.blendEquationAlpha) {
- return false;
- }
+ if (blendMode == BlendMode.Custom) {
+ if (blendEquation != rs.blendEquation) {
+ return false;
+ }
+ if (blendEquationAlpha != rs.blendEquationAlpha) {
+ return false;
+ }
- if (blendMode != rs.blendMode) {
- return false;
+ if (sfactorRGB != rs.sfactorRGB) {
+ return false;
+ }
+ if (dfactorRGB != rs.dfactorRGB) {
+ return false;
+ }
+ if (sfactorAlpha != rs.sfactorAlpha) {
+ return false;
+ }
+ if (dfactorAlpha != rs.dfactorAlpha) {
+ return false;
+ }
}
-
if (offsetEnabled != rs.offsetEnabled) {
return false;
}
@@ -675,14 +687,6 @@ 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;
}
@@ -768,80 +772,68 @@ public class RenderState implements Cloneable, Savable {
}
/**
- * Set the blending equation.
+ * Set the blending equation for the color component (RGB).
*
- * 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:
+ * The blending equation determines, how the RGB values of the input pixel
+ * will be blended with the RGB values of the pixel already in the color buffer.
+ * For example, {@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
+ *
+ * Note: This gets only used in {@link BlendMode#Custom} mode. + * All other blend modes will ignore this setting. * - * @param blendEquation The blend equation to use. + * @param blendEquation The {@link BlendEquation} 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:
+ * The alpha blending equation determines, how the alpha values of the input pixel
+ * will be blended with the alpha values of the pixel already in the color buffer.
+ * For example, {@link BlendEquationAlpha#Add} will add the input pixel's color
+ * to the color 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
+ * Result = Source Color + Destination Color
+ *
+ * Note: This gets only used in {@link BlendMode#Custom} mode.
+ * All other blend modes will ignore this setting.
*
- * @param blendEquationAlpha The blend equation to use for the alpha
- * component.
+ * @param blendEquationAlpha The {@link BlendEquationAlpha} to use.
*/
public void setBlendEquationAlpha(BlendEquationAlpha blendEquationAlpha) {
- applyBlendEquationAlpha = true;
this.blendEquationAlpha = blendEquationAlpha;
cachedHashCode = -1;
}
-
/**
- * Sets the custom blend factors for BlendMode.Custom
as
- * defined by the appropriate BlendFunc
.
- *
+ * Sets the blend factors used for the source and destination color.
+ *
+ * These factors will be multiplied with the color values of the input pixel + * and the pixel already in the color buffer, before both colors gets combined by the {@link BlendEquation}. + *
+ * Note: This gets only used in {@link BlendMode#Custom} mode. + * All other blend modes will ignore this setting. + * * @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) - { + 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. * @@ -1374,14 +1366,6 @@ public class RenderState implements Cloneable, Savable { return applyBlendMode; } - public boolean isApplyBlendEquation() { - return applyBlendEquation; - } - - public boolean isApplyBlendEquationAlpha() { - return applyBlendEquationAlpha; - } - public boolean isApplyColorWrite() { return applyColorWrite; } @@ -1511,27 +1495,26 @@ 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.blendEquationAlpha = blendEquationAlpha; - } if (additionalState.applyBlendMode) { state.blendMode = additionalState.blendMode; - if (additionalState.getBlendMode().equals(BlendMode.Custom)) { - state.setCustomBlendFactors( - additionalState.getCustomSfactorRGB(), - additionalState.getCustomDfactorRGB(), - additionalState.getCustomSfactorAlpha(), - additionalState.getCustomDfactorAlpha()); + if (additionalState.blendMode == BlendMode.Custom) { + state.blendEquation = additionalState.blendEquation; + state.blendEquationAlpha = additionalState.blendEquationAlpha; + state.sfactorRGB = additionalState.sfactorRGB; + state.dfactorRGB = additionalState.dfactorRGB; + state.sfactorAlpha = additionalState.sfactorAlpha; + state.dfactorAlpha = additionalState.dfactorAlpha; } } else { state.blendMode = blendMode; + if (blendMode == BlendMode.Custom) { + state.blendEquation = blendEquation; + state.blendEquationAlpha = blendEquationAlpha; + state.sfactorRGB = sfactorRGB; + state.dfactorRGB = dfactorRGB; + state.sfactorAlpha = sfactorAlpha; + state.dfactorAlpha = dfactorAlpha; + } } if (additionalState.applyPolyOffset) { @@ -1608,8 +1591,6 @@ public class RenderState implements Cloneable, Savable { applyDepthWrite = true; applyDepthTest = true; applyColorWrite = true; - applyBlendEquation = true; - applyBlendEquationAlpha = true; applyBlendMode = true; applyPolyOffset = true; applyDepthFunc = true; @@ -1636,8 +1617,6 @@ public class RenderState implements Cloneable, Savable { + "\ncolorWrite=" + colorWrite + "\napplyColorWrite=" + applyColorWrite + "\nblendEquation=" + blendEquation - + "\napplyBlendEquation=" + applyBlendEquation - + "\napplyBlendEquationAlpha=" + applyBlendEquationAlpha + "\nblendMode=" + blendMode + "\napplyBlendMode=" + applyBlendMode + "\noffsetEnabled=" + offsetEnabled 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 49f25240a..4599fdbb3 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/RenderContext.java +++ b/jme3-core/src/main/java/com/jme3/renderer/RenderContext.java @@ -32,6 +32,7 @@ package com.jme3.renderer; import com.jme3.material.RenderState; +import com.jme3.material.RenderState.BlendFunc; import com.jme3.math.ColorRGBA; import com.jme3.scene.Mesh; import com.jme3.scene.VertexBuffer; @@ -110,6 +111,30 @@ public class RenderContext { */ public RenderState.BlendEquationAlpha blendEquationAlpha = RenderState.BlendEquationAlpha.InheritColor; + /** + * @see RenderState#setCustomBlendFactors(com.jme3.material.RenderState.BlendFunc, com.jme3.material.RenderState.BlendFunc, + * com.jme3.material.RenderState.BlendFunc, com.jme3.material.RenderState.BlendFunc) + */ + public RenderState.BlendFunc sfactorRGB = RenderState.BlendFunc.One; + + /** + * @see RenderState#setCustomBlendFactors(com.jme3.material.RenderState.BlendFunc, com.jme3.material.RenderState.BlendFunc, + * com.jme3.material.RenderState.BlendFunc, com.jme3.material.RenderState.BlendFunc) + */ + public RenderState.BlendFunc dfactorRGB = RenderState.BlendFunc.One; + + /** + * @see RenderState#setCustomBlendFactors(com.jme3.material.RenderState.BlendFunc, com.jme3.material.RenderState.BlendFunc, + * com.jme3.material.RenderState.BlendFunc, com.jme3.material.RenderState.BlendFunc) + */ + public RenderState.BlendFunc sfactorAlpha = RenderState.BlendFunc.One; + + /** + * @see RenderState#setCustomBlendFactors(com.jme3.material.RenderState.BlendFunc, com.jme3.material.RenderState.BlendFunc, + * com.jme3.material.RenderState.BlendFunc, com.jme3.material.RenderState.BlendFunc) + */ + public RenderState.BlendFunc dfactorAlpha = RenderState.BlendFunc.One; + /** * @see RenderState#setWireframe(boolean) */ @@ -266,6 +291,10 @@ public class RenderContext { blendMode = RenderState.BlendMode.Off; blendEquation = RenderState.BlendEquation.Add; blendEquationAlpha = RenderState.BlendEquationAlpha.InheritColor; + sfactorRGB = BlendFunc.One; + dfactorRGB = BlendFunc.One; + sfactorAlpha = BlendFunc.One; + dfactorAlpha = BlendFunc.One; wireframe = false; boundShaderProgram = 0; boundShader = null; 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 9851f3418..746db4084 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 @@ -33,6 +33,7 @@ package com.jme3.renderer.opengl; import com.jme3.material.RenderState; import com.jme3.material.RenderState.BlendFunc; +import com.jme3.material.RenderState.BlendMode; import com.jme3.material.RenderState.StencilOperation; import com.jme3.material.RenderState.TestFunction; import com.jme3.math.*; @@ -743,68 +744,57 @@ public final class GLRenderer implements Renderer { context.cullMode = state.getFaceCullMode(); } - if (state.getBlendMode() != context.blendMode) { - if (state.getBlendMode() == RenderState.BlendMode.Off) { - gl.glDisable(GL.GL_BLEND); - } else { - if (context.blendMode == RenderState.BlendMode.Off) { - gl.glEnable(GL.GL_BLEND); - } - switch (state.getBlendMode()) { - case Off: - break; - case Additive: - gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE); - break; - case AlphaAdditive: - gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE); - break; - case Alpha: - gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA); - break; - case PremultAlpha: - gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE_MINUS_SRC_ALPHA); - break; - case Modulate: - gl.glBlendFunc(GL.GL_DST_COLOR, GL.GL_ZERO); - break; - case ModulateX2: - gl.glBlendFunc(GL.GL_DST_COLOR, GL.GL_SRC_COLOR); - break; - case Color: - case Screen: - gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE_MINUS_SRC_COLOR); - break; - 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()); - } - - if (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()); - } - gl.glBlendEquationSeparate(colorMode, alphaMode); - context.blendEquation = state.getBlendEquation(); - context.blendEquationAlpha = state.getBlendEquationAlpha(); - } + // Always update the blend equations and factors when using custom blend mode. + if (state.getBlendMode() == BlendMode.Custom) { + changeBlendMode(BlendMode.Custom); + + blendFuncSeparate( + state.getCustomSfactorRGB(), + state.getCustomDfactorRGB(), + state.getCustomSfactorAlpha(), + state.getCustomDfactorAlpha()); + blendEquationSeparate(state.getBlendEquation(), state.getBlendEquationAlpha()); + + // Update the blend equations and factors only on a mode change for all the other (common) blend modes. + } else if (state.getBlendMode() != context.blendMode) { + changeBlendMode(state.getBlendMode()); + + switch (state.getBlendMode()) { + case Off: + break; + case Additive: + blendFunc(RenderState.BlendFunc.One, RenderState.BlendFunc.One); + break; + case AlphaAdditive: + blendFunc(RenderState.BlendFunc.Src_Alpha, RenderState.BlendFunc.One); + break; + case Alpha: + blendFunc(RenderState.BlendFunc.Src_Alpha, RenderState.BlendFunc.One_Minus_Src_Alpha); + break; + case PremultAlpha: + blendFunc(RenderState.BlendFunc.One, RenderState.BlendFunc.One_Minus_Src_Alpha); + break; + case Modulate: + blendFunc(RenderState.BlendFunc.Dst_Color, RenderState.BlendFunc.Zero); + break; + case ModulateX2: + blendFunc(RenderState.BlendFunc.Dst_Color, RenderState.BlendFunc.Src_Color); + break; + case Color: + case Screen: + blendFunc(RenderState.BlendFunc.One, RenderState.BlendFunc.One_Minus_Src_Color); + break; + case Exclusion: + blendFunc(RenderState.BlendFunc.One_Minus_Dst_Color, RenderState.BlendFunc.One_Minus_Src_Color); + break; + default: + throw new UnsupportedOperationException("Unrecognized blend mode: " + + state.getBlendMode()); } - context.blendMode = state.getBlendMode(); + // All of the common modes requires the ADD equation. + // (This might change in the future?) + blendEquationSeparate(RenderState.BlendEquation.Add, RenderState.BlendEquationAlpha.InheritColor); } if (context.stencilTest != state.isStencilTest() @@ -852,6 +842,65 @@ public final class GLRenderer implements Renderer { } } + private void changeBlendMode(RenderState.BlendMode blendMode) { + if (blendMode != context.blendMode) { + if (blendMode == RenderState.BlendMode.Off) { + gl.glDisable(GL.GL_BLEND); + } else if (context.blendMode == RenderState.BlendMode.Off) { + gl.glEnable(GL.GL_BLEND); + } + + context.blendMode = blendMode; + } + } + + private void blendEquationSeparate(RenderState.BlendEquation blendEquation, RenderState.BlendEquationAlpha blendEquationAlpha) { + if (blendEquation != context.blendEquation || blendEquationAlpha != context.blendEquationAlpha) { + int glBlendEquation = convertBlendEquation(blendEquation); + int glBlendEquationAlpha = blendEquationAlpha == RenderState.BlendEquationAlpha.InheritColor + ? glBlendEquation + : convertBlendEquationAlpha(blendEquationAlpha); + gl.glBlendEquationSeparate(glBlendEquation, glBlendEquationAlpha); + context.blendEquation = blendEquation; + context.blendEquationAlpha = blendEquationAlpha; + } + } + + private void blendFunc(RenderState.BlendFunc sfactor, RenderState.BlendFunc dfactor) { + if (sfactor != context.sfactorRGB + || dfactor != context.dfactorRGB + || sfactor != context.sfactorAlpha + || dfactor != context.dfactorAlpha) { + + gl.glBlendFunc( + convertBlendFunc(sfactor), + convertBlendFunc(dfactor)); + context.sfactorRGB = sfactor; + context.dfactorRGB = dfactor; + context.sfactorAlpha = sfactor; + context.dfactorAlpha = dfactor; + } + } + + private void blendFuncSeparate(RenderState.BlendFunc sfactorRGB, RenderState.BlendFunc dfactorRGB, + RenderState.BlendFunc sfactorAlpha, RenderState.BlendFunc dfactorAlpha) { + if (sfactorRGB != context.sfactorRGB + || dfactorRGB != context.dfactorRGB + || sfactorAlpha != context.sfactorAlpha + || dfactorAlpha != context.dfactorAlpha) { + + gl.glBlendFuncSeparate( + convertBlendFunc(sfactorRGB), + convertBlendFunc(dfactorRGB), + convertBlendFunc(sfactorAlpha), + convertBlendFunc(dfactorAlpha)); + context.sfactorRGB = sfactorRGB; + context.dfactorRGB = dfactorRGB; + context.sfactorAlpha = sfactorAlpha; + context.dfactorAlpha = dfactorAlpha; + } + } + private int convertBlendEquation(RenderState.BlendEquation blendEquation) { switch (blendEquation) { case Add: