Download

Is masking performance costly?

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.

It’s not as bad as translucency, but it’s more impactful than not using opacity masks.

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.

Thanks Guys. Think i have to do some FPS tests on the performance on “normal static meshes with variations” and masked approach.

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.

MaskedTrees2a.jpg

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.
HideAll.png

Thanks for the advice. Will report back if i have managed to make something of this.

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).

Thank you Kalle_H,

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! :slight_smile:

Masked-versus-WPO-vertex.jpg

Thanks, that is good to know. Should i be looking at “mask early material in early z pass” in the project settings for this to work?

You can enable mask in early depth only in project settings to have zero overdraw on masked objects, provided that you are using early z pass.

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.

Thank you. You have solved an issue that i was having with LOD when using this technique.

Masked-versus-WPO-vertex-2.png

Thank you guys for the information. I will play around with the settings to check on the masking performance effects.

Looks like i have barely scratch the surface of rendering forum in unreal. You guys have been great help.

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.

You can get the same effect by ensuring that triangle area is zero.

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.