Search Unity

Is it possible to use baked lighting with Tilemaps & Sprites?

Discussion in 'Global Illumination' started by Aurigan, Nov 10, 2020.

  1. Aurigan

    Aurigan

    Joined:
    Jun 30, 2013
    Posts:
    291
    I'm building a 2.5D game with 2D tilemaps, sprites, Spine animated things, and 3D perspective camera, lights, some scenery. Unity 2020.1.12, URP, custom (PBR master node) Shader Graph for all the 2D stuff.

    Baked lighting works fine on MeshRenderers but it looks like Unity won't bake anything for Tilemaps or Sprites ... is there any way to get this to work?

    SG looks like this:
    upload_2020-11-10_15-53-1.png

    Scene (the spot is realtime and works, tree/pole shadows are from a directional realtime light which I want to be mixed (baked on static ground/trees), point light on left is baked and doesn't do anything at all):
    upload_2020-11-10_15-55-45.png

    Same scene in 'UV Charts' scene view mode (looks like GI is only seeing UVs for the mesh ribbons that make up the world 'edges' under the tilemap): upload_2020-11-10_15-58-16.png
     
    Last edited: Nov 19, 2020
  2. Aurigan

    Aurigan

    Joined:
    Jun 30, 2013
    Posts:
    291
    Bump ... really don't want to give up on tilemaps & sprite workflows in order to get performant lighting!
     
    AldeRoberge likes this.
  3. KEngelstoft

    KEngelstoft

    Unity Technologies

    Joined:
    Aug 13, 2013
    Posts:
    1,366
    Sprites can be lit with baked light probes. I don't think there is built in support for tilemap + GI but if you need the sprintes and tilemap to affect baked GI, try writing a script to convert the ground and ribbons to MeshRenderers, mark those as Contribute GI and place light probes around them and bake GI. When rendering your game afterwards, the generated GI proxy mesh should be hidden and the sprites and tilemap should be shaded using the baked light probes. You might have to create a custom tilemap shader to sample the light probes. Hope this helps.
     
  4. Aurigan

    Aurigan

    Joined:
    Jun 30, 2013
    Posts:
    291
    Many thanks for the reply, has given me an interesting day poking at bits of Unity I've not used before.

    Sprites getting lit via light probes is neat to see ... using a baked directional (or spot) light there are no shadows cast by the sprites though (shadows will cast/receive as expected with a realtime light). Is there any way to remedy this?

    I'm assuming this is related to the issue I'm seeing where if, for instance, there's a light behind a sprite then the front face will still be lit (?)

    The ribbons are mesh renderers already (using probuilder) and I *think* are working fine ... do you have any suggestions or pointers for how to 'convert the ground' (as in, a tilemap) to a mesh renderer?
     
  5. KEngelstoft

    KEngelstoft

    Unity Technologies

    Joined:
    Aug 13, 2013
    Posts:
    1,366
    For creating a mesh from the Tilemap, you could consider adding a TilemapCollider2D component and a CompositeCollider2D component, and checking the Used by Composite property in the TilemapCollider2D (https://docs.unity3d.com/Manual/class-TilemapCollider2D.html). You can then extract the mesh from the CompositeCollider2D using CompositeCollider2D.CreateMesh (https://docs.unity3d.com/ScriptReference/Collider2D.CreateMesh.html).

    I don't think that Sprites or the Tilemap support baked shadows from baked lights. You may have to stick to mixed lighting if you need this.
     
  6. Aurigan

    Aurigan

    Joined:
    Jun 30, 2013
    Posts:
    291
    @KEngelstoft Thanks again for the pointers.

    I happened to have low poly meshes on the decorations (like the trees) that sorta match their shapes from a (probably way over-engineered) raycast/occlusion system. Setting those to 'shadows only' I can get some nice baked lighting like this (the floor is a default cube):

    upload_2020-12-2_16-32-57.png

    Remaining issues with this setup:
    • I can't see a sensible way to get point lights/probes to work with sprites where the point light is behind the sprite. In this scenario, sprites get lit as though the light is in front of it (or, I guess, more accurately, around it). The front/center tree is an example of this.
    • Sprites indeed don't support baked shadows ... so no nice tree-casting-shadow-onto-another-tree, etc. In the screenshot above the big tree on right should darken the tree behind/to its left. With the blurry shadows that's a lot more tolerable than with hard shadows.
    • No way to bake shadows onto a tilemap.
    It would be great if there were a way to achieve that last part ... otherwise, this has been an interesting couple of days exploring what's possible. Again, thank you.
     
  7. KEngelstoft

    KEngelstoft

    Unity Technologies

    Joined:
    Aug 13, 2013
    Posts:
    1,366
    To address the light behind the tree scenario, you probably have to edit your shader. Do a dot product test of the normalized sprite normal (camera vector negated) against the normalized vector from the sprite position towards the light. Use this value to attenuate the lighting.

    I will pass your feedback on to the 2D team, perhaps we can improve this in a future version of Unity.
     
  8. Aurigan

    Aurigan

    Joined:
    Jun 30, 2013
    Posts:
    291
    This sounded ... complicated. Well beyond my shader skills anyway!

    I did happen to find 'Probe Anchor' in debug settings for Sprites which I'm setting lower to the ground and in front of the Sprites to get the sprite to blend probes on the 'front' side / near where light sources actually are.

    For posterity. The setup I've ended up with is:

    Have a sprite:

    upload_2020-12-4_11-24-3.png

    Add a thin (0.1 extruded) polyshape mesh using probuilder:

    upload_2020-12-4_11-24-15.png

    Set that mesh renderer to 'shadows only'

    Add an empty game object slightly in front of the tree, use that as 'probe anchor' for the sprite.

    Using https://assetstore.unity.com/packages/tools/utilities/magic-light-probes-157812 to auto-add light probes ... this took a lot of tweaking to find usable settings ... this is kinda difficult to show in a screenshot but the end result leaves probes on the front and back of the trees:

    upload_2020-12-4_11-32-21.png

    This is what the scene looks like without the probe anchors set in front of each sprite:

    upload_2020-12-4_11-44-11.png

    The left big tree is dark (because it's using probes high up/away from the light), trees in front of/closer to the fires are lighter than ones behind.

    And with the probe anchors set:

    upload_2020-12-4_11-35-36.png

    Trees on the far side of lights are getting lit up more, large tree (on left) is getting lit by probes near the ground. Nice.
     
    KEngelstoft likes this.
  9. Aurigan

    Aurigan

    Joined:
    Jun 30, 2013
    Posts:
    291
    Minor update on this for anyone going through the same journey - https://github.com/sr4dev/Unity-SpriteAssist gives a much easier way to create sprite meshes (vs. using probuilder as I was previously). BUT, in order for GI to work, the generated meshes require normals ... so I needed to add this to the UpdateMesh() method:

    Code (CSharp):
    1.             Vector3[] normals = new Vector3[v.Length];
    2.             for (var i = 0; i < normals.Length; i++)
    3.             {
    4.                 normals[i] = Vector3.back;
    5.             }
     
    Seromu likes this.
  10. Graigy1337

    Graigy1337

    Joined:
    Oct 26, 2019
    Posts:
    9

    Was this the best solution to the problem in the end? I am also wanting to have sprite shadows baked in but its a bit of a pain to have to make a mesh for each sprite.
     
  11. Aurigan

    Aurigan

    Joined:
    Jun 30, 2013
    Posts:
    291
    'Best' IDK ... was workable for my game but the entire workflow does feel very hacky!