# 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

(C) 2020 David Lettier
lettier.com