bool XM_CALLCONV DirectX::XMSHEvalConeLight()

in SHMath/DirectXSH.cpp [4675:4779]


bool XM_CALLCONV DirectX::XMSHEvalConeLight(
    size_t order,
    FXMVECTOR dir,
    float radius,
    FXMVECTOR color,
    float *resultR,
    float *resultG,
    float *resultB) noexcept
{
    if (!resultR)
        return false;

    if (radius < 0.f || radius >(XM_PI*1.00001f))
        return false;

    if (radius < 0.0001f)
    {
        // turn it into a pure directional light...
        return XMSHEvalDirectionalLight(order, dir, color, resultR, resultG, resultB);
    }
    else
    {
        float fTmpL0[XM_SH_MAXORDER];
        float fTmpDir[XM_SH_MAXORDER * XM_SH_MAXORDER];

        const float fConeAngle = radius;
        const float fAngCheck = (fConeAngle > XM_PIDIV2) ? (XM_PIDIV2) : fConeAngle;

        const float fNewNorm = 1.0f / (sinf(fAngCheck)*sinf(fAngCheck));

        ComputeCapInt(order, fConeAngle, fTmpL0);

        XMFLOAT3A vd;
        XMStoreFloat3(&vd, dir);

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

        switch (order)
        {
        case 2:
            sh_eval_basis_1(fX, fY, fZ, fTmpDir);
            break;

        case 3:
            sh_eval_basis_2(fX, fY, fZ, fTmpDir);
            break;

        case 4:
            sh_eval_basis_3(fX, fY, fZ, fTmpDir);
            break;

        case 5:
            sh_eval_basis_4(fX, fY, fZ, fTmpDir);
            break;

        case 6:
            sh_eval_basis_5(fX, fY, fZ, fTmpDir);
            break;

        default:
            assert(order < XM_SH_MINORDER || order > XM_SH_MAXORDER);
            return false;
        }

        XMFLOAT3A clr;
        XMStoreFloat3A(&clr, color);

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

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

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

    return true;
}