UnigineScript
The Language
Core Library
Engine Library
Node-Related Classes
GUI-Related Classes
Plugins Library
High-Level Systems
Samples
C++ API
API Reference
Integration Samples
Usage Examples
C++ Plugins
Content Creation
Materials
Unigine Material Library

Using Tessellation

This tutorial describes how to automatically generate a highly detailed model that casts finely contoured shadow in real-time at the little performance expense using distance-adaptive hardware tessellation. For this tutorial there will be used a dragon from the Heaven benchmark, where you can see tessellation in full action.

Heaven benchmark

Using tessellation is quite easy: we will need to feed to the Unigine engine a displacement map and a simple low-poly model to be tessellated (which is done very quickly). As a result we will get an impressively spiky dragon rendered in much higher visual detail - it will look like the high-poly model. By tweaking different tessellation settings it is easy to control the exact amount of displacement and achieve the optimal performance.

Hardware Requirements

Hardware tessellation is available only on:

  • DirectX 11
  • OpenGL 4.0
If these APIs are not supported by your graphics card, models will be rendered with similar materials except they are non-tessellating.

Step 1. Create Textures for Tessellation

After a low-poly and a high-poly models were created in the external 3D editor and exported into Unigine format, specific textures (a height map and a tessellation density map) should be created that will tell the engine and a graphics card how to tessellate a model in real time.

  1. Go to the <SDK>/bin/ResourceEditor_x64.exe to run the ResourceEditor.
    Notice
    It is strongly recommended to load a 64-bit version of ResourceEditor, because high-poly models for tessellation usually have a very big size and hence require using as much memory as possible.
  2. Go to the NormalMapper tab.

  3. On the right panel choose Load low to add a low-poly model (or press Ctrl + O). For this model a height texture will be created.

  4. Select the path to the low-poly mesh.

    The model is shown in the Normalmap display mode. There is no normal map and the default empty one is displayed in red:

    Here, we are going to use a halved model of the dragon, because it has a symmetrical UV map for both sides. It will both reduce the time required to calculate a normal map and allow more details.
    Notice
    NormalMapper does not support multiple UV tiles. Calculations will be done only for texture coordinates [0;1] while everything outside them is disregarded.
  5. When using a halved model, it is important that all normals are directed correctly, especially along the partition. For this model of the dragon it was done manually.
    If necessary, you can check normals by switching to the Tangent display mode. They will be displayed in blue.
    Notice
    Press G if you want to reset the pivot to the camera.

  6. Go back to the Normalmap display mode.

  7. Choose Load high to add a high-poly model.

  8. Select the path to the hi-poly mesh.

    The high-poly mesh is shown in the High mesh display mode.

  9. The dragon has a complex surface, that is why we need to load also a Cage mesh. It will allow to bake a clean normal map.

  10. Select the path to the cage.

  11. To view the loaded cage mesh, switch to the Cage mesh display mode.

    As you can see, it is a mesh that is slightly bloated to be bigger than a low-poly and a high-poly mesh. It encloses both of them.

  12. Now we can start creating a height map for tessellation. First of all, check the Height option.

  13. Set the Size of the map to 2048 (valid for both a height map and a normal map). The bigger the size, the longer calculations will take.

  14. Set Anti-Aliasing to 2x or 4x to get smoother lines in a texture.

  15. Set Level to 0. In this case, the real maximum height displacement between a low-poly and a high-poly mesh will be used as texture pure white (or pure black, depending whether it is above or below a low-poly mesh).

  16. Set Clamp to 0 as well. No heights need to be clamped within a normalized range.
    Notice
    If there will be some unnecessary height peaks after the texture is baked, we can re-bake it using this parameter.

  17. Set Extrude to 4 pixels to avoid seams. This would appropriate for the current texture size.

  18. Click Run to start creating both a normal map and a height map.

    You can see the generated normal map applied to the low-poly mesh at once:

  19. Click Save to save the created maps.

  20. Select the folder where maps should be saved to. Specify the name of the normal map with _n postfix.
    Notice
    A height map will be automatically stored in the same folder with _h postfix.

    Here is our saved height map:

  21. Using any texture as a base (for example, using a Surfaces texture would be very convenient), manually create a tessellation map.
    • Black color to indicate areas that should not be tessellated.
    • White color to indicate areas that should be tessellated as specified by materials settings.
    When coloring, remember that it will be sampled only in mesh vertices. Plus we can freely make two times smaller (1024 × 1024).

    A tessellation map is very efficient for optimizing real-time performance. Here, we only need a dragon head and chest to be highly tessellated, while the wings are flat and can be tessellated less.

