Continuing my post process shader adventures, I decided to look into edge detection. This was a lot more complicated than I anticipated and used a lot of math! I’ve added some of the resources I used in the post.
To do this, I set all of my objects to use custom depth, and for each pixel in the custom depth buffer, compared it to the adjacent pixels. If the weighted average of the pixels multiplied by a kernel is greater than 0, then the pixel is on the edge of an object, so I colour it with a solid colour.
I started by making a material function to get a pixel adjacent to the current pixel. It takes the custom depth buffer and a pixel offset value. Multiplying these together and adding it to the uv of the screen gives us the UV coordinate of the desired pixel. Imputing different pixel offset values will give us different pixels.
Image by Michael Orzelek
To get the depth of the adjacent pixel, we use the pixel depth material function. It takes the UV coord that we got from the adjacent pixel material function and uses that as the UV input to the custom depth. This is clamped to 0-5000 and then divided by 5000, to ensure that we always get a value between 0 and 1.
We get this custom depth for each pixel surrounding our current pixel. Now that we have this, we can calculate which pixels are edges.
To do this we input the depth values of the pixels and the values of a kernel into the ConvoleTex function. I’ve used 3 vector3s to represent the 9 values in the kernel.
Each pixel value is multiplied by the corresponding value in the kernel and then they are all added together. This gives us one number that is the weighted average of all of the pixels surrounding our current pixel.
We do this twice, once for horizonal and once for vertical.
Info on kerenels here.
The horizontal and vertical values are then turned into a vector2 and we get its length. If the length is greater than 0, set the pixel to be the line colour, otherwise make it the postprocess output.
I’ve added a couple of extra controls on top of this, adding an optional colour multiplier to give the purple look in the first image of the post. I’ve also changed the 0 in the if statement to an editable edge thickness value, to give the user some control over the amount of pixels that are affected.
Here’s the shader without the colour multiplier.
And here’s it with it!