Hello everyone, I have been trying to figure this one out for quite a while now. After some digging, I found three acceptable ways to render alpha tested vegetation, one of them seemingly being the ultimate solution, but, so far, I have been unable to implement it in Unity URP Forward renderer.
I will list here the three solutions and describe the problems with them:
-
Alpha Blending - No pixel aliasing at all, but your geometry won’t be sorted properly. Depending on your foliage mesh it might actually work for you.
-
MSAA + Alpha to Coverage (using fwidth()) - The most common you stumble upon when searching about this on the internet. It actually helps correcting the pixel aliasing, if you use stylized foliage textures where the leaves don’t have much detail and are big enough, I guess you can get away with it. It still gets very pixelated, especially if you use more detailed textures, unless you crank up the resolution which will have a big performance impact of course.
references: Advanced VR Graphics Techniques (arm.com), Anti-aliased Alpha Test: The Esoteric Alpha To Coverage | by Ben Golus | Medium
- Alpha Blending + Alpha Testing - For me, the ultimate solution, you get all benefits of Alpha Blending with correct sorting, plus it is faster than Alpha Blending alone because pixels that don’t pass the ZTest are discarded. How to implement this on Unity URP Forward renderer though, if possible at all? Anyone got any luck with that? You can see an implementation of this in Unity legacy docs Unity - Manual: ShaderLab: legacy alpha testing (unity3d.com).
I am currently trying to implement the latest, it seemed simple enough, but either the sorting fails in some spots or I still get pixel alising.
Conclusions (so far) based on tests made on Meta Quest 2:
-
Foliage mesh stats: 16212 Verts | 8106 tris | 24318 indices.
Scene contains 6 of them. -
Shader uses only baked lighting, with some vertex displacement for wind and a standard specular lighting calculation using only the main light direction.
Alpha blending is expensive, the closer you get to the trees the higher the GPU load until frame rate starts to go down below 20.
At reasonable distances (I’d say about 2-3meters) all 6 trees on my scene are taking about 20~30% GPU load. They can be optimized, but one would have to be very conservative about using foliage with this technique.
A possible solution would be disabling the alpha blending pass if the pixel is too close to the camera, but I am not sure if this is at all possible. What can be done easily is switch the material to one that doesn’t use the alpha blending pass when the tree model is too close. In these cases alpha to coverage should be enough I guess.