Hi, Qns… Is masking as bad as translucent in terms of performance? I have intentions of making all my props using some form of masking technique to provide variations to static meshes. For example : different variation of branches to a tree. Or should i just stop as this is a futile attempt, and it is just going to make everything slow?
Both shown are same tree type with left showing all branches, while the right showing some of it.
So if i have a couple of thousands of them as HISMC and overlapping in the background, would the performance drop tremendously due to the overdraw? If so, how much would be acceptable drop in FPS performance for such tradeoff for the variations?
if they were transparent, the performance impact would be very significant. If masked, no, probably not.
A masked material’s performance cost, correlates with how much of the mask is transparent. The opaque parts of thge mask cost far less to render. Translucent object however, cost the same regardless of how much of the mask is opaque.
I did some simple tests (from qty 2 to 8001) and found that the masking technique dropped about 3 fps from the normal static meshes using HISMC (optimised LODs and simple collision). Not bad considering how red it was in the shader complexity.
Masked pixels that has zero opacity still has non zero pixel cost. If you really need to hide something that way you can do it on vertex shader. This way you get zero pixel cost for clipped pixels and zero overhead for non clipped pixels. This is one way to hide triangles. Setting NaN to vertex position also hides a triangle.
Best case scenario: your triangles are fully sorted from front to back, so that the foreground masked pixels all get drawn first. In this case, there is no overdraw at all. You can theoretically achieve this if all your masked meshes are convex, as the engine will attempt to order draw calls in that way.
Using a full depth prepass will also greatly reduce the cost of overdraw, because the prepass will use a simpler pixel shader that only executes nodes connected to the Opacity Mask output pin. Once that depth buffer is constructed, each pixel on the screen only runs a single pixel shader for masked or opaque (not quite due to quads but close enough).
The technique worked perfectly. It saved 3-5 FPS from 700 HISMC instances. It is however, rather fussy about the accuracy of the mask. I was using 256x256 color mask and it gave me bad streaks. I had to upgrade to 512x512 color mask to get error free. I have never known about this unusual method. Learned something new today. Thanks again!
Since there are a lot of project settings that can affect the behavior of the prepass, I strongly suggest checking the behavior using something like RenderDoc (which has a convenient engine plugin included with UE4). You can see exactly when it is rendering what, and there is a view mode that shows you which pixels for a given draw call were early-Z rejected, allowing the shader to be skipped.
You can produce a NaN by passing a number divided by zero to the WPO pin. Causes the GPU to skip processing all triangles that use that vertex entirely, before backface culling even has a chance to do anything.
I tested NaN discarding with vertex color mask. I prefer negative number to square root. This should always be NaN. Dividing by zero could be also infinity.
Sure but without knowing anything about other vertices in triangle and without way to set vertex location directly but just the offset. Also if mask is procedural or texture and not per triangle then it’s impossible to do. NaN trick is only way to do it. It’s not documented feature but it works on all platforms that I know.