Foliage + Lightmaps is broken/bugged/dysfunctional - Detailed explanation

So I’ve been looking into this issue for a the past few days now and have come to the conclusion that either foliage with baked static lighting is currently fundamentally broken due to what seems like some design oversights, or that I’m missing something with how it works altogether.

.

My scenario is this:

  • I have a large landscape with
    approximately 31k trees, currently
    consisting of 1 tree model.
  • The tree model has lightmap Uvs
    carefully laid out for a minimum of a
    32 x 32 px lightmap, which the model
    is set to by default in the static
    mesh editor.
  • Tested and baked individually with
    the default lightmap size of 32px,
    the tree lights correctly as
    expected.

.

Upon painting and baking lighting of the tree on the landscape, I am receiving the following warning:

InstancedFoliageActor_0 The total lightmap size for this InstancedStaticMeshComponent was too big and it was automatically reduced. Consider reducing the component's lightmap resolution or number of mesh instances in this component


InstancedFoliageActor_0 The total lightmap size for this InstancedStaticMeshComponent is large, consider reducing the component's lightmap resolution or number of mesh instances in this component

.

The result of this is that the lighting for the trees looks very bad, seemingly due to the lightmaps now being reduced below 32px. Looking at the warning, it tells me to * “consider reducing the component’s lightmap resolution or number of mesh instances in this component” *

.

Now, to me this is unexpected - my landscape is made up of 64 components, each with approximately 484 trees, my Packed Light and Shadow Map Texture Size is set to 1024in World Settings, so it seems like there should be plenty of room for 484 32x32 lightmap atlases. (if my calculations are correct, you can fit 1024 32x32 lightmaps into a 1024x1024 texture).

Regardless, I gave it the benefit of the doubt and increased Packed Light and Shadow Map Texture Size to 2048, and then 4096. No matter what I set Packed Light and Shadow Map Texture Size to, the result was always the same; same warning + bad lighting on my trees.

.

I did some further investigation, looking at the baked lightmaps themselves with Packed Light and Shadow Map Texture Size maxed out at 4096, and concluded that it currently tries to bake all foliage into the same atlas, regardless of any landscape component. With this and the fact that the editor references all foliage as InstancedFoliageActor_0, It seems that all foliage is treated by the lightmapper as one giant model which seems highly inefficient, especially when it comes to texture/lightmap streaming.

.

Here are the following things I have tried to break up the foliage into smaller components/lightmap atlases:

  • Duplicating the model and painting
    the copies as different foliage
    types.
  • Creating multiple Foliage Type
    assets with the same model and
    painting them as above.
  • Separating the landscape into 4
    different sub-levels and re-baking
    (highly inefficient workflow)

None of the above worked for me, I still receive the same warnings and the same issues for all scenarios.

.

In Epics own documentation on [Folaige Instance Meshes][2] I found this under Lighting:

  • Lightmap Resolution - This must be a
    small enough number so that all the
    shadow maps for instances in a single
    cluster (by default 100) can be tiled
    together without exceeding the
    maximum texture resolution
    (4094x4096).

.

Has the cluster size been changed? Can it be changed manually? I cannot reduce the lightmap size of my trees any lower than what they are right now and it seems crazy to me that it’s struggling with this. I’ve seen dozens of threads posted about this issue with zero solutions.

Can someone out there offer me some information or advice about this?

I’d be happy to upload an example project if necessary.

Thanks.

Adding some more info regarding my model and test scene:

No problem Andrew, let me put something together for you quickly and I will post back here when it’s ready! :slight_smile:

Here’s an example project In it you will find an example tree (the same one im currently using for testing, minus LODs) and an example scene which is similar to my own (Static Lighting, similar number of trees and a Landscape)

Please let me know if you need anything more and I will package it up ASAP!

Thanks!
-Rob

Hey brisk1,

Would you mind sharing with me the tree asset or the example project in question so I can see the issue on my end? I would say, you can lower you min lightmap resolution to 16 and it will still look okay.

I can more than likely find a solution once I have messed around in your project for a bit.

Cheers,

H

Hi Andrew, I just wanted to check in and see if you had a chance to look at the test scene and if you were able to replicate the problem?

Hey Rob,

So I went into the test project you provided and immediately had some things for you to improve your situation. This might not be the case in your actual scene, but with levels this large be sure to use a Lightmass Importance Volume.

