|
|
|
@ -36,75 +36,106 @@ import com.jme3.light.DirectionalLight; |
|
|
|
|
import com.jme3.material.Material; |
|
|
|
|
import com.jme3.material.RenderState; |
|
|
|
|
import com.jme3.math.ColorRGBA; |
|
|
|
|
import com.jme3.math.FastMath; |
|
|
|
|
import com.jme3.math.Vector3f; |
|
|
|
|
import com.jme3.renderer.queue.RenderQueue; |
|
|
|
|
import com.jme3.scene.Geometry; |
|
|
|
|
import com.jme3.scene.Spatial; |
|
|
|
|
import com.jme3.scene.shape.Quad; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* This test demonstrates the usage of customized blend equations and factors on a material.<br/> |
|
|
|
|
* Customized blend equations and factors always requires {@link RenderState.BlendMode#Custom}. |
|
|
|
|
* |
|
|
|
|
* @author the_Minka |
|
|
|
|
*/ |
|
|
|
|
public class TestBlendEquations extends SimpleApplication { |
|
|
|
|
|
|
|
|
|
private Geometry leftQuad; |
|
|
|
|
private Geometry rightQuad; |
|
|
|
|
|
|
|
|
|
private float timer; |
|
|
|
|
|
|
|
|
|
public static void main(String[] args) { |
|
|
|
|
TestBlendEquations app = new TestBlendEquations(); |
|
|
|
|
app.start(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void simpleInitApp() { |
|
|
|
|
Geometry teaGeom = (Geometry) assetManager.loadModel("Models/Teapot/Teapot.obj"); |
|
|
|
|
teaGeom.scale(6); |
|
|
|
|
teaGeom.getMaterial().getAdditionalRenderState().setBlendEquation(RenderState.BlendEquation.Add); |
|
|
|
|
teaGeom.move(0, -2f, 0); |
|
|
|
|
|
|
|
|
|
DirectionalLight dl = new DirectionalLight(); |
|
|
|
|
dl.setColor(ColorRGBA.Red); |
|
|
|
|
dl.setDirection(Vector3f.UNIT_XYZ.negate()); |
|
|
|
|
|
|
|
|
|
rootNode.addLight(dl); |
|
|
|
|
rootNode.attachChild(teaGeom); |
|
|
|
|
|
|
|
|
|
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); |
|
|
|
|
mat.setColor("Color", new ColorRGBA(0.5f, 0f, 1f, 0.3f)); |
|
|
|
|
mat.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Color); |
|
|
|
|
mat.getAdditionalRenderState().setBlendEquation(RenderState.BlendEquation.Subtract); |
|
|
|
|
|
|
|
|
|
Geometry geo = new Geometry("BottomLeft", new Quad(guiViewPort.getCamera().getWidth() / 2, guiViewPort.getCamera().getHeight() / 2)); |
|
|
|
|
geo.setMaterial(mat); |
|
|
|
|
geo.setQueueBucket(RenderQueue.Bucket.Gui); |
|
|
|
|
geo.setLocalTranslation(0, 0, 1); |
|
|
|
|
|
|
|
|
|
guiNode.attachChild(geo); |
|
|
|
|
|
|
|
|
|
Material m = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); |
|
|
|
|
m.getAdditionalRenderState().setBlendEquation(RenderState.BlendEquation.ReverseSubtract); |
|
|
|
|
m.setColor("Color", new ColorRGBA(0.0f, 1f, 1.f, 1f)); |
|
|
|
|
m.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.AlphaAdditive); |
|
|
|
|
|
|
|
|
|
geo = new Geometry("BottomRight", new Quad(guiViewPort.getCamera().getWidth() / 2, guiViewPort.getCamera().getHeight() / 2)); |
|
|
|
|
geo.setMaterial(m); |
|
|
|
|
geo.setQueueBucket(RenderQueue.Bucket.Gui); |
|
|
|
|
geo.setLocalTranslation(guiViewPort.getCamera().getWidth() / 2, 0, 1); |
|
|
|
|
|
|
|
|
|
guiNode.attachChild(geo); |
|
|
|
|
|
|
|
|
|
m = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); |
|
|
|
|
m.getAdditionalRenderState().setBlendEquation(RenderState.BlendEquation.Min); |
|
|
|
|
m.setColor("Color", new ColorRGBA(0.3f, 0f, 0.1f, 0.3f)); |
|
|
|
|
m.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Additive); |
|
|
|
|
|
|
|
|
|
geo = new Geometry("TopRight", new Quad(guiViewPort.getCamera().getWidth() / 2, guiViewPort.getCamera().getHeight() / 2)); |
|
|
|
|
geo.setMaterial(m); |
|
|
|
|
geo.setQueueBucket(RenderQueue.Bucket.Gui); |
|
|
|
|
geo.setLocalTranslation(guiViewPort.getCamera().getWidth() / 2, guiViewPort.getCamera().getHeight() / 2, 1); |
|
|
|
|
|
|
|
|
|
guiNode.attachChild(geo); |
|
|
|
|
|
|
|
|
|
geo = new Geometry("OverTeaPot", new Quad(guiViewPort.getCamera().getWidth() / 2, guiViewPort.getCamera().getHeight() / 2)); |
|
|
|
|
geo.setMaterial(mat); |
|
|
|
|
geo.setQueueBucket(RenderQueue.Bucket.Transparent); |
|
|
|
|
geo.setLocalTranslation(0, -100, 5); |
|
|
|
|
|
|
|
|
|
rootNode.attachChild(geo); |
|
|
|
|
cam.setLocation(new Vector3f(0f, 0.5f, 3f)); |
|
|
|
|
viewPort.setBackgroundColor(ColorRGBA.LightGray); |
|
|
|
|
|
|
|
|
|
// Add a light source to the scene.
|
|
|
|
|
DirectionalLight directionalLight = new DirectionalLight(); |
|
|
|
|
directionalLight.setColor(ColorRGBA.Magenta); |
|
|
|
|
directionalLight.setDirection(Vector3f.UNIT_XYZ.negate()); |
|
|
|
|
rootNode.addLight(directionalLight); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Create and add a teapot to the scene graph.
|
|
|
|
|
Spatial teapotModel = assetManager.loadModel("Models/Teapot/Teapot.obj"); |
|
|
|
|
rootNode.attachChild(teapotModel); |
|
|
|
|
|
|
|
|
|
// Create the two moving quads with custom blend modes.
|
|
|
|
|
createLeftQuad(); |
|
|
|
|
createRightQuad(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Adds a "transparent" quad to the scene, that shows an inverse blue value sight of the scene behind. |
|
|
|
|
*/ |
|
|
|
|
private void createLeftQuad() { |
|
|
|
|
Material material = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); |
|
|
|
|
|
|
|
|
|
// This color creates a blue value image. The effect will have a strength of 80% (set by the alpha value).
|
|
|
|
|
material.setColor("Color", new ColorRGBA(0f, 0f, 1f, 0.8f)); |
|
|
|
|
|
|
|
|
|
// Result.RGB = Source.A * Source.RGB - Source.A * Destination.RGB
|
|
|
|
|
// Result.A = Destination.A
|
|
|
|
|
material.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Custom); |
|
|
|
|
material.getAdditionalRenderState().setBlendEquation(RenderState.BlendEquation.Subtract); |
|
|
|
|
material.getAdditionalRenderState().setBlendEquationAlpha(RenderState.BlendEquationAlpha.Add); |
|
|
|
|
material.getAdditionalRenderState().setCustomBlendFactors( |
|
|
|
|
RenderState.BlendFunc.Src_Alpha, RenderState.BlendFunc.Src_Alpha, |
|
|
|
|
RenderState.BlendFunc.Zero, RenderState.BlendFunc.One); |
|
|
|
|
|
|
|
|
|
leftQuad = new Geometry("LeftQuad", new Quad(1f, 1f)); |
|
|
|
|
leftQuad.setMaterial(material); |
|
|
|
|
leftQuad.setQueueBucket(RenderQueue.Bucket.Transparent); |
|
|
|
|
rootNode.attachChild(leftQuad); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Adds a "transparent" quad to the scene, that limits the color values of the scene behind the object.<br/> |
|
|
|
|
* This effect can be good seen on bright areas of the scene (e.g. areas with specular lighting effects). |
|
|
|
|
*/ |
|
|
|
|
private void createRightQuad() { |
|
|
|
|
Material material = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); |
|
|
|
|
material.setColor("Color", new ColorRGBA(0.4f, 0.4f, 0.4f, 1f)); |
|
|
|
|
|
|
|
|
|
// Min( Source , Destination)
|
|
|
|
|
material.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Custom); |
|
|
|
|
material.getAdditionalRenderState().setBlendEquation(RenderState.BlendEquation.Min); |
|
|
|
|
material.getAdditionalRenderState().setBlendEquationAlpha(RenderState.BlendEquationAlpha.Min); |
|
|
|
|
|
|
|
|
|
// In OpenGL no blend factors are used, when using the blend equations Min or Max!
|
|
|
|
|
//material.getAdditionalRenderState().setCustomBlendFactors(
|
|
|
|
|
// RenderState.BlendFunc.One, RenderState.BlendFunc.One,
|
|
|
|
|
// RenderState.BlendFunc.One, RenderState.BlendFunc.One);
|
|
|
|
|
|
|
|
|
|
rightQuad = new Geometry("RightQuad", new Quad(1f, 1f)); |
|
|
|
|
rightQuad.setMaterial(material); |
|
|
|
|
rightQuad.setQueueBucket(RenderQueue.Bucket.Transparent); |
|
|
|
|
rootNode.attachChild(rightQuad); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public void simpleUpdate(float tpf) { |
|
|
|
|
timer += tpf; |
|
|
|
|
|
|
|
|
|
float xOffset = FastMath.sin(timer * 0.5f) * 2f; |
|
|
|
|
leftQuad.setLocalTranslation(xOffset - 2f, 0f, 0.5f); |
|
|
|
|
rightQuad.setLocalTranslation(xOffset + 1f, 0f, 0.5f); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|