Example #1
0
LightSampler::LightSampler(const Scene& scene)
  : m_total_emissive_area(0.0)
{
    RENDERER_LOG_INFO("collecting light emitters...");

    // Collect all lights and light-emitting triangles.
    collect_lights(scene);
    collect_emitting_triangles(scene);

    // Precompute some values.
    m_light_count = m_lights.size();
    m_rcp_total_emissive_area = 1.0 / m_total_emissive_area;

    // Prepare the CDFs for sampling.
    if (m_emitter_cdf.valid())
        m_emitter_cdf.prepare();
    if (m_emitting_triangle_cdf.valid())
        m_emitting_triangle_cdf.prepare();

    RENDERER_LOG_INFO(
        "found %s %s, %s emitting %s.",
        pretty_int(m_light_count).c_str(),
        plural(m_light_count, "light").c_str(),
        pretty_int(m_emitting_triangles.size()).c_str(),
        plural(m_emitting_triangles.size(), "triangle").c_str());
}
Example #2
0
LightSampler::LightSampler(const Scene& scene)
  : m_total_emissive_area(0.0)
{
    RENDERER_LOG_INFO("collecting light emitters...");

    // Collect all lights and light-emitting triangles.
    for (const_each<AssemblyInstanceContainer> i = scene.assembly_instances(); i; ++i)
    {
        const AssemblyInstance& assembly_instance = *i;
        const Assembly& assembly = assembly_instance.get_assembly();

        collect_lights(assembly, assembly_instance);

        if (has_emitting_materials(assembly))
            collect_emitting_triangles(assembly, assembly_instance);
    }

    // Precompute some values.
    m_light_count = m_lights.size();
    m_rcp_total_emissive_area = 1.0 / m_total_emissive_area;

    // Prepare the CDFs for sampling.
    if (m_emitter_cdf.valid())
        m_emitter_cdf.prepare();
    if (m_emitting_triangle_cdf.valid())
        m_emitting_triangle_cdf.prepare();

    RENDERER_LOG_INFO(
        "found %s %s, %s emitting %s.",
        pretty_int(m_light_count).c_str(),
        plural(m_light_count, "light").c_str(),
        pretty_int(m_emitting_triangles.size()).c_str(),
        plural(m_emitting_triangles.size(), "triangle").c_str());
}
Example #3
0
void show_results(int num_spins, int num_wins){

    char spins_string[] = {' ', ' ', ' ', ' ', ' ', ' ', 
			   ' ', ' ', ' ', ' ', ' ', ' ', '\0'};
    char wins_string[]  = {' ', ' ', ' ', ' ', ' ', ' ', 
			   ' ', ' ', ' ', ' ', ' ', ' ', '\0'};
    double percent = 100.0* (double)num_wins / (double)num_spins;

    pretty_int(num_spins, spins_string);
    pretty_int(num_wins,  wins_string);

    printf(" | %15s | %14s | %11.2f%% |\n", spins_string, wins_string, percent);
}
Example #4
0
void FrameRendererBase::print_rendering_thread_count(const size_t thread_count)
{
    RENDERER_LOG_INFO(
        "using %s %s for rendering.",
        pretty_int(thread_count).c_str(),
        plural(thread_count, "thread").c_str());
}
Example #5
0
void AssemblyTree::rebuild_assembly_tree()
{
    // Clear the current tree.
    clear();
    m_assembly_instances.clear();

    Statistics statistics;

    // Collect all assembly instances of the scene.
    AABBVector assembly_instance_bboxes;
    collect_assembly_instances(assembly_instance_bboxes);

    RENDERER_LOG_INFO(
        "building assembly tree (%s %s)...",
        pretty_int(m_assembly_instances.size()).c_str(),
        plural(m_assembly_instances.size(), "assembly instance").c_str());

    // Create the partitioner.
    typedef bvh::SAHPartitioner<AABBVector> Partitioner;
    Partitioner partitioner(
        assembly_instance_bboxes,
        AssemblyTreeMaxLeafSize,
        AssemblyTreeInteriorNodeTraversalCost,
        AssemblyTreeTriangleIntersectionCost);

    // Build the assembly tree.
    typedef bvh::Builder<AssemblyTree, Partitioner> Builder;
    Builder builder;
    builder.build<DefaultWallclockTimer>(*this, partitioner, m_assembly_instances.size(), AssemblyTreeMaxLeafSize);
    statistics.insert_time("build time", builder.get_build_time());
    statistics.merge(bvh::TreeStatistics<AssemblyTree>(*this, AABB3d(m_scene.compute_bbox())));

    if (!m_assembly_instances.empty())
    {
        const vector<size_t>& ordering = partitioner.get_item_ordering();
        assert(m_assembly_instances.size() == ordering.size());

        // Reorder the assembly instances according to the tree ordering.
        vector<const AssemblyInstance*> temp_assembly_instances(ordering.size());
        small_item_reorder(
            &m_assembly_instances[0],
            &temp_assembly_instances[0],
            &ordering[0],
            ordering.size());

        // Store assembly instances in the tree leaves whenever possible.
        store_assembly_instances_in_leaves(statistics);
    }

    // Print assembly tree statistics.
    RENDERER_LOG_DEBUG("%s",
        StatisticsVector::make(
            "assembly tree statistics",
            statistics).to_string().c_str());
}
Example #6
0
LightSampler::LightSampler(const Scene& scene, const ParamArray& params)
  : m_params(params)
  , m_emitting_triangle_hash_table(m_triangle_key_hasher)
{
    RENDERER_LOG_INFO("collecting light emitters...");

    // Collect all non-physical lights.
    collect_non_physical_lights(scene.assembly_instances(), TransformSequence());
    m_non_physical_light_count = m_non_physical_lights.size();

    // Collect all light-emitting triangles.
    collect_emitting_triangles(
        scene.assembly_instances(),
        TransformSequence());

    // Build the hash table of emitting triangles.
    build_emitting_triangle_hash_table();

    // Prepare the CDFs for sampling.
    if (m_non_physical_lights_cdf.valid())
        m_non_physical_lights_cdf.prepare();
    if (m_emitting_triangles_cdf.valid())
        m_emitting_triangles_cdf.prepare();

    // Store the triangle probability densities into the emitting triangles.
    const size_t emitting_triangle_count = m_emitting_triangles.size();
    for (size_t i = 0; i < emitting_triangle_count; ++i)
        m_emitting_triangles[i].m_triangle_prob = m_emitting_triangles_cdf[i].second;

   RENDERER_LOG_INFO(
        "found %s %s, %s emitting %s.",
        pretty_int(m_non_physical_light_count).c_str(),
        plural(m_non_physical_light_count, "non-physical light").c_str(),
        pretty_int(m_emitting_triangles.size()).c_str(),
        plural(m_emitting_triangles.size(), "triangle").c_str());
}
Example #7
0
void OBJMeshFileWriter::write_vertices(const IMeshWalker& walker) const
{
    const size_t vertex_count = walker.get_vertex_count();

    fprintf(
        m_file,
        "# %s %s.\n",
        pretty_int(vertex_count).c_str(),
        plural(vertex_count, "vertex", "vertices").c_str());

    for (size_t i = 0; i < vertex_count; ++i)
    {
        const Vector3d v = walker.get_vertex(i);
        write_vector("v", v);
    }
}
Example #8
0
void OBJMeshFileWriter::write_texture_coordinates(const IMeshWalker& walker) const
{
    const size_t tex_coords_count = walker.get_tex_coords_count();

    if (tex_coords_count == 0)
        return;

    fprintf(
        m_file,
        "# %s %s.\n",
        pretty_int(tex_coords_count).c_str(),
        plural(tex_coords_count, "texture coordinate").c_str());

    for (size_t i = 0; i < tex_coords_count; ++i)
    {
        const Vector2d vt = walker.get_tex_coords(i);
        write_vector("vt", vt);
    }
}
Example #9
0
void OBJMeshFileWriter::write_vertex_normals(const IMeshWalker& walker) const
{
    const size_t vertex_normal_count = walker.get_vertex_normal_count();

    if (vertex_normal_count == 0)
        return;

    fprintf(
        m_file,
        "# %s %s.\n",
        pretty_int(vertex_normal_count).c_str(),
        plural(vertex_normal_count, "vertex normal").c_str());

    for (size_t i = 0; i < vertex_normal_count; ++i)
    {
        const Vector3d vn = walker.get_vertex_normal(i);
        write_vector("vn", vn);
    }
}
void LightPathsWidget::dump_selected_light_path() const
{
    if (m_selected_light_path_index == -1)
    {
        if (m_light_paths.empty())
            RENDERER_LOG_INFO("no light path to display.");
        else
        {
            RENDERER_LOG_INFO("displaying all %s light path%s.",
                pretty_uint(m_light_paths.size()).c_str(),
                m_light_paths.size() > 1 ? "s" : "");
        }
    }
    else
    {
        RENDERER_LOG_INFO("displaying light path %s:",
            pretty_int(m_selected_light_path_index + 1).c_str());

        const auto& light_path_recorder = m_project.get_light_path_recorder();
        const auto& path = m_light_paths[m_selected_light_path_index];

        for (size_t i = path.m_vertex_begin_index; i < path.m_vertex_end_index; ++i)
        {
            LightPathVertex v;
            light_path_recorder.get_light_path_vertex(i, v);

            const string entity_name =
                v.m_entity != nullptr
                    ? foundation::format("\"{0}\"", v.m_entity->get_path().c_str())
                    : "n/a";

            RENDERER_LOG_INFO("  vertex " FMT_SIZE_T ": entity: %s - position: (%f, %f, %f) - radiance: (%f, %f, %f) - total radiance: %f",
                i - path.m_vertex_begin_index + 1,
                entity_name.c_str(),
                v.m_position[0], v.m_position[1], v.m_position[2],
                v.m_radiance[0], v.m_radiance[1], v.m_radiance[2],
                v.m_radiance[0] + v.m_radiance[1] + v.m_radiance[2]);
        }
    }
}
Example #11
0
void OBJMeshFileWriter::write_faces(const IMeshWalker& walker) const
{
    const size_t face_count = walker.get_face_count();

    fprintf(
        m_file,
        "# %s %s.\n",
        pretty_int(face_count).c_str(),
        plural(face_count, "face").c_str());

    const size_t feature_mask =
        (walker.get_vertex_normal_count() > 0 ? 1 : 0) +
        (walker.get_tex_coords_count() > 0 ? 2 : 0);

    switch (feature_mask)
    {
      case 0: write_faces_no_vn_no_vt(walker); break;
      case 1: write_faces_vn_no_vt(walker); break;
      case 2: write_faces_no_vn_vt(walker); break;
      case 3: write_faces_vn_vt(walker); break;
      assert_otherwise;
    }
}
Example #12
0
void AssemblyTree::build_assembly_tree()
{
    // Insert all assembly instances of the scene into the tree.
    for (const_each<AssemblyInstanceContainer> i = m_scene.assembly_instances(); i; ++i)
    {
        // Retrieve the assembly instance.
        const AssemblyInstance& assembly_instance = *i;

        // Retrieve the assembly.
        const Assembly& assembly = assembly_instance.get_assembly();

        // Skip empty assemblies.
        if (assembly.object_instances().empty())
            continue;

        // Insert the assembly instance into the root leaf.
        insert(
            assembly_instance.get_uid(),
            assembly_instance.compute_parent_bbox());
    }

    // Log a progress message.
    RENDERER_LOG_INFO(
        "building assembly bvh (%s %s)...",
        pretty_int(size()).c_str(),
        plural(size(), "assembly instance").c_str());

    // Build the assembly tree.
    AssemblyTreePartitioner partitioner;
    AssemblyTreeBuilder builder;
    builder.build(*this, partitioner);

    // Collect and print assembly tree statistics.
    AssemblyTreeStatistics tree_stats(*this, builder);
    RENDERER_LOG_DEBUG("assembly bvh statistics:");
    tree_stats.print(global_logger());
}
Example #13
0
const ShadingPoint& Tracer::do_trace(
    const Vector3d&             origin,
    const Vector3d&             direction,
    const double                time,
    const ShadingRay::Type      ray_type,
    const ShadingRay::DepthType ray_depth,
    double&                     transmission,
    const ShadingPoint*         parent_shading_point)
{
    transmission = 1.0;

    const ShadingPoint* shading_point_ptr = parent_shading_point;
    size_t shading_point_index = 0;
    Vector3d point = origin;
    size_t iterations = 0;

    while (true)
    {
        // Put a hard limit on the number of iterations.
        if (++iterations >= m_max_iterations)
        {
            RENDERER_LOG_WARNING(
                "reached hard iteration limit (%s), breaking trace loop.",
                pretty_int(m_max_iterations).c_str());
            break;
        }

        // Construct the visibility ray.
        const ShadingRay ray(
            point,
            direction,
            time,
            m_ray_dtime,
            ray_type,
            ray_depth);         // ray depth does not increase when passing through an alpha-mapped surface

        // Trace the ray.
        m_shading_points[shading_point_index].clear();
        m_intersector.trace(
            ray,
            m_shading_points[shading_point_index],
            shading_point_ptr);

        // Update the pointers to the shading points.
        shading_point_ptr = &m_shading_points[shading_point_index];
        shading_point_index = 1 - shading_point_index;

        // Stop if the ray escaped the scene.
        if (!shading_point_ptr->hit())
            break;

        // Retrieve the material at the shading point.
        const Material* material = shading_point_ptr->get_material();
        if (material == 0)
            break;

        Alpha alpha;
        evaluate_alpha(*material, *shading_point_ptr, alpha);

        // Stop at the first fully opaque occluder.
        if (alpha[0] >= 1.0f)
            break;

        // Update the transmission factor.
        transmission *= 1.0 - static_cast<double>(alpha[0]);

        // Stop once we hit full opacity.
        if (transmission < m_transmission_threshold)
            break;

        // Move past this partial occluder.
        point = shading_point_ptr->get_point();
    }

    return *shading_point_ptr;
}
string Statistics::IntegerEntry::to_string() const
{
    return pretty_int(m_value);
}
Example #15
0
const ShadingPoint& Tracer::do_trace_between(
    const Vector3d&             origin,
    const Vector3d&             target,
    const ShadingRay::Time&     ray_time,
    const VisibilityFlags::Type ray_flags,
    const ShadingRay::DepthType ray_depth,
    float&                      transmission,
    const ShadingPoint*         parent_shading_point)
{
    transmission = 1.0f;

    const ShadingPoint* shading_point_ptr = parent_shading_point;
    size_t shading_point_index = 0;
    Vector3d point = origin;
    size_t iterations = 0;

    while (true)
    {
        // Put a hard limit on the number of iterations.
        if (++iterations >= m_max_iterations)
        {
            RENDERER_LOG_WARNING(
                "reached hard iteration limit (%s), breaking trace loop.",
                pretty_int(m_max_iterations).c_str());
            break;
        }

        // Construct the visibility ray.
        const Vector3d direction = target - point;
        const double dist = norm(direction);

        const ShadingRay ray(
            point,
            direction / dist,
            0.0,                    // ray tmin
            dist * (1.0 - 1.0e-6),  // ray tmax
            ray_time,
            ray_flags,
            ray_depth);         // ray depth does not increase when passing through an alpha-mapped surface

        // Trace the ray.
        m_shading_points[shading_point_index].clear();
        m_intersector.trace(
            ray,
            m_shading_points[shading_point_index],
            shading_point_ptr);

        // Update the pointers to the shading points.
        shading_point_ptr = &m_shading_points[shading_point_index];
        shading_point_index = 1 - shading_point_index;

        // Stop if the ray reached the target point.
        if (!shading_point_ptr->hit())
            break;

        // Retrieve the material at the shading point.
        const Material* material = shading_point_ptr->get_material();
        if (material == 0)
            break;

        // Evaluate the alpha map at the shading point.
        Alpha alpha;
        evaluate_alpha(*material, *shading_point_ptr, alpha);

        // Stop at the first fully opaque occluder.
        if (alpha[0] >= 1.0f)
            break;

        // Update the transmission factor.
        transmission *= 1.0f - alpha[0];

        // Stop once we hit full opacity.
        if (transmission < m_transmission_threshold)
            break;

        // Move past this partial occluder.
        point = shading_point_ptr->get_point();
    }

    return *shading_point_ptr;
}