So, as you might know, Unity default cutout shader is the best thing to use for non-semi-transparent objects like: metal grids, grass, foliage, etc. But is it?
Yes, talking about performance, it's much better then transparent, it also supports proper depth sorting.. But! It can't be anti-aliased with MSAA.
Look at this edges:
No anti-aliasing at all! But we can use FXAA, or SMAA on the post-processing stage - you can say. Yes, but this methods gives us a super blurry result, which looks absolutely horrible in VR!
So, how to solve this problem? And the answer is - Alpha to Coverage (or A2C) method. A2C is a super cool feature, which can make your cutout edges be anti-aliased while using MSAA anti-aliasing.
If you want to know how it works exactly, I would recommend you to read this cool article by Ben Golus
But for now, what you need to know, that A2C is basically a better cutout, which also draws on alpha-test but supports 2, 4 or 8 levels of transparency, depending on your anti-aliasing settings. It supports proper depth sorting, don't causes overdrawing and no performance loss, as the result.
So, let's make a simple cutout shader for our grass using Amplify Shader Editor.
Let's begin with adding some nodes for our default PBR shader setup:
Now, let's make it a default cutout shader. Just choose the blend mode preset called "Masked" in your Output Node settings.
Then, connect your Albedo Alpha to the Opacity Mask input:
If you want your shader to be double sided, turn off the culling in your output node settings:
And now it looks just like a default cutout shader:
So, let's make some magic. Switch your Blend mode to "Custom" and turn the "Alpha To Coverage" mode on:
NOTE: Check your "Blend RGB" option, it must be turned off, as on the screenshot above!
Now, just switch your connection from "Albedo Alpha -> Opacity Mask" to "Albedo Alpha -> Opacity".
And... It's done!
Oh... wait, what?
Yes. This is Alpha To Coverage. But.. Why is it so blurry and ugly? That's because we didn't finished yet!
To make our edge sharp and anti-aliased, lets use the FWidth node. I already told about it in this article (Available for my patrons)
Just make this simple construction:
This is a mathematical formula, which basically generates a cutout anti-aliased edges for your alpha mask. I borrowed it from this article i mentioned above and translated it to nodes.
The "Opacity" variable goes straight from your Albedo alpha channel, and "A2C" variable should be connected to your "Opacity" input on your output node.
So, the final shader should look something like this:
And now... Look at our grass!
Isn't it pretty? But it is still not everything we should do.
Here comes another problem, mip-mapping. When we go far from your A2C object, the thin parts starts to disappear slowly. Look at the thin grass!
And the easiest way to solve this problem is to reconfigure our Albedo texture in unity.
Just turn on the option called "Mip Maps Preserve Coverage" in your texture properties.
Alpha Cutoff Value should be manually selected for every texture you working with. For my grass, the 0.75 looks the best.
Now, apply the changes and... Here it is! Much better!
Just compare this 2 screenshots:
The left one is before the fix, the right one is after.
PS: Specially for my patrons, I made a simple Amplify Shader Editor node called "A2C Mask". It makes your shader look even more compact and clear:
A2C Mask node and source files:
This node file and all of the shader source files from this tutorial are available here for my patrons.