Understanding baked GI lightmap UV packing

Hi!

I’m giving my shot at baking lighting and so far so good. Nevertheless I still don’t understand how the baking process decides the sizes of the UV charts in the lightmap atlas.

I create my albedo UV in blender, carefully sorted, without overlapping areas and with extra padding between them. After the baking process in Unity, when I inspect the lightmap atlas, some of the UV charts got reduced to TINY sizes while others got enlarged.

Furthermore, if I let Unity generate its own UV maps (through the model import option), the objects which previously got a nice slice of the atlas, now gets a tiny corner, UV shells utterly unfathomable without max zooming.

Is this something I should simply ignore? Just bake and forget? I’m aware that, for small props (like a wall torch) I should not try to bake lighting but rely on light probes, however this is something I would like to understand before moving forward.

Regards.

It depends on the size of the object in the scene and the scale in lightmap value in its mesh renderer (and finally by the maximum atlas size, because it can’t be larger than 1 map)

See the padding between is kinda relative. If you give padding of 2-3 pixels assuming a 1024 map and then it gets baked to a much smaller area the padding won’t be enough.

Yeah, Unity’s generate UV algorithm is old and terrible (I mean it wasn’t even good back in the day and it’s 10 year old tech now).

So here’s some general advice if you want high quality lightmaps with as little wasted space as possible.

RULE 1: Never use Unity’s Generate UVs, maybe only early on when you’re really just testing things and changing the mesh a lot and you want something that is “bakable” for testing.

RULE 2: Keep your Max Lightmap Atlas to 1024 or 2048, unless you have a really specific reason for going smaller than that (which I don’t really know what that would be).

Now the steps

Step 1: Do a really rough packing job in your DCC of choice. A quick atlasing / relaxing / packing in any DCC shouldn’t take much time and will still be 1000x better than Unity’s UV.

Step 2: Do a rough bake. Just put really low sample values. We are trying to get a good UV layout at this point, we don’t care about it looking good (but it shouldn’t be so low that you don’t understand what you’re looking at either). Also ignore any “overlapping UVs” warning, we’ll deal with those later.

Step 3: Look at the lightmaps and also look your scene in the baked lightmap mode, with “Show Lightmap Resolution” checked (it’s the last checkbox in the dropdown in sceneview). If texel density looks low everywhere, raise the Lightmap resolution value.

Step 4: Assuming you have a good base lightmap resolution value, then try to look for meshes that are wasting lightmap space. Is there a big building in the distance you don’t really get close to? Is there maybe a mountain? Is it an interior scene and you have a street in the background? Surely we don’t want them hogging all the lightmap space when you’re never going to look at the up close.

Select those big / distant meshes in the scene and significantly reduce the Scale In Lightmap value in the mesh renderer.
7707172--965809--upload_2021-12-3_17-59-43.jpg

Or maybe you have close up shots and some really need more than average texels. So raise those values.

7707172--965812--upload_2021-12-3_18-0-35.jpg

Step 5: Keep massaging those values until you have a reasonable amount of lightmaps and all meshes have a reasonable amount of lightmap pixels associated with them.

Step 6: Now it’s time to ACTUALLY properly pack your lightmap UVs. Select a mesh and look at the tiling values:
7707172--965815--upload_2021-12-3_18-2-27.png

Here it’s 0.08183337 and it’s a on lightmap that has a size of 1024. Which means the UVs of this mesh occupy an area of around 84x84 pixels.

Repack the UVs of that mesh, aiming to leave at least 2 (preferably 3 so you have a little wiggle room) pixels of padding when it’s scaled down to 84x84pixels. You will need to calculate how to do that in your DCC. Some software (like Rizom UV) let you enter the size of the whole square in pixels and then you can enter the padding you want. Others (like modo) assume you are talking about a 1024x1024 map, so for that you would need to enter a value of (1024/84)*2 at least 25 pixels.

Step 7: DO THAT FOR EVERY MESH IN THE SCENE.

Step 8: You are done! (at least until you decide you want to change the layout and then you have to do a big chunk of these steps from scratch).

Finally: Don’t pay too much attention to the overlapping UV message. It’s useful, but if you can’t actually see the overlap or something wrong in general, then you don’t have to worry about it.

Finally #2: I generally feel like I did a pretty good job when the baker reports coverage of about 70% of the theoretical maximum. So if I am baking 1 1024x1024 map, I’m happy with anything above 0.7M texels occupied.
7707172--965827--upload_2021-12-3_18-13-0.png

8 Likes

A huge thank you AcidArrow, for your time and your deep explanation on this process. That exactly what I was looking for, crystal clear, cheers!

It was precisely UV overlap messages which set my on this path although what you state seems reasonable enough, If don’t notice lightning bleed, I shouldn’t pay much attention to those warnings.

