Hey! I recently updated the engine to 4.11.1.
Whenever I build my levels I get this HLOD folder popping up in the same folder as my map is placed in.
The folder is empty and doesn’t show any signs of being useful to anything as of now.
Does any one know what this is?
Hey! I recently updated the engine to 4.11.1.
Hierarchical LOD. It is what is used on Paragon to have distant objects combine together into an LOD made of smaller pieces.
So say we have a rock mesh. The rock itself has maybe 3 LODs, but in the level we build a giant cliff by using 5-10 of these rocks are maybe some busted arches etc. A level designer will select that whole group of meshes, load up the HLOD menu (window ->HLOD outliner) and add selected meshes to a ‘cluster’. Once enough clusters are added we will then press ‘generate clusters’ which can take quite a while.
The goal is to make it so we can still render the other side of the map, and to group meshes together that would typically be viewed at the same time so that we aren’t really making more overall geometry come into view. So thats why sticking to ‘clusters’ is a good rule of thumb. I don’t think I have seen too many clusters on paragon with more than 30 meshes and the average is probably more like 15-20. Of course I have been on other projects for a few months so that may have changed.
I believe the engine uses simplygon to generate the cluster LOD so it may not be available without.
Keep in mind the HLOD materials are not 100% perfect since they are a bake and will lose some dynamic attributes. If you want to keep advanced material things like fresnel in there, you may have to disable it during generation and add it specifically to the HLOD material and match them by hand.
Wow thank you so much for the detailed explanation!
I thought that I would be left with a lot of questions, but frankly you covered it all!
This helped quite a lot! Have a good rest of the week Ryan.
Well, when I come to think of it… If I would like to disable the HLOD during generation, how would I go about doing that?
During generation of what? I am not sure what you mean. The generate clusters button generates only HLOD, and no other generation process affects HLOD. Its completely self contained as far as I know.
Oh okey! I asked it because of: “Keep in mind the HLOD materials are not 100% perfect since they are a bake and will lose some dynamic attributes. If you want to keep advanced material things like fresnel in there, you may have to disable it during generation and add it specifically to the HLOD material and match them by hand.”
- may have to disable it during generation = Made me wonder of how I would disable it during generation.
Ah ok the manual material step… the only way is to rip it out or bypass it manually and recompile the material and then fix it back to how it was after you generate HLOD.
What about using this feature without simplygon? Is it possible in some way, I mean combining lod`s to reduce draw calls
So it works only with simplygon?
@RyanB: I am kinda lost with hierarchical instanced static meshes
Basically I have a static mesh, a rock, with several LODs. I would like to build a cave and some other elements in my scene (larger rock formations) using that rock (by copying, rotating, scaling and piling copies up to form what I need to form; kinda like modular design). Once I build a cave and/or rock formation, I’d like to turn all of those copies into hierarchical instanced static mesh to improve performance.
How do I do that? I can’t find any info online and no one can provide a clear answer
Please help :o
There is no automated way to convert hand placed meshes to hierarchical right now. You can technically do it but you will need to make your own blueprint that basically harvests the meshes and converts them. We never made anything like this public since there are just too many edge cases that cause problems, like negative drawscale meshes must actually be tracked and added to another container than has the root negatively scaled on that axis. Still we may eventually release soemthing like that but its kind of in a weird place where the solution we have is a long way from working, and to make it properly we would have to dedicate some code resources.
Look into blutilities. If you make a new actor of class Editor Placed Utility (something very like that), you have access to the editor selected mesh set and you can make a custom event and mark it “call in editor” (actually any BP can do that part, but the special class gives you access to selected meshes which is helpful) and then select it from the blutilities drop down and convert selected meshes to instances. So you will be basically doing a for loop, macking sure each mesh is the same mesh, if so adding the transform to an array and at the end of the loop marking the original meshes hidden (and no collision etc) and then spawn a new instance container per unique mesh and then spawn the individual instances by reading back the transforms.
Hmm… Sounds overly complicated and totally unfriendly to artists
What would be the other, easier way of doing this? (I assume I can manipulate individual instances in the BP’s viewport, and if so, I could build caves/formation in BP viewport and then simply drop HISM BP actor into the scene)
It is not intended as an artist tool. It is intended as a rendering method made specifically for grass and forest rendering, but it just so happens you can experiment with it in blueprint land if you want to.
You could basically make a transform array and then for each transform, add the mesh you want inside of the BP construction script. You don’t have to build it in the BP window, then you can place instances of the “cave” bp and then add elements to the transform array right in the level, then you just have to select those transforms to move/rot/scale. Remember to make the transform array both editable and ‘show 3d widget’.
I see. I guess I am just gonna have to dig it and see if I can manage to build such construction script.
Do I do that in the Level BP or in the HISM Actor’s BP ?
Also forgot to ask how does HLOD factors into this ? (do I need to build clusters as you described above first and then do the instancing, or something else?)
P.S. Just trying to understand to what extent performance optimization can be taken using instancing and HLOD for mobile VR (and in what order to do things to achieve it)
You would want to make a BP that actually spawns another class of Container BP. so you need
- BP that you place that is only to spawn other containers. This is the one where you place the blutility function
- the BP that acts as a container for the instances. This one is pretty simple. needs a variable for staticmesh, array of transforms, and a construction script that adds the meshes based on the transforms. When I first did this, I had to actually select and modify a dummy boolean on the ‘container’ BP since changing the transform array with a blutility was not calling re-run construction script, but I think you can get around that now by setting “Expose on Spawn” for the transforms, and actually setting them when you do “spawn actor from class”.
Additional node, it will only ever add actors to the currently selected sublevel.
Thanks a bunch for the tips! I got HISM working, I think (didn’t do any containers or blutility stuff):
Now I wonder about two things:
first - if I need to generate HLOD at this stage using HISM actors (after HISM is on the level and original meshes are hidden away) or do I need to generate HLOD first using original meshes and only then spawn HISM actor (and hide original meshes);
second - since I get world transforms of the original objects, I have to put HISM actors at 0 0 0 of the world so that the instances are right on the spot of original meshes. Would that affect visibility culling? I know that for conventional static meshes it doesn’t matter - engine culls based on the bounds of actual surface. So let’s say origin is at 0 0 0 and is in player’s view, but the mesh itself is somewhere behind player - that mesh will be culled anyway. How does it work with HISM? (let’s say I have a wall built out of instances; if player sees only one end of the wall, will engine render whole HISM wall, or only instances that are in the view?)
I am not aware of any way at all for HLOD and HISM to work together. They weren’t meant to be but maybe there is a way. They are pretty different systems. On paragon we used both but there was no overlap between them (actually didn’t use the hierarchical just regular instances but same diff here). Rock meshes and architecture used HLOD, foliage and ivy used ISMC. One reason was that it looked a bit nicer to exclude the ivy from the HLOD since when the ivy + rocks all went to HLOD at the same moment it was very obvious and the quality loss was most apparent on the previously sharp ivy edges etc.
I do not believe it will be an issue but I can see how it would be less than ideal for multiple reaons, like its hard to select the actor based on the root sprite if they are all at the origin. You can simply break the transform and subtract the container BP location, and then when adding the actors you always add the location. You can also do the same thing with raw transforms using compose transforms, by composing the actor transform with the inverse of the container transform but the break/location version is easier.
I was thinking about that approach, but then it will be a real pain to match HISM actor with original meshes in the scene (probably not a big deal, but too much hassle). Placing all HISMs at 0 0 0 guarantees exact match. I can always use outliner to select actors instead of trying to select them in the scene.
@RyanB: While on the subject of HISMC, is there any way you could pass this on to the team(s) that works on HISM and foliage ?
I tried my hand at creating a BP that would turn static mesh placements into HISMs. I think I succeeded, but I wonder what implications this setup has. Like:
- How are the original placements going to affect performance?
- Will this correctly bake lighting?
- How would I bake out the transform array?
Can you please explain the blutilities thing? I think I am using it, but I don’t know why, what for, or whether I am using it correctly.