Skip to content

Instantly share code, notes, and snippets.

@rickomax
Last active August 10, 2022 00:34
Show Gist options
  • Save rickomax/ffe2ff840ca5baf2830a8cdcc48223f5 to your computer and use it in GitHub Desktop.
Save rickomax/ffe2ff840ca5baf2830a8cdcc48223f5 to your computer and use it in GitHub Desktop.
//Original code from:
//https://github.com/RishiAstra/Survive-From-Scratch/blob/21d98a4dcbb3ef25a79bb3ca9733b35b866eda74/Assets/AwesomeTechnologies/VegetationStudio/Utility/LightProbeUtility.cs
//Added EvaluateSH2 method to evaluate the SH2 with C#, so it will work with Unity Jobs
public class LightProbeUtility
{
public struct LightProbeData
{
public Vector4 unity_SHAr;
public Vector4 unity_SHAg;
public Vector4 unity_SHAb;
public Vector4 unity_SHBr;
public Vector4 unity_SHBg;
public Vector4 unity_SHBb;
public Vector4 unity_SHC;
}
public static LightProbeData GetLightProbeData(SphericalHarmonicsL2 sh)
{
return new LightProbeData
{
unity_SHAr = Get_Unity_SHAr(sh),
unity_SHAg = Get_unity_SHAg(sh),
unity_SHAb = Get_unity_SHAb(sh),
unity_SHBr = Get_Unity_SHBr(sh),
unity_SHBg = Get_Unity_SHBg(sh),
unity_SHBb = Get_Unity_SHBb(sh),
unity_SHC = Get_Unity_SHC(sh)
};
}
public static Vector4 Get_Unity_SHAr(SphericalHarmonicsL2 sh)
{
return new Vector4(sh[0, 3], sh[0, 1], sh[0, 2], sh[0, 0] - sh[0, 6]);
}
public static Vector4 Get_unity_SHAg(SphericalHarmonicsL2 sh)
{
return new Vector4(sh[1, 3], sh[1, 1], sh[1, 2], sh[1, 0] - sh[1, 6]);
}
public static Vector4 Get_unity_SHAb(SphericalHarmonicsL2 sh)
{
return new Vector4(sh[2, 3], sh[2, 1], sh[2, 2], sh[2, 0] - sh[2, 6]);
}
public static Vector4 Get_Unity_SHBr(SphericalHarmonicsL2 sh)
{
return new Vector4(sh[0, 4], sh[0, 5], sh[0, 6] * 3, sh[0, 7]);
}
public static Vector4 Get_Unity_SHBg(SphericalHarmonicsL2 sh)
{
return new Vector4(sh[1, 4], sh[1, 5], sh[1, 6] * 3, sh[1, 7]);
}
public static Vector4 Get_Unity_SHBb(SphericalHarmonicsL2 sh)
{
return new Vector4(sh[2, 4], sh[2, 5], sh[2, 6] * 3, sh[2, 7]);
}
public static Vector4 Get_Unity_SHC(SphericalHarmonicsL2 sh)
{
return new Vector4(sh[0, 8], sh[2, 8], sh[1, 8], 1);
}
// normal should be normalized, w=1.0
private static Vector3 SHEvalLinearL0L1(Vector4 normal, LightProbeData lightProbeData)
{
Vector3 x;
// Linear (L1) + constant (L0) polynomial terms
x.x = Vector4.Dot(lightProbeData.unity_SHAr, normal);
x.y = Vector4.Dot(lightProbeData.unity_SHAg, normal);
x.z = Vector4.Dot(lightProbeData.unity_SHAb, normal);
return x;
}
// normal should be normalized, w=1.0
private static Vector3 SHEvalLinearL2(Vector4 normal, LightProbeData lightProbeData)
{
Vector3 x1, x2;
// 4 of the quadratic (L2) polynomials
Vector4 vB;
vB.x = normal.x * normal.y;
vB.y = normal.y * normal.z;
vB.z = normal.z * normal.z;
vB.w = normal.z * normal.x;
x1.x = Vector4.Dot(lightProbeData.unity_SHBr, vB);
x1.y = Vector4.Dot(lightProbeData.unity_SHBg, vB);
x1.z = Vector4.Dot(lightProbeData.unity_SHBb, vB);
// Final (5th) quadratic (L2) polynomial
float vC = normal.x * normal.x - normal.y * normal.y;
x2 = lightProbeData.unity_SHC * vC;
return x1 + x2;
}
// normal should be normalized, w=1.0
// output in active color space
private static Vector3 ShadeSH9(Vector4 normal, LightProbeData lightProbeData)
{
// Linear + constant polynomial terms
Vector3 res = SHEvalLinearL0L1(normal, lightProbeData);
// Quadratic polynomials
res += SHEvalLinearL2(normal, lightProbeData);
//todo: ?
//# ifdef UNITY_COLORSPACE_GAMMA
// res = LinearToGammaSpace(res);
//#endif
return res;
}
public static Color EvaluateSH2(SphericalHarmonicsL2 sh2, Vector3 normal)
{
var lightProbeData = LightProbeUtility.GetLightProbeData(sh2);
var vector = ShadeSH9(new Vector4(normal.x, normal.y, normal.z, 1.0f), lightProbeData);
return new Color(vector.x, vector.y, vector.z, 1.0f);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment