bool XM_CALLCONV DirectX::XMSHEvalHemisphereLight()

in SHMath/DirectXSH.cpp [4796:4907]


bool XM_CALLCONV DirectX::XMSHEvalHemisphereLight(
    size_t order,
    FXMVECTOR dir,
    FXMVECTOR topColor,
    FXMVECTOR bottomColor,
    float *resultR,
    float *resultG,
    float *resultB) noexcept
{
    if (!resultR)
        return false;

    if (order < XM_SH_MINORDER || order > XM_SH_MAXORDER)
        return false;

    // seperate "R/G/B colors...

    float fTmpDir[XM_SH_MAXORDER * XM_SH_MAXORDER];  // rotation "vector"
    float fTmpL0[XM_SH_MAXORDER];

    const float fNewNorm = 3.0f / 2.0f; // normalizes things for 1 sky color, 0 ground color...

    XMFLOAT3A vd;
    XMStoreFloat3(&vd, dir);

    const float fX = vd.x;
    const float fY = vd.y;
    const float fZ = vd.z;

    sh_eval_basis_1(fX, fY, fZ, fTmpDir);

    XMFLOAT3A clrTop;
    XMStoreFloat3A(&clrTop, topColor);

    XMFLOAT3A clrBottom;
    XMStoreFloat3A(&clrBottom, bottomColor);

    float fA = clrTop.x;
    float fAvrg = (clrTop.x + clrBottom.x)*0.5f;

    fTmpL0[0] = fAvrg*2.0f*SHEvalHemisphereLight_fSqrtPi;
    fTmpL0[1] = (fA - fAvrg)*2.0f*SHEvalHemisphereLight_fSqrtPi3;

    size_t i = 0;
    for (; i < 2; ++i)
    {
        _Analysis_assume_(i < order);
        const size_t cNumCoefs = 2 * i + 1;
        const size_t cStart = i*i;
        const float fValUse = fTmpL0[i] * fNewNorm*fExtraNormFac[i];
        for (size_t j = 0; j < cNumCoefs; ++j) resultR[cStart + j] = fTmpDir[cStart + j] * fValUse;
    }

    for (; i < order; ++i)
    {
        const size_t cNumCoefs = 2 * i + 1;
        const size_t cStart = i*i;
        for (size_t j = 0; j < cNumCoefs; ++j) resultR[cStart + j] = 0.0f;
    }

    if (resultG)
    {
        fA = clrTop.y;
        fAvrg = (clrTop.y + clrBottom.y)*0.5f;

        fTmpL0[0] = fAvrg*2.0f*SHEvalHemisphereLight_fSqrtPi;
        fTmpL0[1] = (fA - fAvrg)*2.0f*SHEvalHemisphereLight_fSqrtPi3;

        for (i = 0; i < 2; ++i)
        {
            _Analysis_assume_(i < order);
            const size_t cNumCoefs = 2 * i + 1;
            const size_t cStart = i*i;
            const float fValUse = fTmpL0[i] * fNewNorm*fExtraNormFac[i];
            for (size_t j = 0; j < cNumCoefs; ++j) resultG[cStart + j] = fTmpDir[cStart + j] * fValUse;
        }

        for (; i < order; ++i)
        {
            const size_t cNumCoefs = 2 * i + 1;
            const size_t cStart = i*i;
            for (size_t j = 0; j < cNumCoefs; ++j) resultG[cStart + j] = 0.0f;
        }
    }

    if (resultB)
    {
        fA = clrTop.z;
        fAvrg = (clrTop.z + clrBottom.z)*0.5f;

        fTmpL0[0] = fAvrg*2.0f*SHEvalHemisphereLight_fSqrtPi;
        fTmpL0[1] = (fA - fAvrg)*2.0f*SHEvalHemisphereLight_fSqrtPi3;

        for (i = 0; i < 2; ++i)
        {
            _Analysis_assume_(i < order);
            const size_t cNumCoefs = 2 * i + 1;
            const size_t cStart = i*i;
            const float fValUse = fTmpL0[i] * fNewNorm*fExtraNormFac[i];
            for (size_t j = 0; j < cNumCoefs; ++j) resultB[cStart + j] = fTmpDir[cStart + j] * fValUse;
        }

        for (; i < order; ++i)
        {
            const size_t cNumCoefs = 2 * i + 1;
            const size_t cStart = i*i;
            for (size_t j = 0; j < cNumCoefs; ++j) resultB[cStart + j] = 0.0f;
        }
    }

    return true;
}