Search Unity

GetInterpolatedLightProbe() interpreting the coefficients

Discussion in 'Shaders' started by jack-riddell, Mar 15, 2017.

  1. jack-riddell

    jack-riddell

    Joined:
    Feb 11, 2014
    Posts:
    326
    I seem to have run into a bit of an Information black hole related to interpreting the light probe returned from the GetInterpolatedLightProbe() function.

    there are a couple of threads related to this topic already which i have listed below but there doesn't seem to be a correct solution to the problem yet.

    https://forum.unity3d.com/threads/getinterpolatedlightprobe-interpreting-the-coefficients.209223/
    https://forum.unity3d.com/threads/lightprobes-getinterpolatedprobe-includes-dynamic-lights.311097/

    How do you take the values returned from GetInterpolatedLightProbe() and use them to calculate a light value for a given direction?

    under the hood unity seems to be using the code described here
    http://www.ppsloan.org/publications/StupidSH36.pdf
    in the UnityCG.include file there is a function called "ShadeSH9(Normal)" that matches the function described in the above publication but the steps described in "StupidSH36" to prepare the coefficients for the "ShadeSH9(Normal)" function don't work correctly.


    my issue is I need to render/calculate multiple direct/dynamic light lights as well as calculate ambient occlusion/light probe data in a single vertex lit pass (no lighting calculations in fragment and no multiple passes).
    At the moment my shader uses a LightMode = "Vertex" pass tag to get 8 dynamic light values which unity passes in using the "unity_LightPosition[]" arrays. However in LightMode = "Vertex" passes unity does not pass in the spherical harmonics which I need for baked lighting or global illumination/ambient lighting.
    My solution to this problem is to get the spherical harmonics using GetInterpolatedLightProbe() and pass it in to the shader manually but I am having trouble decoding the coefficients correctly.
    At the moment my shader sort of decodes the spherical harmonics but has issues with colour saturation and brightness.


    multiple directional lights using the 8 light values passed in when in LightMode = "Vertex".
    both the dynamic and spherical harmonic lighting can run at the same time provided they are passed in.


    particle system being lit by emissive lighting baked into light probes and passed to the material using GetInterpolatedLightProbe().
    you can sort of see the errors from my hack of the sperical harmonics here, the colours are off and not transitioning smoothly.



    Close up of a particle system being lit from a single directional light.


    If anyone knows any additional information about the format of the data returned by GetInterpolatedLightProbe() or how to translate the Spherical Harmonic components into something I can decode in a shader that would be very helpful.
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
  3. jack-riddell

    jack-riddell

    Joined:
    Feb 11, 2014
    Posts:
    326
    That is the code I am currently using but the output is not matching the lighting of other objects in the scene.

    the 2 spheres at the top are the light probes the bottom left sphere is using the light probe utility code and the bottom right is using the mobile defuse shader. As you can see the light probe utility code is darker and bluer than the light probe.

    LightProbe.png
     
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    Hmm, they changed a bunch of stuff in how the probes work for 5.3 or so, so they may have changed the encoding / decoding since that utility was written. :/
     
    jack-riddell likes this.
  5. jack-riddell

    jack-riddell

    Joined:
    Feb 11, 2014
    Posts:
    326
    Ok so after some extensive research I found the problem and it was a mistake on my end. Normally when dealing with float4 vectors in a shader if it is a direction vector you set the w value to 0 if it is a position you set the w value to 1. the ShadeSH9(Normal) function requires the w value to be set to 1 but due to my overconfidence I was passing in the normal with a w value of 0. The weird thing is this mostly works the colours are just a bit off which is why I thought it might be due to the way I was decoding the Coefficients. there are still some minor differences between the 2 but i think that might just be rounding errors and floating point inaccuracy.
     
    bgolus and richardkettlewell like this.
  6. Shane_Michael

    Shane_Michael

    Joined:
    Jul 8, 2013
    Posts:
    158
    Old thread, I know, but just an FYI for anyone who is having trouble with setting the spherical harmonics coefficients in the future, I found that they have been reordered (in Unity 2019.1 at least) requiring this

    Code (csharp):
    1.  
    2. material.SetVector(_idSHC, new Vector4(
    3.      sh[0, 8], sh[2, 8], sh[1, 8], 1
    4. ));
    5.  
    to be changed to

    Code (csharp):
    1.  
    2. material.SetVector(_idSHC, new Vector4(
    3.      sh[0, 8], sh[1, 8], sh[2, 8], 1
    4. ));
    5.  
    That seems to be working now, but this behavior seems to be both undocumented and subject to change. So just be aware if it's not working you may need to poke at the swizzling with a stick a bit until it looks right :)
     
  7. Raccoonteur

    Raccoonteur

    Joined:
    Jun 4, 2017
    Posts:
    23
    I'm trying to get this to work with Unity 2019 LTS so I can use it with MudBun, (MudBun generates its meshes with DrawMesh), but in spite of making the change outlined above to SetVector in both SetSHCoefficients() for the Material and MaterialPropertyBlock, I get this weird effect on one side of the sphere:

    sh.png

    And what's even stranger is that the dark splotch flips from one side of the sphere to the other as it moves. When the sphere is moving to the right, the dark splotch is on the left side of the sphere. And as soon as the sphere begins moving to the left again, the dark splotch flips over to the right side of the sphere.
     
  8. Raccoonteur

    Raccoonteur

    Joined:
    Jun 4, 2017
    Posts:
    23
    I figured it out!

    For Unity 2019 LTS, in addition to changing this:
    Code (CSharp):
    1. sh[0, 8], sh[2, 8], sh[1, 8], 1
    2.  
    To this:
    Code (CSharp):
    1. sh[0, 8], sh[1, 8], sh[2, 8], 1
    ...both times it occurs in the code under "Final quadratic polynomial", you also have to change this:

    Code (CSharp):
    1. sh[i, 4], sh[i, 6], sh[i, 5] * 3, sh[i, 7]
    To this:
    Code (CSharp):
    1. sh[i, 4], sh[i, 5], sh[i, 6] * 3, sh[i, 7]
    ...under "Quadratic polynomials" both places it occurs.

    And for whatever reason the order of operations for "Constant + Linear" have not changed, so don't alter those ones.