Fixed the DepthOfFieldFilter to properly get the near/far distance from JME

instead of having it hard-coded.  Previous behavior caused focus to go all out
of whack if you ever changed the near/far plane (and even the default hard-coded
value was not the same as JME's default camera setup.)
While I was here, I made the unfocus threshold configurable and added a debug
toggle that will turn the 'unfocus' amount into grayscale color for better visualizing
where unfocusing is happening.
monkanim
Paul Speed 7 years ago
parent b62fbdbf84
commit 81667f8f45
  1. 57
      jme3-effects/src/main/java/com/jme3/post/filters/DepthOfFieldFilter.java
  2. 16
      jme3-effects/src/main/resources/Common/MatDefs/Post/DepthOfField.frag
  3. 5
      jme3-effects/src/main/resources/Common/MatDefs/Post/DepthOfField.j3md

@ -54,11 +54,14 @@ public class DepthOfFieldFilter extends Filter {
private float focusDistance = 50f; private float focusDistance = 50f;
private float focusRange = 10f; private float focusRange = 10f;
private float blurScale = 1f; private float blurScale = 1f;
private float blurThreshold = 0.2f;
// These values are set internally based on the // These values are set internally based on the
// viewport size. // viewport size.
private float xScale; private float xScale;
private float yScale; private float yScale;
private boolean debugUnfocus;
/** /**
* Creates a DepthOfField filter * Creates a DepthOfField filter
*/ */
@ -83,7 +86,8 @@ public class DepthOfFieldFilter extends Filter {
material = new Material(assets, "Common/MatDefs/Post/DepthOfField.j3md"); material = new Material(assets, "Common/MatDefs/Post/DepthOfField.j3md");
material.setFloat("FocusDistance", focusDistance); material.setFloat("FocusDistance", focusDistance);
material.setFloat("FocusRange", focusRange); material.setFloat("FocusRange", focusRange);
material.setFloat("BlurThreshold", blurThreshold);
material.setBoolean("DebugUnfocus", debugUnfocus);
xScale = 1.0f / w; xScale = 1.0f / w;
yScale = 1.0f / h; yScale = 1.0f / h;
@ -161,13 +165,62 @@ public class DepthOfFieldFilter extends Filter {
return blurScale; return blurScale;
} }
/**
* Sets the minimum blur factor before the convolution filter is
* calculated. The default is 0.2 which means if the "unfocus"
* amount is less than 0.2 (where 0 is no blur and 1.0 is full blurScale)
* then no blur will be applied at all. Depending on the GPU implementation,
* this may be an optimization since it uses branching to skip the expensive
* convolution filter.
*
* <p>In scenes where the focus distance is close (like 0) and the focus range
* is relatively large, this threshold will remove some subtlety in
* the near-camera blurring and should be set smaller than the default
* or to 0 to disable completely. Sometimes that cut-off is desired if
* mid-to-far field unfocusing is all that is desired.</p>
*/
public void setBlurThreshold( float f ) {
this.blurThreshold = f;
if (material != null) {
material.setFloat("BlurThreshold", blurThreshold);
}
}
/**
* returns the blur threshold.
* @return
*/
public float getBlurThreshold() {
return blurThreshold;
}
/**
* Turns on/off debugging of the 'unfocus' value that is used to
* mix the convolution filter. When this is on, the 'unfocus' value
* is rendered as gray scale. This can be used to more easily visualize
* where in your view the focus is centered and how steep the gradient/cutoff
* is, etc..
*/
public void setDebugUnfocus( boolean b ) {
this.debugUnfocus = b;
if( material != null ) {
material.setBoolean("DebugUnfocus", debugUnfocus);
}
}
public boolean getDebugUnfocus() {
return debugUnfocus;
}
@Override @Override
public void write(JmeExporter ex) throws IOException { public void write(JmeExporter ex) throws IOException {
super.write(ex); super.write(ex);
OutputCapsule oc = ex.getCapsule(this); OutputCapsule oc = ex.getCapsule(this);
oc.write(blurScale, "blurScale", 1f); oc.write(blurScale, "blurScale", 1f);
oc.write(blurScale, "blurThreshold", 0.2f);
oc.write(focusDistance, "focusDistance", 50f); oc.write(focusDistance, "focusDistance", 50f);
oc.write(focusRange, "focusRange", 10f); oc.write(focusRange, "focusRange", 10f);
oc.write(debugUnfocus, "debugUnfocus", false); // strange to write this I guess
} }
@Override @Override
@ -175,7 +228,9 @@ public class DepthOfFieldFilter extends Filter {
super.read(im); super.read(im);
InputCapsule ic = im.getCapsule(this); InputCapsule ic = im.getCapsule(this);
blurScale = ic.readFloat("blurScale", 1f); blurScale = ic.readFloat("blurScale", 1f);
blurThreshold = ic.readFloat("blurThreshold", 0.2f);
focusDistance = ic.readFloat("focusDistance", 50f); focusDistance = ic.readFloat("focusDistance", 50f);
focusRange = ic.readFloat("focusRange", 10f); focusRange = ic.readFloat("focusRange", 10f);
debugUnfocus = ic.readBoolean("debugUnfocus", false);
} }
} }

