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

The code below demonstrates the most straightforward way to achieve this blur. It is done in 3 passes.

### Step 0 – Blur Function

First, let’s define our blur function. This will be reused along the way.

float4 BlurTexture(sampler2D tex, float2 uv, float2 direction) { float4 finalColor = 0.0f; float blurAmount = 0.0f; // This offset is important. Will explain later. ;) uv += direction * 0.5f; for (int i = 0; i < NUM_SAMPLES; ++i) { float4 color = tex2D(tex, uv + direction * i); color *= color.a; blurAmount += color.a; finalColor += color; } return (finalColor / blurAmount); }

### Step 1 – Vertical Blur

First, we blur vertically.

// Get the local CoC to determine the radius of the blur. float coc = tex2D(sceneTexture, uv).a; // CoC-weighted vertical blur. float2 blurDirection = coc * invViewDims * float2(cos(PI/2), sin(PI/2)); float3 color = BlurTexture(sceneTexture, uv, blurDirection) * coc; // Done! return float4(color, coc);

### Step 2 – Diagonal Blur

Second we blur diagonally.

This stage is similar to *Stage 1*, but now with a 30 degree (PI/6) angle. We also combine the diagonal blur with the vertical blur.

// CoC-weighted diagonal blur float2 blurDir = coc * invViewDims * float2(cos(-PI/6), sin(-PI/6)); float4 color = BlurTexture(verticalBlurTexture, uv, blurDir) * coc; // Combine with the vertical blur // We don't need to divide by 2 here, because there is no overlap return float4(color.xyz + tex2D(verticalBlurTexture, uv).rgb, coc);

Which gives:

### Step 3 – Rhomboid Blur

The final step is the rhomboid blur.

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; // And we're done! float3 output = (color.rgb + color2.rgb) * 0.5f;

### Putting It All Together

As you can see, the code listed previously is pretty straightforward and should be a good base for you to achieve this blur. Additionally a code sample is provided here.

We can do better. Let’s do it in 2 passes!