diff --git a/engine/src/android/com/jme3/renderer/android/OGLESShaderRenderer.java b/engine/src/android/com/jme3/renderer/android/OGLESShaderRenderer.java index 1f0ec917f..5b2b3b7b1 100644 --- a/engine/src/android/com/jme3/renderer/android/OGLESShaderRenderer.java +++ b/engine/src/android/com/jme3/renderer/android/OGLESShaderRenderer.java @@ -31,7 +31,6 @@ */ package com.jme3.renderer.android; -import android.opengl.GLES10; import android.opengl.GLES20; import android.os.Build; import com.jme3.asset.AndroidImageInfo; @@ -419,7 +418,7 @@ public class OGLESShaderRenderer implements Renderer { */ if (state.isDepthTest() && !context.depthTestEnabled) { GLES20.glEnable(GLES20.GL_DEPTH_TEST); - GLES20.glDepthFunc(GLES20.GL_LEQUAL); + GLES20.glDepthFunc(convertTestFunction(context.depthFunc)); RendererUtil.checkGLError(); context.depthTestEnabled = true; } else if (!state.isDepthTest() && context.depthTestEnabled) { @@ -427,6 +426,10 @@ public class OGLESShaderRenderer implements Renderer { RendererUtil.checkGLError(); context.depthTestEnabled = false; } + if (state.getDepthFunc() != context.depthFunc) { + GLES20.glDepthFunc(convertTestFunction(state.getDepthFunc())); + context.depthFunc = state.getDepthFunc(); + } if (state.isDepthWrite() && !context.depthWriteEnabled) { GLES20.glDepthMask(true); @@ -1016,6 +1019,29 @@ public class OGLESShaderRenderer implements Renderer { shader.resetObject(); } + private int convertTestFunction(RenderState.TestFunction testFunc) { + switch (testFunc) { + case Never: + return GLES20.GL_NEVER; + case Less: + return GLES20.GL_LESS; + case LessOrEqual: + return GLES20.GL_LEQUAL; + case Greater: + return GLES20.GL_GREATER; + case GreaterOrEqual: + return GLES20.GL_GEQUAL; + case Equal: + return GLES20.GL_EQUAL; + case NotEqual: + return GLES20.GL_NOTEQUAL; + case Always: + return GLES20.GL_ALWAYS; + default: + throw new UnsupportedOperationException("Unrecognized test function: " + testFunc); + } + } + /*********************************************************************\ |* Framebuffers *| \*********************************************************************/ diff --git a/engine/src/core-plugins/com/jme3/material/plugins/J3MLoader.java b/engine/src/core-plugins/com/jme3/material/plugins/J3MLoader.java index 4adb5a692..9a1d6be6a 100644 --- a/engine/src/core-plugins/com/jme3/material/plugins/J3MLoader.java +++ b/engine/src/core-plugins/com/jme3/material/plugins/J3MLoader.java @@ -330,6 +330,10 @@ public class J3MLoader implements AssetLoader { renderState.setColorWrite(parseBoolean(split[1])); }else if (split[0].equals("PointSprite")){ renderState.setPointSprite(parseBoolean(split[1])); + }else if (split[0].equals("DepthFunc")){ + renderState.setDepthFunc(RenderState.TestFunction.valueOf(split[1])); + }else if (split[0].equals("AlphaFunc")){ + renderState.setAlphaFunc(RenderState.TestFunction.valueOf(split[1])); } else { throw new MatParseException(null, split[0], statement); } diff --git a/engine/src/core/com/jme3/material/RenderState.java b/engine/src/core/com/jme3/material/RenderState.java index 0aa8b45d6..ef39ddc46 100644 --- a/engine/src/core/com/jme3/material/RenderState.java +++ b/engine/src/core/com/jme3/material/RenderState.java @@ -296,6 +296,12 @@ public class RenderState implements Cloneable, Savable { boolean applyPolyOffset = true; boolean stencilTest = false; boolean applyStencilTest = false; + TestFunction depthFunc = TestFunction.LessOrEqual; + //by default depth func will be applied anyway if depth test is applied + boolean applyDepthFunc = false; + //by default alpha func will be applied anyway if alpha test is applied + TestFunction alphaFunc = TestFunction.Greater; + boolean applyAlphaFunc = false; StencilOperation frontStencilStencilFailOperation = StencilOperation.Keep; StencilOperation frontStencilDepthFailOperation = StencilOperation.Keep; StencilOperation frontStencilDepthPassOperation = StencilOperation.Keep; @@ -341,6 +347,10 @@ public class RenderState implements Cloneable, Savable { oc.write(applyAlphaTest, "applyAlphaTest", true); oc.write(applyAlphaFallOff, "applyAlphaFallOff", true); oc.write(applyPolyOffset, "applyPolyOffset", true); + oc.write(applyDepthFunc, "applyDepthFunc", true); + oc.write(applyAlphaFunc, "applyAlphaFunc", false); + oc.write(depthFunc, "depthFunc", TestFunction.LessOrEqual); + oc.write(alphaFunc, "alphaFunc", TestFunction.Greater); } @@ -367,6 +377,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); + depthFunc = ic.readEnum("depthFunc", TestFunction.class, TestFunction.LessOrEqual); + alphaFunc = ic.readEnum("alphaFunc", TestFunction.class, TestFunction.Greater); applyPointSprite = ic.readBoolean("applyPointSprite", true); applyWireFrame = ic.readBoolean("applyWireFrame", true); @@ -378,6 +390,9 @@ public class RenderState implements Cloneable, Savable { applyAlphaTest = ic.readBoolean("applyAlphaTest", true); applyAlphaFallOff = ic.readBoolean("applyAlphaFallOff", true); applyPolyOffset = ic.readBoolean("applyPolyOffset", true); + applyDepthFunc = ic.readBoolean("applyDepthFunc", true); + applyAlphaFunc = ic.readBoolean("applyAlphaFunc", false); + } /** @@ -427,6 +442,11 @@ public class RenderState implements Cloneable, Savable { if (depthTest != rs.depthTest) { return false; } + if (depthTest) { + if (depthFunc != rs.depthFunc) { + return false; + } + } if (colorWrite != rs.colorWrite) { return false; @@ -439,6 +459,11 @@ public class RenderState implements Cloneable, Savable { if (alphaTest != rs.alphaTest) { return false; } + if (alphaTest) { + if (alphaFunc != rs.alphaFunc) { + return false; + } + } if (alphaFallOff != rs.alphaFallOff) { return false; @@ -515,6 +540,12 @@ public class RenderState implements Cloneable, Savable { *
If the pixel's alpha value is greater than the
* alphaFallOff
then the pixel will be rendered, otherwise
* the pixel will be discarded.
+ *
+ * Note : Alpha test is deprecated since opengl 3.0 and does not exists in
+ * openglES 2.0.
+ * The prefered way is to use the alphaDiscardThreshold on the material
+ * Or have a shader that discards the pixel when its alpha value meets the
+ * discarding condition.
*
* @param alphaFallOff The alpha of all rendered pixels must be higher
* than this value to be rendered. This value should be between 0 and 1.
@@ -536,6 +567,13 @@ public class RenderState implements Cloneable, Savable {
* otherwise it will be discarded.
*
* @param alphaTest Set to true to enable alpha testing.
+ *
+ * Note : Alpha test is deprecated since opengl 3.0 and does not exists in
+ * openglES 2.0.
+ * The prefered way is to use the alphaDiscardThreshold on the material
+ * Or have a shader that discards the pixel when its alpha value meets the
+ * discarding condition.
+ *
*
* @see RenderState#setAlphaFallOff(float)
*/
@@ -666,7 +704,7 @@ public class RenderState implements Cloneable, Savable {
offsetUnits = units;
}
cachedHashCode = -1;
- }
+ }
/**
* Enable stencil testing.
@@ -717,6 +755,42 @@ public class RenderState implements Cloneable, Savable {
cachedHashCode = -1;
}
+ /**
+ * Set the depth conparison function to the given TestFunction
+ * default is LessOrEqual (GL_LEQUAL)
+ * @see TestFunction
+ * @see RenderState#setDepthTest(boolean)
+ * @param depthFunc the depth comparison function
+ */
+ public void setDepthFunc(TestFunction depthFunc) {
+ applyDepthFunc = true;
+ this.depthFunc = depthFunc;
+ cachedHashCode = -1;
+ }
+
+ /**
+ * Sets the alpha comparision function to the given TestFunction
+ * default is Greater (GL_GREATER)
+ *
+ * Note : Alpha test is deprecated since opengl 3.0 and does not exists in
+ * openglES 2.0.
+ * The prefered way is to use the alphaDiscardThreshold on the material
+ * Or have a shader taht discards the pixel when its alpha value meets the
+ * discarding condition.
+ *
+ * @see TestFunction
+ * @see RenderState#setAlphaTest(boolean)
+ * @see RenderState#setAlphaFallOff(float)
+ * @param alphaFunc the alpha comparision function
+ */
+ public void setAlphaFunc(TestFunction alphaFunc) {
+ applyAlphaFunc = true;
+ this.alphaFunc = alphaFunc;
+ cachedHashCode = -1;
+ }
+
+
+
/**
* Check if stencil test is enabled.
*
@@ -1008,6 +1082,30 @@ public class RenderState implements Cloneable, Savable {
return alphaFallOff;
}
+ /**
+ * Retrieve the depth comparison function
+ *
+ * @return the depth comparison function
+ *
+ * @see RenderState#setDepthFunc(com.jme3.material.RenderState.TestFunction)
+ */
+ public TestFunction getDepthFunc() {
+ return depthFunc;
+ }
+
+ /**
+ * Retrieve the alpha comparison function
+ *
+ * @return the alpha comparison function
+ *
+ * @see RenderState#setAlphaFunc(com.jme3.material.RenderState.TestFunction)
+ */
+ public TestFunction getAlphaFunc() {
+ return alphaFunc;
+ }
+
+
+
public boolean isApplyAlphaFallOff() {
return applyAlphaFallOff;
}
@@ -1048,6 +1146,16 @@ public class RenderState implements Cloneable, Savable {
return applyWireFrame;
}
+ public boolean isApplyDepthFunc() {
+ return applyDepthFunc;
+ }
+
+ public boolean isApplyAlphaFunc() {
+ return applyAlphaFunc;
+ }
+
+
+
/**
*
*/
@@ -1059,9 +1167,11 @@ public class RenderState implements Cloneable, Savable {
hash = 79 * hash + (this.cullMode != null ? this.cullMode.hashCode() : 0);
hash = 79 * hash + (this.depthWrite ? 1 : 0);
hash = 79 * hash + (this.depthTest ? 1 : 0);
+ 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.alphaTest ? 1 : 0);
+ hash = 79 * hash + (this.alphaFunc != null ? this.alphaFunc.hashCode() : 0);
hash = 79 * hash + Float.floatToIntBits(this.alphaFallOff);
hash = 79 * hash + Float.floatToIntBits(this.offsetFactor);
hash = 79 * hash + Float.floatToIntBits(this.offsetUnits);
@@ -1132,6 +1242,11 @@ public class RenderState implements Cloneable, Savable {
} else {
state.depthTest = depthTest;
}
+ if (additionalState.applyDepthFunc) {
+ state.depthFunc = additionalState.depthFunc;
+ } else {
+ state.depthFunc = depthFunc;
+ }
if (additionalState.applyColorWrite) {
state.colorWrite = additionalState.colorWrite;
} else {
@@ -1147,6 +1262,11 @@ public class RenderState implements Cloneable, Savable {
} else {
state.alphaTest = alphaTest;
}
+ if (additionalState.applyAlphaFunc) {
+ state.alphaFunc = additionalState.alphaFunc;
+ } else {
+ state.alphaFunc = alphaFunc;
+ }
if (additionalState.applyAlphaFallOff) {
state.alphaFallOff = additionalState.alphaFallOff;
@@ -1205,19 +1325,21 @@ public class RenderState implements Cloneable, Savable {
+ "\ndepthWrite=" + depthWrite
+ "\napplyDepthWrite=" + applyDepthWrite
+ "\ndepthTest=" + depthTest
+ + "\ndepthFunc=" + depthFunc
+ "\napplyDepthTest=" + applyDepthTest
+ "\ncolorWrite=" + colorWrite
+ "\napplyColorWrite=" + applyColorWrite
+ "\nblendMode=" + blendMode
+ "\napplyBlendMode=" + applyBlendMode
+ "\nalphaTest=" + alphaTest
+ + "\nalphaFunc=" + alphaFunc
+ "\napplyAlphaTest=" + applyAlphaTest
+ "\nalphaFallOff=" + alphaFallOff
+ "\napplyAlphaFallOff=" + applyAlphaFallOff
+ "\noffsetEnabled=" + offsetEnabled
+ "\napplyPolyOffset=" + applyPolyOffset
+ "\noffsetFactor=" + offsetFactor
- + "\noffsetUnits=" + offsetUnits
+ + "\noffsetUnits=" + offsetUnits
+ "\n]";
}
}
diff --git a/engine/src/core/com/jme3/renderer/RenderContext.java b/engine/src/core/com/jme3/renderer/RenderContext.java
index 67023e4f8..80ef55b64 100644
--- a/engine/src/core/com/jme3/renderer/RenderContext.java
+++ b/engine/src/core/com/jme3/renderer/RenderContext.java
@@ -263,6 +263,16 @@ public class RenderContext {
* Use vertex color (GL1 only)
*/
public boolean useVertexColor;
+
+ /**
+ * depth tets function
+ */
+ public RenderState.TestFunction depthFunc = RenderState.TestFunction.LessOrEqual;
+
+ /**
+ * alpha tets function
+ */
+ public RenderState.TestFunction alphaFunc = RenderState.TestFunction.Greater;
/**
* Reset the RenderContext to default GL state
@@ -314,5 +324,7 @@ public class RenderContext {
ambient = diffuse = specular = color = null;
shininess = 0;
useVertexColor = false;
+ depthFunc = RenderState.TestFunction.LessOrEqual;
+ alphaFunc = RenderState.TestFunction.Greater;
}
}
diff --git a/engine/src/jogl/com/jme3/renderer/jogl/JoglRenderer.java b/engine/src/jogl/com/jme3/renderer/jogl/JoglRenderer.java
index 9f8a1b6f3..81dc2b47f 100644
--- a/engine/src/jogl/com/jme3/renderer/jogl/JoglRenderer.java
+++ b/engine/src/jogl/com/jme3/renderer/jogl/JoglRenderer.java
@@ -517,17 +517,21 @@ public class JoglRenderer implements Renderer {
if (state.isDepthTest() && !context.depthTestEnabled) {
gl.glEnable(GL.GL_DEPTH_TEST);
- gl.glDepthFunc(GL.GL_LEQUAL);
+ gl.glDepthFunc(convertTestFunction(context.depthFunc));
context.depthTestEnabled = true;
} else if (!state.isDepthTest() && context.depthTestEnabled) {
gl.glDisable(GL.GL_DEPTH_TEST);
context.depthTestEnabled = false;
}
+ if (state.getDepthFunc() != context.depthFunc) {
+ gl.glDepthFunc(convertTestFunction(state.getDepthFunc()));
+ context.depthFunc = state.getDepthFunc();
+ }
if (state.isAlphaTest() && context.alphaTestFallOff == 0) {
gl.glEnable(GL2ES1.GL_ALPHA_TEST);
if (gl.isGL2ES1()) {
- gl.getGL2ES1().glAlphaFunc(GL.GL_GREATER, state.getAlphaFallOff());
+ gl.getGL2ES1().glAlphaFunc(convertTestFunction(context.alphaFunc), state.getAlphaFallOff());
}
context.alphaTestFallOff = state.getAlphaFallOff();
} else if (!state.isAlphaTest() && context.alphaTestFallOff != 0) {
@@ -536,6 +540,10 @@ public class JoglRenderer implements Renderer {
}
context.alphaTestFallOff = 0;
}
+ if (state.getAlphaFunc() != context.alphaFunc && gl.isGL2ES1()) {
+ gl.getGL2ES1().glAlphaFunc(convertTestFunction(context.alphaFunc), state.getAlphaFallOff());
+ context.alphaFunc = state.getAlphaFunc();
+ }
if (state.isDepthWrite() && !context.depthWriteEnabled) {
gl.glDepthMask(true);
diff --git a/engine/src/lwjgl/com/jme3/renderer/lwjgl/LwjglRenderer.java b/engine/src/lwjgl/com/jme3/renderer/lwjgl/LwjglRenderer.java
index 0b2cd1507..fec5ddf41 100644
--- a/engine/src/lwjgl/com/jme3/renderer/lwjgl/LwjglRenderer.java
+++ b/engine/src/lwjgl/com/jme3/renderer/lwjgl/LwjglRenderer.java
@@ -482,22 +482,30 @@ public class LwjglRenderer implements Renderer {
}
if (state.isDepthTest() && !context.depthTestEnabled) {
- glEnable(GL_DEPTH_TEST);
- glDepthFunc(GL_LEQUAL);
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(convertTestFunction(context.depthFunc));
context.depthTestEnabled = true;
} else if (!state.isDepthTest() && context.depthTestEnabled) {
glDisable(GL_DEPTH_TEST);
context.depthTestEnabled = false;
}
+ if (state.getDepthFunc() != context.depthFunc) {
+ glDepthFunc(convertTestFunction(state.getDepthFunc()));
+ context.depthFunc = state.getDepthFunc();
+ }
if (state.isAlphaTest() && context.alphaTestFallOff == 0) {
glEnable(GL_ALPHA_TEST);
- glAlphaFunc(GL_GREATER, state.getAlphaFallOff());
+ glAlphaFunc(convertTestFunction(context.alphaFunc), state.getAlphaFallOff());
context.alphaTestFallOff = state.getAlphaFallOff();
} else if (!state.isAlphaTest() && context.alphaTestFallOff != 0) {
glDisable(GL_ALPHA_TEST);
context.alphaTestFallOff = 0;
}
+ if (state.getAlphaFunc() != context.alphaFunc) {
+ glAlphaFunc(convertTestFunction(state.getAlphaFunc()), state.getAlphaFallOff());
+ context.alphaFunc = state.getAlphaFunc();
+ }
if (state.isDepthWrite() && !context.depthWriteEnabled) {
glDepthMask(true);
diff --git a/engine/src/test/jme3test/model/anim/TestSkeletonControlRefresh.java b/engine/src/test/jme3test/model/anim/TestSkeletonControlRefresh.java
new file mode 100644
index 000000000..d594f197f
--- /dev/null
+++ b/engine/src/test/jme3test/model/anim/TestSkeletonControlRefresh.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2009-2012 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.model.anim;
+
+/**
+ *
+ * @author Nehon
+ */
+
+
+
+import com.jme3.animation.*;
+import com.jme3.app.SimpleApplication;
+import com.jme3.asset.TextureKey;
+import com.jme3.font.BitmapText;
+import com.jme3.input.KeyInput;
+import com.jme3.input.controls.ActionListener;
+import com.jme3.input.controls.KeyTrigger;
+import com.jme3.light.DirectionalLight;
+import com.jme3.material.Material;
+import com.jme3.math.ColorRGBA;
+import com.jme3.math.FastMath;
+import com.jme3.math.Quaternion;
+import com.jme3.math.Vector2f;
+import com.jme3.math.Vector3f;
+import com.jme3.post.FilterPostProcessor;
+import com.jme3.post.ssao.SSAOFilter;
+import com.jme3.renderer.queue.RenderQueue;
+import com.jme3.scene.Geometry;
+import com.jme3.scene.Spatial;
+import com.jme3.scene.shape.Quad;
+import com.jme3.shadow.DirectionalLightShadowFilter;
+import com.jme3.shadow.DirectionalLightShadowRenderer;
+import java.util.ArrayList;
+import java.util.List;
+import jme3test.post.SSAOUI;
+
+public class TestSkeletonControlRefresh extends SimpleApplication implements ActionListener{
+
+ private AnimChannel channel;
+ private AnimControl control;
+ private String[] animNames = {"Dodge", "Walk", "pull", "push"};
+ private final static int SIZE = 10;
+ private boolean hwSkinningEnable = true;
+ private List