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

How does unity calculate spherical harmonics with Trilight?

Discussion in 'Shaders' started by Philip_Zhang, Sep 15, 2020.

  1. Philip_Zhang

    Philip_Zhang

    Joined:
    Feb 15, 2017
    Posts:
    25
    Hi, I'm trying to reproduce unity's ambient lighting.
    I wonder how unity internally calculate spherical harmonics when the scene is not baked and using Gradient (Sky Color, Equator Color, Ground Color) environment lighting mode.
     
    MUGIK likes this.
  2. MUGIK

    MUGIK

    Joined:
    Jul 2, 2015
    Posts:
    476
    IT DRIVES ME NUTS:mad:

    I found somewhere this code:
    Code (CSharp):
    1. private static SphericalHarmonicsL2 CalculateTrilightAmbient(Color groundColor, Color equatorColor,
    2.         Color skyColor)
    3.     {
    4.         const float scale1 = 1f / 7f;
    5.         const float scale2 = 2f / 7f;
    6.         const float scale3 = 3f / 7f;
    7.         SphericalHarmonicsL2 sphericalHarmonics = new SphericalHarmonicsL2();
    8.         var halfway = new Vector3(0.61237243569579f, 0.5f, 0.61237243569579f);
    9.         sphericalHarmonics.AddDirectionalLight(Vector3.up, skyColor, scale3);
    10.         sphericalHarmonics.AddDirectionalLight(Vector3.down, groundColor, scale3);
    11.  
    12.         var upperColor = Color.Lerp(skyColor, equatorColor, 0.5f);
    13.  
    14.         // upper
    15.         sphericalHarmonics.AddDirectionalLight(new Vector3(-halfway.x, +halfway.y, -halfway.z), upperColor, scale2);
    16.         sphericalHarmonics.AddDirectionalLight(new Vector3(+halfway.x, +halfway.y, -halfway.z), upperColor, scale2);
    17.         sphericalHarmonics.AddDirectionalLight(new Vector3(-halfway.x, +halfway.y, +halfway.z), upperColor, scale2);
    18.         sphericalHarmonics.AddDirectionalLight(new Vector3(+halfway.x, +halfway.y, +halfway.z), upperColor, scale2);
    19.  
    20.         var centerColor = equatorColor;
    21.         // center
    22.         sphericalHarmonics.AddDirectionalLight(Vector3.left, centerColor, scale1);
    23.         sphericalHarmonics.AddDirectionalLight(Vector3.right, centerColor, scale1);
    24.         sphericalHarmonics.AddDirectionalLight(Vector3.forward, centerColor, scale1);
    25.         sphericalHarmonics.AddDirectionalLight(Vector3.back, centerColor, scale1);
    26.  
    27.         var lowerColor = Color.Lerp(groundColor, equatorColor, 0.5f);
    28.         // lower
    29.         sphericalHarmonics.AddDirectionalLight(new Vector3(-halfway.x, -halfway.y, -halfway.z), lowerColor, scale2);
    30.         sphericalHarmonics.AddDirectionalLight(new Vector3(+halfway.x, -halfway.y, -halfway.z), lowerColor, scale2);
    31.         sphericalHarmonics.AddDirectionalLight(new Vector3(-halfway.x, -halfway.y, +halfway.z), lowerColor, scale2);
    32.         sphericalHarmonics.AddDirectionalLight(new Vector3(+halfway.x, -halfway.y, +halfway.z), lowerColor, scale2);
    33.  
    34.         return sphericalHarmonics;
    35.     }
    But it doesn't work properly! I tweaked all possible values but with no luck.
    Please, help:(
     
  3. MUGIK

    MUGIK

    Joined:
    Jul 2, 2015
    Posts:
    476
    UPD:
    Now I'm using
    UnityEngine.LightProbes.CalculateInterpolatedLightAndOcclusionProbes which returns perfect results and is quite cheap.


    Original:
    I have progress.
    I found some magic values that make it a bit better.
    Unfortunately, this still not an answer.

    Code (CSharp):
    1. private SphericalHarmonicsL2 CalculateTrilightAmbient(
    2.         Color groundColor,
    3.         Color equatorColor,
    4.         Color skyColor)
    5.         {
    6.             // idk why linear is needed
    7.             groundColor = groundColor.linear;
    8.             equatorColor = equatorColor.linear;
    9.             skyColor = skyColor.linear;
    10.             // idk what that 0.55f multiplier is
    11.             float scale1 = 1f / 7f * 0.55f;
    12.             float scale2 = 2f / 7f * 0.55f;
    13.             float scale3 = 3f / 7f * 0.55f;
    14.             SphericalHarmonicsL2 sphericalHarmonics = new SphericalHarmonicsL2();
    15.             sphericalHarmonics.AddDirectionalLight(Vector3.up, skyColor, scale3);
    16.             sphericalHarmonics.AddDirectionalLight(Vector3.down, groundColor, scale3);
    17.  
    18.             // 0.61f instead of 0.5f
    19.             Vector3 halfway = new Vector3(0.61237243569579f, 0.61f, 0.61237243569579f);
    20.  
    21.             // 0.77f instead of 0.5f
    22.             var upperColor = Color.Lerp(skyColor, equatorColor, 0.77f);
    23.  
    24.             // upper
    25.             sphericalHarmonics.AddDirectionalLight(new Vector3(-halfway.x, +halfway.y, -halfway.z), upperColor, scale2);
    26.             sphericalHarmonics.AddDirectionalLight(new Vector3(+halfway.x, +halfway.y, -halfway.z), upperColor, scale2);
    27.             sphericalHarmonics.AddDirectionalLight(new Vector3(-halfway.x, +halfway.y, +halfway.z), upperColor, scale2);
    28.             sphericalHarmonics.AddDirectionalLight(new Vector3(+halfway.x, +halfway.y, +halfway.z), upperColor, scale2);
    29.  
    30.             var centerColor = equatorColor;
    31.             // center
    32.             sphericalHarmonics.AddDirectionalLight(Vector3.left, centerColor, scale1);
    33.             sphericalHarmonics.AddDirectionalLight(Vector3.right, centerColor, scale1);
    34.             sphericalHarmonics.AddDirectionalLight(Vector3.forward, centerColor, scale1);
    35.             sphericalHarmonics.AddDirectionalLight(Vector3.back, centerColor, scale1);
    36.  
    37.             // 0.77f instead of 0.5f
    38.             var lowerColor = Color.Lerp(groundColor, equatorColor, 0.77f);
    39.             // lower
    40.             sphericalHarmonics.AddDirectionalLight(new Vector3(-halfway.x, -halfway.y, -halfway.z), lowerColor, scale2);
    41.             sphericalHarmonics.AddDirectionalLight(new Vector3(+halfway.x, -halfway.y, -halfway.z), lowerColor, scale2);
    42.             sphericalHarmonics.AddDirectionalLight(new Vector3(-halfway.x, -halfway.y, +halfway.z), lowerColor, scale2);
    43.             sphericalHarmonics.AddDirectionalLight(new Vector3(+halfway.x, -halfway.y, +halfway.z), lowerColor, scale2);
    44.  
    45.             return sphericalHarmonics;
    46.         }
     
    Last edited: Jan 23, 2021
    carlislejonah likes this.