1 uniform sampler2D m_Texture; 2 uniform sampler2D m_DepthTexture; 3 varying vec2 texCoord; 4 5 uniform float m_FocusRange; 6 uniform float m_FocusDistance; 7 uniform float m_XScale; 8 uniform float m_YScale; 9 10 vec2 m_NearFar = vec2( 0.1, 1000.0 ); 11 12 void main() { 13 14 vec4 texVal = texture2D( m_Texture, texCoord ); 15 16 float zBuffer = texture2D( m_DepthTexture, texCoord ).r; 17 18 // 19 // z_buffer_value = a + b / z; 20 // 21 // Where: 22 // a = zFar / ( zFar - zNear ) 23 // b = zFar * zNear / ( zNear - zFar ) 24 // z = distance from the eye to the object 25 // 26 // Which means: 27 // zb - a = b / z; 28 // z * (zb - a) = b 29 // z = b / (zb - a) 30 // 31 float a = m_NearFar.y / (m_NearFar.y - m_NearFar.x); 32 float b = m_NearFar.y * m_NearFar.x / (m_NearFar.x - m_NearFar.y); 33 float z = b / (zBuffer - a); 34 35 // Above could be the same for any depth-based filter 36 37 // We want to be purely focused right at 38 // m_FocusDistance and be purely unfocused 39 // at +/- m_FocusRange to either side of that. 40 float unfocus = min( 1.0, abs( z - m_FocusDistance ) / m_FocusRange ); 41 42 if( unfocus < 0.2 ) { 43 // If we are mostly in focus then don't bother with the 44 // convolution filter 45 gl_FragColor = texVal; 46 } else { 47 // Perform a wide convolution filter and we scatter it 48 // a bit to avoid some texture look-ups. Instead of 49 // a full 5x5 (25-1 lookups) we'll skip every other one 50 // to only perform 12. 51 // 1 0 1 0 1 52 // 0 1 0 1 0 53 // 1 0 x 0 1 54 // 0 1 0 1 0 55 // 1 0 1 0 1 56 // 57 // You can get away with 8 just around the outside but 58 // it looks more jittery to me. 59 60 vec4 sum = vec4(0.0); 61 62 float x = texCoord.x; 63 float y = texCoord.y; 64 65 float xScale = m_XScale; 66 float yScale = m_YScale; 67 68 // In order from lower left to right, depending on how you look at it 69 sum += texture2D( m_Texture, vec2(x - 2.0 * xScale, y - 2.0 * yScale) ); 70 sum += texture2D( m_Texture, vec2(x - 0.0 * xScale, y - 2.0 * yScale) ); 71 sum += texture2D( m_Texture, vec2(x + 2.0 * xScale, y - 2.0 * yScale) ); 72 sum += texture2D( m_Texture, vec2(x - 1.0 * xScale, y - 1.0 * yScale) ); 73 sum += texture2D( m_Texture, vec2(x + 1.0 * xScale, y - 1.0 * yScale) ); 74 sum += texture2D( m_Texture, vec2(x - 2.0 * xScale, y - 0.0 * yScale) ); 75 sum += texture2D( m_Texture, vec2(x + 2.0 * xScale, y - 0.0 * yScale) ); 76 sum += texture2D( m_Texture, vec2(x - 1.0 * xScale, y + 1.0 * yScale) ); 77 sum += texture2D( m_Texture, vec2(x + 1.0 * xScale, y + 1.0 * yScale) ); 78 sum += texture2D( m_Texture, vec2(x - 2.0 * xScale, y + 2.0 * yScale) ); 79 sum += texture2D( m_Texture, vec2(x - 0.0 * xScale, y + 2.0 * yScale) ); 80 sum += texture2D( m_Texture, vec2(x + 2.0 * xScale, y + 2.0 * yScale) ); 81 82 sum = sum / 12.0; 83 84 gl_FragColor = mix( texVal, sum, unfocus ); 85 86 // I used this for debugging the range 87 // gl_FragColor.r = unfocus; 88 } 89 }