* Deleted StencilFunction and replaced it with TestFunction (in case it will be used in more than one place)

* RenderContext.reset() now properly resets stencil render state.
 * Added full javadoc to RenderState

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@7581 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
sha..rd 14 years ago
parent 87116ba4bc
commit dce2dd2eb1
  1. 743
      engine/src/core/com/jme3/material/RenderState.java
  2. 15
      engine/src/core/com/jme3/renderer/RenderContext.java
  3. 40
      engine/src/lwjgl-ogl/com/jme3/renderer/lwjgl/LwjglRenderer.java

@ -36,26 +36,100 @@ import com.jme3.export.JmeImporter;
import com.jme3.export.InputCapsule; import com.jme3.export.InputCapsule;
import com.jme3.export.OutputCapsule; import com.jme3.export.OutputCapsule;
import com.jme3.export.Savable; import com.jme3.export.Savable;
import com.jme3.scene.Mesh;
import java.io.IOException; import java.io.IOException;
/**
* <code>RenderState</code> 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 { public class RenderState implements Cloneable, Savable {
/**
* The <code>DEFAULT</code> render state is the one used by default
* on all materials unless changed otherwise by the user.
*
* <p>
* It has the following properties:
* <ul>
* <li>Back Face Culling</li>
* <li>Depth Testing Enabled</li>
* <li>Depth Writing Enabled</li>
* </ul>
*/
public static final RenderState DEFAULT = new RenderState(); public static final RenderState DEFAULT = new RenderState();
/**
* The <code>NULL</code> 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(); public static final RenderState NULL = new RenderState();
/**
* The <code>ADDITIONAL</code> render state is identical to the
* {@link RenderState#DEFAULT} render state except that all apply
* values are set to false. This allows the <code>ADDITIONAL</code> 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(); public static final RenderState ADDITIONAL = new RenderState();
public enum TestFunc { /**
* <code>TestFunction</code> specifies the testing function for stencil test
* function and alpha test function.
*
* <p>The functions work similarly as described except that 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, Never,
/**
* The test succeeds if the input value is equal to the reference value.
*/
Equal, Equal,
/**
* The test succeeds if the input value is less than the reference value.
*/
Less, Less,
/**
* The test succeeds if the input value is less than or equal to
* the reference value.
*/
LessOrEqual, LessOrEqual,
/**
* The test succeeds if the input value is greater than the reference value.
*/
Greater, Greater,
/**
* The test succeeds if the input value is greater than or equal to
* the reference value.
*/
GreaterOrEqual, GreaterOrEqual,
/**
* The test succeeds if the input value does not equal the
* reference value.
*/
NotEqual, NotEqual,
Always, /**
} * The test always passes
*/
Always,}
/**
* <code>BlendMode</code> specifies the blending operation to use.
*
* @see RenderState#setBlendMode(com.jme3.material.RenderState.BlendMode)
*/
public enum BlendMode { public enum BlendMode {
/** /**
@ -64,52 +138,57 @@ public class RenderState implements Cloneable, Savable {
Off, Off,
/** /**
* Additive blending. For use with glows and particle emitters. * Additive blending. For use with glows and particle emitters.
* * <p>
* Result = Source Color + Destination Color * Result = Source Color + Destination Color
*/ */
Additive, Additive,
/** /**
* Premultiplied alpha blending, for use with premult alpha textures. * Premultiplied alpha blending, for use with premult alpha textures.
* * <p>
* Result = Source Color + (Dest Color * 1 - Source Alpha) * Result = Source Color + (Dest Color * (1 - Source Alpha) )
*/ */
PremultAlpha, PremultAlpha,
/** /**
* Additive blending that is multiplied with source alpha. * Additive blending that is multiplied with source alpha.
* For use with glows and particle emitters. * For use with glows and particle emitters.
* * <p>
* Result = (Source Alpha * Source Color) + Dest Color * Result = (Source Alpha * Source Color) + Dest Color
*/ */
AlphaAdditive, AlphaAdditive,
/** /**
* Color blending, blends in color from dest color * Color blending, blends in color from dest color
* using source color. * using source color.
* * <p>
* Result = Source Color + (1 - Source Color) * Dest Color * Result = Source Color + (1 - Source Color) * Dest Color
*/ */
Color, Color,
/** /**
* Alpha blending, interpolates to source color from dest color * Alpha blending, interpolates to source color from dest color
* using source alpha. * using source alpha.
* * <p>
* Result = Source Alpha * Source Color + * Result = Source Alpha * Source Color +
* (1 - Source Alpha) * Dest Color * (1 - Source Alpha) * Dest Color
*/ */
Alpha, Alpha,
/** /**
* Multiplies the source and dest colors. * Multiplies the source and dest colors.
* * <p>
* Result = Source Color * Dest Color * Result = Source Color * Dest Color
*/ */
Modulate, Modulate,
/** /**
* Multiplies the source and dest colors then doubles the result. * Multiplies the source and dest colors then doubles the result.
* * <p>
* Result = 2 * Source Color * Dest Color * Result = 2 * Source Color * Dest Color
*/ */
ModulateX2 ModulateX2
} }
/**
* <code>FaceCullMode</code> specifies the criteria for faces to be culled.
*
* @see RenderState#setFaceCullMode(com.jme3.material.RenderState.FaceCullMode)
*/
public enum FaceCullMode { public enum FaceCullMode {
/** /**
@ -130,27 +209,58 @@ public class RenderState implements Cloneable, Savable {
FrontAndBack FrontAndBack
} }
/**
* <code>StencilOperation</code> 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.StencilFunction,
* com.jme3.material.RenderState.StencilFunction)}
*/
public enum StencilOperation { public enum StencilOperation {
Keep, //keep the current value
Zero, //set the value to 0 /**
Replace, //sets the buffer to * 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,
/**
* Increment the value in the stencil buffer and wrap to 0 when
* reaching the maximum value.
*/
IncrementWrap, IncrementWrap,
/**
* Decrement the value in the stencil buffer and clamp once reaching 0.
*/
Decrement, Decrement,
/**
* Decrement the value in the stencil buffer and wrap to the maximum
* value when reaching 0.
*/
DecrementWrap, DecrementWrap,
Invert
}
public enum StencilFunction { /**
Never, * Does a bitwise invert of the value in the stencil buffer.
Less, */
LessEqual, Invert
Greater,
GreaterEqual,
Equal,
NotEqual,
Always
} }
static { static {
@ -173,35 +283,46 @@ public class RenderState implements Cloneable, Savable {
boolean pointSprite = false; boolean pointSprite = false;
boolean applyPointSprite = true; boolean applyPointSprite = true;
boolean wireframe = false; boolean wireframe = false;
boolean applyWireFrame = true; boolean applyWireFrame = true;
FaceCullMode cullMode = FaceCullMode.Back; FaceCullMode cullMode = FaceCullMode.Back;
boolean applyCullMode = true; boolean applyCullMode = true;
boolean depthWrite = true; boolean depthWrite = true;
boolean applyDepthWrite = true; boolean applyDepthWrite = true;
boolean depthTest = true; boolean depthTest = true;
boolean applyDepthTest = true; boolean applyDepthTest = true;
boolean colorWrite = true; boolean colorWrite = true;
boolean applyColorWrite = true; boolean applyColorWrite = true;
BlendMode blendMode = BlendMode.Off; BlendMode blendMode = BlendMode.Off;
boolean applyBlendMode = true; boolean applyBlendMode = true;
boolean alphaTest = false; boolean alphaTest = false;
boolean applyAlphaTest = true; boolean applyAlphaTest = true;
float alphaFallOff = 0; float alphaFallOff = 0;
boolean applyAlphaFallOff = true; boolean applyAlphaFallOff = true;
boolean offsetEnabled = false;
boolean applyPolyOffset = true;
float offsetFactor = 0; float offsetFactor = 0;
float offsetUnits = 0; float offsetUnits = 0;
boolean offsetEnabled = false;
boolean applyPolyOffset = true;
boolean stencilTest = false; boolean stencilTest = false;
boolean applyStencilTest = false;
StencilOperation frontStencilStencilFailOperation = StencilOperation.Keep; StencilOperation frontStencilStencilFailOperation = StencilOperation.Keep;
StencilOperation frontStencilDepthFailOperation = StencilOperation.Keep; StencilOperation frontStencilDepthFailOperation = StencilOperation.Keep;
StencilOperation frontStencilDepthPassOperation = StencilOperation.Keep; StencilOperation frontStencilDepthPassOperation = StencilOperation.Keep;
StencilOperation backStencilStencilFailOperation = StencilOperation.Keep; StencilOperation backStencilStencilFailOperation = StencilOperation.Keep;
StencilOperation backStencilDepthFailOperation = StencilOperation.Keep; StencilOperation backStencilDepthFailOperation = StencilOperation.Keep;
StencilOperation backStencilDepthPassOperation = StencilOperation.Keep; StencilOperation backStencilDepthPassOperation = StencilOperation.Keep;
StencilFunction frontStencilFunction = StencilFunction.Always; TestFunction frontStencilFunction = TestFunction.Always;
StencilFunction backStencilFunction = StencilFunction.Always; TestFunction backStencilFunction = TestFunction.Always;
public void write(JmeExporter ex) throws IOException { public void write(JmeExporter ex) throws IOException {
OutputCapsule oc = ex.getCapsule(this); OutputCapsule oc = ex.getCapsule(this);
@ -224,8 +345,8 @@ public class RenderState implements Cloneable, Savable {
oc.write(backStencilStencilFailOperation, "frontStencilStencilFailOperation", StencilOperation.Keep); oc.write(backStencilStencilFailOperation, "frontStencilStencilFailOperation", StencilOperation.Keep);
oc.write(backStencilDepthFailOperation, "backStencilDepthFailOperation", StencilOperation.Keep); oc.write(backStencilDepthFailOperation, "backStencilDepthFailOperation", StencilOperation.Keep);
oc.write(backStencilDepthPassOperation, "backStencilDepthPassOperation", StencilOperation.Keep); oc.write(backStencilDepthPassOperation, "backStencilDepthPassOperation", StencilOperation.Keep);
oc.write(frontStencilFunction, "frontStencilFunction", StencilFunction.Always); oc.write(frontStencilFunction, "frontStencilFunction", TestFunction.Always);
oc.write(backStencilFunction, "backStencilFunction", StencilFunction.Always); oc.write(backStencilFunction, "backStencilFunction", TestFunction.Always);
} }
public void read(JmeImporter im) throws IOException { public void read(JmeImporter im) throws IOException {
@ -249,10 +370,15 @@ public class RenderState implements Cloneable, Savable {
backStencilStencilFailOperation = ic.readEnum("backStencilStencilFailOperation", StencilOperation.class, StencilOperation.Keep); backStencilStencilFailOperation = ic.readEnum("backStencilStencilFailOperation", StencilOperation.class, StencilOperation.Keep);
backStencilDepthFailOperation = ic.readEnum("backStencilDepthFailOperation", StencilOperation.class, StencilOperation.Keep); backStencilDepthFailOperation = ic.readEnum("backStencilDepthFailOperation", StencilOperation.class, StencilOperation.Keep);
backStencilDepthPassOperation = ic.readEnum("backStencilDepthPassOperation", StencilOperation.class, StencilOperation.Keep); backStencilDepthPassOperation = ic.readEnum("backStencilDepthPassOperation", StencilOperation.class, StencilOperation.Keep);
frontStencilFunction = ic.readEnum("frontStencilFunction", StencilFunction.class, StencilFunction.Always); frontStencilFunction = ic.readEnum("frontStencilFunction", TestFunction.class, TestFunction.Always);
backStencilFunction = ic.readEnum("backStencilFunction", StencilFunction.class, StencilFunction.Always); backStencilFunction = ic.readEnum("backStencilFunction", TestFunction.class, TestFunction.Always);
} }
/**
* Create a clone of this <code>RenderState</code>
*
* @return Clone of this render state.
*/
@Override @Override
public RenderState clone() { public RenderState clone() {
try { try {
@ -262,62 +388,154 @@ public class RenderState implements Cloneable, Savable {
} }
} }
public boolean isPointSprite() { /**
return pointSprite; * Enables point sprite mode.
} *
* <p>When point sprite is enabled, any meshes
* with the type of {@link Mesh#Mode#Points} will be rendered as 2D quads
* with texturing enabled. Fragment shaders can write to the
* <code>gl_PointCoord</code> variable to manipulate the texture coordinate
* for each pixel. The size of the 2D quad can be controlled by writing
* to the <code>gl_PointSize</code> variable in the vertex shader.
*
* @param pointSprite Enables Point Sprite mode.
*/
public void setPointSprite(boolean pointSprite) { public void setPointSprite(boolean pointSprite) {
applyPointSprite = true; applyPointSprite = true;
this.pointSprite = pointSprite; this.pointSprite = pointSprite;
} }
public boolean isColorWrite() { /**
return colorWrite; * Sets the alpha fall off value for alpha testing.
} *
* <p>If the pixel's alpha value is greater than the
public float getPolyOffsetFactor() { * <code>alphaFallOff</code> then the pixel will be rendered, otherwise
return offsetFactor; * the pixel will be discarded.
} *
* @param alphaFallOff The alpha of all rendered pixels must be higher
public float getPolyOffsetUnits() { * than this value to be rendered.
return offsetUnits; *
* @see RenderState#setAlphaTest(boolean)
*/
public void setAlphaFallOff(float alphaFallOff) {
applyAlphaFallOff = true;
this.alphaFallOff = alphaFallOff;
} }
public boolean isPolyOffset() { /**
return offsetEnabled; * Enable alpha testing.
*
* <p>When alpha testing is enabled, all input pixels' alpha are compared
* to the constant alpha falloff. If the input alpha is greater than
* the falloff, the pixel will be rendered, otherwise it will be discarded.
*
* @param alphaTest Set to true to enable alpha testing.
*
* @see RenderState#setAlphaFallOff(float)
*/
public void setAlphaTest(boolean alphaTest) {
applyAlphaTest = true;
this.alphaTest = alphaTest;
} }
public float getAlphaFallOff() { /**
return alphaFallOff; * Enable writing color.
*
* <p>When color write is enabled, the result of a fragment shader, the
* <code>gl_FragColor</code>, 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;
} }
public void setAlphaFallOff(float alphaFallOff) { /**
applyAlphaFallOff = true; * Set the face culling mode.
this.alphaFallOff = alphaFallOff; *
* <p>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;
} }
public boolean isAlphaTest() { /**
return alphaTest; * Set the blending mode.
*
* <p>When blending is enabled, (<code>blendMode</code> is not 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:
* <br/>
* <code>Result = Source Color + Destination Color</code>
*
* @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;
} }
public void setAlphaTest(boolean alphaTest) { /**
applyAlphaTest = true; * Enable depth testing.
this.alphaTest = alphaTest; *
* <p>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;
} }
public FaceCullMode getFaceCullMode() { /**
return cullMode; * Enable depth writing.
*
* <p>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;
} }
public void setColorWrite(boolean colorWrite) { /**
applyColorWrite = true; * Enables wireframe rendering mode.
this.colorWrite = colorWrite; *
* <p>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;
} }
/** /**
* Offsets the on-screen z-order of the material's polygons, to combat visual artefacts like * Offsets the on-screen z-order of the material's polygons, to combat visual artefacts like
* stitching, bleeding and z-fighting for overlapping polygons. * 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, * 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. * typically with positive Z pointing into the screen.
* Typical values are (1.0f, 1.0f) or (-1.0f, -1.0f) * Typical values are (1.0f, 1.0f) or (-1.0f, -1.0f)
* *
@ -332,6 +550,32 @@ public class RenderState implements Cloneable, Savable {
offsetUnits = units; offsetUnits = units;
} }
/**
* Enable stencil testing.
*
* <p>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, public void setStencil(boolean enabled,
StencilOperation _frontStencilStencilFailOperation, StencilOperation _frontStencilStencilFailOperation,
StencilOperation _frontStencilDepthFailOperation, StencilOperation _frontStencilDepthFailOperation,
@ -339,10 +583,11 @@ public class RenderState implements Cloneable, Savable {
StencilOperation _backStencilStencilFailOperation, StencilOperation _backStencilStencilFailOperation,
StencilOperation _backStencilDepthFailOperation, StencilOperation _backStencilDepthFailOperation,
StencilOperation _backStencilDepthPassOperation, StencilOperation _backStencilDepthPassOperation,
StencilFunction _frontStencilFunction, TestFunction _frontStencilFunction,
StencilFunction _backStencilFunction){ TestFunction _backStencilFunction) {
stencilTest = enabled; stencilTest = enabled;
applyStencilTest = true;
this.frontStencilStencilFailOperation = _frontStencilStencilFailOperation; this.frontStencilStencilFailOperation = _frontStencilStencilFailOperation;
this.frontStencilDepthFailOperation = _frontStencilDepthFailOperation; this.frontStencilDepthFailOperation = _frontStencilDepthFailOperation;
this.frontStencilDepthPassOperation = _frontStencilDepthPassOperation; this.frontStencilDepthPassOperation = _frontStencilDepthPassOperation;
@ -353,61 +598,298 @@ public class RenderState implements Cloneable, Savable {
this.backStencilFunction = _backStencilFunction; this.backStencilFunction = _backStencilFunction;
} }
/**
* Check if stencil test is enabled.
*
* @return True if stencil test is enabled.
*/
public boolean isStencilTest() { public boolean isStencilTest() {
return stencilTest; return stencilTest;
} }
public StencilOperation getFrontStencilStencilFailOperation(){ return frontStencilStencilFailOperation; } /**
public StencilOperation getFrontStencilDepthFailOperation(){ return frontStencilDepthFailOperation; } * Retrieve the front stencil fail operation.
public StencilOperation getFrontStencilDepthPassOperation(){ return frontStencilDepthPassOperation; } *
public StencilOperation getBackStencilStencilFailOperation(){ return backStencilStencilFailOperation; } * @return the front stencil fail operation.
public StencilOperation getBackStencilDepthFailOperation(){ return backStencilDepthFailOperation; } *
public StencilOperation getBackStencilDepthPassOperation(){ return backStencilDepthPassOperation; } * @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;
}
public StencilFunction getFrontStencilFunction(){ return frontStencilFunction; } /**
public StencilFunction getBackStencilFunction(){ return backStencilFunction; } * 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;
}
public void setFaceCullMode(FaceCullMode cullMode) { /**
applyCullMode = true; * Retrieve the back stencil fail operation.
this.cullMode = cullMode; *
* @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 mode.
*
* @return the blend mode.
*/
public BlendMode getBlendMode() { public BlendMode getBlendMode() {
return blendMode; return blendMode;
} }
public void setBlendMode(BlendMode blendMode) { /**
applyBlendMode = true; * Check if point sprite mode is enabled
this.blendMode = blendMode; *
* @return True if point sprite mode is enabled.
*
* @see RenderState#setPointSprite(boolean)
*/
public boolean isPointSprite() {
return pointSprite;
} }
public boolean isDepthTest() { /**
return depthTest; * Check if alpha test is enabled.
*
* @return True if alpha test is enabled.
*
* @see RenderState#setAlphaTest(boolean)
*/
public boolean isAlphaTest() {
return alphaTest;
} }
public void setDepthTest(boolean depthTest) { /**
applyDepthTest = true; * Retrieve the face cull mode.
this.depthTest = depthTest; *
* @return the face cull mode.
*
* @see RenderState#setFaceCullMode(com.jme3.material.RenderState.FaceCullMode)
*/
public FaceCullMode getFaceCullMode() {
return cullMode;
} }
public boolean isDepthWrite() { /**
return depthWrite; * Check if depth test is enabled.
*
* @return True if depth test is enabled.
*
* @see RenderState#setDepthTest(boolean)
*/
public boolean isDepthTest() {
return depthTest;
} }
public void setDepthWrite(boolean depthWrite) { /**
applyDepthWrite = true; * Check if depth write is enabled.
this.depthWrite = depthWrite; *
* @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() { public boolean isWireframe() {
return wireframe; return wireframe;
} }
public void setWireframe(boolean wireframe) { /**
applyWireFrame = true; * Check if color writing is enabled.
this.wireframe = wireframe; *
* @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;
} }
/**
* Retrieve the alpha falloff value.
*
* @return the alpha falloff value.
*
* @see RenderState#setAlphaFallOff(float)
*/
public float getAlphaFallOff() {
return alphaFallOff;
}
/*
public boolean isApplyAlphaFallOff() { public boolean isApplyAlphaFallOff() {
return applyAlphaFallOff; return applyAlphaFallOff;
} }
@ -447,73 +929,100 @@ public class RenderState implements Cloneable, Savable {
public boolean isApplyWireFrame() { public boolean isApplyWireFrame() {
return applyWireFrame; return applyWireFrame;
} }
*/
public RenderState copyMergedTo(RenderState additionalState,RenderState state) { /**
* Merges <code>this</code> state and <code>additionalState</code> into
* the parameter <code>state</code> based on a specific criteria.
*
* <p>The criteria for this merge is the following:<br/>
* For every given property, such as alpha test or depth write, check
* if it was modified from the original in the <code>additionalState</code>
* if it was modified, then copy the property from the <code>additionalState</code>
* into the parameter <code>state</code>, otherwise, copy the property from <code>this</code>
* into the parameter <code>state</code>. If <code>additionalState</code>
* is <code>null</code>, then no modifications are made and <code>this</code> is returned,
* otherwise, the parameter <code>state</code> is returned with the result
* of the merge.
*
* @param additionalState The <code>additionalState</code>, from which data is taken only
* if it was modified by the user.
* @param state Contains output of the method if <code>additionalState</code>
* is not null.
* @return <code>state</code> if <code>additionalState</code> is non-null,
* otherwise returns <code>this</code>
*/
public RenderState copyMergedTo(RenderState additionalState, RenderState state) {
if (additionalState == null) { if (additionalState == null) {
return this; return this;
} }
if (additionalState.isApplyPointSprite()) { if (additionalState.applyPointSprite) {
state.pointSprite = additionalState.pointSprite; state.pointSprite = additionalState.pointSprite;
}else{ } else {
state.pointSprite = pointSprite; state.pointSprite = pointSprite;
} }
if (additionalState.isApplyWireFrame()) { if (additionalState.applyWireFrame) {
state.wireframe = additionalState.wireframe; state.wireframe = additionalState.wireframe;
}else{ } else {
state.wireframe = wireframe; state.wireframe = wireframe;
} }
if (additionalState.isApplyCullMode()) { if (additionalState.applyCullMode) {
state.cullMode = additionalState.cullMode; state.cullMode = additionalState.cullMode;
}else{ } else {
state.cullMode = cullMode; state.cullMode = cullMode;
} }
if (additionalState.isApplyDepthWrite()) { if (additionalState.applyDepthWrite) {
state.depthWrite = additionalState.depthWrite; state.depthWrite = additionalState.depthWrite;
}else{ } else {
state.depthWrite = depthWrite; state.depthWrite = depthWrite;
} }
if (additionalState.isApplyDepthTest()) { if (additionalState.applyDepthTest) {
state.depthTest = additionalState.depthTest; state.depthTest = additionalState.depthTest;
}else{ } else {
state.depthTest = depthTest; state.depthTest = depthTest;
} }
if (additionalState.isApplyColorWrite()) { if (additionalState.applyColorWrite) {
state.colorWrite = additionalState.colorWrite; state.colorWrite = additionalState.colorWrite;
}else{ } else {
state.colorWrite = colorWrite; state.colorWrite = colorWrite;
} }
if (additionalState.isApplyBlendMode()) { if (additionalState.applyBlendMode) {
state.blendMode = additionalState.blendMode; state.blendMode = additionalState.blendMode;
}else{ } else {
state.blendMode = blendMode; state.blendMode = blendMode;
} }
if (additionalState.isApplyAlphaTest()) { if (additionalState.applyAlphaTest) {
state.alphaTest = additionalState.alphaTest; state.alphaTest = additionalState.alphaTest;
}else{ } else {
state.alphaTest = alphaTest; state.alphaTest = alphaTest;
} }
if (additionalState.isApplyAlphaFallOff()) { if (additionalState.applyAlphaFallOff) {
state.alphaFallOff = additionalState.alphaFallOff; state.alphaFallOff = additionalState.alphaFallOff;
}else{ } else {
state.alphaFallOff = alphaFallOff; state.alphaFallOff = alphaFallOff;
} }
if (additionalState.isApplyPolyOffset()) { if (additionalState.applyPolyOffset) {
state.offsetEnabled = additionalState.offsetEnabled; state.offsetEnabled = additionalState.offsetEnabled;
state.offsetFactor = additionalState.offsetFactor; state.offsetFactor = additionalState.offsetFactor;
state.offsetUnits = additionalState.offsetUnits; state.offsetUnits = additionalState.offsetUnits;
}else{ } else {
state.offsetEnabled = offsetEnabled; state.offsetEnabled = offsetEnabled;
state.offsetFactor = offsetFactor; state.offsetFactor = offsetFactor;
state.offsetUnits = offsetUnits; state.offsetUnits = offsetUnits;
} }
if (additionalState.applyStencilTest){
state.stencilTest = additionalState.stencilTest;
}else{
state.stencilTest = stencilTest;
}
return state; return state;
} }
@Override @Override
public String toString() { public String toString() {
return "RenderState{" + "pointSprite=" + pointSprite + "applyPointSprite=" + applyPointSprite + "wireframe=" + wireframe + "applyWireFrame=" + applyWireFrame + "cullMode=" + cullMode + "applyCullMode=" + applyCullMode + "depthWrite=" + depthWrite + "applyDepthWrite=" + applyDepthWrite + "depthTest=" + depthTest + "applyDepthTest=" + applyDepthTest + "colorWrite=" + colorWrite + "applyColorWrite=" + applyColorWrite + "blendMode=" + blendMode + "applyBlendMode=" + applyBlendMode + "alphaTest=" + alphaTest + "applyAlphaTest=" + applyAlphaTest + "alphaFallOff=" + alphaFallOff + "applyAlphaFallOff=" + applyAlphaFallOff + "offsetEnabled=" + offsetEnabled + "applyPolyOffset=" + applyPolyOffset + "offsetFactor=" + offsetFactor + "offsetUnits=" + offsetUnits + '}'; return "RenderState[" + "pointSprite=" + pointSprite + "applyPointSprite=" + applyPointSprite + "wireframe=" + wireframe + "applyWireFrame=" + applyWireFrame + "cullMode=" + cullMode + "applyCullMode=" + applyCullMode + "depthWrite=" + depthWrite + "applyDepthWrite=" + applyDepthWrite + "depthTest=" + depthTest + "applyDepthTest=" + applyDepthTest + "colorWrite=" + colorWrite + "applyColorWrite=" + applyColorWrite + "blendMode=" + blendMode + "applyBlendMode=" + applyBlendMode + "alphaTest=" + alphaTest + "applyAlphaTest=" + applyAlphaTest + "alphaFallOff=" + alphaFallOff + "applyAlphaFallOff=" + applyAlphaFallOff + "offsetEnabled=" + offsetEnabled + "applyPolyOffset=" + applyPolyOffset + "offsetFactor=" + offsetFactor + "offsetUnits=" + offsetUnits + ']';
} }
} }

@ -35,7 +35,6 @@ package com.jme3.renderer;
import com.jme3.material.RenderState; import com.jme3.material.RenderState;
import com.jme3.scene.VertexBuffer; import com.jme3.scene.VertexBuffer;
import com.jme3.texture.Image; import com.jme3.texture.Image;
import com.jme3.texture.Texture;
/** /**
* Represents the current state of the graphics library. This class is used * Represents the current state of the graphics library. This class is used
@ -149,8 +148,8 @@ public class RenderContext {
public RenderState.StencilOperation backStencilStencilFailOperation = RenderState.StencilOperation.Keep; public RenderState.StencilOperation backStencilStencilFailOperation = RenderState.StencilOperation.Keep;
public RenderState.StencilOperation backStencilDepthFailOperation = RenderState.StencilOperation.Keep; public RenderState.StencilOperation backStencilDepthFailOperation = RenderState.StencilOperation.Keep;
public RenderState.StencilOperation backStencilDepthPassOperation = RenderState.StencilOperation.Keep; public RenderState.StencilOperation backStencilDepthPassOperation = RenderState.StencilOperation.Keep;
public RenderState.StencilFunction frontStencilFunction = RenderState.StencilFunction.Always; public RenderState.TestFunction frontStencilFunction = RenderState.TestFunction.Always;
public RenderState.StencilFunction backStencilFunction = RenderState.StencilFunction.Always; public RenderState.TestFunction backStencilFunction = RenderState.TestFunction.Always;
/** /**
* Vertex attribs currently bound and enabled. If a slot is null, then * Vertex attribs currently bound and enabled. If a slot is null, then
@ -193,5 +192,15 @@ public class RenderContext {
boundAttribs[i] = null; boundAttribs[i] = null;
attribIndexList.reset(); attribIndexList.reset();
stencilTest = false;
frontStencilStencilFailOperation = RenderState.StencilOperation.Keep;
frontStencilDepthFailOperation = RenderState.StencilOperation.Keep;
frontStencilDepthPassOperation = RenderState.StencilOperation.Keep;
backStencilStencilFailOperation = RenderState.StencilOperation.Keep;
backStencilDepthFailOperation = RenderState.StencilOperation.Keep;
backStencilDepthPassOperation = RenderState.StencilOperation.Keep;
frontStencilFunction = RenderState.TestFunction.Always;
backStencilFunction = RenderState.TestFunction.Always;
} }
} }

@ -33,6 +33,8 @@ package com.jme3.renderer.lwjgl;
import com.jme3.light.LightList; import com.jme3.light.LightList;
import com.jme3.material.RenderState; import com.jme3.material.RenderState;
import com.jme3.material.RenderState.StencilOperation;
import com.jme3.material.RenderState.TestFunction;
import com.jme3.math.ColorRGBA; import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath; import com.jme3.math.FastMath;
import com.jme3.math.Matrix4f; import com.jme3.math.Matrix4f;
@ -67,6 +69,7 @@ import com.jme3.util.BufferUtils;
import com.jme3.util.IntMap; import com.jme3.util.IntMap;
import com.jme3.util.IntMap.Entry; import com.jme3.util.IntMap.Entry;
import com.jme3.util.ListMap; import com.jme3.util.ListMap;
import java.io.File;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.DoubleBuffer; import java.nio.DoubleBuffer;
import java.nio.FloatBuffer; import java.nio.FloatBuffer;
@ -632,28 +635,27 @@ public class LwjglRenderer implements Renderer {
if (state.isStencilTest()) { if (state.isStencilTest()) {
glEnable(GL_STENCIL_TEST); glEnable(GL_STENCIL_TEST);
glStencilOpSeparate(GL_FRONT, glStencilOpSeparate(GL_FRONT,
glStencilOpFromStencilOp(state.getFrontStencilStencilFailOperation()), convertStencilOperation(state.getFrontStencilStencilFailOperation()),
glStencilOpFromStencilOp(state.getFrontStencilDepthFailOperation()), convertStencilOperation(state.getFrontStencilDepthFailOperation()),
glStencilOpFromStencilOp(state.getFrontStencilDepthPassOperation())); convertStencilOperation(state.getFrontStencilDepthPassOperation()));
glStencilOpSeparate(GL_BACK, glStencilOpSeparate(GL_BACK,
glStencilOpFromStencilOp(state.getBackStencilStencilFailOperation()), convertStencilOperation(state.getBackStencilStencilFailOperation()),
glStencilOpFromStencilOp(state.getBackStencilDepthFailOperation()), convertStencilOperation(state.getBackStencilDepthFailOperation()),
glStencilOpFromStencilOp(state.getBackStencilDepthPassOperation())); convertStencilOperation(state.getBackStencilDepthPassOperation()));
glStencilFuncSeparate(GL_FRONT, glStencilFuncSeparate(GL_FRONT,
glStencilFuncFromStencilFunc(state.getFrontStencilFunction()), convertTestFunction(state.getFrontStencilFunction()),
0, Integer.MAX_VALUE); 0, Integer.MAX_VALUE);
glStencilFuncSeparate(GL_BACK, glStencilFuncSeparate(GL_BACK,
glStencilFuncFromStencilFunc(state.getBackStencilFunction()), convertTestFunction(state.getBackStencilFunction()),
0, Integer.MAX_VALUE); 0, Integer.MAX_VALUE);
} else { } else {
glDisable(GL_STENCIL_TEST); glDisable(GL_STENCIL_TEST);
} }
} }
} }
private int glStencilOpFromStencilOp(RenderState.StencilOperation s) { private int convertStencilOperation(StencilOperation stencilOp) {
switch (s) { switch (stencilOp) {
case Keep: case Keep:
return GL_KEEP; return GL_KEEP;
case Zero: case Zero:
@ -671,21 +673,21 @@ public class LwjglRenderer implements Renderer {
case Invert: case Invert:
return GL_INVERT; return GL_INVERT;
default: default:
throw new UnsupportedOperationException("Unrecognized front stencil operation: " + s); throw new UnsupportedOperationException("Unrecognized stencil operation: " + stencilOp);
} //end switch }
} }
private int glStencilFuncFromStencilFunc(RenderState.StencilFunction s) { private int convertTestFunction(TestFunction testFunc) {
switch (s) { switch (testFunc) {
case Never: case Never:
return GL_NEVER; return GL_NEVER;
case Less: case Less:
return GL_LESS; return GL_LESS;
case LessEqual: case LessOrEqual:
return GL_LEQUAL; return GL_LEQUAL;
case Greater: case Greater:
return GL_GREATER; return GL_GREATER;
case GreaterEqual: case GreaterOrEqual:
return GL_GEQUAL; return GL_GEQUAL;
case Equal: case Equal:
return GL_EQUAL; return GL_EQUAL;
@ -694,8 +696,8 @@ public class LwjglRenderer implements Renderer {
case Always: case Always:
return GL_ALWAYS; return GL_ALWAYS;
default: default:
throw new UnsupportedOperationException("Unrecognized front stencil functin: " + s); throw new UnsupportedOperationException("Unrecognized test function: " + testFunc);
} //end switch }
} }
/*********************************************************************\ /*********************************************************************\

Loading…
Cancel
Save