I disabled Unity UV generation and the following screenshot is the result. Torch takes a tiny space, about 3 texels, which I think it makes sense as I’m using a lightmap resolution of 10 texels/unit and torch measures roughly 30cm.

Comparing the torch (yellow highlight) with the column (rounded in red) scales fit but I find the bars (green, forgive the rough UV) out of proportion. I can live with that xD

Anyway, I will definitely go down the road you lay before me, making my own UV unwrap and tinkering after a fast first bake.

I forgot to mention: Lighting small assets with lightprobes is definitely valid. It depends on the use case.

  • If it’s a dynamic object that might move, then 90% of the time the correct answer is a light probe (the other 10% is split between having it fully baked anyway if it doesn’t move much, or doing something weird like custom lighting it with a cubemap).
  • If it’s a static object, then definitely try switching “Receive Global Illumination” to Light Probes. It will be shaded by lightprobes, but it will also cast shadows in the environment. If you’re using realtime / mixed lights, it might look pretty good.

I generally don’t like lighting static things with light probes, but that’s because I use no realtime lights at all, and probes that include direct light are even more inaccurate so things look weird. So I have adopted the stance that either I spend as much lightmap space as needed for it to look good, or if it’s far away, I don’t mind it looking weird as long as it is roughly the right color (and actually, if we’re not seeing it closely, I usually simplify the geometry and sew as many UV seams as I can, even hard ones, so there’s less UV space needed).

But certainly do play with light probes and see what kind of results you get.

@AcidArrow I know this post is old, but I just found this as I am trying to learn how to fix overlapping UVs in my lightmaps. The explanation is very helpful, but I have a few questions if you, or anyone, can answer.

What is a DCC? I’m not familiar with that acronym.

After following your steps carefully, I seem to have either made a mistake, or misunderstood something.

Here is what I did step by step:

  • I modeled my object in blender an unwrapped its uvs manually (with 16 pixels of padding between islands) for texturing. Texture, and import into unity
  • Setup my scene how I want it, then go to bake the scene using a 1024 lightmap. Boom overlapping UVs (expected at this point)
  • Inspect the scene and find objects that can be scaled down in the lightmap. I took a lot of my static walls and scaled them down to 0.5 since the camera won’t be all that close to them (though I’m not sure what effect this has exactly)
  • Time to properly pack my lightmap uvs. I look at an object, and it has 0.3179377 for its tiling (x and y)… I do the math of lightmap size * tiling x/y and get 1024 * 0.3179377 = 325.568… round up to 326.
  • I go back into blender, and I add a 2nd UV map, and I do this math of (1024/326) * 2 = 6.28… round up to 7. So, this this tells me I need my 2nd UV islands to have a minimum of 7 pixels between them.
  • Since my initial uv unwrap has 16 pixels between islands, I just duplicate that into my 2nd uv map, export, import back into unity.
  • Bake my scene again. Still have overlapping UVs (not expected)

So, my assumption is I did something wrong with step 6, but I’m not completely sure. Any help that you, or anyone else on this forum can provide would be wonderful.

Also, your post was the most helpful thing I’ve read about lightmap UVs so thanks for that too.

I’m about to take a nap, so answer will probably be brief, feel free to ping me again if I leave unanswered stuff.

Digital Content Creation. In this context I meant the 3D modeling software you use (blender, max, Maya, Modo, whatever).

The process seems correct. If you look through the uv overlap debug view in scene, does any red area show at all?

My guess is that the UVs might be a little weird in some area (maybe an island almost intersects with itself at some point?) and Unity detects that as UV overlapping. If that’s the case, the uv overlap debug scene view should show (almost?) everything as white. If there something more majorly wrong, there will be plenty red.

Also sidenote, step 6 the way you did it is fine for figuring stuff out, and it shouldn’t price uv overlaps, but when the scene starts to stabilize you would repack with the calculated padding in order to have less wasted space.

Thanks for the reply. I re-checked everything and the scene view overlap is practically all white. Some small red lines in places. When I look at the preview of the lightmap for a specific object and chose the UV overlap view I see what you are talking about. Some of the islands show up as overlapping red areas even though there is no overlap there at all. I went back into blender and moved my UV1 islands a little further apart and it has removed the overlap in Unity.

Many thanks for an excellent explanation of how to do this, and how to troubleshoot and fix my issue. This has been much more helpful than any Unity documentation on overlapping lightmap UVs.

Hi all, so I have tried following this forum thread for my VR URP project and am still getting artifacts. I am not seeing as much overlap as I was, but my lightmaps are still pretty rough and have some artifacts. Does anyone have a good guide for a Blender to Unity workflow? I have tried for days to get good results but it seems to always fall flat.

1 Like

Start a new thread and post images with the issues you’re having.