Lately I’ve been really disappointed by the poor performances of my first depth of field implementation, thus I decided to do something about it…
The most natural step to do was to give a look to the second Direct3D example from the same paper I used for the first one, as I was sure it would have led to more satisfactory results.
I spent the two last nights converting, correcting and fine tuning it, but I was rewarded by the fact that I was right: even if it is a five passes algorithm which is using four different Frame Buffer Objects, it is about 2.5 times faster than my previous implementation!
I think the speed boost depends on the two following:
- image blurring is achieved by a gaussian filter which is calculated separating the X from the Y axis, it is an approximation of a standard 2D kernel but it also means that the convolution matrix calculation complexity decreases from a quadratic to a linear factor.
- this filter operates only on a downsampled (1/4th of the screen resolution actually) FBO
Another nice note about this new implementation is that there are only two focal parameters, focus depth and focus range, which really help to setup a correct scene.
Now let’s review the five passes in detail:
- Render the scene normally while calculating a blur amount per-vertex, then store the interpolated value per-pixel inside the alpha component of the fragment.
The calculation at the vertex shader is just:
Blur = clamp(abs(-PosWV.z - focalDistance) / focalRange, 0.0, 1.0);
- Downsample the scene rendered at the previous pass storing it in a smaller FBO
- Apply the gaussian filter along the X axis on the downsampled scene and store it in a new FBO
- Apply the gaussian filter along the Y axis on the already X blurred scene and store it in a new FBO
- Calculate a linear interpolation between the first full resolution FBO and the XY downsampled blurred one
This is performed in the fragment shader as:
gl_FragColor = Fullres + Fullres.a * (Blurred - Fullres);
Again, you can view it in action on my YouTube Channel, or in a high definition 720p version hosted on my Vimeo page. 😉
That’s some really nice work, would be nice to see source though 🙂
Keep it up!
Thank you for your appreciation. 😉
The source is released under the GPL license and available on my site: http://encelo.netsons.org/programming/opengl
i think the gaussian filter Costs too much pass to blur the image,al though very effective. i haven’t used it in my program, does it Lower the FPS a lot, sorry for my poor english, waiting for your reply! thanks.
Yes, it’s a bit heavy, not precise as a real lens blur but, as you wrote, very effective.
I have implemented the ATI paper about high quality DoF, so I made use of their 2-passes Gaussian blur, but of course you can try with other means to achieve, more or less, the same result. 🙂