Level Construction Set Part 3: An Instancing Issue
Instancing is great! It improves performance drastically and it's almost like getting 100 pizza's for the same price as 1. However, there is one instance (excuse the pun) in which instancing is not ideal and that is when you want to have the same mesh to have different materials applied. Basically the problem occurs when you apply a material to one mesh in a set of instanced meshes all of those instanced meshes change material.
In my Level construction set I have multiple pre-fabricated pieces and materials. As you may have seen I can apply materials to those pieces individually in the editor. Say for example I want to have a room floor with material 'A' but then I have a corridor as well using material 'B' but some of the same meshes... How do I solve this? I few thoughts came to mind and they are as follows.
1. Have Multiple GMF Files for Each Piece
2. Use Some LE Commands To Try Make An Un-Instanced Mesh
Now I hope you figured it out for yourself that option 2 is the way to go without me having to tell you. Option 1 is a rather outrageous work around which is a bit like the epitome of ugly!
So the next question is how do you carry out step two. Well I fished around in the LE wiki for commands that may help that I have never used before and I found just the right code for it. The algorithm is as follows:
1. Load the mesh from the file path - LE::LoadMesh()
2. Create an empty mesh - LE::CreateMesh()
3. Add the mesh from the 1st mesh to the empty mesh - LE::AddMesh()
4. Update the new mesh - LE::UpdateMesh()
5. Delete the first mesh - LE::FreeEntity()
Although this takes a lot more than simply loading a mesh it is the quickest and cleanest workaround I could find for this problem. See below the function:
LE::TMesh LoadMeshNoInstance(std::string meshPath){ LE::TMesh instMesh = LE::LoadMesh(meshPath.c_str()); LE::TMesh noInstMesh = LE::CreateMesh(); LE::AddMesh(instMesh, noInstMesh); LE::UpdateMesh(noInstMesh); LE::FreeEntity(instMesh); return noInstMesh; }
PROBLEM:
Now we have solved the problem of not being able to load un-instanced meshes but the global problem isn't solved just yet right....... right?
Well no its not solved. You may recall the first line of this blog, "Instancing is great". We don't want to apply this non instancing loading functions to everything in the scene otherwise we will get horrible performance in run time and no body wants that!
Basically the ideal outcome would be that every "same" object with the "same" material utilize instancing. For example, if you had 10 2X1m blocks with Material 'A' and 15 2X1m blocks with Material 'B', 9 of the blocks with material 'A' would be instances of the first block with material A and 14 of the 2X1m blocks with Material 'B' would be instances of the first block with material B.
To solve this I will organize all of my blocks in a list. Each object has a type ID and a material ID which is inherent from my DDD system prior this problem. When a piece is to be loaded into the game it will look for a piece with a matching type ID and material ID from the list. If there is a match it will load the piece with instancing and if there is no match it will load the piece without instancing using the above function.
This will add a fair bit of overhead but fortunately it is overhead in the load time of the game rather than game play time and, therefore, it is less crucial.
The below image shows the result in my editor. 4 of the same piece with 4 different materials applied.
Thanks for reading. Hope you enjoyed
- 4
6 Comments
Recommended Comments