diff --git a/engine/src/core-effects/Common/MatDefs/Post/DepthOfField.frag b/engine/src/core-effects/Common/MatDefs/Post/DepthOfField.frag index 658da546f..576fecac6 100644 --- a/engine/src/core-effects/Common/MatDefs/Post/DepthOfField.frag +++ b/engine/src/core-effects/Common/MatDefs/Post/DepthOfField.frag @@ -84,6 +84,6 @@ void main() { gl_FragColor = mix( texVal, sum, unfocus ); // I used this for debugging the range - // gl_FragColor.r = unfocus; -} + // gl_FragColor.r = unfocus; + } } \ No newline at end of file diff --git a/engine/src/core-effects/Common/MatDefs/Post/DepthOfField.j3md b/engine/src/core-effects/Common/MatDefs/Post/DepthOfField.j3md index 644bed7d9..cd190253a 100644 --- a/engine/src/core-effects/Common/MatDefs/Post/DepthOfField.j3md +++ b/engine/src/core-effects/Common/MatDefs/Post/DepthOfField.j3md @@ -11,6 +11,19 @@ MaterialDef Depth Of Field { Float YScale; } + Technique { + VertexShader GLSL150: Common/MatDefs/Post/Post15.vert + FragmentShader GLSL150: Common/MatDefs/Post/DepthOfField15.frag + + WorldParameters { + } + + Defines { + RESOLVE_MS : NumSamples + RESOLVE_DEPTH_MS : NumSamplesDepth + } + } + Technique { VertexShader GLSL100: Common/MatDefs/Post/Post.vert FragmentShader GLSL100: Common/MatDefs/Post/DepthOfField.frag diff --git a/engine/src/core-effects/Common/MatDefs/Post/DepthOfField15.frag b/engine/src/core-effects/Common/MatDefs/Post/DepthOfField15.frag new file mode 100644 index 000000000..80cf3c530 --- /dev/null +++ b/engine/src/core-effects/Common/MatDefs/Post/DepthOfField15.frag @@ -0,0 +1,91 @@ +#import "Common/ShaderLib/MultiSample.glsllib" + +uniform COLORTEXTURE m_Texture; +uniform DEPTHTEXTURE m_DepthTexture; +varying vec2 texCoord; + +uniform float m_FocusRange; +uniform float m_FocusDistance; +uniform float m_XScale; +uniform float m_YScale; + +vec2 m_NearFar = vec2( 0.1, 1000.0 ); + +void main() { + + vec4 texVal = getColor( m_Texture, texCoord ); + + float zBuffer = getDepth( m_DepthTexture, texCoord ).r; + + // + // z_buffer_value = a + b / z; + // + // Where: + // a = zFar / ( zFar - zNear ) + // b = zFar * zNear / ( zNear - zFar ) + // z = distance from the eye to the object + // + // Which means: + // zb - a = b / z; + // 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 z = b / (zBuffer - a); + + // Above could be the same for any depth-based filter + + // We want to be purely focused right at + // m_FocusDistance and be purely unfocused + // at +/- m_FocusRange to either side of that. + float unfocus = min( 1.0, abs( z - m_FocusDistance ) / m_FocusRange ); + + if( unfocus < 0.2 ) { + // If we are mostly in focus then don't bother with the + // convolution filter + gl_FragColor = texVal; + } else { + // Perform a wide convolution filter and we scatter it + // a bit to avoid some texture look-ups. Instead of + // a full 5x5 (25-1 lookups) we'll skip every other one + // to only perform 12. + // 1 0 1 0 1 + // 0 1 0 1 0 + // 1 0 x 0 1 + // 0 1 0 1 0 + // 1 0 1 0 1 + // + // You can get away with 8 just around the outside but + // it looks more jittery to me. + + vec4 sum = vec4(0.0); + + float x = texCoord.x; + float y = texCoord.y; + + float xScale = m_XScale; + float yScale = m_YScale; + + // In order from lower left to right, depending on how you look at it + sum += getColor( m_Texture, vec2(x - 2.0 * xScale, y - 2.0 * yScale) ); + sum += getColor( m_Texture, vec2(x - 0.0 * xScale, y - 2.0 * yScale) ); + sum += getColor( m_Texture, vec2(x + 2.0 * xScale, y - 2.0 * yScale) ); + sum += getColor( m_Texture, vec2(x - 1.0 * xScale, y - 1.0 * yScale) ); + sum += getColor( m_Texture, vec2(x + 1.0 * xScale, y - 1.0 * yScale) ); + sum += getColor( m_Texture, vec2(x - 2.0 * xScale, y - 0.0 * yScale) ); + sum += getColor( m_Texture, vec2(x + 2.0 * xScale, y - 0.0 * yScale) ); + sum += getColor( m_Texture, vec2(x - 1.0 * xScale, y + 1.0 * yScale) ); + sum += getColor( m_Texture, vec2(x + 1.0 * xScale, y + 1.0 * yScale) ); + sum += getColor( m_Texture, vec2(x - 2.0 * xScale, y + 2.0 * yScale) ); + sum += getColor( m_Texture, vec2(x - 0.0 * xScale, y + 2.0 * yScale) ); + sum += getColor( m_Texture, vec2(x + 2.0 * xScale, y + 2.0 * yScale) ); + + sum = sum / 12.0; + + gl_FragColor = mix( texVal, sum, unfocus ); + + // I used this for debugging the range + // gl_FragColor.r = unfocus; + } +}