Secondly, the density in which the foliage has been painted is very extreme and even on my powerhouse of a machine, I was having some performance issues. Be sure you are establishing an End Cull Distance by setting up the Per Instance Fade amount within the static meshes material.

Third, the only way I see to workaround this is to reduce the density of your trees a little bit, per landscape component. What you can do is give them a bit larger scale so you can have less that occupy the same amount of space. You then need to go into the foliage setting and set the lightmap resolution there to override the static mesh settings.

Next, you need to establish LODs, this makes it so you don’t have one single LOD which quickly fills your packed lightmap size for your landscape components. Also using the cascaded shadow maps to help conceal what might be poor lightmap resolution. This way as you get closer, the nice high resolution shadow will stream in, and the far shadows with low lightmap resolutions will not be as noticeable.

If none of this seems to be working, you can resample your landscape to have a larger amount of components and divide them into 2x2 subsections to have greater control over the packed lightmap resolution per component.

Let me know if you have additional questions.

Cheers,

Hi Andrew, thanks for getting back to me!

Regarding the scene and models -

Lightmass volume: Apologies, I totally forgot to put this in the test map but rest assured I do have one in my current level.

The density of trees: They are simply this extreme as a benchmark to see how lightmass and Unreal will cope when the level is fully filled with more complete foliage.

LODs and culling: The model provided in the project is without it’s LOD, but the main version I have here LODs out to an impostor pretty early so the perf is pretty good - culling is something I will definitely implement at some point too. If it helps with testing, I can update the project with the LODs, just say the word! :slight_smile:

**“Next, you need to establish LODs, this makes it so you don’t have one single LOD which quickly fills your packed lightmap size for your landscape components.” **

I’m not sure what you mean by this - doesn’t foliage share the LOD0 lightmap between all LODs? Wouldn’t the lightmap size be the same regardless of having LODs?

**“Also using the cascaded shadow maps to help conceal what might be poor lightmap resolution. This way as you get closer, the nice high resolution shadow will stream in, and the far shadows with low lightmap resolutions will not be as noticeable.” **

This is something I am currently trying; using a Stationary Directional Light up to mid-distance, but there’s such high disparity between lightmaps and cascade shadows that there is quite a glaring transition - the lightmaps are simply not of a high enough quality due to them being resized down drastically. No matter what I do with that tree model it is not possible to reduce it further without breaking the lightmaps completely. 32x32 should be really be ok for a tree that size…

1/2…

2/2

"If none of this seems to be working, you can resample your landscape to have a larger amount of components and divide them into 2x2 subsections to have greater control over the packed lightmap resolution per component."

This brings me to the main problem I’m having, which is not perf but that currently Lightmass does not seem to atlas/group instance foliage according to the landscape component on which it’s painted - right now, no mater how many landscape components, foliage types or sub-levels I have, Unreal attempts to atlas ALL foliage together into one sheet, it doesn’t seem to care about clustering it intelligently by distance, surface, component or anything, which is really bad for both texture streaming and also being able to have lots of baked foliage in one level (all foliage squeezed on to one giant atlas).

Could you check to see if this is correct?

Thanks again for taking the time to look into this - very much appreciated! :slight_smile:

Ok so I wanted to be absolutely sure that that component size/number was being ignored by foliage, so I did another test where the landscape was made of much, much smaller components:

Here you can see that my landscape component size is quite small, each component containing only around 30 trees, with the entire landscape consisting of 1024 components and a total of 30k trees.

My Packed lightmap sheet size is maxed out at 4096 and I am still getting the same warning: “InstancedStaticMeshComponent was too big”

This seems to confirm my theory that foliage instancing + lightmaps is broken in some way. There is no way 30 32px lightmaps can fill an entire 4096 lightmap atlas! :slight_smile:

Does this seem right to you?

Spent the weekend agonising over this - I tried it with a simple box + a 16x16 and even 8x8 res lightmap but this issue is still occurring after a certain amount of foliage instances are in the map. Have you had any luck reproducing the bug on your end? I might roll back a couple of versions to see if this is a recent bug or if it’s always been this way.

Ok so I’ve fully explored all possible solutions to this and come up empty, so I’m moving this to the bugs section.

It’s fully reproduce-able using the project provided - if performance is making it hard to test with the example tree then you can simply replace the tree in the foliage editor with a cube that also has a 32x32 lightmap.

