3.9 KiB
3D Game Shaders For Beginners
Dilation
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.
Source
Copyright
(C) 2020 David Lettier
lettier.com