Occlusion is a mechanism by which instances of assets can be determined not to be visible because something is between them and the camera. HeroEngine's client supports the concept of occluder assets which are designed to block the visibility of things. This is done by a process known as Dynamic Potentially Visible Sets (dPVS).
Because the wall occludes the wagon in this scene (when viewed from the character), the wagon will be culled (not drawn).
To make this work, art assets must be designed with special occluder meshes which are designed to "block" visibility through them. Special occluder-only meshes can also be used to place visibility blockers manually in a scene. Heightmaps automatically provide occlusion by breaking themselves up into occluder chunks.
Proper use of occlusion is critical to frame rate management.
This section details how to create and use occlusion meshes. As such this article is intended for both artists and world builders.
The HeroEngine client will attempt to determine if an object is being occluded by something else and, if so, cull that object out so it does not render. With sufficient occluding, frame rate can be dramatically improved. At the same time, the need to "room" out an area is greatly reduced. However, both rooming and occluding should work hand in hand for an effective visibility solution.
By default, Assets are not automatically occluders. This means just because you drop an instance of an asset into the world, don't expect it to act as an occluder. For that to happen, the asset has to be specially prepared by the artist (as explained below).
There are three ways for occlusion to take place:
- Place instances of special occluder-only assets to block visibility manually
- Use assets with occluder meshes built-in
For something to be considered a good occluder, it should have the following characteristics:
- Big enough to block stuff (a wall is good, a salt-shaker is bad)
- Opaque (translucent stuff doesn't block visiblity)
- Solid (holes are bad)
- Flat (unless nothing can be inside of it that you want occluded)
The "flat" requirement may seem odd. This is because an occluder cannot occlude something that is in its own bounding volume. This is critical, because it means that a house "shape" will not occlude anything that is inside of the house. Instead, each of the walls (and roof) need to be their own individual occluders. So "flat" is more of a guideline, as anything that won't have something inside of it will also make a good occluder.
As part of the Required System assets, you will find various occluder-only assets which represent various shapes you can use to manually occlude things.
Using Occluder-Only Assets
For World Builders
Several occluder-only assets are available in the Asset Library (part of the Required System Assets). Artists can make more. You can place these assets to block visibility.
Occluder-Only Assets are normally invisible. In order to see and/or select them, you have to turn on Occluders from the Filters drop-down menu. If you don't turn on the Occluder filter, you won't be able to select, manipulate or even see them!
Once you add an occluder to the scene, then you can resize it (the bounds tool works well with these), move and rotate them into place. The idea is to match them up with real occluding surfaces in the scene as precisely as possible. Be very careful to test how these intersect things. There is a fair bit of fiddling with these to get things right.
To help make it easier, one thing you can do is turn on the dPVS Bounding Boxes, in the "Debug" section of the Renderer panel. This will show a bounding box for every object dPVS thinks is visible. As you move an occluder around, you can see things behind it start to cull away. Note that not everything behind an occluder will cull, and sometimes things will "flash" on and off. This is normal behavior as the algorithm does a cost-benefit analysis to see if it's better just to go ahead and draw something vs. figuring out if it's occluded. Generally, though, things entirely on the opposite side of an occluder will go cull.
- There is 2 other switches on the DPVS render panel. They are the Write switch and Test switch.
- The write model is the what is used to occlude. The write model "writes" (or draws) its polygons into a buffer. Then each object tests to see if it's test model is visible by testing if any of all of the pixels of the test model's polygons are hidden behind whats been written to that buffer.
- The test model is what is used to see if something is occluded.
When artists embed Occluders in their models, the write model is what they are producing. The test models are automatically created as an oriented bounding box surrounding the geometry.
You can also watch the dPVS section of the Statistics panel to see how well the occlusion is culling away objects.
In the above example, image A shows the bounding boxes of all the objects that are being rendered with Occlusion Culling is turned off in the render panel. The B image shows how many are drawn with Occlusion Culling turned on. Notice the dramatic reduction in objects being drawn. The statistics panel can help determine how many objects are being successfully culled by occlusion.
Creating Occluder-Only Assets
- Create a mesh in Max
- Name it "occluder_only".
- For instance of asset, set Viewability property to OCCLUDER_ONLY
You'll want to texture map it with some standard occlusion texture (using the HeroMaterial). Normally an occluder_only asset is completely invisible, but World Builders can turn on visualizing these assets via the Filters, so you'll need to texture it for that purpose.
- Generally you will want to make thin objects. Be sure that if you make paper-thin objects that you build them double-sided.
When you create an instance of this asset in HeroBlade, set the Viewability property to OCCLUDER_ONLY. It might be a good idea to put these in the Library this way too.
There is nothing special you have to do in order for Heightmaps to act as occluders. A Heightmap is automatically broken into chunks of a particular size (say 8 by 8 grid cells, but this might change) which each act as an individual object that both has a write and test model. In other words, each chunk can be individually culled and can block things behind it. Note that it cannot block things that are inside of the chunk in question (that is, standing on it).
Ideally you want to sculpt your land to give as many opportunities for heightmap terrain to occlude as possible. Make tall hills/mountains that players cannot get on top of so that it will occlude things on the other side.
Assets With Occluder Meshes
Artists can build assets that have occluder shapes already embeded in them. This can be done in two ways:
- Entire Asset is Occulder
- Asset has special Occluder Meshes
Placing Assets with Occluder Meshes
For World Builders
Assets that have occluder meshes are placed normally. The occluder parts move along with them. There is no way to visualize the occluder surfaces in a textured way, but you can turn on the Write Models debugging in the dPVS section of the render panel. This will draw red outlines of things that are occluders (the write models).
It is important to check if assets have occluders, in this manner, before placing occluder_only assets. Otherwise you may burn up any frame-rate improvement with too many redundant occluder writes.
If an asset is one that should have occluder meshes built in, but does not, it is important to communicate this back to the art team so that they can correct the situation. Further, keep an eye on assets that have mistakes in the occluder meshes. This might be where they don't match the shape well enough, occlude too much, or have seams or junctions that break the seamlessness of the occlusion such that they don't work as well as they should.
Creating Assets with Occluder Meshes
Entire Asset as Occluder
You can assign an entire asset as an occluder by adding the User Defined property on a mesh of "DPVSOccluder=true". If no embeded occluder_only meshes exist, then the entire model will be used as an occluder. There is also a max tool that will write this field out along with the grid snap settings, you can find instructions on it here Asset Settings
This works best for solid objects (things that nothing can be inside of), like a chunk of wall or a big door. These are often no-brainer occluder assets. But be careful of such shapes if they are extremely poly dense; in such a case you would probably want to use a simplified imbeded occluder mesh or meshes.
Only non-animated (static asset export) assets can be occluders.
You might also find that using an entire asset as an occluder works well enough even for assets that are intended to have things inside (despite the general rule against it). For example, if you have a dungeon "tile set" made up of a lot of small segments of corridor that World Builders can place, then you might find that making each segment an occluder works well. This is especially true if the segments are relatively small and the geometry is not complex.
This works because even though a particular tunnel segment won't occlude anything in it, there will be so many of these small segments linked together than they will tend to block each other effectively.
The "Dungeon Tile Set" in the Hero's Journey reference implementation is an example of assets where this works well.
Embeding Occluder Meshes
Because many assets are too complex or improperly shaped to be good occluders, but should otherwise have occlusion happening, it is possible to create meshes that become simple occluders and embed them in your assets for export to HeroEngine.
The set of meshes must be conservatively smaller that the object they represent. That means, the occlusion meshes should not be "larger", or extend beyond the boarder of, the visible mesh of the object. Parts that are translucent or alpha masked cannot participate, so the embeded occluder meshes need to not represent those sections either. If the occlusion meshes extend beyond the borders of the visual mesh, then things that should be visible may end up being improperly occluded.
Only non-animated (static asset export) assets can have occluder meshes.
To do this,
- Create one or more occluder meshes (no texturing)
- Group all of these meshes together
- Named the group "occluder_only"
This house is a very complex mesh. It has lots of polygons, and alpha masked areas.
If no one can go inside of the building, then a single solid occluder mesh can be used similar to what is shown at the right. In this case, this mesh would be named "occluder_only" and, as there is only one mesh representing the occluder, no grouping is needed.
If this is the sort of building with an inside, then the occluder mesh has to be broken into a bunch of sub-meshes. In the image on the right, each colored surface would be a unique mesh and all of these would be grouped, with the grouping node named "occluder_only" (though you'd want to cut a hole for any portals too). The reason this is required is because an occluder cannot occlude anything within its own bounding volume. So if it wasn't broken into a bunch of planar meshes as shown above, then it would not occlude anything inside the house (but would occlude things on the other side of the house).
The key to occluder meshes is to simplify the geometry. It must be conservatively smaller than the mesh it represents so it doesn't improperly occlude things that the visible mesh wouldn't. It should be relatively simple because the silhouette of each of these occluder meshes must be rendered on the CPU (via a very fast scan-line rendering method) into an occlusion buffer; so the fewer the polygons the better!
Notice in this example that the occusion mesh is just roughly the same of the real mesh. With more polygons it could more precisely match the visible mesh, but that may not be desireable. A small number of polygons that approximate the visible mesh "good enough" is typically all you want.
If this building would not allow anyone inside, technically it could be done by just setting the whole asset to be the occluder. But this is a bad idea for this model because it has a tremendous amount of detail polygons (like the vines growing up the sides and so forth) that would slow down the occlusion calculations. Plus it has polygons with alpha mask, so they would occlude things improperly (being solid as far as occlusion is concerned). For these reasons, this sort of shape should have an embeded occlusion mesh or meshes as the case may be.
So why not just not use any embeded occlusion mesh and let the World Builders place occlusion assets? That's one approach, but it makes building areas more tedious. If assets that are used a lot have built-in occluder meshes, then World Building becomes a great deal more efficient. Further, artists can be much more precise about occlusion surfaces when geometry is complex.
Here is an example of a building that you can go into. In this case the the occluder mesh is a group of individual planes as noted by the different colors. In addition to the occluders on the outside of the group, there is also cross sections on the inside so that when you are in side the building it occludes what is outside.
Here is another example of an interior room with a specialized occluder group