public float[] coeffs; // Must have the size of 3

    public static ZonalHarmonicsL2 GetHenyeyGreensteinPhaseFunction(float asymmetry)
    {
        float g = asymmetry;

        var zh = new ZonalHarmonicsL2();

        zh.coeffs = new float[3];

        zh.coeffs[0] = 0.5f * Mathf.Sqrt(1.0f / Mathf.PI);
        zh.coeffs[1] = 0.5f * Mathf.Sqrt(3.0f / Mathf.PI) * g;
        zh.coeffs[2] = 0.5f * Mathf.Sqrt(5.0f / Mathf.PI) * g * g;

        return(zh);
    }
    public static ZonalHarmonicsL2 GetCornetteShanksPhaseFunction(float asymmetry)
    {
        float g = asymmetry;

        var zh = new ZonalHarmonicsL2();

        zh.coeffs = new float[3];

        zh.coeffs[0] = 0.282095f;
        zh.coeffs[1] = 0.293162f * g * (4.0f + (g * g)) / (2.0f + (g * g));
        zh.coeffs[2] = (0.126157f + 1.44179f * (g * g) + 0.324403f * (g * g) * (g * g)) / (2.0f + (g * g));

        return(zh);
    }
    // Ref: "Stupid Spherical Harmonics Tricks", p. 6.
    public static SphericalHarmonicsL2 Convolve(SphericalHarmonicsL2 sh, ZonalHarmonicsL2 zh)
    {
        for (int l = 0; l <= 2; l++)
        {
            float n = Mathf.Sqrt((4.0f * Mathf.PI) / (2 * l + 1));
            float k = zh.coeffs[l];
            float p = n * k;

            for (int m = -l; m <= l; m++)
            {
                int i = l * (l + 1) + m;

                for (int c = 0; c < 3; c++)
                {
                    sh[c, i] *= p;
                }
            }
        }

        return(sh);
    }