Ive been working on a DOF shader for my game project some times ago. Ive decided to post an exemple demo here, so that it could be useful for someone else!
Thanks! I hope this makes it's way into the Wiki eventually.
For this shader, I'm using a 5X5 gaussian blur shader with two pass, then I mix the blurred image with the original rendered image depending on the distance.
I made some tweaks to your shader/pipeline to make it more 'blurry', hope this is useful too
First, I dropped down the resolution of the blur buffer. This naturally makes it more blurry (which isn't a problem in this case!) and greatly reduces the cost of the blur shader. I've also enabled bilinear filtering, to get some more samples:
<RenderTarget id="DOFBLUR" depthBuf="true" numColBufs="1" format="RGBA16F" scale="0.25" bilinear="true" />
Second, I tweaked your sample offsets to be at 0, 1.5 and 3.5 texels.
I've hard-coded in 256 & 192 here (which correspond to 1024 & 768 * 0.25), in a robust solution these should come from the application so that other resolutions also work.
if (passNumber.r == 1.0)
samples = -3.5/256.0;
samples = -1.5/256.0;
samples = 0.0;
samples = 1.5/256.0;
samples = 3.5/256.0;
samples = -3.5/192.0;
samples = -1.5/192.0;
samples = 0.0;
samples = 1.5/192.0;
samples = 3.5/192.0;
Sampling at half-pixel offsets allows us to sample two pixels at once (bilinear must be enabled in the pipeline for this to work).
samples is the same as before, samples/samples is the average of the +/- 1st & 2nd offset pixel, and samples/samples is the average of the +/- 3rd & 4th offset pixel.
Basically we get 9 texels with only 5 samples.
The depth buffer is a custom linear depth buffer, but you could change this to the original one.
It would probably be much faster if the actual depth buffer from the GBuffer pass was used, maybe I'll do some work on this later