Post processing shader
This shader was made for the Graphics Programming course in the DAE curriculum. It is able to reduce the scene in simple linework in post processing. The shader creates 3 types of lines, each with a different thickness.
The shader looks at the difference of the minimum and maximum color values of 8 surrounding pixels to determin if the pixel should be part of a line. If the difference is bigger then 0.5 - a certain weight (each thickness has it's own weight) the pixel will turn into a line pixel. The surrounding pixels get sampled at a certain distance from the original distance, this allows to link smaller lines to more local (small sample distance) details and thicker lines to outline the main objects in the scene.
Colors are blurred to give a water paint effect. It is also possible to produce a grayscale image that allows 4 shades of gray (including black and white), this is based on the brightness of the pixel. This value then get used for the colored image aswel, it gets multiplied with the blurred color. This makes brighter colors pop out more.
Code snippet below the example images.
float4 PS(PS_INPUT input) : SV_Target
{
...
//Parameters
float separation0 = 3.f;
float weight0 = 0.1f;
float separation1 = 1.f;
float weight1 = 0.37f;
float separation2 = 0.5f;
float weight2 = 0.43f;
//Define texture
float4 color = gTexture.Sample(samPoint, input.TexCoord);
uint2 size;
gTexture.GetDimensions(size.x, size.y);
////CALCULATE LINE
float4 minimum0 = float4(1, 1, 1, 1);
float4 maximum0 = float4(0, 0, 0, 0);
float4 minimum1 = float4(1, 1, 1, 1);
float4 maximum1 = float4(0, 0, 0, 0);
float4 minimum2 = float4(1, 1, 1, 1);
float4 maximum2 = float4(0, 0, 0, 0);
for (int x = -1; x <= 1; ++x)
{
for (int y = -1; y <= 1; ++y)
{
float4 color0 = gTexture.Sample(
samPoint,
float2(
input.TexCoord.x + x * separation0 / size.x,
input.TexCoord.y + y * separation0 / size.y));
minimum0 = min(color0, minimum0);
maximum0 = max(color0, maximum0);
float4 color1 = gTexture.Sample(
samPoint,
float2(
input.TexCoord.x + x * separation1 / size.x,
input.TexCoord.y + y * separation1 / size.y));
minimum1 = min(color1, minimum1);
maximum1 = max(color1, maximum1);
float4 color2 = gTexture.Sample(
samPoint,
float2(
input.TexCoord.x + x * separation2 / size.x,
input.TexCoord.y + y * separation2 / size.y));
minimum2 = min(color2, minimum2);
maximum2 = max(color2, maximum2);
}
}
float4 line = float4(0, 0, 0, 0);
float minBrightness;
float maxBrightness;
minBrightness = (minimum0.r + minimum0.g + minimum0.b) / 3;
maxBrightness = (maximum0.r + maximum0.g + maximum0.b) / 3;
line += round(weight0 + maxBrightness - minBrightness);
minBrightness = (minimum1.r + minimum1.g + minimum1.b) / 3;
maxBrightness = (maximum1.r + maximum1.g + maximum1.b) / 3;
line += round(weight1 + maxBrightness - minBrightness);
minBrightness = (minimum2.r + minimum2.g + minimum2.b) / 3;
maxBrightness = (maximum2.r + maximum2.g + maximum2.b) / 3;
line += round(weight2 + maxBrightness - minBrightness);
//CALCULATE BLUR COLOR
int blurRadius = 10;
float4 blurColor;
for (int i = -blurRadius; i <= blurRadius; i += 2)
{
for (int j = -blurRadius; j <= blurRadius; j += 2)
{
blurColor += gTexture.Sample(
samPoint,
float2(
input.TexCoord.x + (float) i / size.x,
input.TexCoord.y + (float) j / size.y));
}
}
blurColor /= ((blurRadius + 1) * (blurRadius + 1));
blurColor.w = 1;
//CALCULATE GRAY SHADING
float dark = min(0.3f + round((color.r + color.g + color.b)), 1.f);
dark *= min(0.7f + round((color.r + color.g + color.b) / 3), 1.f);
//CALCULATE OUTPUT
float4 output = float4(dark, dark, dark, 1);
output *= 1 - line;
output *= blurColor * 1.2f; //ADD COLOR
output.w = 1;
return output;
}