Пример #1
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);
        }
Пример #2
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")));
    }