#include "diffuse.h"
#include <render/intersection.h>
#include <core/utils.h>
#include <assert.h>
#include "light_path.h"

Spectrum DiffuseBSDF::eval(const Intersection &its, const Vector &wo,
                           EBSDFMode mode) const
{
    if (its.wi.z() < Epsilon || wo.z() < Epsilon)
        return Spectrum::Zero();
    else
    {
        if (mode == EBSDFMode::EImportanceWithCorrection)
            return reflectance.eval(its.uv) * INV_PI * wo.z() * correction(its, wo);
        else
            return reflectance.eval(its.uv) * INV_PI * wo.z();
    }
}

Spectrum DiffuseBSDF::sample(const Intersection &its, const Array3 &rnd,
                             Vector &wo, Float &pdf, Float &eta,
                             EBSDFMode mode) const
{
    if (its.wi.z() < Epsilon)
        return Spectrum::Zero();
    wo = squareToCosineHemisphere(Vector2(rnd[0], rnd[1]));
    eta = 1.0f;
    pdf = squareToCosineHemispherePdf(wo);
    if (mode == EBSDFMode::EImportanceWithCorrection)
        return reflectance.eval(its.uv) * correction(its, wo);
    else
        return reflectance.eval(its.uv);
}

Float DiffuseBSDF::pdf(const Intersection &its, const Vector &wo) const
{
    if (its.wi.z() < Epsilon || wo.z() < Epsilon)
        return 0.0;
    else
        return squareToCosineHemispherePdf(wo);
}

// =============================================================================
// c-style functions
IMPLEMENT_BSDF_HELPER_FUNCTIONS(DiffuseBSDF)