#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 ); out vec4 fragColor; 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 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; fragColor = mix( texVal, sum, unfocus ); // I used this for debugging the range // gl_FragColor.r = unfocus; } }