Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Best way to render fast day and night change scenes

Discussion in 'Universal Render Pipeline' started by Flindt, Sep 18, 2019.

  1. Flindt

    Flindt

    Joined:
    Dec 28, 2016
    Posts:
    78
    Hi

    Im working on project where we do nigh/day cycles - during 10-20 seconds for one day.
    Can i use anyting but realtime lighting here? any mixed? and/or any use of light probes?

    It is very low poly scene - with simple house and trees on a plane - but we need the lighting to be as realistic as possible.

    We are using LWRP - are there any occlusion probes or similar that can work in LWRP?

    Thanks a lot for any replies
     
  2. Shane_Michael

    Shane_Michael

    Joined:
    Jul 8, 2013
    Posts:
    158
    It's hard to know what is "best", but I would probably approach this by doing the direct light in real-time and parameterizing the indirect lighting with spherical harmonics (i.e. basically a big light probe to approximate your sky). Bake out an indirect lightmap for each of the spherical harmonic coefficients. There are 9 so you baking will take some time, and you will end up with 3 maps (pack a different coefficient in each RGB channel), but that is the cost of partially pre-computing your dynamic lighting. To make it a bit easier you could write an editor script to automate the baking and merging; then just start it up and let it bake everything out.

    At runtime, you can align a (disabled) white directional light to your sun direction and add it to a SphericalHarmonicsL2 object. That will calculate the weighting for each of the coefficients for you. Then, use a standard lit Shader Graph and multiplies out each lightmap, multiply it by your sunlight color, and just add it as emissive light to your output node.

    If that's too much texture memory for your application, you could use Valve's 3 vector tangent basis instead (search for "Radiosity Normal Maps"). It uses only 3 coefficients for 3 different light directions so it can be packed into a single 3-channel lightmap, but it will give correspondingly less convincing results. Will be faster to bake out though.

    If you parameterize your lighting in the lightmaps, you will need to do it for any light probes that you might want to use on dynamic objects too. Which means baking and saving out 9 different sets of light probes coefficients, and using the coefficient weights to set the actual values of your light probes every frame. That will be an extra cost if you need any dynamic objects in your scene to pick up the indirect lighting.

    Here is a spherical harmonic skybox shader to get your started if you want to try baking out the different coefficients to see what they look like in your scene:

    Code (csharp):
    1.  
    2. Shader "Skybox/Spherical Harmonic Skybox"
    3. {
    4.     Properties
    5.     {
    6.         _SHAr("Spherical Harmonics A Red", Color) = (1, 1, 1, 0)
    7.         _SHAg("Spherical Harmonics A Green", Color) = (1, 1, 1, 0)
    8.         _SHAb("Spherical Harmonics A Blue", Color) = (1, 1, 1, 0)
    9.         _SHBr("Spherical Harmonics B Red", Color) = (1, 1, 1, 0)
    10.         _SHBg("Spherical Harmonics B Green", Color) = (1, 1, 1, 0)
    11.         _SHBb("Spherical Harmonics B Blue", Color) = (1, 1, 1, 0)
    12.         _SHC("Spherical Harmonics C", Color) = (1, 1, 1, 0)
    13.     }
    14.  
    15.         CGINCLUDE
    16.  
    17. #include "UnityCG.cginc"
    18.  
    19.         struct appdata
    20.     {
    21.         float4 position : POSITION;
    22.         float3 texcoord : TEXCOORD0;
    23.     };
    24.  
    25.     struct v2f
    26.     {
    27.         float4 position : SV_POSITION;
    28.         float3 texcoord : TEXCOORD0;      
    29.     };
    30.  
    31.     half4 _SHAr;
    32.     half4 _SHAg;
    33.     half4 _SHAb;
    34.     half4 _SHBr;
    35.     half4 _SHBg;
    36.     half4 _SHBb;
    37.     half4 _SHC;
    38.  
    39.     // normal should be normalized, w=1.0
    40.     half3 SHEvalLinear(half4 normal)
    41.     {
    42.         half3 color;
    43.  
    44.         // Linear (L1) + constant (L0) polynomial terms
    45.         color.r = dot(_SHAr, normal);
    46.         color.g = dot(_SHAg, normal);
    47.         color.b = dot(_SHAb, normal);
    48.  
    49.         // 4 of the quadratic (L2) polynomials
    50.         half4 vB = normal.xyzz * normal.yzzx;
    51.         color.r += dot(_SHBr, vB);
    52.         color.g += dot(_SHBg, vB);
    53.         color.b += dot(_SHBb, vB);
    54.  
    55.         // Final (5th) quadratic (L2) polynomial
    56.         half vC = normal.x*normal.x - normal.y*normal.y;
    57.         color += _SHC.rgb * vC;
    58.  
    59.         return color;
    60.     }
    61.  
    62.     v2f vert(appdata v)
    63.     {
    64.         v2f o;
    65.         o.position = UnityObjectToClipPos(v.position);
    66.         o.texcoord = v.texcoord;
    67.         return o;
    68.     }
    69.  
    70.     half4 frag(v2f i) : COLOR
    71.     {
    72.         return half4(SHEvalLinear(float4(i.texcoord, 1)), 1);
    73.     }
    74.  
    75.         ENDCG
    76.  
    77.         SubShader
    78.     {
    79.         Tags{ "RenderType" = "Background" "Queue" = "Background" }
    80.             Pass
    81.         {
    82.             ZWrite Off
    83.             Cull Off
    84.             Fog{ Mode Off }
    85.             CGPROGRAM
    86. #pragma fragmentoption ARB_precision_hint_fastest
    87. #pragma vertex vert
    88. #pragma fragment frag
    89.             ENDCG
    90.         }
    91.     }
    92. }
    93.  
    And here is a useful light probe utility if you want to set your shader variables from a SphericalHarmonicsL2 object:
    https://github.com/keijiro/LightProbeUtility/blob/master/Assets/LightProbeUtility.cs