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. 18
      jme3-effects/src/main/resources/Common/MatDefs/Post/DepthOfField.frag
  3. 7
      jme3-effects/src/main/resources/Common/MatDefs/Post/DepthOfField.j3md

@ -54,10 +54,13 @@ public class DepthOfFieldFilter extends Filter {
private float focusDistance = 50f;
private float focusRange = 10f;
private float blurScale = 1f;
private float blurThreshold = 0.2f;
// These values are set internally based on the
// viewport size.
private float xScale;
private float yScale;
private boolean debugUnfocus;
/**
* Creates a DepthOfField filter
@ -83,7 +86,8 @@ public class DepthOfFieldFilter extends Filter {
material = new Material(assets, "Common/MatDefs/Post/DepthOfField.j3md");
material.setFloat("FocusDistance", focusDistance);
material.setFloat("FocusRange", focusRange);
material.setFloat("BlurThreshold", blurThreshold);
material.setBoolean("DebugUnfocus", debugUnfocus);
xScale = 1.0f / w;
yScale = 1.0f / h;
@ -161,13 +165,62 @@ public class DepthOfFieldFilter extends Filter {
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
public void write(JmeExporter ex) throws IOException {
super.write(ex);
OutputCapsule oc = ex.getCapsule(this);
oc.write(blurScale, "blurScale", 1f);
oc.write(blurScale, "blurThreshold", 0.2f);
oc.write(focusDistance, "focusDistance", 50f);
oc.write(focusRange, "focusRange", 10f);
oc.write(debugUnfocus, "debugUnfocus", false); // strange to write this I guess
}
@Override
@ -175,7 +228,9 @@ public class DepthOfFieldFilter extends Filter {
super.read(im);
InputCapsule ic = im.getCapsule(this);
blurScale = ic.readFloat("blurScale", 1f);
blurThreshold = ic.readFloat("blurThreshold", 0.2f);
focusDistance = ic.readFloat("focusDistance", 50f);
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_YScale;
vec2 m_NearFar = vec2( 0.1, 1000.0 );
uniform vec2 g_FrustumNearFar;
void main() {
@ -31,8 +31,8 @@ void main() {
// z * (zb - a) = b
// z = b / (zb - a)
//
float a = m_NearFar.y / (m_NearFar.y - m_NearFar.x);
float b = m_NearFar.y * m_NearFar.x / (m_NearFar.x - m_NearFar.y);
float a = g_FrustumNearFar.y / (g_FrustumNearFar.y - g_FrustumNearFar.x);
float b = g_FrustumNearFar.y * g_FrustumNearFar.x / (g_FrustumNearFar.x - g_FrustumNearFar.y);
float z = b / (zBuffer - a);
// Above could be the same for any depth-based filter
@ -42,7 +42,7 @@ void main() {
// at +/- m_FocusRange to either side of that.
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
// convolution filter
gl_FragColor = texVal;
@ -86,7 +86,11 @@ void main() {
gl_FragColor = mix( texVal, sum, unfocus );
// I used this for debugging the range
// gl_FragColor.r = unfocus;
#ifdef DEBUG_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 XScale;
Float YScale;
Float BlurThreshold : 0.2;
Boolean DebugUnfocus : false;
}
Technique {
@ -16,12 +18,15 @@ MaterialDef Depth Of Field {
FragmentShader GLSL150 GLSL100: Common/MatDefs/Post/DepthOfField.frag
WorldParameters {
FrustumNearFar
}
Defines {
RESOLVE_MS : NumSamples
RESOLVE_DEPTH_MS : NumSamplesDepth
BLUR_THRESHOLD : BlurThreshold
DEBUG_UNFOCUS : DebugUnfocus
}
}
}
}

Loading…
Cancel
Save