# Hexagonal Bokeh Blur Revisited – Part 1: Basic 3-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.

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!

## 4 thoughts on “Hexagonal Bokeh Blur Revisited – Part 1: Basic 3-pass Version”

1. Eduardo Castiñeyra says:

Hi, I have a question concerning the diagonal blur pass

The line

float4 color = BlurTexture(verticalBlurTexture, uv, blurDir) * coc;

Shouldn’t it be using “sceneTexture” instead of verticalBlurTexture ?