#extension GL_ARB_texture_rectangle : enable uniform sampler2DRect osgOcean_FullColourMap; // full resolution image uniform sampler2DRect osgOcean_FullDepthMap; // full resolution depth map uniform sampler2DRect osgOcean_BlurMap; // downsampled and filtered image uniform vec2 osgOcean_ScreenRes; uniform vec2 osgOcean_ScreenResInv; uniform vec2 osgOcean_LowRes; #define NUM_TAPS 4 // maximum CoC radius and diameter in pixels const vec2 vMaxCoC = vec2(5.0,10); // scale factor for maximum CoC size on low res. image const float radiusScale = 0.4; // contains poisson-distributed positions on the unit circle vec2 poisson[8]; void main(void) { poisson[0] = vec2( 0.0, 0.0); poisson[1] = vec2( 0.527837, -0.085868); poisson[2] = vec2(-0.040088, 0.536087); poisson[3] = vec2(-0.670445, -0.179949); poisson[4] = vec2(-0.419418, -0.616039); poisson[5] = vec2( 0.440453, -0.639399); poisson[6] = vec2(-0.757088, 0.349334); poisson[7] = vec2( 0.574619, 0.685879); // pixel size (1/image resolution) of full resolution image vec2 pixelSizeHigh = osgOcean_ScreenResInv; // pixel size of low resolution image vec2 pixelSizeLow = 4.0 * pixelSizeHigh; vec4 color = texture2DRect( osgOcean_FullColourMap, gl_TexCoord[0].st ); // fetch center tap // float centerDepth = color.a; // save its depth float centerDepth = texture2DRect( osgOcean_FullDepthMap, gl_TexCoord[0].st ).r; // save its depth // convert depth into blur radius in pixels float discRadius = abs(centerDepth * vMaxCoC.y - vMaxCoC.x); // compute disc radius on low-res image float discRadiusLow = discRadius * radiusScale; vec4 colorAccum = vec4(0.0); float depthAccum = 0.0; for(int t = 0; t < NUM_TAPS; t++) { vec2 coordHigh = gl_TexCoord[0].st + ( osgOcean_ScreenRes * (pixelSizeHigh * poisson[t] * discRadius )); vec2 coordLow = gl_TexCoord[1].st + ( osgOcean_LowRes * (pixelSizeLow * poisson[t] * discRadiusLow )); // fetch low-res tap vec4 tapLow = texture2DRect( osgOcean_BlurMap, coordLow ); // fetch high-res tap vec4 tapHigh = texture2DRect( osgOcean_FullColourMap, coordHigh ); float tapHighDepth = texture2DRect( osgOcean_FullDepthMap, coordHigh ).r; // put tap blurriness into [0, 1] range float tapBlur = abs(tapHighDepth * 2.0 - 1.0); // mix low- and hi-res taps based on tap blurriness vec4 tapColor = mix(tapHigh, tapLow, tapBlur); // apply leaking reduction: lower weight for taps that are // closer than the center tap and in focus float tapDepth = (tapHighDepth >= centerDepth) ? 1.0 : abs(tapHighDepth * 2.0 - 1.0); // accumulate colorAccum += tapColor * tapDepth; depthAccum += tapDepth; } // normalize and return result gl_FragColor = colorAccum / depthAccum; }