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()); }
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()); }
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); }
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()); }
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()); }
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()); }
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); } }
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); } }
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]); } } }
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; } }
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()); }
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); }
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; }