@ -10,7 +10,7 @@ uniform float m_FocusDistance;
uniform float m_XScale; uniform float m_XScale;
uniform float m_YScale; uniform float m_YScale;
vec2 m_NearFar = vec2( 0.1, 1000.0 ); uniform vec2 g_FrustumNearFar;
void main() { void main() {
@ -31,8 +31,8 @@ void main() {
// z * (zb - a) = b // z * (zb - a) = b
// z = b / (zb - a) // z = b / (zb - a)
// //
float a = m_NearFar.y / (m_NearFar.y - m_NearFar.x); float a = g_FrustumNearFar.y / (g_FrustumNearFar.y - g_FrustumNearFar.x);
float b = m_NearFar.y * m_NearFar.x / (m_NearFar.x - m_NearFar.y); float b = g_FrustumNearFar.y * g_FrustumNearFar.x / (g_FrustumNearFar.x - g_FrustumNearFar.y);
float z = b / (zBuffer - a); float z = b / (zBuffer - a);
// Above could be the same for any depth-based filter // Above could be the same for any depth-based filter
@ -42,7 +42,7 @@ void main() {
// at +/- m_FocusRange to either side of that. // at +/- m_FocusRange to either side of that.
float unfocus = min( 1.0, abs( z - m_FocusDistance ) / m_FocusRange ); float unfocus = min( 1.0, abs( z - m_FocusDistance ) / m_FocusRange );
if( unfocus < 0.2 ) { if( unfocus < BLUR_THRESHOLD ) {
// If we are mostly in focus then don't bother with the // If we are mostly in focus then don't bother with the
// convolution filter // convolution filter
gl_FragColor = texVal; gl_FragColor = texVal;
@ -86,7 +86,11 @@ void main() {
gl_FragColor = mix( texVal, sum, unfocus ); gl_FragColor = mix( texVal, sum, unfocus );
// I used this for debugging the range #ifdef DEBUG_UNFOCUS
// gl_FragColor.r = unfocus; // Used for debugging the range or user settings
gl_FragColor.r = unfocus;
gl_FragColor.g = unfocus;
gl_FragColor.b = unfocus;
#endif
} }
} }

@ -9,6 +9,8 @@ MaterialDef Depth Of Field {
Float FocusDistance; Float FocusDistance;
Float XScale; Float XScale;
Float YScale; Float YScale;
Float BlurThreshold : 0.2;
Boolean DebugUnfocus : false;
} }
Technique { Technique {
@ -16,11 +18,14 @@ MaterialDef Depth Of Field {
FragmentShader GLSL150 GLSL100: Common/MatDefs/Post/DepthOfField.frag FragmentShader GLSL150 GLSL100: Common/MatDefs/Post/DepthOfField.frag
WorldParameters { WorldParameters {
FrustumNearFar
} }
Defines { Defines {
RESOLVE_MS : NumSamples RESOLVE_MS : NumSamples
RESOLVE_DEPTH_MS : NumSamplesDepth RESOLVE_DEPTH_MS : NumSamplesDepth
BLUR_THRESHOLD : BlurThreshold
DEBUG_UNFOCUS : DebugUnfocus
} }
} }

Loading…
Cancel
Save