/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation * * SPDX-License-Identifier: Apache-2.0 */ #pragma once #include "kernel/light/light.h" #include "kernel/light/triangle.h" CCL_NAMESPACE_BEGIN /* Simple CDF based sampling over all lights in the scene, without taking into * account shading position or normal. */ ccl_device int light_distribution_sample(KernelGlobals kg, const float rand) { /* This is basically std::upper_bound as used by PBRT, to find a point light or * triangle to emit from, proportional to area. a good improvement would be to * also sample proportional to power, though it's not so well defined with * arbitrary shaders. */ int first = 0; int len = kernel_data.integrator.num_distribution + 1; do { int half_len = len >> 1; int middle = first + half_len; if (rand < kernel_data_fetch(light_distribution, middle).totarea) { len = half_len; } else { first = middle + 1; len = len - half_len - 1; } } while (len > 0); /* Clamping should not be needed but float rounding errors seem to * make this fail on rare occasions. */ int index = clamp(first - 1, 0, kernel_data.integrator.num_distribution - 1); return index; } template ccl_device_noinline bool light_distribution_sample(KernelGlobals kg, const float3 rand, const float time, const float3 P, const float3 N, const int object_receiver, const int shader_flags, const int bounce, const uint32_t path_flag, ccl_private LightSample *ls) { /* Sample light index from distribution. */ /* The first two dimensions of the Sobol sequence have better stratification. */ const int index = light_distribution_sample(kg, rand.z); const float pdf_selection = kernel_data.integrator.distribution_pdf_lights; const float2 rand_uv = float3_to_float2(rand); return light_sample(kg, rand_uv, time, P, N, object_receiver, shader_flags, bounce, path_flag, index, 0, pdf_selection, ls); } ccl_device_inline float light_distribution_pdf_lamp(KernelGlobals kg) { return kernel_data.integrator.distribution_pdf_lights; } CCL_NAMESPACE_END