com.jme3.material.RenderState Maven / Gradle / Ivy
Show all versions of jme3-core Show documentation
/*
* 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 com.jme3.material;
import com.jme3.export.*;
import com.jme3.scene.Mesh;
import com.jme3.scene.Mesh.Mode;
import java.io.IOException;
/**
* RenderState
specifies material rendering properties that cannot
* be controlled by a shader on a {@link Material}. The properties
* allow manipulation of rendering features such as depth testing, alpha blending,
* face culling, stencil operations, and much more.
*
* @author Kirill Vainer
*/
public class RenderState implements Cloneable, Savable {
/**
* The DEFAULT
render state is the one used by default
* on all materials unless changed otherwise by the user.
*
*
* It has the following properties:
*
* - Back Face Culling
* - Depth Testing Enabled
* - Depth Writing Enabled
*
*/
public static final RenderState DEFAULT = new RenderState();
/**
* The NULL
render state is identical to the {@link RenderState#DEFAULT}
* render state except that depth testing and face culling are disabled.
*/
public static final RenderState NULL = new RenderState();
/**
* The ADDITIONAL
render state is identical to the
* {@link RenderState#DEFAULT} render state except that all apply
* values are set to false. This allows the ADDITIONAL
render
* state to be combined with other state but only influencing values
* that were changed from the original.
*/
public static final RenderState ADDITIONAL = new RenderState();
/**
* TestFunction
specifies the testing function for stencil test
* function.
*
*
* The reference value given in the stencil command is the input value while
* the reference is the value already in the stencil buffer.
*/
public enum TestFunction {
/**
* The test always fails
*/
Never,
/**
* The test succeeds if the input value is equal to the reference value.
*/
Equal,
/**
* The test succeeds if the input value is less than the reference value.
*/
Less,
/**
* The test succeeds if the input value is less than or equal to
* the reference value.
*/
LessOrEqual,
/**
* The test succeeds if the input value is greater than the reference value.
*/
Greater,
/**
* The test succeeds if the input value is greater than or equal to
* the reference value.
*/
GreaterOrEqual,
/**
* The test succeeds if the input value does not equal the
* reference value.
*/
NotEqual,
/**
* The test always passes
*/
Always
}
/**
* BlendEquation
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
}
/**
* BlendEquationAlpha
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
}
/**
* BlendMode
specifies the blending operation to use.
*
* @see RenderState#setBlendMode(com.jme3.material.RenderState.BlendMode)
*/
public enum BlendMode {
/**
* No blending mode is used.
*/
Off,
/**
* Additive blending. For use with glows and particle emitters.
*
* Result = Source Color + Destination Color -> (GL_ONE, GL_ONE)
*/
Additive,
/**
* Premultiplied alpha blending, for use with premult alpha textures.
*
* Result = Source Color + (Dest Color * (1 - Source Alpha) ) -> (GL_ONE, GL_ONE_MINUS_SRC_ALPHA)
*/
PremultAlpha,
/**
* Additive blending that is multiplied with source alpha.
* For use with glows and particle emitters.
*
* Result = (Source Alpha * Source Color) + Dest Color -> (GL_SRC_ALPHA, GL_ONE)
*/
AlphaAdditive,
/**
* Color blending, blends in color from dest color
* using source color.
*
* Result = Source Color + (1 - Source Color) * Dest Color -> (GL_ONE, GL_ONE_MINUS_SRC_COLOR)
*/
Color,
/**
* Alpha blending, interpolates to source color from dest color
* using source alpha.
*
* Result = Source Alpha * Source Color +
* (1 - Source Alpha) * Dest Color -> (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
*/
Alpha,
/**
* Multiplies the source and dest colors.
*
* Result = Source Color * Dest Color -> (GL_DST_COLOR, GL_ZERO)
*/
Modulate,
/**
* Multiplies the source and dest colors then doubles the result.
*
* Result = 2 * Source Color * Dest Color -> (GL_DST_COLOR, GL_SRC_COLOR)
*/
ModulateX2,
/**
* Opposite effect of Modulate/Multiply. Invert both colors, multiply and
* then invert the result.
*
* Result = 1 - (1 - Source Color) * (1 - Dest Color) -> (GL_ONE, GL_ONE_MINUS_SRC_COLOR)
*/
Screen,
/**
* Mixes the destination and source colors similar to a color-based XOR
* operation. This is directly equivalent to Photoshop's "Exclusion" blend.
*
* Result = (Source Color * (1 - Dest Color)) + (Dest Color * (1 - Source Color))
* -> (GL_ONE_MINUS_DST_COLOR, GL_ONE_MINUS_SRC_COLOR)
*/
Exclusion
}
/**
* FaceCullMode
specifies the criteria for faces to be culled.
*
* @see RenderState#setFaceCullMode(com.jme3.material.RenderState.FaceCullMode)
*/
public enum FaceCullMode {
/**
* Face culling is disabled.
*/
Off,
/**
* Cull front faces
*/
Front,
/**
* Cull back faces
*/
Back,
/**
* Cull both front and back faces.
*/
FrontAndBack
}
/**
* StencilOperation
specifies the stencil operation to use
* in a certain scenario as specified in {@link RenderState#setStencil(boolean,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.TestFunction,
* com.jme3.material.RenderState.TestFunction) }
*/
public enum StencilOperation {
/**
* Keep the current value.
*/
Keep,
/**
* Set the value to 0
*/
Zero,
/**
* Replace the value in the stencil buffer with the reference value.
*/
Replace,
/**
* Increment the value in the stencil buffer, clamp once reaching
* the maximum value.
*/
Increment,
/**
* Increment the value in the stencil buffer and wrap to 0 when
* reaching the maximum value.
*/
IncrementWrap,
/**
* Decrement the value in the stencil buffer and clamp once reaching 0.
*/
Decrement,
/**
* Decrement the value in the stencil buffer and wrap to the maximum
* value when reaching 0.
*/
DecrementWrap,
/**
* Does a bitwise invert of the value in the stencil buffer.
*/
Invert
}
static {
NULL.cullMode = FaceCullMode.Off;
NULL.depthTest = false;
}
static {
ADDITIONAL.applyWireFrame = false;
ADDITIONAL.applyCullMode = false;
ADDITIONAL.applyDepthWrite = false;
ADDITIONAL.applyDepthTest = false;
ADDITIONAL.applyColorWrite = false;
ADDITIONAL.applyBlendEquation = false;
ADDITIONAL.applyBlendEquationAlpha = false;
ADDITIONAL.applyBlendMode = false;
ADDITIONAL.applyPolyOffset = false;
}
boolean wireframe = false;
boolean applyWireFrame = true;
FaceCullMode cullMode = FaceCullMode.Back;
boolean applyCullMode = true;
boolean depthWrite = true;
boolean applyDepthWrite = true;
boolean depthTest = true;
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;
float offsetFactor = 0;
float offsetUnits = 0;
boolean offsetEnabled = false;
boolean applyPolyOffset = true;
boolean stencilTest = false;
boolean applyStencilTest = false;
float lineWidth = 1;
boolean applyLineWidth = false;
TestFunction depthFunc = TestFunction.LessOrEqual;
//by default depth func will be applied anyway if depth test is applied
boolean applyDepthFunc = false;
StencilOperation frontStencilStencilFailOperation = StencilOperation.Keep;
StencilOperation frontStencilDepthFailOperation = StencilOperation.Keep;
StencilOperation frontStencilDepthPassOperation = StencilOperation.Keep;
StencilOperation backStencilStencilFailOperation = StencilOperation.Keep;
StencilOperation backStencilDepthFailOperation = StencilOperation.Keep;
StencilOperation backStencilDepthPassOperation = StencilOperation.Keep;
TestFunction frontStencilFunction = TestFunction.Always;
TestFunction backStencilFunction = TestFunction.Always;
int cachedHashCode = -1;
public void write(JmeExporter ex) throws IOException {
OutputCapsule oc = ex.getCapsule(this);
oc.write(true, "pointSprite", false);
oc.write(wireframe, "wireframe", false);
oc.write(cullMode, "cullMode", FaceCullMode.Back);
oc.write(depthWrite, "depthWrite", true);
oc.write(depthTest, "depthTest", true);
oc.write(colorWrite, "colorWrite", true);
oc.write(blendMode, "blendMode", BlendMode.Off);
oc.write(offsetEnabled, "offsetEnabled", false);
oc.write(offsetFactor, "offsetFactor", 0);
oc.write(offsetUnits, "offsetUnits", 0);
oc.write(stencilTest, "stencilTest", false);
oc.write(frontStencilStencilFailOperation, "frontStencilStencilFailOperation", StencilOperation.Keep);
oc.write(frontStencilDepthFailOperation, "frontStencilDepthFailOperation", StencilOperation.Keep);
oc.write(frontStencilDepthPassOperation, "frontStencilDepthPassOperation", StencilOperation.Keep);
oc.write(backStencilStencilFailOperation, "frontStencilStencilFailOperation", StencilOperation.Keep);
oc.write(backStencilDepthFailOperation, "backStencilDepthFailOperation", StencilOperation.Keep);
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(lineWidth, "lineWidth", 1);
// Only "additional render state" has them set to false by default
oc.write(applyWireFrame, "applyWireFrame", true);
oc.write(applyCullMode, "applyCullMode", true);
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);
oc.write(applyLineWidth, "applyLineWidth", true);
}
public void read(JmeImporter im) throws IOException {
InputCapsule ic = im.getCapsule(this);
wireframe = ic.readBoolean("wireframe", false);
cullMode = ic.readEnum("cullMode", FaceCullMode.class, FaceCullMode.Back);
depthWrite = ic.readBoolean("depthWrite", true);
depthTest = ic.readBoolean("depthTest", true);
colorWrite = ic.readBoolean("colorWrite", true);
blendMode = ic.readEnum("blendMode", BlendMode.class, BlendMode.Off);
offsetEnabled = ic.readBoolean("offsetEnabled", false);
offsetFactor = ic.readFloat("offsetFactor", 0);
offsetUnits = ic.readFloat("offsetUnits", 0);
stencilTest = ic.readBoolean("stencilTest", false);
frontStencilStencilFailOperation = ic.readEnum("frontStencilStencilFailOperation", StencilOperation.class, StencilOperation.Keep);
frontStencilDepthFailOperation = ic.readEnum("frontStencilDepthFailOperation", StencilOperation.class, StencilOperation.Keep);
frontStencilDepthPassOperation = ic.readEnum("frontStencilDepthPassOperation", StencilOperation.class, StencilOperation.Keep);
backStencilStencilFailOperation = ic.readEnum("backStencilStencilFailOperation", StencilOperation.class, StencilOperation.Keep);
backStencilDepthFailOperation = ic.readEnum("backStencilDepthFailOperation", StencilOperation.class, StencilOperation.Keep);
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);
lineWidth = ic.readFloat("lineWidth", 1);
applyWireFrame = ic.readBoolean("applyWireFrame", true);
applyCullMode = ic.readBoolean("applyCullMode", true);
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);
}
/**
* Create a clone of this RenderState
*
* @return Clone of this render state.
*/
@Override
public RenderState clone() {
try {
return (RenderState) super.clone();
} catch (CloneNotSupportedException ex) {
throw new AssertionError();
}
}
/**
* 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
public boolean equals(Object o) {
if (o == null) {
return false;
}
if (!(o instanceof RenderState)) {
return false;
}
RenderState rs = (RenderState) o;
if (wireframe != rs.wireframe) {
return false;
}
if (cullMode != rs.cullMode) {
return false;
}
if (depthWrite != rs.depthWrite) {
return false;
}
if (depthTest != rs.depthTest) {
return false;
}
if (depthTest) {
if (depthFunc != rs.depthFunc) {
return false;
}
}
if (colorWrite != rs.colorWrite) {
return false;
}
if (blendEquation != rs.blendEquation) {
return false;
}
if (blendEquationAlpha != rs.blendEquationAlpha) {
return false;
}
if (blendMode != rs.blendMode) {
return false;
}
if (offsetEnabled != rs.offsetEnabled) {
return false;
}
if (offsetFactor != rs.offsetFactor) {
return false;
}
if (offsetUnits != rs.offsetUnits) {
return false;
}
if (stencilTest != rs.stencilTest) {
return false;
}
if (stencilTest) {
if (frontStencilStencilFailOperation != rs.frontStencilStencilFailOperation) {
return false;
}
if (frontStencilDepthFailOperation != rs.frontStencilDepthFailOperation) {
return false;
}
if (frontStencilDepthPassOperation != rs.frontStencilDepthPassOperation) {
return false;
}
if (backStencilStencilFailOperation != rs.backStencilStencilFailOperation) {
return false;
}
if (backStencilDepthFailOperation != rs.backStencilDepthFailOperation) {
return false;
}
if (backStencilDepthPassOperation != rs.backStencilDepthPassOperation) {
return false;
}
if (frontStencilFunction != rs.frontStencilFunction) {
return false;
}
if (backStencilFunction != rs.backStencilFunction) {
return false;
}
}
if(lineWidth != rs.lineWidth){
return false;
}
return true;
}
/**
* @deprecated Does nothing. Point sprite is already enabled by default for
* all supported platforms. jME3 does not support rendering conventional
* point clouds.
*/
@Deprecated
public void setPointSprite(boolean pointSprite) {
}
/**
* @deprecated Does nothing. To use alpha test, set the
* AlphaDiscardThreshold
material parameter.
* @param alphaFallOff does nothing
*/
@Deprecated
public void setAlphaFallOff(float alphaFallOff) {
}
/**
* @deprecated Does nothing. To use alpha test, set the
* AlphaDiscardThreshold
material parameter.
* @param alphaTest does nothing
*/
@Deprecated
public void setAlphaTest(boolean alphaTest) {
}
/**
* Enable writing color.
*
*
When color write is enabled, the result of a fragment shader, the
* gl_FragColor
, will be rendered into the color buffer
* (including alpha).
*
* @param colorWrite Set to true to enable color writing.
*/
public void setColorWrite(boolean colorWrite) {
applyColorWrite = true;
this.colorWrite = colorWrite;
cachedHashCode = -1;
}
/**
* Set the face culling mode.
*
*
See the {@link FaceCullMode} enum on what each value does.
* Face culling will project the triangle's points onto the screen
* and determine if the triangle is in counter-clockwise order or
* clockwise order. If a triangle is in counter-clockwise order, then
* it is considered a front-facing triangle, otherwise, it is considered
* a back-facing triangle.
*
* @param cullMode the face culling mode.
*/
public void setFaceCullMode(FaceCullMode cullMode) {
applyCullMode = true;
this.cullMode = cullMode;
cachedHashCode = -1;
}
/**
* Set the blending mode.
*
*
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 operation is determined
* by the {@link BlendMode}. For example, the {@link BlendMode#Additive}
* will add the input pixel's color to the color already in the color buffer:
*
* Result = Source Color + Destination Color
*
* @param blendMode The blend mode to use. Set to {@link BlendMode#Off}
* to disable blending.
*/
public void setBlendMode(BlendMode blendMode) {
applyBlendMode = true;
this.blendMode = blendMode;
cachedHashCode = -1;
}
/**
* Set the blending equation.
*
* 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:
*
* 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
*
* @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.
*
* 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:
*
* 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
*
* @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.
*
*
When depth testing is enabled, a pixel must pass the depth test
* before it is written to the color buffer.
* The input pixel's depth value must be less than or equal than
* the value already in the depth buffer to pass the depth test.
*
* @param depthTest Enable or disable depth testing.
*/
public void setDepthTest(boolean depthTest) {
applyDepthTest = true;
this.depthTest = depthTest;
cachedHashCode = -1;
}
/**
* Enable depth writing.
*
*
After passing the {@link RenderState#setDepthTest(boolean) depth test},
* a pixel's depth value will be written into the depth buffer if
* depth writing is enabled.
*
* @param depthWrite True to enable writing to the depth buffer.
*/
public void setDepthWrite(boolean depthWrite) {
applyDepthWrite = true;
this.depthWrite = depthWrite;
cachedHashCode = -1;
}
/**
* Enables wireframe rendering mode.
*
*
When in wireframe mode, {@link Mesh meshes} rendered in triangle mode
* will not be solid, but instead, only the edges of the triangles
* will be rendered.
*
* @param wireframe True to enable wireframe mode.
*/
public void setWireframe(boolean wireframe) {
applyWireFrame = true;
this.wireframe = wireframe;
cachedHashCode = -1;
}
/**
* Offsets the on-screen z-order of the material's polygons, to combat visual artefacts like
* stitching, bleeding and z-fighting for overlapping polygons.
* Factor and units are summed to produce the depth offset.
* This offset is applied in screen space,
* typically with positive Z pointing into the screen.
* Typical values are (1.0f, 1.0f) or (-1.0f, -1.0f)
*
* @see http://www.opengl.org/resources/faq/technical/polygonoffset.htm
* @param factor scales the maximum Z slope, with respect to X or Y of the polygon
* @param units scales the minimum resolvable depth buffer value
**/
public void setPolyOffset(float factor, float units) {
applyPolyOffset = true;
if (factor == 0 && units == 0) {
offsetEnabled = false;
} else {
offsetEnabled = true;
offsetFactor = factor;
offsetUnits = units;
}
cachedHashCode = -1;
}
/**
* Enable stencil testing.
*
*
Stencil testing can be used to filter pixels according to the stencil
* buffer. Objects can be rendered with some stencil operation to manipulate
* the values in the stencil buffer, then, other objects can be rendered
* to test against the values written previously.
*
* @param enabled Set to true to enable stencil functionality. If false
* all other parameters are ignored.
*
* @param _frontStencilStencilFailOperation Sets the operation to occur when
* a front-facing triangle fails the front stencil function.
* @param _frontStencilDepthFailOperation Sets the operation to occur when
* a front-facing triangle fails the depth test.
* @param _frontStencilDepthPassOperation Set the operation to occur when
* a front-facing triangle passes the depth test.
* @param _backStencilStencilFailOperation Set the operation to occur when
* a back-facing triangle fails the back stencil function.
* @param _backStencilDepthFailOperation Set the operation to occur when
* a back-facing triangle fails the depth test.
* @param _backStencilDepthPassOperation Set the operation to occur when
* a back-facing triangle passes the depth test.
* @param _frontStencilFunction Set the test function for front-facing triangles.
* @param _backStencilFunction Set the test function for back-facing triangles.
*/
public void setStencil(boolean enabled,
StencilOperation _frontStencilStencilFailOperation,
StencilOperation _frontStencilDepthFailOperation,
StencilOperation _frontStencilDepthPassOperation,
StencilOperation _backStencilStencilFailOperation,
StencilOperation _backStencilDepthFailOperation,
StencilOperation _backStencilDepthPassOperation,
TestFunction _frontStencilFunction,
TestFunction _backStencilFunction) {
stencilTest = enabled;
applyStencilTest = true;
this.frontStencilStencilFailOperation = _frontStencilStencilFailOperation;
this.frontStencilDepthFailOperation = _frontStencilDepthFailOperation;
this.frontStencilDepthPassOperation = _frontStencilDepthPassOperation;
this.backStencilStencilFailOperation = _backStencilStencilFailOperation;
this.backStencilDepthFailOperation = _backStencilDepthFailOperation;
this.backStencilDepthPassOperation = _backStencilDepthPassOperation;
this.frontStencilFunction = _frontStencilFunction;
this.backStencilFunction = _backStencilFunction;
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;
}
/**
* @deprecated
*/
@Deprecated
public void setAlphaFunc(TestFunction alphaFunc) {
}
/**
* Sets the mesh line width.
* This is to use in conjunction with {@link #setWireframe(boolean)} or with a mesh in {@link Mesh.Mode#Lines} mode.
* @param lineWidth the line width.
*/
public void setLineWidth(float lineWidth) {
if (lineWidth < 1f) {
throw new IllegalArgumentException("lineWidth must be greater than or equal to 1.0");
}
this.lineWidth = lineWidth;
this.applyLineWidth = true;
cachedHashCode = -1;
}
/**
* Check if stencil test is enabled.
*
* @return True if stencil test is enabled.
*/
public boolean isStencilTest() {
return stencilTest;
}
/**
* Retrieve the front stencil fail operation.
*
* @return the front stencil fail operation.
*
* @see RenderState#setStencil(boolean,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.TestFunction,
* com.jme3.material.RenderState.TestFunction)
*/
public StencilOperation getFrontStencilStencilFailOperation() {
return frontStencilStencilFailOperation;
}
/**
* Retrieve the front depth test fail operation.
*
* @return the front depth test fail operation.
*
* @see RenderState#setStencil(boolean,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.TestFunction,
* com.jme3.material.RenderState.TestFunction)
*/
public StencilOperation getFrontStencilDepthFailOperation() {
return frontStencilDepthFailOperation;
}
/**
* Retrieve the front depth test pass operation.
*
* @return the front depth test pass operation.
*
* @see RenderState#setStencil(boolean,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.TestFunction,
* com.jme3.material.RenderState.TestFunction)
*/
public StencilOperation getFrontStencilDepthPassOperation() {
return frontStencilDepthPassOperation;
}
/**
* Retrieve the back stencil fail operation.
*
* @return the back stencil fail operation.
*
* @see RenderState#setStencil(boolean,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.TestFunction,
* com.jme3.material.RenderState.TestFunction)
*/
public StencilOperation getBackStencilStencilFailOperation() {
return backStencilStencilFailOperation;
}
/**
* Retrieve the back depth test fail operation.
*
* @return the back depth test fail operation.
*
* @see RenderState#setStencil(boolean,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.TestFunction,
* com.jme3.material.RenderState.TestFunction)
*/
public StencilOperation getBackStencilDepthFailOperation() {
return backStencilDepthFailOperation;
}
/**
* Retrieve the back depth test pass operation.
*
* @return the back depth test pass operation.
*
* @see RenderState#setStencil(boolean,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.TestFunction,
* com.jme3.material.RenderState.TestFunction)
*/
public StencilOperation getBackStencilDepthPassOperation() {
return backStencilDepthPassOperation;
}
/**
* Retrieve the front stencil function.
*
* @return the front stencil function.
*
* @see RenderState#setStencil(boolean,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.TestFunction,
* com.jme3.material.RenderState.TestFunction)
*/
public TestFunction getFrontStencilFunction() {
return frontStencilFunction;
}
/**
* Retrieve the back stencil function.
*
* @return the back stencil function.
*
* @see RenderState#setStencil(boolean,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.StencilOperation,
* com.jme3.material.RenderState.TestFunction,
* com.jme3.material.RenderState.TestFunction)
*/
public TestFunction getBackStencilFunction() {
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.
*
* @return the blend mode.
*/
public BlendMode getBlendMode() {
return blendMode;
}
/**
* @return true
* @deprecated Always returns true since point sprite is always enabled.
* @see #setPointSprite(boolean)
*/
@Deprecated
public boolean isPointSprite() {
return true;
}
/**
* @deprecated To use alpha test, set the AlphaDiscardThreshold
* material parameter.
* @return false
*/
public boolean isAlphaTest() {
return false;
}
/**
* Retrieve the face cull mode.
*
* @return the face cull mode.
*
* @see RenderState#setFaceCullMode(com.jme3.material.RenderState.FaceCullMode)
*/
public FaceCullMode getFaceCullMode() {
return cullMode;
}
/**
* Check if depth test is enabled.
*
* @return True if depth test is enabled.
*
* @see RenderState#setDepthTest(boolean)
*/
public boolean isDepthTest() {
return depthTest;
}
/**
* Check if depth write is enabled.
*
* @return True if depth write is enabled.
*
* @see RenderState#setDepthWrite(boolean)
*/
public boolean isDepthWrite() {
return depthWrite;
}
/**
* Check if wireframe mode is enabled.
*
* @return True if wireframe mode is enabled.
*
* @see RenderState#setWireframe(boolean)
*/
public boolean isWireframe() {
return wireframe;
}
/**
* Check if color writing is enabled.
*
* @return True if color writing is enabled.
*
* @see RenderState#setColorWrite(boolean)
*/
public boolean isColorWrite() {
return colorWrite;
}
/**
* Retrieve the poly offset factor value.
*
* @return the poly offset factor value.
*
* @see RenderState#setPolyOffset(float, float)
*/
public float getPolyOffsetFactor() {
return offsetFactor;
}
/**
* Retrieve the poly offset units value.
*
* @return the poly offset units value.
*
* @see RenderState#setPolyOffset(float, float)
*/
public float getPolyOffsetUnits() {
return offsetUnits;
}
/**
* Check if polygon offset is enabled.
*
* @return True if polygon offset is enabled.
*
* @see RenderState#setPolyOffset(float, float)
*/
public boolean isPolyOffset() {
return offsetEnabled;
}
/**
* @return 0
* @deprecated
*/
@Deprecated
public float getAlphaFallOff() {
return 0f;
}
/**
* Retrieve the depth comparison function
*
* @return the depth comparison function
*
* @see RenderState#setDepthFunc(com.jme3.material.RenderState.TestFunction)
*/
public TestFunction getDepthFunc() {
return depthFunc;
}
/**
* @return {@link TestFunction#Greater}.
* @deprecated
*/
@Deprecated
public TestFunction getAlphaFunc() {
return TestFunction.Greater;
}
/**
* returns the wireframe line width
*
* @return the line width
*/
public float getLineWidth() {
return lineWidth;
}
public boolean isApplyBlendMode() {
return applyBlendMode;
}
public boolean isApplyBlendEquation() {
return applyBlendEquation;
}
public boolean isApplyBlendEquationAlpha() {
return applyBlendEquationAlpha;
}
public boolean isApplyColorWrite() {
return applyColorWrite;
}
public boolean isApplyCullMode() {
return applyCullMode;
}
public boolean isApplyDepthTest() {
return applyDepthTest;
}
public boolean isApplyDepthWrite() {
return applyDepthWrite;
}
public boolean isApplyPolyOffset() {
return applyPolyOffset;
}
public boolean isApplyWireFrame() {
return applyWireFrame;
}
public boolean isApplyDepthFunc() {
return applyDepthFunc;
}
public boolean isApplyLineWidth() {
return applyLineWidth;
}
/**
*
*/
public int contentHashCode() {
if (cachedHashCode == -1){
int hash = 7;
hash = 79 * hash + (this.wireframe ? 1 : 0);
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.blendEquation != null ? this.blendEquation.hashCode() : 0);
hash = 79 * hash + (this.blendEquationAlpha != null ? this.blendEquationAlpha.hashCode() : 0);
hash = 79 * hash + Float.floatToIntBits(this.offsetFactor);
hash = 79 * hash + Float.floatToIntBits(this.offsetUnits);
hash = 79 * hash + (this.offsetEnabled ? 1 : 0);
hash = 79 * hash + (this.stencilTest ? 1 : 0);
hash = 79 * hash + (this.frontStencilStencilFailOperation != null ? this.frontStencilStencilFailOperation.hashCode() : 0);
hash = 79 * hash + (this.frontStencilDepthFailOperation != null ? this.frontStencilDepthFailOperation.hashCode() : 0);
hash = 79 * hash + (this.frontStencilDepthPassOperation != null ? this.frontStencilDepthPassOperation.hashCode() : 0);
hash = 79 * hash + (this.backStencilStencilFailOperation != null ? this.backStencilStencilFailOperation.hashCode() : 0);
hash = 79 * hash + (this.backStencilDepthFailOperation != null ? this.backStencilDepthFailOperation.hashCode() : 0);
hash = 79 * hash + (this.backStencilDepthPassOperation != null ? this.backStencilDepthPassOperation.hashCode() : 0);
hash = 79 * hash + (this.frontStencilFunction != null ? this.frontStencilFunction.hashCode() : 0);
hash = 79 * hash + (this.backStencilFunction != null ? this.backStencilFunction.hashCode() : 0);
hash = 79 * hash + Float.floatToIntBits(this.lineWidth);
cachedHashCode = hash;
}
return cachedHashCode;
}
/**
* Merges this
state and additionalState
into
* the parameter state
based on a specific criteria.
*
*
The criteria for this merge is the following:
* For every given property, such as alpha test or depth write, check
* if it was modified from the original in the additionalState
* if it was modified, then copy the property from the additionalState
* into the parameter state
, otherwise, copy the property from this
* into the parameter state
. If additionalState
* is null
, then no modifications are made and this
is returned,
* otherwise, the parameter state
is returned with the result
* of the merge.
*
* @param additionalState The additionalState
, from which data is taken only
* if it was modified by the user.
* @param state Contains output of the method if additionalState
* is not null.
* @return state
if additionalState
is non-null,
* otherwise returns this
*/
public RenderState copyMergedTo(RenderState additionalState, RenderState state) {
if (additionalState == null) {
return this;
}
if (additionalState.applyWireFrame) {
state.wireframe = additionalState.wireframe;
} else {
state.wireframe = wireframe;
}
if (additionalState.applyCullMode) {
state.cullMode = additionalState.cullMode;
} else {
state.cullMode = cullMode;
}
if (additionalState.applyDepthWrite) {
state.depthWrite = additionalState.depthWrite;
} else {
state.depthWrite = depthWrite;
}
if (additionalState.applyDepthTest) {
state.depthTest = additionalState.depthTest;
} else {
state.depthTest = depthTest;
}
if (additionalState.applyDepthFunc) {
state.depthFunc = additionalState.depthFunc;
} else {
state.depthFunc = depthFunc;
}
if (additionalState.applyColorWrite) {
state.colorWrite = additionalState.colorWrite;
} 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;
} else {
state.blendMode = blendMode;
}
if (additionalState.applyPolyOffset) {
state.offsetEnabled = additionalState.offsetEnabled;
state.offsetFactor = additionalState.offsetFactor;
state.offsetUnits = additionalState.offsetUnits;
} else {
state.offsetEnabled = offsetEnabled;
state.offsetFactor = offsetFactor;
state.offsetUnits = offsetUnits;
}
if (additionalState.applyStencilTest) {
state.stencilTest = additionalState.stencilTest;
state.frontStencilStencilFailOperation = additionalState.frontStencilStencilFailOperation;
state.frontStencilDepthFailOperation = additionalState.frontStencilDepthFailOperation;
state.frontStencilDepthPassOperation = additionalState.frontStencilDepthPassOperation;
state.backStencilStencilFailOperation = additionalState.backStencilStencilFailOperation;
state.backStencilDepthFailOperation = additionalState.backStencilDepthFailOperation;
state.backStencilDepthPassOperation = additionalState.backStencilDepthPassOperation;
state.frontStencilFunction = additionalState.frontStencilFunction;
state.backStencilFunction = additionalState.backStencilFunction;
} else {
state.stencilTest = stencilTest;
state.frontStencilStencilFailOperation = frontStencilStencilFailOperation;
state.frontStencilDepthFailOperation = frontStencilDepthFailOperation;
state.frontStencilDepthPassOperation = frontStencilDepthPassOperation;
state.backStencilStencilFailOperation = backStencilStencilFailOperation;
state.backStencilDepthFailOperation = backStencilDepthFailOperation;
state.backStencilDepthPassOperation = backStencilDepthPassOperation;
state.frontStencilFunction = frontStencilFunction;
state.backStencilFunction = backStencilFunction;
}
if (additionalState.applyLineWidth) {
state.lineWidth = additionalState.lineWidth;
} else {
state.lineWidth = lineWidth;
}
state.cachedHashCode = -1;
return state;
}
public void set(RenderState state) {
wireframe = state.wireframe;
cullMode = state.cullMode;
depthWrite = state.depthWrite;
depthTest = state.depthTest;
colorWrite = state.colorWrite;
blendMode = state.blendMode;
offsetEnabled = state.offsetEnabled;
offsetFactor = state.offsetFactor;
offsetUnits = state.offsetUnits;
stencilTest = state.stencilTest;
frontStencilStencilFailOperation = state.frontStencilStencilFailOperation;
frontStencilDepthFailOperation = state.frontStencilDepthFailOperation;
frontStencilDepthPassOperation = state.frontStencilDepthPassOperation;
backStencilStencilFailOperation = state.backStencilStencilFailOperation;
backStencilDepthFailOperation = state.backStencilDepthFailOperation;
backStencilDepthPassOperation = state.backStencilDepthPassOperation;
frontStencilFunction = state.frontStencilFunction;
backStencilFunction = state.backStencilFunction;
blendEquationAlpha = state.blendEquationAlpha;
blendEquation = state.blendEquation;
depthFunc = state.depthFunc;
lineWidth = state.lineWidth;
applyWireFrame = true;
applyCullMode = true;
applyDepthWrite = true;
applyDepthTest = true;
applyColorWrite = true;
applyBlendEquation = true;
applyBlendEquationAlpha = true;
applyBlendMode = true;
applyPolyOffset = true;
applyDepthFunc = true;
applyLineWidth = true;
}
@Override
public String toString() {
return "RenderState[\n"
+ "\nwireframe=" + wireframe
+ "\napplyWireFrame=" + applyWireFrame
+ "\ncullMode=" + cullMode
+ "\napplyCullMode=" + applyCullMode
+ "\ndepthWrite=" + depthWrite
+ "\napplyDepthWrite=" + applyDepthWrite
+ "\ndepthTest=" + depthTest
+ "\ndepthFunc=" + depthFunc
+ "\napplyDepthTest=" + applyDepthTest
+ "\ncolorWrite=" + colorWrite
+ "\napplyColorWrite=" + applyColorWrite
+ "\nblendEquation=" + blendEquation
+ "\napplyBlendEquation=" + applyBlendEquation
+ "\napplyBlendEquationAlpha=" + applyBlendEquationAlpha
+ "\nblendMode=" + blendMode
+ "\napplyBlendMode=" + applyBlendMode
+ "\noffsetEnabled=" + offsetEnabled
+ "\napplyPolyOffset=" + applyPolyOffset
+ "\noffsetFactor=" + offsetFactor
+ "\noffsetUnits=" + offsetUnits
+ "\nlineWidth=" + lineWidth
+ "\n]";
}
}