About Store Forum Documentation Contact



Post Reply 
Code Snippet for more efficient tessellation
Author Message
Tottel Offline
Member

Post: #1
Code Snippet for more efficient tessellation
I use tessellation on higher graphic settings, but, it completely kills the performance when you have lots of objects (solid + with transparency) in your scene.

By default, tessellation is applied to everything. All LODs and even transparant objects.
So, with the next snippet, we are are calling the shader with different parameters: Only allow tessellation if the material has no transparancy and if it is the first LOD of the mesh.

In Main:
Code:
/******************************************************************************/
// Only allow tessellation on solid objects with first LOD.
ShaderTech* get_shader(RENDER_MODE mode, Material *material[4], UInt mesh_base_flag, Int lod_index, Bool allow_tesselation)
{
   bool tessellate = false;
  
   // Some things should not be tessellated (like terrain when D.tessellateHeightmap == false), set_shader sets this for us
   if(allow_tesselation)
   {
      // If material is a normal material (no alpha)                      
      if(material[0] != null && material[0].technique == MTECH_DEFAULT)
      {
         // We are in solid/simple rendering mode and this is the first LOD
         if(IsTessellationRenderMode(mode) && lod_index == 0)
         {
            tessellate = true;
         }
      }
   }
    
   return GetDefaultShader(mode, material, mesh_base_flag, lod_index, tessellate);
}
/******************************************************************************/
bool IsTessellationRenderMode(RENDER_MODE mode)
{
   return (mode == RM_SIMPLE ||  mode == RM_SOLID);
}
/******************************************************************************/

In InitPre:
Code:
D.tesselation(true).tesselationDensity(50).tesselationHeightmap(true);
D.setGetShaderFunc(get_shader);
(This post was last modified: 10-07-2015 01:39 PM by Tottel.)
08-25-2015 01:51 PM
Find all posts by this user Quote this message in a reply
Pixel Perfect Offline
Member

Post: #2
RE: Code Snippet for more efficient tessellation
Thanks for sharing. From your description of the default behaviour this seems like a prerequisite. I've not personally tried applying tessellation to anything in my game level as yet but will bare this in mind.
08-25-2015 02:11 PM
Find all posts by this user Quote this message in a reply
Tottel Offline
Member

Post: #3
RE: Code Snippet for more efficient tessellation
I noticed a problem with the code snippet above, and something of minor annoyance.

1. FIXED The terrain is also passed through this get_shader function, and if you pass tessellate as TRUE, it will always be tessellated when you turn object tessellation on (if you then turn on Terrain Tessellation, it's tessellated twice.. super slow!). BUT, if you pass tessellate as FALSE, the terrain will never tessellate, even with Terrain Tessellation set to TRUE.. How to solve this?

2. When tessellation is enabled on an object, it will tessellate the first LOD. This means that you need to customize your LODs for every object so that the 2nd LOD does not have a distance that is too high.. Else, it will tessellate objects that are far away. I solved this by making my first LOD and my second exactly the same (100% Quality), but the 2nd LOD has a distance of 5-15 so it won't tessellate beyond that distance and then display the actual first LOD. This seems ok, but it requires an extra LOD for every object.

3. For the LODs, it seems to be exchanging them with distance (from player to object) to the CENTRE of the object, not the ORIGIN. So, for very tall trees this distance is significantly reduced (2nd lod has a distance of 12, I never even see the first LOD, because the distance from the ground to the centre of the tree is more than this distance). Please let the distance be from camera to origin of the object, not the centre.
FIXED ---> INCREASE LOD SWAPPING DISTANCE FOR TALL OBJECTS

That being said, I need more control over which objects to tessellate. I don't want it on tiny bushes (on their solid parts), I don't want it on the player, ...). The material can't hold any custom data to check for this. What I am doing right now, is setting a material option that I never use to a specific value and don't tessellate on objects where the material has that value set. But this is extremely ugly and impractical.

Any ideas on this, Esenthel or anyone else?
(This post was last modified: 10-07-2015 01:41 PM by Tottel.)
10-02-2015 08:17 AM
Find all posts by this user Quote this message in a reply
Esenthel Offline
Administrator

Post: #4
RE: Code Snippet for more efficient tessellation
Hi

1) Meshes can't be tesselated twice, it's impossible.
Can you let me know how do you want it to work?

3) Lod is determined based on "Vec Mesh.lod_center" which is normally set to "Mesh.box.center()"

If you need more control, then I recommend modifying the source code to your needs smile
10-02-2015 11:38 PM
Find all posts by this user Quote this message in a reply
Tottel Offline
Member

Post: #5
RE: Code Snippet for more efficient tessellation
Hello Esenthel,
sorry for the late reply!

Here is what I add in "World with Character" tutorial:

In InitPre
Code:
D.setGetShaderFunc(get_shader);
   D.tesselation(true).tesselationHeightmap(false).tesselationDensity(20);

Function
Code:
ShaderTech* get_shader(RENDER_MODE mode, Material *material[4], UInt mesh_base_flag, Int lod_index, Bool allow_tesselation)
{
   return GetDefaultShader(mode, material, mesh_base_flag, lod_index, true);
}

In Draw
Code:
Renderer.wire = true;

Now, what happens:
If I pass tessellation as TRUE in the GetDefaultShader; all of the objects in the scene get tessellated AND the terrain too. Even with tesselationHeightmap(false). If I pass it as FALSE in the GetDefaultShader, terrain never gets tessellated.

Obviously, the terrain is also being sent through the GetShader, but how can I tell when? Is there some way to differentiate terrain from normal objects in that function?

Thanks!
10-05-2015 08:28 AM
Find all posts by this user Quote this message in a reply
Esenthel Offline
Administrator

Post: #6
RE: Code Snippet for more efficient tessellation
Oh I see,

You can take a look at :
https://github.com/Esenthel/EsenthelEngi...20Part.cpp
MeshPart& MeshPart::setShader(Int lod_index )

line
Code:
REPAO(_variation.shader)=GetCustomShader (RENDER_MODE(i), m, flag, lod_index, _vtx_heightmap ? D.tesselationHeightmap() : true);

_vtx_heightmap specifies a terrain mesh, and based on that D.tesselationHeightmap will be used,
this is "Bool allow_tesselation" in the
Code:
ShaderTech* get_shader(RENDER_MODE mode, Material *material[4], UInt mesh_base_flag, Int lod_index, Bool allow_tesselation)
10-05-2015 07:16 PM
Find all posts by this user Quote this message in a reply
Tottel Offline
Member

Post: #7
RE: Code Snippet for more efficient tessellation
Thanks! Will check on other pc tomorrow.
10-05-2015 07:25 PM
Find all posts by this user Quote this message in a reply
Tottel Offline
Member

Post: #8
RE: Code Snippet for more efficient tessellation
OK, thanks a lot. This solved it.

What I do now is simply not tessellate if set_shader passes false for allow_tessellation (which should be with 2 LL btw pfft)
Updated first post with correct snippet.

For the object_center for LODs: It makes sense to use it that way, but for tessellation of tall objects it does a very poor job. I guess the best solution is to simply increase the distance at which it swaps the first 2 LODs.
10-07-2015 01:37 PM
Find all posts by this user Quote this message in a reply
Post Reply