Hexagonal Bokeh Blur Revisited – Part 2: Improved 2-pass Version

This post is from a multi-part series titled “Hexagonal Bokeh Blur Revisited”. Want to jump directly to the index? If so, click here.

As seen previously, we can achieve this blur in a pretty straightforward fashion in three passes. The code below demonstrates an improvement over such approach, by achieving the blur in two passes. Since it builds on the previous post, make sure to read it beforehand.

If this is obvious to you, I invite you to skip to the next part.

Step 1 – Combined Vertical & Diagonal Blur

We have MRTs, so let’s combine both blurs in the same pass.

Combined4.png

struct PSOUTPUT
{
    float4 vertical : COLOR0;
    float4 diagonal : COLOR1;
};

// Get the local CoC to determine the radius of the blur.
float coc = tex2D(sceneTexture, uv).a; 

// CoC-weighted vertical blur.
float2 blurDir = coc * invViewDims * float2(cos(PI/2), sin(PI/2));
float4 color = BlurTexture(sceneTexture, uv, blurDir) * coc; 

// CoC-weighted diagonal blur.
float2 blurDir2 = CoC * invViewDims * float2(cos(-PI/6), sin(-PI/6));
float4 color2 = BlurTexture(sceneTexture, uv, blurDir2) * coc;

// Output to MRT
PSOUTPUT output;
output.vertical = float4(color.rgb, coc);
output.diagonal = float4(color2.rgb + output.vertical.xyz, coc);

Much simpler! Also means we don’t have to read a temporary (vertical) buffer unlike in the previous 3-pass approach, since we’re doing this all at once.

Step 2 – Rhomboid Blur

Combined5.png

The final step is the rhomboid blur. This is similar to the 3-pass approach. Again, this is done in two parts: via a 30 degrees (-PI/6) blur, as well as its reflection at 150 degrees (-5PI/6).

// Get the center to determine the radius of the blur
float coc = tex2D(verticalBlurTexture, uv).a;
float coc2 = tex2D(diagonalBlurTexture, uv).a;

// Sample the vertical blur (1st MRT) texture with this new blur direction
float2 blurDir = coc * invViewDims * float2(cos(-PI/6), sin(-PI/6));
float4 color = BlurTexture(verticalBlurTexture, uv, blurDir) * coc;

// Sample the diagonal blur (2nd MRT) texture with this new blur direction
float2 blurDir2 = coc2 * invViewDims * float2(cos(-5*PI/6), sin(-5*PI/6));
float4 color2 = BlurTexture(diagonalBlurTexture, uv, blurDir2) * coc2;
 
float3 output = (color.rgb + color2.rgb) * 0.5f;

Well That Was Kind of Obvious…

Yup! Just making sure. Details provided for posterity, and I’ll also be building on this part and the previous for the upcoming sections.

Again, a code sample is provided here. You should be able to toggle between both versions and see… that there is no difference.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s