Wednesday, December 29, 2010

Better Depth of field (but slower)

As I said in my previous post about DOF, there was a nasty bleeding effect I couldn't get rid of, but now I finally found a way to eradicate it by altering a little bit the technique I was using. Instead of having a Blur pass and a merging pass, I now have only a Blur pass, in which I do the merging, and in which I do the blur only if needed. 

Here is a screenshot (5 passes):



It produces a much smoother Blur, and completely eliminates the bleeding. An other artifact of the late merging was a ghosting effect in zones where the blur was mixed at around 10-30% with the Frame Buffer. This is now completely eliminated with this new method.

here I have 615 fps with 3 passes in 1024x768, 500 fps with 4 passes, and 425 fps with 5 passes, on my Nvidia gtx 470. I would recommend a minimum of 4 passes to have a nice blur quality.

Some GLSL code (Horizontal Pass):

void main()
{
   vec2 uv = gl_TexCoord[0].xy;
                       
   vec4 thisPixel = texture2D( blurTex, uv);
   vec4 pixelsAround = vec4(0.0);

   samples[0] = -2.0/texWidth;
   samples[1] = -1.0/texWidth;
   samples[2] = 1.0/texWidth;
   samples[3] = 2.0/texWidth;
                       
   // Calculate a 5 X 5 Gaussian Blur Horiz
   for (int i = 0; i < 4; i++)
   { 
      pixelsAround += texture2D( blurTex, vec2(uv.s + samples[i], uv.t ));  
   }
                       
   pixelsAround /= 4.0;
   float interpolatedKernel = clamp(3.0*abs(LinearizeDepth(vec2(0.50.5)) - 
      LinearizeDepth(uv)), 0.01.0);
                   
   gl_FragColor = mix(thisPixel, pixelsAround, interpolatedKernel);
}

If you have done yourself a DOF shader with a different implementation or have any advice or improvement ideas don't hesitate to leave a comment!

No comments:

Post a Comment