<p>Here is a basic implementation for a rasterized scene.</p>
<ol>
<li>Bind and write the depth buffer as usual.</li>
<li>Bind and write the stencil buffer with the shapes that need to be masked out. A simple 1 or 0 will do here.</li>
<li>Generate the color buffer</li>
<li>Run the bokeh filter as a full screen quad post processing effect.</li>
</ol>
<p>The order here isn't terribly important the only step dependent on the other 3 is doing the actual blur.</p>
<p>In the fragment shader:</p>
<ol>
<li>read the stencil and color buffers. If the stencil value is 1 return the unmodified color.</li>
<li>read the depth buffer.</li>
<li>Run the blur kernel.</li>
</ol>
<hr />
<p>Here is a basic fragment shader implementation:
uBlurRadius is a uniform passed in to set the blur kernel size and uResolution is the width and height of the color buffer.</p>
<pre><code>float stencil = texture(stencilBuffer, uv).r;

if (stencil == 1.0) {
  // Keep the pixel in focus.
  gl_FragColor = texture(colorBuffer, uv);
  return;
}

// Compute the depth of field mask.
float focusDepth = texture( depthBuffer, uv);
float blurDepth = focusDepth + uBlurRadius;
float blurAmount = smoothstep(focusDepth, blurDepth, depth);

// Apply the bokeh blur effect.
vec4 color = vec4(0.0);
float totalWeight = 0.0;
for (float i = -uBlurRadius; i &lt;= uBlurRadius; i++) {
  for (float j = -uBlurRadius; j &lt;= uBlurRadius; j++) {
    vec2 offset = vec2(i, j) / uResolution;
    float weight = exp(-length(offset) * length(offset) / 2.0);
    totalWeight += weight;
    color += texture(colorBuffer, uv + offset * blurAmount) * weight;
  }
}
gl_FragColor = color / totalWeight;
</code></pre>
<p>The biggest issue with this code is that fragments that are in focus can bleed/smear into those that are out of focus inside the blur kernel. If you implement this and look closely at the edges around scene elements that are in focus you will be able to see the effect it has. But the code is simple and relatively fast. The blur kernel size can be used to limit blur and improve performance which can be an easy way to make this work on a variety of hardware.</p>

CC BY-SA 4.0
2023-03-25T01:20:32.303Z
I don’t think this is what Caleb’s asking for—it sounds like the goal is for the bokeh shapes themselves to be non-circular, as described (for real-world photography) in [this Instructables article](https://www.instructables.com/DIY-Heart-shaped-Bokeh/).
Noah Witherspoon
CC BY-SA 4.0
2023-03-25T09:53:04.367Z
All the elements are there to do that exact effect.
pmw1234
CC BY-SA 4.0
2023-03-20T11:48:26.753Z
2023-03-20T11:48:26.753Z
pmw1234
<p>I have a 2d texture and a shape matte, the matte could be any shape, like a star, heart, and so on, and I want to use this matte to generate different-shaped bokeh blur, how can I do it? and normally, creating bokeh blur needs iterations, how to cope with the efficiency problem. hopefully, realize it in glsl</p>

CC BY-SA 4.0
2023-03-18T20:39:02.227Z
One approach is to use the stencil buffer to mask out the areas to keep in focus. This allows a variety of shapes to be used at once, they can move, etc.
pmw1234
CC BY-SA 4.0
2023-03-20T02:18:27.063Z
any detailed code? i'm still a little confused...
Caleb Edwards
<glsl>
want bokeh blur with custom shapes
Caleb Edwards
# want bokeh blur with custom shapes

(Asked by: username_0 on 2023-03-18)

I have a 2d texture and a shape matte, the matte could be any shape, like a star, heart, and so on, and I want to use this matte to generate different-shaped bokeh blur, how can I do it? and normally, creating bokeh blur needs iterations, how to cope with the efficiency problem. hopefully, realize it in glsl

**Tags:** glsl

> **Comments:**
> **username_1**: One approach is to use the stencil buffer to mask out the areas to keep in focus. This allows a variety of shapes to be used at once, they can move, etc.  
> **username_0**: any detailed code? i'm still a little confused...  

---

## 1 answers

### Answer by username_1 on 2023-03-20. Score: 0

Here is a basic implementation for a rasterized scene.

1. Bind and write the depth buffer as usual.
2. Bind and write the stencil buffer with the shapes that need to be masked out. A simple 1 or 0 will do here.
3. Generate the color buffer
4. Run the bokeh filter as a full screen quad post processing effect.

The order here isn't terribly important the only step dependent on the other 3 is doing the actual blur.

In the fragment shader:

1. read the stencil and color buffers. If the stencil value is 1 return the unmodified color.
2. read the depth buffer.
3. Run the blur kernel.

---

Here is a basic fragment shader implementation:
uBlurRadius is a uniform passed in to set the blur kernel size and uResolution is the width and height of the color buffer.

```
float stencil = texture(stencilBuffer, uv).r;

if (stencil == 1.0) {
  // Keep the pixel in focus.
  gl_FragColor = texture(colorBuffer, uv);
  return;
}

// Compute the depth of field mask.
float focusDepth = texture( depthBuffer, uv);
float blurDepth = focusDepth + uBlurRadius;
float blurAmount = smoothstep(focusDepth, blurDepth, depth);

// Apply the bokeh blur effect.
vec4 color = vec4(0.0);
float totalWeight = 0.0;
for (float i = -uBlurRadius; i <= uBlurRadius; i++) {
  for (float j = -uBlurRadius; j <= uBlurRadius; j++) {
    vec2 offset = vec2(i, j) / uResolution;
    float weight = exp(-length(offset) * length(offset) / 2.0);
    totalWeight += weight;
    color += texture(colorBuffer, uv + offset * blurAmount) * weight;
  }
}
gl_FragColor = color / totalWeight;

```

The biggest issue with this code is that fragments that are in focus can bleed/smear into those that are out of focus inside the blur kernel. If you implement this and look closely at the edges around scene elements that are in focus you will be able to see the effect it has. But the code is simple and relatively fast. The blur kernel size can be used to limit blur and improve performance which can be an easy way to make this work on a variety of hardware.

> **Comments:**
> **username_2**: I don’t think this is what username_0’s asking for—it sounds like the goal is for the bokeh shapes themselves to be non-circular, as described (for real-world photography) in [this Instructables article](https://www.instructables.com/DIY-Heart-shaped-Bokeh/).  
> **username_1**: All the elements are there to do that exact effect.  

---

