Exemplo n.º 1
0
bool DipoleBSSRDF::sample(
    SamplingContext&    sampling_context,
    const void*         data,
    BSSRDFSample&       sample) const
{
    const DipoleBSSRDFInputValues* values =
        reinterpret_cast<const DipoleBSSRDFInputValues*>(data);

    if (values->m_weight == 0.0)
        return false;

    sampling_context.split_in_place(3, 1);
    const Vector3d s = sampling_context.next_vector2<3>();

    // Sample a channel.
    const size_t channel =
        sample_cdf(
            &values->m_channel_cdf[0],
            &values->m_channel_cdf[0] + values->m_channel_cdf.size(),
            s[0]);

    // Sample a radius.
    const double sigma_tr = values->m_sigma_tr[channel];
    const double radius = sample_exponential_distribution(s[1], sigma_tr);

    // Sample an angle.
    const double phi = TwoPi * s[2];

    sample.m_eta = values->m_eta;
    sample.m_channel = channel;
    sample.m_point = Vector2d(radius * cos(phi), radius * sin(phi));
    sample.m_rmax2 = values->m_rmax2;

    return true;
}
Exemplo n.º 2
0
double normalized_diffusion_sample(
    const double    u,
    const double    l,
    const double    s,
    const double    eps,
    const size_t    max_iterations)
{
    assert(u >= 0.0);
    assert(u < 1.0);

    const double d = l / s;

    // Handle the case where u is greater than the value we consider 1 in our CDF.
    if (u >= nd_cdf_rmax)
        return NdCdfTableRmax * d;

    // Use the CDF to find an initial interval for the root of cdf(r, 1) - u = 0.
    const size_t i = sample_cdf(nd_cdf_table, nd_cdf_table + NdCdfTableSize, u);
    assert(i > 0);
    assert(nd_cdf_table[i - 1] <= u);
    assert(nd_cdf_table[i] > u);

    // Transform the cdf(r, 1) interval to cdf(r, d) using the fact that cdf(r, d) == cdf(r/d, 1).
    double rmin = fit<size_t, double>(i - 1, 0, NdCdfTableSize - 1, 0.0, NdCdfTableRmax) * d;
    double rmax = fit<size_t, double>(i,     0, NdCdfTableSize - 1, 0.0, NdCdfTableRmax) * d;
    assert(normalized_diffusion_cdf(rmin, d) <= u);
    assert(normalized_diffusion_cdf(rmax, d) > u);

    double r = (rmax + rmin) * 0.5;

    // Refine the root.
    for (size_t i = 0; i < max_iterations; ++i)
    {
        // Use bisection if we go out of bounds.
        if (r < rmin || r > rmax)
            r = (rmax + rmin) * 0.5;

        const double f = normalized_diffusion_cdf(r, d) - u;

        // Convergence test.
        if (abs(f) <= eps)
            break;

        // Update bounds.
        f < 0.0 ? rmin = r : rmax = r;

        // Newton step.
        const double df = normalized_diffusion_pdf(r, d);
        r -= f / df;
    }

    return r;
}
Exemplo n.º 3
0
double normalized_diffusion_sample(
    const double    u,
    const double    l,
    const double    s,
    const double    eps,
    const size_t    max_iterations)
{
    assert(u >= 0.0);
    assert(u < 1.0);

    const double d = l / s;

    // Handle the case where u is greater than the value we consider 1 in our CDF.
    if (u >= nd_cdf_rmax)
        return NDCDFTableRmax * d;

    // Use the CDF to find an initial interval for the root of cdf(r, 1) - u = 0.
    const size_t i = sample_cdf(nd_cdf_table, nd_cdf_table + NDCDFTableSize, u);
    assert(i > 0);
    assert(nd_cdf_table[i - 1] <= u);
    assert(nd_cdf_table[i] > u);

    // Transform the cdf(r, 1) interval to cdf(r, d) using the fact that cdf(r, d) == cdf(r/d, 1).
    const double rmin = fit<size_t, double>(i - 1, 0, NDCDFTableSize - 1, 0.0, NDCDFTableRmax) * d;
    const double rmax = fit<size_t, double>(i,     0, NDCDFTableSize - 1, 0.0, NDCDFTableRmax) * d;

    return invert_cdf_function(
        NDCDFFun(d),
        NDPDFFun(d),
        u,
        rmin,
        rmax,
        (rmax + rmin) * 0.5,
        eps,
        max_iterations);
}
Exemplo n.º 4
0
size_t CompositeClosure::choose_closure(const double w) const
{
    return sample_cdf(m_cdf, m_cdf + get_num_closures(), w);
}