How do I build correct Landscape HLODs in world partition?

Hi,

I’m having difficulties to understand the logic behind the HLOD of the landscape in world partition. I’ve made a lot of tests with all HLOD Layers possible but it seems that HLOD layer are not taken into account for the landscape. Or I am missing something…
When I build the HLOD with the default HLOD layer type (instancing), I have this :

  • In the first image, I’ve set the grid loading range in world partition to far far away , so there’s only the landscape without any HLOD. 61K tris and 1200 drawcalls
  • In the second, I’ve set the range so close that there are only HLODs. 16 Million tris and 650 drawcalls
  • The third is to show the resolution differences between the landscape and the HLOD.

As you can see the HLOD have less draw calls but meshes are massive polycount-wise and I’m only on a 2K terrain.

So, how would you build correct Landscape HLODs in world partition ?
Can I force a specific landscape LOD for the HLOD creation ?
Or maybe exclude landscape from HLOD build ?

12 Likes

Been trying to achieve the same but got my results are exactly like yours. Generated HLODs has way more triangles. The only video which makes it works is this: Unreal Engine 5 - Preview 1 - World Partition Landscape - YouTube

I tried to at least create same result as in the video but did’t manage to success.

did you find any answers to this? Ive been at it for 2 days now and cant get landscape HLODs working. it just seems broken

2 Likes

Hi! I don’t think landscape HLODs are supported yet, looking at the documentation.
https://docs.unrealengine.com/5.0/en-US/world-partition—hierarchical-level-of-detail-in-unreal-engine/

Some world components, such as Landscapes and Water components, are currently not supported by HLOD Actors.

So I’m wondering how they generated HLODs for the landscape in the default Open World map…

2 Likes

That’s the problem, it does generate some kind of “hlod” mesh. I don’t have a good solution.
For the momemt, I’ve put the landscape proxies in a custom World partition Runtime Grid with a stupidly big loading range. It might be a bad idea though, it just does the job for me now until a better solution is found.

Hi!
I managed to generate better landscape HLODs by doing the following:

  1. Delete existing HLODs (Build/Build HLODs/Delete HLODs)
  2. Restart the editor to make sure all HLODs were gone from the map (Otherwise, they’re still there, unloaded)
  3. Set the HLOD Layer to Custom, then select LandscapeHLODBuilder
  4. Set the Landscape Max LODLevel to 5 (or any level you want to bake)
    image
  5. Build HLODs

This is a workaround, and I hope it’s fixed soon, like the weird cross in the middle of the landscape that does not get any HLODs for some reason.
Another good thing is that HLODs are much faster to generate since they are much lower resolution.

Alex

6 Likes

I’ve just change the MaxLODLevel on the landscape before the bake and it’s working, thanks. :ok_hand:

Sadly I’m unable to get this method to work either.

Where are you assigning this custom HLOD layer? There’s no option in the landscape actor to assign an HLOD layer asset to it. Are you just setting as the world default?

Are you building from the commandlet or from the menu option?

Yes, I’m assigning it in the World Settings as the default HLOD layer.
And I built it using the menu.

Personnaly, I didn’t have to change the HLOD layer. But if you want to change it, I think you have to change the default by a new one, yes. You can then have an other one for the other objetcs .

What I have done to test it in the default open world scene is :

  1. I Changed the Landscape Max LOD to 5

  2. Delete the previous HLOD by using the menu
    image
    image

  3. I’ve then tested the game to be sure there was no more HLODs (If it’s ok, you should have holes in the distant landscape in runtime)

  4. Then I rebuilt the HLODs with same menu “Build>Build HLODs” as before, but this time I chose Build HLODs.
    image

And It’s working.

I do have the “cross” with no HLODs but it may be a technical neccessity to stitch hlods to the landscape.

My results are totally inconsistent, deleting all HLODs and setting MaxLOD to 5 this is my result:

Some areas are fine, some areas are bad, and one particular patch is just terrible.

I’m not sure if it matters but this is a max size landscape from the landscape generator (“fill world”)

Hi Arkiras!
Just in case, after deleting the HLODs, close and launch the editor and make sure that HLODs are gone when you play or simulate.
Then, build HLODs again. I think I had this strange behaviour before.
I hope it helps.

1 Like

Hi @A.Chekroun
When you mention changing Layer type to ‘Custom’ - is that in the Instanced or Merged HLOD layer?
image

Actually, it doesn’t seem to matter whether you use Custom (Landscape HLOD Builder) or Instancing mode.
As long as it is the Default HLOD Layer in the World Partition section of the World Settings.

1 Like

TL;DR: Increase “LOD 0 Screen Size” on your landscape component, and this will result in lower polycounts on HLOD landscapes

(But I’d recommend reading the explanation, as it gives a better sense of what’s going on)

Okay, so, after a lot of experimenting and digging through the engine’s source code, I’ve managed to come up with a solution for this. The above fix works fine for the Open World demo map, but it wouldn’t work on my actual game map.



------------------------------------- Diagnosis -------------------------------------

The issue actually lies in the Landscape’s LOD screen size settings. During landscape HLOD generation, the engine picks the LOD of the landscape component to use as the source based on these screen size values.

