size_t generate_environment_sample( SamplingContext& sampling_context, const EnvironmentEDF* env_edf, SampleVector& samples) { // Sample the environment. sampling_context.split_in_place(2, 1); InputEvaluator input_evaluator(m_texture_cache); Vector3d outgoing; Spectrum env_edf_value; double env_edf_prob; env_edf->sample( m_shading_context, input_evaluator, sampling_context.next_vector2<2>(), outgoing, // points toward the environment env_edf_value, env_edf_prob); // Uniformly sample the tangent disk. sampling_context.split_in_place(2, 1); const Vector2d p = m_scene_radius * sample_disk_uniform(sampling_context.next_vector2<2>()); // Compute the origin of the light ray. const Basis3d basis(-outgoing); const Vector3d ray_origin = m_scene_center - m_safe_scene_diameter * basis.get_normal() + p[0] * basis.get_tangent_u() + + p[1] * basis.get_tangent_v(); // Compute the initial particle weight. Spectrum initial_flux = env_edf_value; initial_flux /= static_cast<float>(m_disk_point_prob * env_edf_prob); // Build the light ray. sampling_context.split_in_place(1, 1); const ShadingRay::Time time = ShadingRay::Time::create_with_normalized_time( sampling_context.next_double2(), m_shutter_open_time, m_shutter_close_time); const ShadingRay light_ray( ray_origin, -outgoing, time, VisibilityFlags::LightRay, 0); // Build the path tracer. PathVisitor path_visitor( m_params, m_scene, m_frame, m_shading_context, sampling_context, samples, initial_flux); PathTracerType path_tracer( path_visitor, m_params.m_rr_min_path_length, m_params.m_max_path_length, m_params.m_max_iterations); // Trace the light path. const size_t path_length = path_tracer.trace( sampling_context, m_shading_context, light_ray); // Update path statistics. ++m_path_count; m_path_length.insert(path_length); // Return the number of samples generated when tracing this light path. return path_visitor.get_sample_count(); }