If there are any other questions please ask.

Hey again brisck1,

So I did some extensive testing and my assumptions about your issue were correct. What you are encountering is expected, as the density per component relative to the lightmap resolution of each instance within that component, are what comprise the overall limitation. As proof of this concept, I took your test example and changed the density of painted instances per component and rebuilt using different Lightmap Resolution Overrides.

There is a reason we have exposed the Lightmap Resolution when painting foliage instances, and why 8 is the default resolution. There is an understanding that users will want to paint these foliage instances fairly densely, and having it fit within the required lightmap resolution limitation with the default lightmap resolution (usually 64) wouldn’t be manageable.

Above you can see my landscape size 8x8 components and the overall resolution. This helps give you an idea of the density per component.

16 Lightmap Resolution - 1024 Packed Lightmap Resolution

Now you can see how I am getting the same message you are reporting, using the settings outlined and mentioned.

16 Lightmap Resolution - 2048 Packed Lightmap Resolution

Here you can see the message has been cleared after increasing the packed lightmap resolution.

All in all, I do understand what you are reporting, but you are simply overloading the allowed resolution per component. This is why we have techniques like Cascaded Shadow Maps and Distance Field Shadowing to help blend to crisper shadows while keeping the low lightmap resolutions at far distances so they are less noticeable.

Cascaded Shadow Map Transition Example

126430-cacscadedshadowsfoliage.gif

As you can see in the above gif, I have set up some the cascaded shadow maps to essentially transition cleaner and hide the low quality lightmap/shadowmaps up to a certain distance.

Your issue is all going to come down to the platform you are developing for, and the techniques allowed per platform. If you want to use fully static lighting for an outdoor scene like this, you will have to work within the limitations of that lighting mobility type, which includes the lightmap limitations for landscapes.

Thank you,

Hi Andrew, firstly, thank you so much for taking the time to both look at the scene and write such a detailed explanation, I really appreciate that.

My only questions are, what is the maximum allowed resolution per component? Is it a percentage of the set Packed Lightmap Resolution? or is it capped in some way?

The reason I ask is just that I’m having trouble figuring out the math in order to calculate how many foliage instances I can have per component and how many components I will need in my landscape.

Right now, the way I’m calculating it is:

Packed Lightmap Resolution: 1,024

Total Packed Lightmap Pixels: 1,024*1,024 = 1,048,576 pixels

Foliage Mesh lightmap size: 32

Total Foliage Mesh Lightmap Pixels: 32*32 = 1,024 pixels

To calculate how many 32x32 lightmaps into 1024 atlas:

1,048,576 / 1,024 = 1,024 lightmaps per component

Now, I just realised that unreal actually uses half of the lightmap atlas for directional lightmap info, so with this in mind, I do this calculation:

1,048,576 / 1,024 / 2 = 512 lightmaps per component

Does this seem correct? Because so far it seems I’m missing something as when I have 2 components with 512 trees total, I’m still getting that error, even though, using the above math, that should leave me with plenty of room on either component’s lightmap.

I think once I figure out how to calculate this properly I can build the landscape and density with these limitations in mind.

Thanks!

So upon further testing I have discovered that it is the foliage component and not the landscape component that was referring to, that’s interesting! I think i can now use this information to better manage my meshes.

So in summary, here’s what I learned:

  • Component sizes and lightmaps; I learned that foliage is not packed in the lightmap atlas according to the landscape component it’s painted on, but via the Instance Static Mesh component. So how it works is basically this:

  • It will try to fit ALL instanced meshes of a certain foliage type in a single level into one atlas, regardless of their location or proximity to one another in the level. This is obviously not a particularly efficient nor streamlined way for the engine to be handling this but I have discovered that by having multiple Foliage Types (Create new asset>Miscellaneous>Foliage Type) with the same mesh component, I can effectively push one foliage mesh counts beyond the limits of a single Packed Lightmap Atlas.

  • Also it seems that moving objects or landscape components which have foliage painted on them to different sub levels helps break things up.

  • Oh and that Half of your Packed Lightmap Atlas size is used for directional lightmaps - so you will need to half the amount of foliage instances you can fit into one atlas!

So I think for now, I think my the solution is to carefully keep track of how many Instance Static Mesh Components are in the level vs the Packed Lightmap size and break them up carefully as described above.