Dilation dilates or enlarges the brighter areas of an image while at the same time, contracts or shrinks the darker areas of an image. This tends to create a pillowy look. You can use dilation for a glow/bloom effect or to add bokeh to your depth of field.
// ...
int size = int(parameters.x);
float separation = parameters.y;
float minThreshold = 0.1;
float maxThreshold = 0.3;
// ...The size and separation parameters control
how dilated the image becomes. A larger size will increase
the dilation at the cost of performance. A larger
separation will increase the dilation at the cost of
quality. The minThreshold and maxThreshold
parameters control which parts of the image become dilated.
// ...
vec2 texSize = textureSize(colorTexture, 0).xy;
vec2 fragCoord = gl_FragCoord.xy;
fragColor = texture(colorTexture, fragCoord / texSize);
// ...Sample the color at the current fragment's position.
// ...
float mx = 0.0;
vec4 cmx = fragColor;
for (int i = -size; i <= size; ++i) {
for (int j = -size; j <= size; ++j) {
// ...
}
}
// ...Loop through a size by size window,
centered at the current fragment position. As you loop, find the
brightest color based on the surrounding greyscale values.
// ...
// For a rectangular shape.
//if (false);
// For a diamond shape;
//if (!(abs(i) <= size - abs(j))) { continue; }
// For a circular shape.
if (!(distance(vec2(i, j), vec2(0, 0)) <= size)) { continue; }
// ...The window shape will determine the shape of the dilated parts of the image. For a rectangular shape, you can use every fragment covered by the window. For any other shape, skip the fragments that fall outside the desired shape.
// ...
vec4 c =
texture
( colorTexture
, ( gl_FragCoord.xy
+ (vec2(i, j) * separation)
)
/ texSize
);
// ...Sample a fragment color from the surrounding window.
// ...
float mxt = dot(c.rgb, vec3(0.21, 0.72, 0.07));
// ...Convert the sampled color to a greyscale value.
// ...
if (mxt > mx) {
mx = mxt;
cmx = c;
}
// ...If the sampled greyscale value is larger than the current maximum greyscale value, update the maximum greyscale value and its corresponding color.
// ...
fragColor.rgb =
mix
( fragColor.rgb
, cmx.rgb
, smoothstep(minThreshold, maxThreshold, mx)
);
// ...The new fragment color is a mixture between the existing fragment
color and the brightest color found. If the maximum greyscale value
found is less than minThreshold, the fragment color is
unchanged. If the maximum greyscale value is greater than
maxThreshold, the fragment color is replaced with the
brightest color found. For any other case, the fragment color is a mix
between the current fragment color and the brightest color.
(C) 2020 David Lettier
lettier.com