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 skControls = new ArrayList(); + private BitmapText hwsText; + + public static void main(String[] args) { + TestSkeletonControlRefresh app = new TestSkeletonControlRefresh(); + app.start(); + } + + @Override + public void simpleInitApp() { + viewPort.setBackgroundColor(ColorRGBA.White); + flyCam.setMoveSpeed(10f); + cam.setLocation(new Vector3f(3.8664846f, 6.2704787f, 9.664585f)); + cam.setRotation(new Quaternion(-0.054774776f, 0.94064945f, -0.27974048f, -0.18418397f)); + makeHudText(); + + DirectionalLight dl = new DirectionalLight(); + dl.setDirection(new Vector3f(-0.1f, -0.7f, -1).normalizeLocal()); + dl.setColor(new ColorRGBA(1f, 1f, 1f, 1.0f)); + rootNode.addLight(dl); + Material m = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); + TextureKey k = new TextureKey("Models/Oto/Oto.jpg", false); + m.setTexture("ColorMap", assetManager.loadTexture(k)); + + for (int i = 0; i < SIZE; i++) { + for (int j = 0; j < SIZE; j++) { + Spatial model = (Spatial) assetManager.loadModel("Models/Oto/Oto.mesh.xml"); + //setting a different material + model.setMaterial(m.clone()); + model.setLocalScale(0.1f); + model.setLocalTranslation(i - SIZE / 2, 0, j - SIZE / 2); + control = model.getControl(AnimControl.class); + + channel = control.createChannel(); + channel.setAnim(animNames[(i + j) % 4]); + channel.setLoopMode(LoopMode.DontLoop); + SkeletonControl skeletonControl = model.getControl(SkeletonControl.class); + + //This is a workaround the issue. this call will make the SkeletonControl gather the targets again. + //skeletonControl.setSpatial(model); + skeletonControl.setHardwareSkinningPreferred(hwSkinningEnable); + skControls.add(skeletonControl); + rootNode.attachChild(model); + } + } + + rootNode.setShadowMode(RenderQueue.ShadowMode.CastAndReceive); + setupFloor(); + + inputManager.addListener(this, "toggleHWS"); + inputManager.addMapping("toggleHWS", new KeyTrigger(KeyInput.KEY_SPACE)); + +// DirectionalLightShadowRenderer pssm = new DirectionalLightShadowRenderer(assetManager, 1024, 2); +// pssm.setLight(dl); +// viewPort.addProcessor(pssm); + + FilterPostProcessor fpp = new FilterPostProcessor(assetManager); + + DirectionalLightShadowFilter sf = new DirectionalLightShadowFilter(assetManager, 1024, 2); + sf.setLight(dl); + fpp.addFilter(sf); + fpp.addFilter(new SSAOFilter()); + viewPort.addProcessor(fpp); + + + } + + public void setupFloor() { + Quad q = new Quad(20, 20); + q.scaleTextureCoordinates(Vector2f.UNIT_XY.mult(10)); + Geometry geom = new Geometry("floor", q); + Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); + mat.setColor("Color", ColorRGBA.White); + geom.setMaterial(mat); + + geom.rotate(-FastMath.HALF_PI, 0, 0); + geom.center(); + geom.move(0, -0.3f, 0); + geom.setShadowMode(RenderQueue.ShadowMode.Receive); + rootNode.attachChild(geom); + } + + + @Override + public void onAction(String name, boolean isPressed, float tpf) { + if(isPressed && name.equals("toggleHWS")){ + hwSkinningEnable = !hwSkinningEnable; + for (SkeletonControl skControl : skControls) { + skControl.setHardwareSkinningPreferred(hwSkinningEnable); + hwsText.setText("HWS : "+ hwSkinningEnable); + } + } + } + + private void makeHudText() { + guiFont = assetManager.loadFont("Interface/Fonts/Default.fnt"); + hwsText = new BitmapText(guiFont, false); + hwsText.setSize(guiFont.getCharSet().getRenderedSize()); + hwsText.setText("HWS : "+ hwSkinningEnable); + hwsText.setLocalTranslation(0, cam.getHeight(), 0); + guiNode.attachChild(hwsText); + } +} \ No newline at end of file diff --git a/engine/src/test/jme3test/renderer/TestDepthFuncChange.java b/engine/src/test/jme3test/renderer/TestDepthFuncChange.java new file mode 100644 index 000000000..1bacf782b --- /dev/null +++ b/engine/src/test/jme3test/renderer/TestDepthFuncChange.java @@ -0,0 +1,90 @@ +/* + * 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.renderer; + +import com.jme3.app.SimpleApplication; +import com.jme3.font.BitmapText; +import com.jme3.material.Material; +import com.jme3.material.RenderState; +import com.jme3.math.ColorRGBA; +import com.jme3.renderer.queue.RenderQueue; +import com.jme3.scene.Geometry; +import com.jme3.scene.shape.Box; + +public class TestDepthFuncChange extends SimpleApplication { + + public static void main(String[] args) { + TestDepthFuncChange app = new TestDepthFuncChange(); + app.start(); + } + + public void simpleInitApp() { + viewPort.setBackgroundColor(ColorRGBA.DarkGray); + flyCam.setMoveSpeed(20); + + + //top of the screen + //default depth func (less or equal) rendering. + //2 cubes, a blue and a red. the red cube is offset by 0.2 WU to the right + //the red cube is put in the transparent bucket to be sure it's rendered after the blue one (but there is no transparency involved). + //You should see a small part of the blue cube on the left and the whole red cube + Box boxshape1 = new Box(1f, 1f, 1f); + Geometry cube1 = new Geometry("box", boxshape1); + Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); + mat.setColor("Color", ColorRGBA.Blue); + + cube1.setMaterial(mat); + rootNode.attachChild(cube1); + cube1.move(0, 1.5f, 0); + + Geometry cube2 = cube1.clone(true); + cube2.move(0.2f, 0 , 0); + cube2.setQueueBucket(RenderQueue.Bucket.Transparent); + cube2.getMaterial().setColor("Color", ColorRGBA.Red); + rootNode.attachChild(cube2); + + //Bottom of the screen + //here the 2 cubes are clonned and the depthFunc for the red cube's material is set to Less + //You should see the whole bleu cube and a small part of the red cube on the right + Geometry cube3 = cube1.clone(); + Geometry cube4 = cube2.clone(true); + cube4.getMaterial().getAdditionalRenderState().setDepthFunc(RenderState.TestFunction.Less); + cube3.move(0,-3,0); + cube4.move(0,-3,0); + rootNode.attachChild(cube3); + rootNode.attachChild(cube4); + + //Note that if you move the camera z fighting will occur but that's expected. + + + } +}