Step 2. Add a Mesh into the World

Now we've got all textures necessary to tessellate the dragon in real-time.

  1. Export a mirrored low-poly mesh with its LODs as surfaces as described here. Though the mesh would not be tessellated when the camera moves far from it, it is still better to use low-poly LODs to keep the frame rate high.
    1. It is recommended to create a dummy (that is a smaller and very rough low-poly mesh) inside of a low-poly mesh and export it as its separate surface. It will allow to cover gaps at the seams, otherwise visible.

      Here is how our underneath dummy surface looks like:

    2. On the Exporter panel at the side check the Groups as surfaces box.

    3. Set up other options and click Export.

  2. Add a mesh into the world as described here.

  3. Disable all distant LODs as as described here, if necessary.

Step 3. Create a Tessellating Material

  1. Press M to open Materials editor. For further actions, you should already have a material library associated with the world (see how to add a new material library, steps 1-5).
  2. Select a basic (and therefore unchangeable) mesh_tessellation_base material in the list and click Inherit the material.

  3. Choose the world-associated material library where to save a new tessellation material and specify its name.

  4. To assign the created material, go to the Nodes panel -> Surfaces tab. Select a surface (or multiple surfaces when holding CTRL or SHIFT) and click Load the material icon.
    Notice
    You can also assign a material to the currently selected surface using Assign material button.

  5. Choose the material from the list:

  6. The tessellating material is now assigned and we can modify it.
    In the Materials editor go to the Textures tab. Load the height map that was previously created.

  7. Select the path to the height map.

    Notice
    A height map that has _h postfix and is located in a folder named uncompressed will be automatically compressed by the engine. Compressed texture is stored in the root folder of the uncompressed one.

  8. Load the tessellation map we also created beforehand. It is not obligatory, but allows to save performance by indicating less tessellated areas. Without it, everything will be tessellated to the maximum, even flat surfaces.

  9. Select the path to the tessellation map.

    Notice
    A tessellation map that has _t postfix and is located in a folder named uncompressed will be automatically compressed by the engine.

  10. In the same way, load base textures: a diffuse texture, generated normal map and a specular map.

    Notice
    To be automatically compressed by the engine, the texture should be located in a folder named uncompressed and has the following postfixes:
    • diffuse texture — _d
    • normal map — _n
    • specular map — _s

    Here, our dragon is completely textured:

  11. Go to the Parameters tab. Set the Threshold to 7 units. Within this distance polygons will be tessellated as specified by settings.

    To tweak tessellation, you also may need to move the camera closer, so it is in range of the Threshold distance:

  12. Increase the Factor to 9. Take notice that wings are almost not tessellated as the loaded tessellation map specifies.

  13. Increase the Scale to 0.9. It scales up the displacement that was baked into the height map, so that vertices are displaced even further away in the result.

    The spikes became longer:

  14. Press hot key 2 to toggle the wireframe on and see how how polygons are subdivided. There are too much polygons created:

    To optimize performance, we can skip tessellation of small polygons.
    Set the Length to 0.12 units. If a polygon is smaller, it will not be tessellated any further.

    As you can see, big enough polygons are not affected. The dragon still looks the same, while we gained benefit performance-wise:

  15. Now we need to adjust how the tessellation will fade out with the distance.
    Increase the Distance up to 15 units. Within this distance tessellation will smoothly fade out. When the camera reaches its end, vertices are not displaced at all.

    Overall, the mesh will be tessellated in range 7 + 15 = 22 units.
  16. Right now the Factor within the tessellation fade Distance drops down too fast.

    Decrease the Attenuation down to 0.5, so that polygon subdivision factor decreases slower.

  17. The Scale also drops down within the tessellation fade Distance too fast to our liking.

    Decrease the Power down to 0.5, so that displacement scale decreases slower.

Step 4. Further Adjustments

  1. Tweak coloring and specular reflections of the mesh. All non-tessellating parameters are the same as in the simple mesh_base material.
    1. Decrease the Glossiness to 1 for wider specular highlights. It will accentuate the spikes.

    2. Increase the Specular up to 2 to make the dragon look shinier.

  2. When the mesh is tessellated, the seams are almost unavoidable. They are visible against the light background.

    Go to the Nodes panel panel -> Surfaces tab and enable the underneath dummy surface.

    For it, you will have to create a similar material, but non-tessellating (inherited from mesh_base). As a result, seams are nicely covered:

  3. Set up LODs as described here.
  4. And here is our the final result, with all other tessellated objects added to the scene:

Last update: 2017-07-03