Fake "Lightmaps" for Prefabs

In my current project I need prefabs with lightmaps, but from everything I’ve researched… that is not possible because the Beast code is tied to scenes.

So I have hacked together this idea.

Problem: I have a prefab road section that will sometimes be placed at y=0, y=90, y=-90, or y=180 rotation angles. I want the shadows from the trees to be correct for each section’s rotation, as in the image below:

2108796--138275--Sections.jpg

But… I don’t want to have full 2048 res textures for each orientation. So I am adding 512 res 8 bit RGB “lightmaps” as shader decals for each orientation.

Here are the maps:

Color:

Lightmap for 0 Degree Rotation:

Lightmap for 90 Degree rotation:

And… Here is the shader I’ve hacked together, based on Unity’s Mobile/Diffuse shader:

Shader "Mobile/Diffuse-Decal" {
Properties {
    _MainTex ("Base (RGB)", 2D) = "white" {}
    _DecalTex ("Decal (RGB)", 2D) = "black" {}
}
SubShader {
    Tags { "RenderType"="Opaque" }
    LOD 150

CGPROGRAM
#pragma surface surf Lambert noforwardadd

sampler2D _MainTex;
sampler2D _DecalTex;

struct Input {
    float2 uv_MainTex;
    float2 uv_DecalTex;
};

void surf (Input IN, inout SurfaceOutput o) {
    fixed4 c = tex2D(_MainTex, IN.uv_MainTex);
    fixed4 decal = tex2D(_DecalTex, IN.uv_DecalTex);
    c.rgb *= decal.rgb;
    o.Albedo = c.rgb;
}
ENDCG
}

Fallback "Mobile/VertexLit"
}

However, I know very little about shaders, and I imagine somebody has already thought of something similar, but better. So, is there a better way to do this? This is for an iOS game.

I’ve been searching around the forums all day, but I may not know the good words to search for if this has already been discussed.

Same problem here - in my endless runner game i have multiple baked platforms that i am spawning from prefabs. My solution is:

  1. In your game scene create empty game object, name it “BakedPlatforms”
  2. Create platfroms, add lights and bake them
  3. Add platforms as childs to BakedPlatforms game object
  4. Drag each platform from Inspector to Project window (this will create prefabs)
  5. Reset Transform position in your prefabs (not in childs of BakedPlatforms game object)
  6. DISABLE BakedPlatforms game object - do not remove it from scene, just disable it.
  7. Now You can spawn platforms with baked lights from prefabs
    NOTE: this will work in current scene only, You can’t spawn those prefabs in other scene, because You will lost Lightmaps. To fix that:
  8. Create empy Scene
  9. Create platfroms, add lights and bake them
  10. Drag each platform from Inspector to Project window (this will create prefabs)
  11. Reset Transform position in your prefabs (not in childs of BakedPlatforms game object)
  12. Save scene as BakedPlatformsScene
  13. Create new Scene and open it
  14. Open Window → Lightmapping
  15. Open Maps tab
  16. Set Array Size to valid number. In my case BakedPlatformsScene scene has two lightmaps, so i must set Array Size to “2”
  17. In Maps tab, click Select and choose lightmaps from BakedPlatformsScene. Be sure to add lightmaps in correct order. You can check it by opening BakedPlatformsScene, and then opening Windows->Lightmapping->Maps

Checked in Unity 4.6.

I don’t understand. The original texture of the prefab would take the same ram if baked down, as the lightmap. so why not just bake it all into one chunk with it’s own texture? it would look 10x better and perform faster and consume less ram.

There’s also the possibility to add a simplified shadow mesh (or plane with texture) to the prefabs and use a shadow projection shader. This however adds another draw call per object, or batch if you have pro. And only works on planar (Y=0) surfaces, unless you manage to implement projection on arbitrary planes.

Pros/Cons

  • simple real-time shadows
  • can render shadows on top of vehicles etc.
  • less texture memory
  • more draw calls (or batching)
  • only on a planar surface
  • not always correct (go through other objects, extend beyond mesh bounds)

this is as far as I can tell. Just throwing that option out there.

Btw., do you really need unique a 2048 texture for that element? With some additional polygons you could easily cut it down to a reusable 512 tile texture I’d say.

For my method at the top, I am using the 512 shadow maps to save on app size. I have many different kinds of road prefabs (turns, hills, jumps, etc.) that all share the same base 2048 texture… so 2048 is needed (for the road’s width and textures must be square) since the camera is very close to that road. The uv’s in the image only uses a portion of the texture, but longer prefabs use the entire u length of the texture.

So the shadow map method above it is:

(2048 for the base shared texture across 20+ prefabs) + (4 light directions * 512 per prefab)

if I use a single texture with shadows baked in for each of the 4 light directions of each prefab:

(2048 x 4) x 20+ prefabs