Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Mixing interiors and exteriors: selectively disabling global directional light.

Discussion in 'General Graphics' started by neginfinity, Apr 6, 2015.

  1. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,327
    I'd like to have single scene with multiple areas connected by "teleports".

    Several "exterior" areas with sun, and multiple interiors where there is no sun.

    The problem: sun is currently represented by global directional light, and it affects everything, including interiors.

    How can I limit directional light to portions of the scene, or (even better) have separate directional lights for different parts of the scene?

    At the moment I built a huge wall between "exterior" and "interior" areas of the world to block light from directional "sun" in interiors, but that's not really a good solution.

    Is there a better way to do it?

    Or do I have to turn sun into spotlight?
     
  2. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,327
    Alright. I've made a script that turns off the sun when player enters the room. It works.

    Is there a better way to do it?
     
  3. topofsteel

    topofsteel

    Joined:
    Dec 2, 2011
    Posts:
    999
    Enable shadows on the directional light and use a 'roof', some mesh with a normal face pointing up. I use separate meshes for the interior and exterior with reflection probes inside and probes disabled for the exterior mesh.
     
  4. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,327
    As far as I know, that is not a proper solution because it does not guarantee that sun is not being processed during render pass for all indoor objects (which is what I want).

    Most likely scenario is that even when there is a roof, as long as global directional light is on, a shadow map is being rendered for all objects in scene and is being applied to everything within interior, even though there is no chance of light ever reaching an object. (Unless documentation explicitly states otherwise).

    That's how game engines normally work, anyway. If roof is not an occluder, shadowmap applies to everything.

    Another problem is that when sun can move, "roof" won't be enough and you'll need a box. Which will repeatedly get in your way during level design.
     
  5. topofsteel

    topofsteel

    Joined:
    Dec 2, 2011
    Posts:
    999
    I didn't know where you were coming from, I thought maybe the sun was shining on your floor or something, in which case my 'roof' would have been a simple solution.
    My last big project in Unity4 was about 90,000 sf. I had the interior of the building broken up into scenes that I would bring together at runtime. It was all lightmapped with a realtime sun. I had the shadows In the individual scenes enabled for lightmapping reason. But when I brought them into the main scene I would disable the shadows on the mesh renderer, at least doubling my performance (script below). In the main scene I had the building shell (a box) with shadows enabled and simple planes in the floor to keep the sun from shining through the floor when it came into a window.
    My current project in Unity5 is a 120,000 sf manufacturing facility (screenshot attached). All emissive materials with a realtime sun. The shadows are so well optimized in Unity5 that I dont even think I need to bother disabling the shadows on the interior mesh renderers. I'm getting 100 to 150 fps with bloom, tonemapping and AA on the cameras. I might if the client requests it on a mobile device. Plus i'll be using occlusion culling.

    Code (CSharp):
    1. public class RuntimeRemoveShadows : MonoBehaviour
    2. {
    3.     public GameObject Models;
    4.  
    5.     void Awake()
    6.     {
    7.         Transform[] T = Models.GetComponentsInChildren<Transform>();
    8.  
    9.         foreach (Transform t in T)
    10.         {
    11.             MeshFilter mF = (MeshFilter)t.GetComponent<MeshFilter>();
    12.             if (mF)
    13.             {
    14.                 Renderer r = mF.renderer;
    15.                 r.castShadows = false;
    16.             }
    17.         }
    18.     }
    19. }
    Shadow-Example.png
     
  6. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,327
    Hmm... good points here, thank you. I suppose I might be guilty of premature optimization in this case.

    I think I'll keep the sun-disabling trigger for now (it does its job) and will post more if I come up across some interest bit of info.

    So far the thread can be marked as solved, and I'm unsubscribing.

    Thanks for the replies.
     
  7. ToMorning

    ToMorning

    Joined:
    Apr 8, 2015
    Posts:
    4
    If you click on your light, you will notice a drop-down called "Culling Mask" in the inspector. You can use this to determine which layers that particular light will affect. You can assign the renderable geometry of each "area" to its own layer, then have each light only affect certain layers.
     
  8. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,327
    I thought about it, but I'll still need to modify layer flags on objects that enter area from exterior. Although I suppose it would work better in edit mode. Will give it a try.