Пример #1
0
    void plot(
        MapleFile&      file,
        const string&   name,
        const MDF&      mdf,
        const size_t    point_count,
        const size_t    sample_count)
    {
        vector<double> angles(point_count);
        vector<double> densities(point_count);

        for (size_t i = 0; i < point_count; ++i)
        {
            const double angle =
                fit(
                    static_cast<double>(i), 0.0, static_cast<double>(point_count - 1),
                    -HalfPi, +HalfPi);
            const double cos_angle = cos(angle);

            angles[i] = rad_to_deg(angle);
            densities[i] = mdf.evaluate(cos_angle) * cos_angle;
        }

        vector<double> angle_samples(sample_count);
        vector<double> density_samples(sample_count);

        for (size_t i = 0; i < sample_count; ++i)
        {
            static const size_t Bases[] = { 2 };
            const Vector2d s = hammersley_sequence<double, 2>(Bases, i, sample_count);
            const Vector3d w = mdf.sample(s);
            const double cos_angle = w.y;
            const double angle = acos(cos_angle) * (w.x < 0.0 ? -1.0 : 1.0);

            angle_samples[i] = rad_to_deg(angle);
            density_samples[i] = mdf.evaluate(cos_angle) * cos_angle;
        }

        file.define(name, angles, densities);
        file.define(name + "_samples", angle_samples, density_samples);

        file.plot(
            make_vector(
                MaplePlotDef(name)
                    .set_legend("Microfacet Distribution Function (" + name + ")"),
                MaplePlotDef(name + "_samples")
                    .set_legend("Integration Samples")
                    .set_style("point")
                    .set_color("red")));
    }
Пример #2
0
    double integrate_sampling(
        const MDF&      mdf,
        const Sampler&  sampler,
        const size_t    sample_count)
    {
        double integral = 0.0;

        for (size_t i = 0; i < sample_count; ++i)
        {
            static const size_t Bases[] = { 2 };
            const Vector2d s = hammersley_sequence<double, 2>(Bases, i, sample_count);

            const Vector3d w = sampler.sample(s);
            const double pdf = sampler.pdf(w);
            const double cos_theta = w.y;

            const double value = mdf.evaluate(cos_theta);
            const double sample = value / pdf;

            integral += sample * cos_theta;
        }

        integral /= static_cast<double>(sample_count);

        return integral;
    }
Пример #3
0
        static void compute_specular_albedo(
            const MDF&          mdf,
            const Spectrum&     rs,
            const Vector3d&     V,
            Spectrum&           albedo)
        {
            // V must lie above or in the surface.
            assert(V.y >= 0.0);

            albedo.set(0.0f);

            for (size_t i = 0; i < AlbedoSampleCount; ++i)
            {
                // Generate a uniform sample in [0,1)^2.
                static const size_t Bases[] = { 2 };
                const Vector2d s = hammersley_sequence<double, 2>(Bases, i, AlbedoSampleCount);

                // Sample the microfacet distribution to get an halfway vector H.
                const Vector3d H = mdf.sample(s);
                const double dot_HV = dot(H, V);
                if (dot_HV <= 0.0)
                    continue;

                // L is the reflection of V around H.
                const Vector3d L = (dot_HV + dot_HV) * H - V;

                // Reject L if it lies in or below the surface.
                if (L.y <= 0.0)
                    continue;

                // Evaluate the PDF of L.
                const double dot_HN = H.y;
                const double pdf_H = mdf.evaluate_pdf(dot_HN);
                const double pdf_L = pdf_H / (4.0 * dot_HV);
                assert(pdf_L >= 0.0);
                if (pdf_L == 0.0)
                    continue;

                // Sanity checks.
                assert(is_normalized(V));
                assert(is_normalized(H));
                assert(is_normalized(L));

                // Evaluate the specular component for this (L, V) pair.
                Spectrum fr_spec;
                fr_spec = fresnel_dielectric_schlick(rs, dot_HV);
                fr_spec *= static_cast<float>((L.y * mdf.evaluate(dot_HN)) / (4.0 * pdf_L * dot_HV * dot_HV));
                albedo += fr_spec;
            }

            albedo /= static_cast<float>(AlbedoSampleCount);
        }
Пример #4
0
        static void evaluate_fr_spec(
            const MDF&          mdf,
            const Spectrum&     rs,
            const double        dot_HL,     // cos_beta in the paper
            const double        dot_HN,
            Spectrum&           fr_spec)
        {
            assert(dot_HL >= 0.0);
            assert(dot_HN >= 0.0);

            fr_spec = fresnel_dielectric_schlick(rs, dot_HL);
            fr_spec *= static_cast<float>(mdf.evaluate(dot_HN) / (4.0 * dot_HL * dot_HL));
        }
Пример #5
0
    bool is_positive(
        const MDF&      mdf,
        const size_t    sample_count)
    {
        for (size_t i = 0; i < sample_count; ++i)
        {
            const double theta = radical_inverse_base2<double>(i) * HalfPi;
            const double cos_theta = cos(theta);

            const double value = mdf.evaluate(cos_theta);

            if (value < 0.0)
                return false;
        }

        return true;
    }
Пример #6
0
    double integrate_quadrature(
        const MDF&      mdf,
        const size_t    sample_count)
    {
        double integral = 0.0;

        for (size_t i = 0; i < sample_count; ++i)
        {
            const double theta = radical_inverse_base2<double>(i) * HalfPi;
            const double cos_theta = cos(theta);
            const double sin_theta = sin(theta);

            const double value = mdf.evaluate(cos_theta);

            integral += value * cos_theta * sin_theta;
        }

        integral *= HalfPi / sample_count;  // integration over theta
        integral *= TwoPi;                  // integration over phi

        return integral;
    }