To understand the fix, we need to understand how landscape HLOD generation works. The HLOD Builder automatically assigns the “LandscapeHLODBuilder” class to any landscape proxies during the HLOD building phase. So the step mentioned in one of the replies above where you have to set the Landscape HLOD Builder as the parent HLOD layer, isn’t actually necessary. The engine automatically makes the Landscape proxies use this layer for HLOD generation.

To generate the HLOD, it essentially works out how big (in terms of screen size) the landscape proxy will be in-game when it turns into a HLOD at distance.

The problematic high poly HLOD meshes are created because the HLOD generator decides that EVERY TILE needs to use LOD 0 for the HLOD. To explain this, I printed out some logs:

This was during HLOD generation on a landscape with settings:

2022-09-02 17_59_43-Stormrite - Unreal Editor

As we can see, during HLOD generation the engine knows that the landscape’s max LOD is 5. It then evaluates that the LOD needed for the HLOD mesh is 0. To reach this value, it calculates that the landscape proxy will have screen-size of 1.26 when it switches into a HLOD, and for screen sizes over 0.5, the landscape should be at LOD 0.

THIS IS WHERE THE PROBLEM LIES, as 0.5 is the default value, but is far from desirable in maps with large landscape tiles.



------------------------------------- Solution -------------------------------------

WITHOUT EDITING ENGINE SOURCE:

If you increase “LOD 0 screen size”, then the engine will pick a lower LOD of the landscape component to generate the HLOD mesh. This is how you fix the issue.

I can’t give exact values that will work for your landscape, but by tweaking, generating HLODs & checking wireframes, you can hone in on the ideal settings for your landscape.

After editing mine, we can see that during HLOD generation, the algorithm now picks LOD 2 as the HLOD’s source instead of LOD 0 (reducing the generated HLOD by over 200k verts)

image

This method is good, but I can’t seem to get the generator to choose a LOD higher than 2 without decimating my landscape’s quality. So this is where the source code solution comes into play…


WITH EDITING ENGINE SOURCE (More control):

Alternatively, if you don’t want to mess with your landscape’s LODs, an easier fix is to force the HLOD generator to use a certain LOD of your landscape. This requires a source build of the engine, and is done by changing the return value of ComputeRequiredLandscapeLOD() in LandscapeHLODBuilder.cpp to the LOD you want.

For example, if I want to force LOD 4 for all Landscape HLODs:

Replace:
return RequiredLOD;

With:
return 4;

This will fix the issue without affecting your landscape’s LOD streaming. However, you need to make sure that your landscape actually has this many LODs. Alternatively, you could use:

return InLandscapeProxy->MaxLODLevel;

To return the highest available LOD, which is safer. (need to also make sure MaxLODLevel isn’t set to -1)

Hopefully this wasn’t too long-winded! :sweat_smile:

5 Likes

On the flip side - can you use the HLOD commandlet to generate HLODs for separate assets like buildings/rocks (potentially placed in another datalayer) whilst not generating any landscape HLODs at the same time? or is it not that granular?

As I would like to create HLODs for other assets, but I’m not comfortable with the state of the landscape HLODs just yet.

or if above is not possible, can you at least filter out HLODS for landscape and delete just those after all HLODS have been generated?

1 Like

Not too sure if there’s a way to do that in the commandlet, but you can edit the LandscapeComponent.h code to stop landscape components from ever computing HLODs:

virtual bool IsHLODRelevant() const { return false; }

(Line 824)

Had to do this because one of my individual landscape HLODs was 25GB, and the others were huge as well. Added about 20GB to the final package size! I have no idea how, since each landscape component in the HLODs is 2k verts at most :confused:

I do agree, landscape HLODs just aren’t in a usable state at the moment, unfortunately.

1 Like

Hlods take everything into account. Not just the level tile or landscape.

It is possible the foliage alone being cut into a landscape could generate a 20gb mesh replacement. Unlikely, and it just shouldn’t happen, but it is possible.

If the idea is to create a proper mesh replacement for the landscape. Use the level tab and generate one.

I would even suggest removing the landscape entierly and going with the mesh on the final iteration (youll have to change a few things, grass output, physmat etc, but it will always perform better).

The hlod system is pretty much just as bugged in ue4: Your problem analysis and proposed solution is probably the most correct thing anyone shared on this forum in the last year.

Still, 20GB generated hlod, sounds like you should pack up the project and share it as a bug report for the epic slackers to figure out.
Wouldn’t be surprised if it is looping over and creating multiple non visible meshes, or similar…

1 Like

Hey, guys.
Just wanted to add a few cents about that “cross empty HLOD”.
I’ve found, that there is an issue for actors, and landscape grids located on the line (or close to) of WP coordinate system.
It could be easily fixed by tweaking some WP options inside config ini file:

wp.Runtime.RuntimeSpatialHashUseAlignedGridLevels=0
wp.Runtime.RuntimeSpatialHashSnapNonAlignedGridLevelsToLowerLevels=0
wp.Runtime.RuntimeSpatialHashPlaceSmallActorsUsingLocation=1

Looks like, it’s related to algorithm which selects on what WP cell target actor should be aligned to.
Hope that helps.
Cheers

2 Likes

Is it looking like this HLOD issues for Landscapes is resolved/improved in 5.1 release?