bool Intersector::trace_same_material( const ShadingRay& ray, const ShadingPoint& parent_shading_point, const bool offset_origin, ShadingPoint& shading_point) const { if (do_trace_same_material(ray, parent_shading_point, offset_origin, shading_point)) { // do_trace_same_material() intersects only with triangles // whose normal points in the same direction as the ray. // Triangles are intersected from the inside of the object and // shading_point.get_shading_normal() points inside the object. // todo: we maybe need a better way to flip the shading normal here. const Basis3d& basis = shading_point.get_shading_basis(); shading_point.set_shading_basis( Basis3d( -basis.get_normal(), -basis.get_tangent_u(), basis.get_tangent_v())); return true; } return false; }
void ShadingEngine::shade_environment( SamplingContext& sampling_context, const ShadingContext& shading_context, const ShadingPoint& shading_point, ShadingResult& shading_result) const { // Retrieve the environment shader of the scene. const EnvironmentShader* environment_shader = shading_point.get_scene().get_environment()->get_environment_shader(); if (environment_shader) { // There is an environment shader: execute it. InputEvaluator input_evaluator(shading_context.get_texture_cache()); const ShadingRay& ray = shading_point.get_ray(); const Vector3d direction = normalize(ray.m_dir); environment_shader->evaluate( input_evaluator, direction, shading_result); // Set environment shader AOV. shading_result.set_entity_aov(*environment_shader); } else { // No environment shader: shade as transparent black. shading_result.set_main_to_transparent_black_linear_rgba(); shading_result.set_aovs_to_transparent_black_linear_rgba(); } }
bool Intersector::trace( const ShadingRay& ray, ShadingPoint& shading_point, const ShadingPoint* parent_shading_point) const { assert(shading_point.m_scene == 0); assert(shading_point.hit() == false); assert(parent_shading_point == 0 || parent_shading_point != &shading_point); assert(parent_shading_point == 0 || parent_shading_point->hit()); // Update ray casting statistics. ++m_ray_count; // Initialize the shading point. shading_point.m_region_kit_cache = &m_region_kit_cache; shading_point.m_tess_cache = &m_tess_cache; shading_point.m_scene = &m_trace_context.get_scene(); shading_point.m_ray = ray; // Compute ray info once for the entire traversal. const ShadingRay::RayInfoType ray_info(shading_point.m_ray); // Refine and offset the previous intersection point. if (parent_shading_point && parent_shading_point->hit() && !(parent_shading_point->m_members & ShadingPoint::HasRefinedPoints)) parent_shading_point->refine_and_offset(); // Retrieve assembly tree. const AssemblyTree& assembly_tree = m_trace_context.get_assembly_tree(); // Check the intersection between the ray and the assembly tree. AssemblyLeafVisitor visitor( shading_point, assembly_tree, m_region_tree_cache, m_triangle_tree_cache, parent_shading_point #ifdef FOUNDATION_BSP_ENABLE_TRAVERSAL_STATS , m_triangle_bsp_traversal_stats #endif ); AssemblyLeafIntersector intersector; intersector.intersect( assembly_tree, shading_point.m_ray, ray_info, visitor #ifdef FOUNDATION_BVH_ENABLE_TRAVERSAL_STATS , m_assembly_bvh_traversal_stats #endif ); // Detect and report self-intersections. if (m_report_self_intersections) report_self_intersection(shading_point, parent_shading_point); return shading_point.hit(); }
float BSSRDF::compute_eta( const ShadingPoint& shading_point, const float ior) { const float outside_ior = shading_point.is_entering() ? shading_point.get_ray().get_current_ior() : shading_point.get_ray().get_previous_ior(); return outside_ior / ior; }
double LightSampler::evaluate_pdf(const ShadingPoint& shading_point) const { assert(shading_point.is_triangle_primitive()); const EmittingTriangleKey triangle_key( shading_point.get_assembly_instance().get_uid(), shading_point.get_object_instance_index(), shading_point.get_region_index(), shading_point.get_primitive_index()); const EmittingTriangle* triangle = m_emitting_triangle_hash_table.get(triangle_key); return triangle->m_triangle_prob * triangle->m_rcp_area; }
void Intersector::trace_back_sides( ShadingRay ray, ShadingPoint& shading_point) const { while (trace(ray, shading_point)) { if (dot(ray.m_dir, shading_point.get_original_shading_normal()) > 0.0) break; shading_point.refine_and_offset(); ray.m_org = shading_point.get_offset_point(ray.m_dir); shading_point.clear(); } }
void add_back_lighting( const InputValues& values, SamplingContext& sampling_context, const PixelContext& pixel_context, const ShadingContext& shading_context, const ShadingPoint& shading_point, Spectrum& radiance, SpectrumStack& aovs) const { const Vector3d& p = shading_point.get_point(); const Vector3d& n = shading_point.get_original_shading_normal(); const Vector3d& d = shading_point.get_ray().m_dir; // Construct a ray perpendicular to the other side of the surface. ShadingRay back_ray(shading_point.get_ray()); back_ray.m_tmax *= norm(d); back_ray.m_dir = dot(d, n) > 0.0 ? -n : n; back_ray.m_org = p - back_ray.m_tmax * back_ray.m_dir; ShadingPoint back_shading_point(shading_point); back_shading_point.set_ray(back_ray); Spectrum back_radiance(0.0f); SpectrumStack back_aovs(aovs.size(), 0.0f); // Compute back lighting. for (size_t i = 0; i < m_back_lighting_samples; ++i) { shading_context.get_lighting_engine()->compute_lighting( sampling_context, pixel_context, shading_context, back_shading_point, back_radiance, back_aovs); } // Apply translucency factor. back_radiance *= values.m_translucency; back_aovs *= values.m_translucency; // Divide by the number of samples. const float rcp_sample_count = 1.0f / static_cast<float>(m_back_lighting_samples); back_radiance *= rcp_sample_count; back_aovs *= rcp_sample_count; // Add back lighting contribution. radiance += back_radiance; aovs += back_aovs; }
void do_compute_lighting( SamplingContext& sampling_context, const ShadingContext& shading_context, const ShadingPoint& shading_point, Spectrum& radiance, // output radiance, in W.sr^-1.m^-2 SpectrumStack& aovs) { PathVisitor path_visitor( m_params, m_light_sampler, sampling_context, shading_context, shading_point.get_scene(), radiance, aovs); PathTracer<PathVisitor, false> path_tracer( // false = not adjoint path_visitor, m_params.m_rr_min_path_length, m_params.m_max_path_length, shading_context.get_max_iterations()); const size_t path_length = path_tracer.trace( sampling_context, shading_context, shading_point); // Update statistics. ++m_path_count; m_path_length.insert(path_length); }
void BSDF::evaluate_inputs( InputEvaluator& input_evaluator, const ShadingPoint& shading_point, const size_t offset) const { input_evaluator.evaluate(get_inputs(), shading_point.get_uv(0), offset); }
void Tracer::evaluate_alpha( const Material& material, const ShadingPoint& shading_point, Alpha& alpha) const { // Init to fully opaque. alpha.set(1.0f); // Evaluate the alpha map at the shading point. if (const Source* alpha_map = material.get_alpha_map()) { alpha_map->evaluate( m_texture_cache, shading_point.get_uv(0), alpha); } #ifdef WITH_OSL if (const ShaderGroup* sg = material.get_osl_surface()) { if (sg->has_transparency()) { Alpha a; m_shadergroup_exec.execute_transparency( *sg, shading_point, a); alpha *= a; } } #endif }
void apply_aerial_perspective( const InputValues& values, const ShadingContext& shading_context, const PixelContext& pixel_context, const ShadingPoint& shading_point, ShadingResult& shading_result) const { Spectrum sky_color; if (m_aerial_persp_mode == AerialPerspSkyColor) sky_color = values.m_aerial_persp_sky_color; else { // Retrieve the environment shader of the scene. const Scene& scene = shading_point.get_scene(); const EnvironmentShader* environment_shader = scene.get_environment()->get_environment_shader(); if (environment_shader) { // Execute the environment shader to obtain the sky color in the direction of the ray. InputEvaluator input_evaluator(shading_context.get_texture_cache()); const ShadingRay& ray = shading_point.get_ray(); const Vector3d direction = normalize(ray.m_dir); ShadingResult sky; environment_shader->evaluate( shading_context, pixel_context, input_evaluator, direction, sky); sky_color = sky.m_main.m_color; } else sky_color.set(0.0f); } // Compute the blend factor. const double d = shading_point.get_distance() * m_aerial_persp_rcp_distance; const double k = m_aerial_persp_intensity * exp(d); const double blend = min(k, 1.0); // Blend the shading result and the sky color. sky_color *= static_cast<float>(blend); shading_result.m_main.m_color *= static_cast<float>(1.0 - blend); shading_result.m_main.m_color += sky_color; }
void OSLShaderGroupExec::do_execute( const ShaderGroup& shader_group, const ShadingPoint& shading_point, const VisibilityFlags::Type ray_flags) const { assert(m_osl_shading_context); assert(m_osl_thread_info); shading_point.initialize_osl_shader_globals( shader_group, ray_flags, m_osl_shading_system.renderer()); m_osl_shading_system.execute( m_osl_shading_context, *reinterpret_cast<OSL::ShaderGroup*>(shader_group.osl_shader_group()), shading_point.get_osl_shader_globals()); }
void OSLShaderGroupExec::choose_bsdf_closure_shading_basis( const ShadingPoint& shading_point, const Vector2f& s) const { CompositeSurfaceClosure c( Basis3f(shading_point.get_shading_basis()), shading_point.get_osl_shader_globals().Ci, m_arena); float pdfs[CompositeSurfaceClosure::MaxClosureEntries]; const size_t num_closures = c.compute_pdfs(ScatteringMode::All, pdfs); if (num_closures == 0) return; const size_t index = c.choose_closure(s[1], num_closures, pdfs); shading_point.set_shading_basis( Basis3d(c.get_closure_shading_basis(index))); }
void OSLShaderGroupExec::execute_shading( const ShaderGroup& shader_group, const ShadingPoint& shading_point) const { do_execute( shader_group, shading_point, shading_point.get_ray().m_flags); }
void BSSRDF::evaluate_inputs( const ShadingContext& shading_context, InputEvaluator& input_evaluator, const ShadingPoint& shading_point, const size_t offset) const { input_evaluator.evaluate(get_inputs(), shading_point.get_uv(0), offset); prepare_inputs(input_evaluator.data() + offset); }
void OSLShaderGroupExec::execute_shading( const ShaderGroup& shader_group, const ShadingPoint& shading_point) const { assert(m_osl_shading_context); assert(m_osl_thread_info); m_osl_shading_system.execute( *m_osl_shading_context, *shader_group.shadergroup_ref(), shading_point.get_osl_shader_globals()); }
void OSLShaderGroupExec::execute_transparency( const ShaderGroup& shader_group, const ShadingPoint& shading_point, Alpha& alpha) const { do_execute( shader_group, shading_point, VisibilityFlags::TransparencyRay); process_transparency_tree(shading_point.get_osl_shader_globals().Ci, alpha); }
void OSLShaderGroupExec::execute_transparency( const ShaderGroup& shader_group, const ShadingPoint& shading_point, Alpha& alpha, float* holdout) const { // Switch temporary the ray type to Shadow. ShadingRay::TypeType saved_type = shading_point.m_ray.m_type; shading_point.m_ray.m_type = ShadingRay::ShadowRay; m_osl_shading_system.execute( *m_osl_shading_context, *shader_group.shadergroup_ref(), shading_point.get_osl_shader_globals()); process_transparency_tree(shading_point.get_osl_shader_globals().Ci, alpha); if (holdout) *holdout = process_holdout_tree(shading_point.get_osl_shader_globals().Ci); // Restore the original ray type. shading_point.m_ray.m_type = saved_type; }
Color3d update_and_evaluate( const ShadingPoint& shading_point, OIIO::TextureSystem& texture_system) { for (each<ptr_vector<TextureSeExprFunc> > it = m_functions_x; it; ++it) it->set_texture_system(&texture_system); const Vector2d& uv = shading_point.get_uv(0); m_vars["u"] = Var(uv[0]); m_vars["v"] = Var(uv[1]); const SeVec3d result = evaluate(); return Color3d(result[0], result[1], result[2]); }
Color3d update_and_evaluate( const ShadingPoint& shading_point, OIIO::TextureSystem& texture_system) { for (each<ptr_vector<TextureSeExprFunc> > i = m_functions_x; i; ++i) i->set_texture_system(&texture_system); const Vector2d& uv = shading_point.get_uv(0); m_u_var.m_val = uv[0]; m_v_var.m_val = uv[1]; const SeVec3d result = evaluate(); return Color3d(result[0], result[1], result[2]); }
void OSLShaderGroupExec::execute_bump( const ShaderGroup& shader_group, const ShadingPoint& shading_point, const Vector2f& s) const { // Choose between BSSRDF and BSDF. if (shader_group.has_subsurface() && s[0] < 0.5f) { do_execute( shader_group, shading_point, VisibilityFlags::SubsurfaceRay); CompositeSubsurfaceClosure c( Basis3f(shading_point.get_shading_basis()), shading_point.get_osl_shader_globals().Ci, m_arena); // Pick a shading basis from one of the BSSRDF closures. if (c.get_closure_count() > 0) { const size_t index = c.choose_closure(s[1]); shading_point.set_shading_basis( Basis3d(c.get_closure_shading_basis(index))); } } else { do_execute( shader_group, shading_point, VisibilityFlags::CameraRay); choose_bsdf_closure_shading_basis(shading_point, s); } }
void Tracer::evaluate_alpha( const Material& material, const ShadingPoint& shading_point, Alpha& alpha) const { alpha = shading_point.get_alpha(); // Apply OSL transparency if needed. if (const ShaderGroup* sg = material.get_render_data().m_shader_group) { if (sg->has_transparency()) { Alpha a; m_shadergroup_exec.execute_shadow(*sg, shading_point, a); alpha *= a; } } }
void compute_ibl_bsdf_sampling( SamplingContext& sampling_context, const ShadingContext& shading_context, const EnvironmentEDF& environment_edf, const ShadingPoint& shading_point, const Vector3d& outgoing, const BSDF& bsdf, const void* bsdf_data, const int bsdf_sampling_modes, const size_t bsdf_sample_count, const size_t env_sample_count, Spectrum& radiance) { assert(is_normalized(outgoing)); const Vector3d& geometric_normal = shading_point.get_geometric_normal(); const Basis3d& shading_basis = shading_point.get_shading_basis(); radiance.set(0.0f); for (size_t i = 0; i < bsdf_sample_count; ++i) { // Sample the BSDF. // todo: rendering will be incorrect if the BSDF value returned by the sample() method // includes the contribution of a specular component since these are explicitly rejected // afterward. We need a mechanism to indicate that we want the contribution of some of // the components only. Vector3d incoming; Spectrum bsdf_value; double bsdf_prob; const BSDF::Mode bsdf_mode = bsdf.sample( sampling_context, bsdf_data, false, // not adjoint true, // multiply by |cos(incoming, normal)| geometric_normal, shading_basis, outgoing, incoming, bsdf_value, bsdf_prob); // Filter scattering modes. if (!(bsdf_sampling_modes & bsdf_mode)) return; // Discard occluded samples. const double transmission = shading_context.get_tracer().trace( shading_point, incoming, ShadingRay::ShadowRay); if (transmission == 0.0) continue; // Evaluate the environment's EDF. InputEvaluator input_evaluator(shading_context.get_texture_cache()); Spectrum env_value; double env_prob; environment_edf.evaluate( input_evaluator, incoming, env_value, env_prob); // Apply all weights, including MIS weight. if (bsdf_mode == BSDF::Specular) env_value *= static_cast<float>(transmission); else { const double mis_weight = mis_power2( bsdf_sample_count * bsdf_prob, env_sample_count * env_prob); env_value *= static_cast<float>(transmission / bsdf_prob * mis_weight); } // Add the contribution of this sample to the illumination. env_value *= bsdf_value; radiance += env_value; } if (bsdf_sample_count > 1) radiance /= static_cast<float>(bsdf_sample_count); }
void compute_ibl_bssrdf_sampling( SamplingContext& sampling_context, const ShadingContext& shading_context, const EnvironmentEDF& environment_edf, const BSSRDF& bssrdf, const void* bssrdf_data, const ShadingPoint& incoming_point, const ShadingPoint& outgoing_point, const Dual3d& outgoing, const size_t bssrdf_sample_count, const size_t env_sample_count, Spectrum& radiance) { assert(is_normalized(outgoing.get_value())); radiance.set(0.0f); sampling_context.split_in_place(2, bssrdf_sample_count); for (size_t i = 0; i < bssrdf_sample_count; ++i) { // Generate a uniform sample in [0,1)^2. const Vector2d s = sampling_context.next_vector2<2>(); // Sample the BSSRDF (hemisphere cosine). Vector3d incoming = sample_hemisphere_cosine(s); const double cos_in = incoming.y; const double bssrdf_prob = cos_in * RcpPi; incoming = incoming_point.get_shading_basis().transform_to_parent(incoming); if (incoming_point.get_side() == ObjectInstance::BackSide) incoming = -incoming; assert(is_normalized(incoming)); // Discard occluded samples. const double transmission = shading_context.get_tracer().trace( incoming_point, incoming, VisibilityFlags::ShadowRay); if (transmission == 0.0) continue; // Evaluate the BSSRDF. Spectrum bssrdf_value; bssrdf.evaluate( bssrdf_data, outgoing_point, outgoing.get_value(), incoming_point, incoming, bssrdf_value); // Evaluate the environment's EDF. InputEvaluator input_evaluator(shading_context.get_texture_cache()); Spectrum env_value; double env_prob; environment_edf.evaluate( shading_context, input_evaluator, incoming, env_value, env_prob); // Compute MIS weight. const double mis_weight = mis_power2( bssrdf_sample_count * bssrdf_prob, env_sample_count * env_prob); // Add the contribution of this sample to the illumination. env_value *= static_cast<float>(transmission * cos_in / bssrdf_prob * mis_weight); env_value *= bssrdf_value; radiance += env_value; } if (bssrdf_sample_count > 1) radiance /= static_cast<float>(bssrdf_sample_count); }
void compute_ibl_environment_sampling( SamplingContext& sampling_context, const ShadingContext& shading_context, const EnvironmentEDF& environment_edf, const BSSRDF& bssrdf, const void* bssrdf_data, const ShadingPoint& incoming_point, const ShadingPoint& outgoing_point, const Dual3d& outgoing, const size_t bssrdf_sample_count, const size_t env_sample_count, Spectrum& radiance) { assert(is_normalized(outgoing.get_value())); const Basis3d& shading_basis = incoming_point.get_shading_basis(); radiance.set(0.0f); sampling_context.split_in_place(2, env_sample_count); for (size_t i = 0; i < env_sample_count; ++i) { // Generate a uniform sample in [0,1)^2. const Vector2d s = sampling_context.next_vector2<2>(); // Sample the environment. InputEvaluator input_evaluator(shading_context.get_texture_cache()); Vector3d incoming; Spectrum env_value; double env_prob; environment_edf.sample( shading_context, input_evaluator, s, incoming, env_value, env_prob); // Cull samples behind the shading surface. assert(is_normalized(incoming)); const double cos_in = dot(incoming, shading_basis.get_normal()); if (cos_in <= 0.0) continue; // Discard occluded samples. const double transmission = shading_context.get_tracer().trace( incoming_point, incoming, VisibilityFlags::ShadowRay); if (transmission == 0.0) continue; // Evaluate the BSSRDF. Spectrum bssrdf_value; bssrdf.evaluate( bssrdf_data, outgoing_point, outgoing.get_value(), incoming_point, incoming, bssrdf_value); // Compute MIS weight. const double bssrdf_prob = cos_in * RcpPi; const double mis_weight = mis_power2( env_sample_count * env_prob, bssrdf_sample_count * bssrdf_prob); // Add the contribution of this sample to the illumination. env_value *= static_cast<float>(transmission * cos_in / env_prob * mis_weight); env_value *= bssrdf_value; radiance += env_value; } if (env_sample_count > 1) radiance /= static_cast<float>(env_sample_count); }
void ShadingEngine::shade_hit_point( SamplingContext& sampling_context, const PixelContext& pixel_context, const ShadingContext& shading_context, const ShadingPoint& shading_point, ShadingResult& shading_result) const { // Retrieve the material of the intersected surface. const Material* material = shading_point.get_material(); // Compute the alpha channel of the main output. if (material && material->get_alpha_map()) { // There is an alpha map: evaluate it. material->get_alpha_map()->evaluate( shading_context.get_texture_cache(), shading_point.get_uv(0), shading_result.m_main.m_alpha); } else { // No alpha map: solid sample. shading_result.m_main.m_alpha = Alpha(1.0f); } #ifdef WITH_OSL if (material && material->get_osl_surface() && material->get_osl_surface()->has_transparency()) { Alpha a; shading_context.execute_osl_transparency( *material->get_osl_surface(), shading_point, a); shading_result.m_main.m_alpha *= a; } #endif if (shading_result.m_main.m_alpha[0] > 0.0f || material->shade_alpha_cutouts()) { // Use the diagnostic surface shader if there is one. const SurfaceShader* surface_shader = m_diagnostic_surface_shader.get(); if (surface_shader == 0) { if (material == 0) { // The intersected surface has no material: return solid pink. shading_result.set_main_to_opaque_pink_linear_rgba(); shading_result.set_aovs_to_transparent_black_linear_rgba(); return; } // Use the surface shader of the intersected surface. surface_shader = material->get_surface_shader(); if (surface_shader == 0) { // The intersected surface has no surface shader: return solid pink. shading_result.set_main_to_opaque_pink_linear_rgba(); shading_result.set_aovs_to_transparent_black_linear_rgba(); return; } } // Execute the surface shader. surface_shader->evaluate( sampling_context, pixel_context, shading_context, shading_point, shading_result); // Set AOVs. shading_result.set_entity_aov(shading_point.get_assembly()); shading_result.set_entity_aov(shading_point.get_assembly_instance()); shading_result.set_entity_aov(shading_point.get_object()); shading_result.set_entity_aov(shading_point.get_object_instance()); if (material) shading_result.set_entity_aov(*material); shading_result.set_entity_aov(*surface_shader); } else { // Alpha is zero: shade as transparent black. shading_result.set_main_to_transparent_black_linear_rgba(); shading_result.set_aovs_to_transparent_black_linear_rgba(); } }
void compute_ibl_environment_sampling( SamplingContext& sampling_context, const ShadingContext& shading_context, const EnvironmentEDF& environment_edf, const ShadingPoint& shading_point, const Vector3d& outgoing, const BSDF& bsdf, const void* bsdf_data, const int env_sampling_modes, const size_t bsdf_sample_count, const size_t env_sample_count, Spectrum& radiance) { assert(is_normalized(outgoing)); const Vector3d& geometric_normal = shading_point.get_geometric_normal(); const Basis3d& shading_basis = shading_point.get_shading_basis(); radiance.set(0.0f); // todo: if we had a way to know that a BSDF is purely specular, we could // immediately return black here since there will be no contribution from // such a BSDF. sampling_context.split_in_place(2, env_sample_count); for (size_t i = 0; i < env_sample_count; ++i) { // Generate a uniform sample in [0,1)^2. const Vector2d s = sampling_context.next_vector2<2>(); // Sample the environment. InputEvaluator input_evaluator(shading_context.get_texture_cache()); Vector3d incoming; Spectrum env_value; double env_prob; environment_edf.sample( input_evaluator, s, incoming, env_value, env_prob); // Cull samples behind the shading surface. assert(is_normalized(incoming)); const double cos_in = dot(incoming, shading_basis.get_normal()); if (cos_in < 0.0) continue; // Discard occluded samples. const double transmission = shading_context.get_tracer().trace( shading_point, incoming, ShadingRay::ShadowRay); if (transmission == 0.0) continue; // Evaluate the BSDF. Spectrum bsdf_value; const double bsdf_prob = bsdf.evaluate( bsdf_data, false, // not adjoint true, // multiply by |cos(incoming, normal)| geometric_normal, shading_basis, outgoing, incoming, env_sampling_modes, bsdf_value); if (bsdf_prob == 0.0) continue; // Compute MIS weight. const double mis_weight = mis_power2( env_sample_count * env_prob, bsdf_sample_count * bsdf_prob); // Add the contribution of this sample to the illumination. env_value *= static_cast<float>(transmission / env_prob * mis_weight); env_value *= bsdf_value; radiance += env_value; } if (env_sample_count > 1) radiance /= static_cast<float>(env_sample_count); }
void EDF::evaluate_inputs( InputEvaluator& input_evaluator, const ShadingPoint& shading_point) const { input_evaluator.evaluate(get_inputs(), shading_point.get_uv(0)); }
void DiagnosticSurfaceShader::evaluate( SamplingContext& sampling_context, const PixelContext& pixel_context, const ShadingContext& shading_context, const ShadingPoint& shading_point, ShadingResult& shading_result) const { switch (m_shading_mode) { case Color: { shading_result.set_main_to_opaque_pink_linear_rgba(); const Material* material = shading_point.get_material(); if (material) { const Material::RenderData& material_data = material->get_render_data(); #ifdef APPLESEED_WITH_OSL // Execute the OSL shader if there is one. if (material_data.m_shader_group) { shading_context.execute_osl_shading( *material_data.m_shader_group, shading_point); } #endif if (material_data.m_bsdf) { InputEvaluator input_evaluator(shading_context.get_texture_cache()); material_data.m_bsdf->evaluate_inputs( shading_context, input_evaluator, shading_point); const Vector3d direction = -normalize(shading_point.get_ray().m_dir); material_data.m_bsdf->evaluate( input_evaluator.data(), false, false, shading_point.get_geometric_normal(), shading_point.get_shading_basis(), direction, direction, ScatteringMode::All, shading_result.m_main.m_color); shading_result.m_color_space = ColorSpaceSpectral; } } } break; case Coverage: shading_result.set_main_to_linear_rgb(Color3f(1.0f)); break; case Barycentric: shading_result.set_main_to_linear_rgb( vector2_to_color(shading_point.get_bary())); break; case UV: shading_result.set_main_to_linear_rgb( uvs_to_color(shading_point.get_uv(0))); break; case Tangent: case Bitangent: case ShadingNormal: { #ifdef APPLESEED_WITH_OSL const Material* material = shading_point.get_material(); if (material) { const Material::RenderData& material_data = material->get_render_data(); // Execute the OSL shader if there is one. if (material_data.m_shader_group) { sampling_context.split_in_place(2, 1); shading_context.execute_osl_bump( *material_data.m_shader_group, shading_point, sampling_context.next_vector2<2>()); } } #endif const Vector3d v = m_shading_mode == ShadingNormal ? shading_point.get_shading_basis().get_normal() : m_shading_mode == Tangent ? shading_point.get_shading_basis().get_tangent_u() : shading_point.get_shading_basis().get_tangent_v(); shading_result.set_main_to_linear_rgb(vector3_to_color(v)); } break; case GeometricNormal: shading_result.set_main_to_linear_rgb( vector3_to_color(shading_point.get_geometric_normal())); break; case OriginalShadingNormal: shading_result.set_main_to_linear_rgb( vector3_to_color(shading_point.get_original_shading_normal())); break; case WorldSpacePosition: { const Vector3d& p = shading_point.get_point(); shading_result.set_main_to_linear_rgb( Color3f(Color3d(p.x, p.y, p.z))); } break; case Sides: shading_result.set_main_to_linear_rgb( shading_point.get_side() == ObjectInstance::FrontSide ? Color3f(0.0f, 0.0f, 1.0f) : Color3f(1.0f, 0.0f, 0.0f)); break; case Depth: shading_result.set_main_to_linear_rgb( Color3f(static_cast<float>(shading_point.get_distance()))); break; case ScreenSpaceWireframe: { // Initialize the shading result to the background color. shading_result.set_main_to_linear_rgba(Color4f(0.0f, 0.0f, 0.8f, 0.5f)); if (shading_point.is_triangle_primitive()) { // Film space thickness of the wires. const double SquareWireThickness = square(0.00025); // Retrieve the time, the scene and the camera. const double time = shading_point.get_time().m_absolute; const Scene& scene = shading_point.get_scene(); const Camera& camera = *scene.get_camera(); // Compute the film space coordinates of the intersection point. Vector2d point_ndc; camera.project_point(time, shading_point.get_point(), point_ndc); // Loop over the triangle edges. for (size_t i = 0; i < 3; ++i) { // Retrieve the end points of this edge. const size_t j = (i + 1) % 3; const Vector3d vi = shading_point.get_vertex(i); const Vector3d vj = shading_point.get_vertex(j); // Compute the film space coordinates of the edge's end points. Vector2d vi_ndc, vj_ndc; if (!camera.project_segment(time, vi, vj, vi_ndc, vj_ndc)) continue; // Compute the film space distance from the intersection point to the edge. const double d = square_distance_point_segment(point_ndc, vi_ndc, vj_ndc); // Shade with the wire's color if the hit point is close enough to the edge. if (d < SquareWireThickness) { shading_result.set_main_to_linear_rgba(Color4f(1.0f)); break; } } } else { assert(shading_point.is_curve_primitive()); // todo: implement. } } break; case WorldSpaceWireframe: { // Initialize the shading result to the background color. shading_result.set_main_to_linear_rgba(Color4f(0.0f, 0.0f, 0.8f, 0.5f)); if (shading_point.is_triangle_primitive()) { // World space thickness of the wires. const double SquareWireThickness = square(0.0015); // Retrieve the world space intersection point. const Vector3d& point = shading_point.get_point(); // Loop over the triangle edges. for (size_t i = 0; i < 3; ++i) { // Retrieve the end points of this edge. const size_t j = (i + 1) % 3; const Vector3d& vi = shading_point.get_vertex(i); const Vector3d& vj = shading_point.get_vertex(j); // Compute the world space distance from the intersection point to the edge. const double d = square_distance_point_segment(point, vi, vj); // Shade with the wire's color if the hit point is close enough to the edge. if (d < SquareWireThickness) { shading_result.set_main_to_linear_rgba(Color4f(1.0f)); break; } } } else { assert(shading_point.is_curve_primitive()); // todo: implement. } } break; case AmbientOcclusion: { // Compute the occlusion. const double occlusion = compute_ambient_occlusion( sampling_context, sample_hemisphere_uniform<double>, shading_context.get_intersector(), shading_point, m_ao_max_distance, m_ao_samples); // Return a gray scale value proportional to the accessibility. const float accessibility = static_cast<float>(1.0 - occlusion); shading_result.set_main_to_linear_rgb(Color3f(accessibility)); } break; case AssemblyInstances: shading_result.set_main_to_linear_rgb( integer_to_color(shading_point.get_assembly_instance().get_uid())); break; case ObjectInstances: shading_result.set_main_to_linear_rgb( integer_to_color(shading_point.get_object_instance().get_uid())); break; case Regions: { const uint32 h = mix_uint32( static_cast<uint32>(shading_point.get_object_instance().get_uid()), static_cast<uint32>(shading_point.get_region_index())); shading_result.set_main_to_linear_rgb(integer_to_color(h)); } break; case Primitives: { const uint32 h = mix_uint32( static_cast<uint32>(shading_point.get_object_instance().get_uid()), static_cast<uint32>(shading_point.get_region_index()), static_cast<uint32>(shading_point.get_primitive_index())); shading_result.set_main_to_linear_rgb(integer_to_color(h)); } break; case Materials: { const Material* material = shading_point.get_material(); if (material) shading_result.set_main_to_linear_rgb(integer_to_color(material->get_uid())); else shading_result.set_main_to_opaque_pink_linear_rgba(); } break; case RaySpread: { const ShadingRay& ray = shading_point.get_ray(); if (!ray.m_has_differentials) break; const Material* material = shading_point.get_material(); if (material) { const Material::RenderData& material_data = material->get_render_data(); #ifdef APPLESEED_WITH_OSL // Execute the OSL shader if there is one. if (material_data.m_shader_group) { shading_context.execute_osl_shading( *material_data.m_shader_group, shading_point); } #endif if (material_data.m_bsdf) { const Dual3d outgoing( -ray.m_dir, ray.m_dir - ray.m_rx.m_dir, ray.m_dir - ray.m_ry.m_dir); InputEvaluator input_evaluator(shading_context.get_texture_cache()); material_data.m_bsdf->evaluate_inputs( shading_context, input_evaluator, shading_point); const void* bsdf_data = input_evaluator.data(); BSDFSample sample(shading_point, outgoing); material_data.m_bsdf->sample( sampling_context, bsdf_data, false, false, sample); if (!sample.m_incoming.has_derivatives()) break; // The 3.0 factor is chosen so that ray spread from Lambertian BRDFs is approximately 1. const double spread = max( norm(sample.m_incoming.get_dx()), norm(sample.m_incoming.get_dy())) * 3.0; shading_result.set_main_to_linear_rgb( Color3f(static_cast<float>(spread))); } } } break; case FacingRatio: { const Vector3d& normal = shading_point.get_shading_normal(); const Vector3d& view = shading_point.get_ray().m_dir; const double facing = abs(dot(normal, view)); shading_result.set_main_to_linear_rgb( Color3f(static_cast<float>(facing))); } break; default: assert(false); shading_result.set_main_to_transparent_black_linear_rgba(); break; } }
void EmbreeScene::intersect(ShadingPoint& shading_point) const { RTCIntersectContext context; rtcInitIntersectContext(&context); RTCRayHit rayhit; shading_ray_to_embree_ray(shading_point.get_ray(), rayhit.ray); rayhit.hit.geomID = RTC_INVALID_GEOMETRY_ID; rtcIntersect1(m_scene, &context, &rayhit); if (rayhit.hit.geomID != RTC_INVALID_GEOMETRY_ID) { assert(rayhit.hit.geomID < m_geometry_container.size()); const auto& geometry_data = m_geometry_container[rayhit.hit.geomID]; assert(geometry_data); shading_point.m_bary[0] = rayhit.hit.u; shading_point.m_bary[1] = rayhit.hit.v; shading_point.m_object_instance_index = geometry_data->m_object_instance_idx; // TODO: remove regions shading_point.m_primitive_index = rayhit.hit.primID; shading_point.m_primitive_type = ShadingPoint::PrimitiveTriangle; shading_point.m_ray.m_tmax = rayhit.ray.tfar; const uint32 v0_idx = geometry_data->m_primitives[rayhit.hit.primID * 3]; const uint32 v1_idx = geometry_data->m_primitives[rayhit.hit.primID * 3 + 1]; const uint32 v2_idx = geometry_data->m_primitives[rayhit.hit.primID * 3 + 2]; if (geometry_data->m_motion_steps_count > 1) { const uint32 last_motion_step_idx = geometry_data->m_motion_steps_count - 1; const uint32 motion_step_begin_idx = static_cast<uint32>(rayhit.ray.time * last_motion_step_idx); const uint32 motion_step_end_idx = motion_step_begin_idx + 1; const uint32 motion_step_begin_offset = motion_step_begin_idx * geometry_data->m_vertices_count; const uint32 motion_step_end_offset = motion_step_end_idx * geometry_data->m_vertices_count; const float motion_step_begin_time = static_cast<float>(motion_step_begin_idx) / last_motion_step_idx; // Linear interpolation coefficients. const float p = (rayhit.ray.time - motion_step_begin_time) * last_motion_step_idx; const float q = 1.0f - p; assert(p > 0.0f && p <= 1.0f); const TriangleType triangle( Vector3d( geometry_data->m_vertices[motion_step_begin_offset + v0_idx] * q + geometry_data->m_vertices[motion_step_end_offset + v0_idx] * p), Vector3d( geometry_data->m_vertices[motion_step_begin_offset + v1_idx] * q + geometry_data->m_vertices[motion_step_end_offset + v1_idx] * p), Vector3d( geometry_data->m_vertices[motion_step_begin_offset + v2_idx] * q + geometry_data->m_vertices[motion_step_end_offset + v2_idx] * p)); shading_point.m_triangle_support_plane.initialize(triangle); } else { const TriangleType triangle( Vector3d(geometry_data->m_vertices[v0_idx]), Vector3d(geometry_data->m_vertices[v1_idx]), Vector3d(geometry_data->m_vertices[v2_idx])); shading_point.m_triangle_support_plane.initialize(triangle); } } }