MeshShadowReceiver component requires a Mesh Tree object in order to search for polygons which are intersecting with the shadow volume. You can create a Mesh Tree object from the context menu of Project window. Right click a folder in which you want to create a Mesh Tree, and select “Create > FastShadowReceiver > XxxxMeshTree”, where Xxxx is Binary, Oct, or Terrain. These mesh trees must be built from mesh object(s) before use as described below, and if the mesh object or the layout of the mesh objects is changed, need to be rebuilt.

BinaryMeshTree and OctMeshTree

BinaryMeshTree and OctMeshTree have almost same functionality. Both are used for either a single mesh object or a game object which consists of many child MeshRenderer objects. Basically, the difference between BinaryMeshTree and OctMeshTree is performance, such as search speed, memory usage and scissoring cost. Roughly speaking, OctMeshTree can save memory but slower for small scene and search result will have larger extra area.

Large extra area will incur a performance penalty. MeshShadowReceiver has “Scissor” option. If you enable it, the extra area can be cut out and GPU performance will be improved. However, it will take some CPU time to scissor polygons. If you use “Scissor” option with “Scissor Margin” property, you can reduce scissoring cost, but it is only applicable for BinaryMeshTree. For more details, see Setup Shadow Receiver section.

If you are not sure which Mesh Tree is better, simply try both and choose the one which has better performance.

The differences between BinaryMeshTree and OctMeshTree
BinaryMeshTree
OctMeshTree
Search Speed
Faster for small scene
Faster for huge scene
Memory Usage
More
Less
Search Result
Smaller extra area
Bigger extra area
Scissoring
Faster
Slower

Before you use a Mesh Tree object, you need to build it from mesh object(s). Set a Mesh object or a root game object of the environment object(s) at ‘Root Object’ in Inspector View. Then, ‘Build’ button will be enabled. It is recommended to set a prefab object as the Root Object instead of a scene object. Otherwise, the reference to the Root Object cannot be serialized. You will need to set the Root Object again when you rebuild the Mesh Tree.
InspectorMeshTree

Optionally, you can specify ‘Layer Mask’ and ‘Exclude Render Types’ when you set a root game object. If you are building OctMeshTree, you can also specify ‘Min Node Size’ before build. Smaller ‘Min Node Size’ will make search result smaller, but memory usage will be bigger.

‘Scaled Offset’ and ‘Fixed Offset’ are used to push each vertex of the mesh along its normal vector. This is necessary for avoiding z fighting problem, especially if the environment is large. The offset value is calculate for each vertex v as follows:
offset = 0.00000025 x |v| x <Scaled Offset> + <Fixed Offset>.
The reason why it has Scaled Offset is, z fighting problem is caused by floating point rounding error, and maximum possible value of the error is roughly proportional to the absolute value of the operands.

TerrainMeshTree

TerrainMeshTree is used for a Terrain object. Set a TerrainData asset to ‘Terrain Data’ in Inspector View, and press ‘Build’ button. There are no other build options for TerrainMeshTree.

InspectorTerrainMeshTree

Building a Mesh Tree at runtime
It is possible to build a Mesh Tree at runtime, if the meshes of the environment objects are readable. It will take long time though, building process is done in background thread. It will not stop your application. However, shadows are not seen until the build process is completed.
There is an example scene in FastShadowReceiver/Demo/SimpleExamples/RandomLevelGeneration. Also, you can find C# source code for the runtime build in FastShadowReceiver/Demo/Scripts/RandomLevelGeneration.cs.

Links

Leave a Reply

Your email address will not be published. Required fields are marked *

Anti Spam Code *