RenderState support for two sided Stencil Buffer operations (in order to support Shadow Volumes in the future)

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@7286 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
jos..om 14 years ago
parent 53f5df5a3f
commit 9cc223c507
  1. 85
      engine/src/core/com/jme3/material/RenderState.java
  2. 13
      engine/src/core/com/jme3/renderer/RenderContext.java
  3. 3
      engine/src/lwjgl-ogl/com/jme3/renderer/lwjgl/LwjglGL1Renderer.java
  4. 93
      engine/src/lwjgl-ogl/com/jme3/renderer/lwjgl/LwjglRenderer.java

@ -130,6 +130,29 @@ public class RenderState implements Cloneable, Savable {
FrontAndBack
}
public enum StencilOperation {
Keep, //keep the current value
Zero, //set the value to 0
Replace, //sets the buffer to
Increment,
IncrementWrap,
Decrement,
DecrementWrap,
Invert
}
public enum StencilFunction {
Never,
Less,
LessEqual,
Greater,
GreaterEqual,
Equal,
NotEqual,
Always
}
static {
NULL.cullMode = FaceCullMode.Off;
NULL.depthTest = false;
@ -170,6 +193,15 @@ public class RenderState implements Cloneable, Savable {
boolean applyPolyOffset = true;
float offsetFactor = 0;
float offsetUnits = 0;
boolean stencilTest = 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;
StencilFunction frontStencilFunction = StencilFunction.Always;
StencilFunction backStencilFunction = StencilFunction.Always;
public void write(JmeExporter ex) throws IOException {
OutputCapsule oc = ex.getCapsule(this);
@ -185,6 +217,15 @@ public class RenderState implements Cloneable, Savable {
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", StencilFunction.Always);
oc.write(backStencilFunction, "backStencilFunction", StencilFunction.Always);
}
public void read(JmeImporter im) throws IOException {
@ -201,6 +242,15 @@ public class RenderState implements Cloneable, Savable {
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", StencilFunction.class, StencilFunction.Always);
backStencilFunction = ic.readEnum("backStencilFunction", StencilFunction.class, StencilFunction.Always);
}
@Override
@ -282,6 +332,41 @@ public class RenderState implements Cloneable, Savable {
offsetUnits = units;
}
public void setStencil(boolean enabled,
StencilOperation _frontStencilStencilFailOperation,
StencilOperation _frontStencilDepthFailOperation,
StencilOperation _frontStencilDepthPassOperation,
StencilOperation _backStencilStencilFailOperation,
StencilOperation _backStencilDepthFailOperation,
StencilOperation _backStencilDepthPassOperation,
StencilFunction _frontStencilFunction,
StencilFunction _backStencilFunction){
stencilTest = enabled;
this.frontStencilStencilFailOperation = _frontStencilStencilFailOperation;
this.frontStencilDepthFailOperation = _frontStencilDepthFailOperation;
this.frontStencilDepthPassOperation = _frontStencilDepthPassOperation;
this.backStencilStencilFailOperation = _backStencilStencilFailOperation;
this.backStencilDepthFailOperation = _backStencilDepthFailOperation;
this.backStencilDepthPassOperation = _backStencilDepthPassOperation;
this.frontStencilFunction = _frontStencilFunction;
this.backStencilFunction = _backStencilFunction;
}
public boolean isStencilTest() {
return stencilTest;
}
public StencilOperation getFrontStencilStencilFailOperation(){ return frontStencilStencilFailOperation; }
public StencilOperation getFrontStencilDepthFailOperation(){ return frontStencilDepthFailOperation; }
public StencilOperation getFrontStencilDepthPassOperation(){ return frontStencilDepthPassOperation; }
public StencilOperation getBackStencilStencilFailOperation(){ return backStencilStencilFailOperation; }
public StencilOperation getBackStencilDepthFailOperation(){ return backStencilDepthFailOperation; }
public StencilOperation getBackStencilDepthPassOperation(){ return backStencilDepthPassOperation; }
public StencilFunction getFrontStencilFunction(){ return frontStencilFunction; }
public StencilFunction getBackStencilFunction(){ return backStencilFunction; }
public void setFaceCullMode(FaceCullMode cullMode) {
applyCullMode = true;
this.cullMode = cullMode;

@ -139,6 +139,19 @@ public class RenderContext {
public int boundTextureUnit = 0;
/**
* Stencil Buffer state
*/
public boolean stencilTest = false;
public RenderState.StencilOperation frontStencilStencilFailOperation = RenderState.StencilOperation.Keep;
public RenderState.StencilOperation frontStencilDepthFailOperation = RenderState.StencilOperation.Keep;
public RenderState.StencilOperation frontStencilDepthPassOperation = RenderState.StencilOperation.Keep;
public RenderState.StencilOperation backStencilStencilFailOperation = RenderState.StencilOperation.Keep;
public RenderState.StencilOperation backStencilDepthFailOperation = RenderState.StencilOperation.Keep;
public RenderState.StencilOperation backStencilDepthPassOperation = RenderState.StencilOperation.Keep;
public RenderState.StencilFunction frontStencilFunction = RenderState.StencilFunction.Always;
public RenderState.StencilFunction backStencilFunction = RenderState.StencilFunction.Always;
/**
* Vertex attribs currently bound and enabled. If a slot is null, then
* it is disabled.

@ -324,6 +324,9 @@ public class LwjglGL1Renderer implements GL1Renderer {
context.blendMode = state.getBlendMode();
}
if(state.isStencilTest())
throw new UnsupportedOperationException("OpenGL 1.1 doesn't support two sided stencil operations.");
}
public void setViewPort(int x, int y, int w, int h) {

@ -471,7 +471,7 @@ public class LwjglRenderer implements Renderer {
if (state.isDepthTest() && !context.depthTestEnabled) {
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glDepthFunc(GL_LESS);
context.depthTestEnabled = true;
} else if (!state.isDepthTest() && context.depthTestEnabled) {
glDisable(GL_DEPTH_TEST);
@ -603,6 +603,97 @@ public class LwjglRenderer implements Renderer {
context.blendMode = state.getBlendMode();
}
if(context.stencilTest!=state.isStencilTest()
|| context.frontStencilStencilFailOperation!=state.getFrontStencilStencilFailOperation()
|| context.frontStencilDepthFailOperation!=state.getFrontStencilDepthFailOperation()
|| context.frontStencilDepthPassOperation!=state.getFrontStencilDepthPassOperation()
|| context.backStencilStencilFailOperation!=state.getBackStencilStencilFailOperation()
|| context.backStencilDepthFailOperation!=state.getBackStencilDepthFailOperation()
|| context.backStencilDepthPassOperation!=state.getBackStencilDepthPassOperation()
|| context.frontStencilFunction!=state.getFrontStencilFunction()
|| context.backStencilFunction!=state.getBackStencilFunction()
){
context.frontStencilStencilFailOperation=state.getFrontStencilStencilFailOperation(); //terrible looking, I know
context.frontStencilDepthFailOperation=state.getFrontStencilDepthFailOperation();
context.frontStencilDepthPassOperation=state.getFrontStencilDepthPassOperation();
context.backStencilStencilFailOperation=state.getBackStencilStencilFailOperation();
context.backStencilDepthFailOperation=state.getBackStencilDepthFailOperation();
context.backStencilDepthPassOperation=state.getBackStencilDepthPassOperation();
context.frontStencilFunction=state.getFrontStencilFunction();
context.backStencilFunction=state.getBackStencilFunction();
if(state.isStencilTest()){
glEnable(GL_STENCIL_TEST);
glStencilOpSeparate(GL_FRONT,
glStencilOpFromStencilOp(state.getFrontStencilStencilFailOperation()),
glStencilOpFromStencilOp(state.getFrontStencilDepthFailOperation()),
glStencilOpFromStencilOp(state.getFrontStencilDepthPassOperation())
);
glStencilOpSeparate(GL_BACK,
glStencilOpFromStencilOp(state.getBackStencilStencilFailOperation()),
glStencilOpFromStencilOp(state.getBackStencilDepthFailOperation()),
glStencilOpFromStencilOp(state.getBackStencilDepthPassOperation())
);
glStencilFuncSeparate(GL_FRONT,
glStencilFuncFromStencilFunc(state.getFrontStencilFunction()),
0,Integer.MAX_VALUE
);
glStencilFuncSeparate(GL_BACK,
glStencilFuncFromStencilFunc(state.getBackStencilFunction()),
0,Integer.MAX_VALUE
);
}else{
glDisable(GL_STENCIL_TEST);
}
}
}
private int glStencilOpFromStencilOp(RenderState.StencilOperation s){
switch(s){
case Keep:
return GL_KEEP;
case Zero:
return GL_ZERO;
case Replace:
return GL_REPLACE;
case Increment:
return GL_INCR;
case IncrementWrap:
return GL_INCR_WRAP;
case Decrement:
return GL_DECR;
case DecrementWrap:
return GL_DECR_WRAP;
case Invert:
return GL_INVERT;
default:
throw new UnsupportedOperationException("Unrecognized front stencil operation: " + s);
} //end switch
}
private int glStencilFuncFromStencilFunc(RenderState.StencilFunction s){
switch(s){
case Never:
return GL_NEVER;
case Less:
return GL_LESS;
case LessEqual:
return GL_LEQUAL;
case Greater:
return GL_GREATER;
case GreaterEqual:
return GL_GEQUAL;
case Equal:
return GL_EQUAL;
case NotEqual:
return GL_NOTEQUAL;
case Always:
return GL_ALWAYS;
default:
throw new UnsupportedOperationException("Unrecognized front stencil functin: " + s);
} //end switch
}
/*********************************************************************\

Loading…
Cancel
Save