24 return M_2PI_F * (1 - cos_theta_o) +
26 2 *
theta_o * sin_theta_o + cos_theta_o);
46 const float cos_a_b =
dot(a->
axis,
b->axis);
57 const float theta_o = (theta_d + a->
theta_o +
b->theta_o) * 0.5f;
65 if (cos_a_b < -0.9995f) {
71 const float theta_r = theta_o - a->
theta_o;
73 new_axis = a->
axis *
cosf(theta_r) + ortho *
sinf(theta_r);
88 bool need_transformation)
95 Mesh *mesh =
static_cast<Mesh *
>(
object->get_geometry());
97 Shader *shader =
static_cast<Shader *
>(mesh->get_used_shaders()[mesh->get_shader()[
prim_id]]);
99 for (
int i = 0;
i < 3;
i++) {
100 vertices[
i] = mesh->get_verts()[triangle.
v[
i]];
103 if (need_transformation) {
105 const Transform &tfm =
object->get_tfm();
106 for (
int i = 0;
i < 3;
i++) {
112 const float area =
triangle_area(vertices[0], vertices[1], vertices[2]);
119 centroid = (vertices[0] + vertices[1] + vertices[2]) / 3.0f;
123 if (is_front_only || is_back_only) {
126 cross(vertices[1] - vertices[0], vertices[2] - vertices[0]));
144 for (
int i = 0;
i < 3;
i++) {
152 Light *lamp =
static_cast<Light *
>(
object->get_geometry());
153 const LightType type = lamp->get_light_type();
154 const float size = lamp->get_size();
155 float3 strength = lamp->get_strength();
157 if (!lamp->get_normalize()) {
158 strength *= lamp->
area(object->get_tfm());
166 measure.bcone.theta_e = lamp->get_spread() * 0.5f;
173 const float3 half_extentu = 0.5f * lamp->get_sizeu() * axisu *
size;
174 const float3 half_extentv = 0.5f * lamp->get_sizev() * axisv *
size;
197 float theta_e =
min(lamp->get_spot_angle() * 0.5f,
M_PI_2_F);
214 measure.bcone.theta_e = theta_e;
231 strength *= lamp->get_average_radiance() *
M_PI_F;
235 measure.bcone.theta_e = 0.5f * lamp->get_angle();
254 std::sort(emitters + start,
262bool LightTree::triangle_usable_as_light(
Mesh *mesh,
const int prim_id)
264 const int shader_index = mesh->get_shader()[prim_id];
265 if (shader_index < mesh->get_used_shaders().
size()) {
266 Shader *shader =
static_cast<Shader *
>(mesh->get_used_shaders()[shader_index]);
274void LightTree::add_mesh(
Scene *scene,
Mesh *mesh,
const int object_id)
277 for (
size_t i = 0;
i < mesh_num_triangles;
i++) {
278 if (triangle_usable_as_light(mesh,
i)) {
279 emitters_.emplace_back(scene,
i, object_id);
287 const uint max_lights_in_leaf)
288 : progress_(progress), max_lights_in_leaf_(max_lights_in_leaf)
290 KernelIntegrator *kintegrator = &dscene->
data.integrator;
292 local_lights_.reserve(kintegrator->num_lights - kintegrator->num_distant_lights);
293 distant_lights_.reserve(kintegrator->num_distant_lights);
298 int device_light_index = 0;
300 if (progress_.get_cancel()) {
304 if (object->get_geometry()->is_light()) {
306 Light *light = static_cast<Light *>(object->get_geometry());
307 if (light->is_enabled) {
308 if (light->light_type == LIGHT_BACKGROUND || light->light_type == LIGHT_DISTANT) {
309 distant_lights_.emplace_back(scene, ~device_light_index, object->index);
312 local_lights_.emplace_back(scene, ~device_light_index, object->index);
315 device_light_index++;
320 light_link_receiver_used |= (
uint64_t(1) <<
object->get_receiver_light_set());
322 if (!object->usable_as_light()) {
326 mesh_lights_.emplace_back(
object, object->index);
329 Mesh *mesh =
static_cast<Mesh *
>(
object->get_geometry());
330 auto map_it = offset_map_.find(mesh);
331 if (map_it == offset_map_.end()) {
332 offset_map_[mesh] = num_triangles;
341 if (local_lights_.empty() && distant_lights_.empty() && mesh_lights_.empty()) {
345 const int num_mesh_lights = mesh_lights_.size();
346 int num_local_lights = local_lights_.size() + num_mesh_lights;
347 const int num_distant_lights = distant_lights_.size();
350 std::unordered_map<Mesh *, std::tuple<LightTreeNode *, int, int>> unique_mesh;
352 emitters_.reserve(
num_triangles + num_local_lights + num_distant_lights);
355 Mesh *mesh =
static_cast<Mesh *
>(
object->get_geometry());
358 auto map_it = unique_mesh.find(mesh);
359 if (map_it == unique_mesh.end()) {
360 const int start = emitters_.size();
361 add_mesh(scene, mesh, emitter.object_id);
362 const int end = emitters_.size();
364 unique_mesh[mesh] = std::make_tuple(emitter.root.get(), start, end);
365 emitter.root->object_id = emitter.object_id;
368 emitter.root->make_instance(std::get<0>(map_it->second), emitter.object_id);
370 object_offsets[emitter.object_id] = offset_map_[mesh];
374 parallel_for_each(unique_mesh, [
this](
auto &map_it) {
376 int const start = std::get<1>(map_it.second);
377 int const end = std::get<2>(map_it.second);
378 recursive_build(
self, node, start, end, emitters_.data(), 0, 0);
381 task_pool.wait_work();
386 Mesh *mesh =
static_cast<Mesh *
>(
object->get_geometry());
388 LightTreeNode *reference = std::get<0>(unique_mesh.find(mesh)->second);
401 for (
size_t i = 0;
i < mesh_num_triangles;
i++) {
402 if (triangle_usable_as_light(mesh,
i)) {
414 const int num_emissive_triangles = emitters_.size();
415 num_local_lights += num_emissive_triangles;
421 std::move(local_lights_.begin(), local_lights_.end(), std::back_inserter(emitters_));
422 std::move(mesh_lights_.begin(), mesh_lights_.end(), std::back_inserter(emitters_));
424 left, root_.get(), num_emissive_triangles, num_local_lights, emitters_.data(), 0, 1);
425 task_pool.wait_work();
427 if (progress_.get_cancel()) {
434 for (
int i = 0;
i < num_distant_lights;
i++) {
435 root_->get_inner().children[
right]->add(distant_lights_[
i]);
438 sort_leaf(0, num_distant_lights, distant_lights_.data());
439 root_->get_inner().children[
right]->make_distant(num_local_lights, num_distant_lights);
441 root_->measure = root_->get_inner().children[
left]->measure +
442 root_->get_inner().children[
right]->measure;
443 root_->light_link = root_->get_inner().children[
left]->light_link +
444 root_->get_inner().children[
right]->light_link;
449 root_->light_link.shareable =
false;
451 std::move(distant_lights_.begin(), distant_lights_.end(), std::back_inserter(emitters_));
456void LightTree::recursive_build(
const Child child,
461 const uint bit_trail,
482 if (should_split(emitters, start, middle, end, node->
measure, node->
light_link, split_dim)) {
484 if (split_dim != -1) {
486 std::nth_element(emitters + start,
489 [split_dim](
const LightTreeEmitter &
l,
const LightTreeEmitter &r) {
490 return l.centroid[split_dim] < r.
centroid[split_dim];
495 if (middle - start > MIN_EMITTERS_PER_THREAD) {
496 task_pool.push([
this, node, start, middle, emitters, bit_trail, depth] {
497 recursive_build(
left, node, start, middle, emitters, bit_trail, depth + 1);
501 recursive_build(
left, node, start, middle, emitters, bit_trail, depth + 1);
505 if (end - middle > MIN_EMITTERS_PER_THREAD) {
506 task_pool.push([
this, node, middle, end, emitters, bit_trail, depth] {
507 recursive_build(
right, node, middle, end, emitters, bit_trail | (1u << depth), depth + 1);
511 recursive_build(
right, node, middle, end, emitters, bit_trail | (1u << depth), depth + 1);
532 measure = emitters[start].
measure;
533 light_link = LightTreeLightLink(emitters[start].light_set_membership);
538 middle = (start + end) / 2;
541 for (
int i = start;
i < end;
i++) {
542 centroid_bbox.
grow((emitters +
i)->centroid);
546 const float max_extent =
max4(extent.
x, extent.
y, extent.
z, 0.0f);
549 float total_cost = 0.0f;
551 for (
int dim = 0; dim < 3; dim++) {
552 std::array<LightTreeBucket, LightTreeBucket::num_buckets> buckets;
555 if (centroid_bbox.
size()[dim] == 0.0f) {
564 for (
int i = start;
i < end;
i++) {
565 buckets[0].add(emitters[
i]);
570 inv_extent = 1 / (centroid_bbox.
size()[dim]);
571 for (
int i = start;
i < end;
i++) {
572 const LightTreeEmitter *emitter = emitters +
i;
577 (emitter->
centroid[dim] - centroid_bbox.
min[dim]) * inv_extent;
580 buckets[bucket_idx].add(*emitter);
586 left_buckets.front() = buckets.front();
588 left_buckets[
i] = left_buckets[
i - 1] + buckets[
i];
593 measure = left_buckets.back().measure + buckets.back().measure;
594 light_link = left_buckets.back().light_link + buckets.back().light_link;
602 if (centroid_bbox.
size()[dim] == 0.0f) {
607 if (total_cost == 0.0f) {
614 right_buckets.back() = buckets.back();
616 right_buckets[
i] = right_buckets[
i + 1] + buckets[
i + 1];
620 const float regularization = max_extent * inv_extent;
622 const float left_cost = left_buckets[
split].measure.calculate();
623 const float right_cost = right_buckets[
split].measure.calculate();
624 const float cost = regularization * (left_cost + right_cost);
626 if (cost < total_cost && cost < min_cost) {
629 middle = start + left_buckets[
split].count;
633 return min_cost < total_cost || num_emitters > max_lights_in_leaf_;
MINLINE float safe_acosf(float a)
static void split(const char *text, const char *seps, char ***str, int *count)
ATTR_WARN_UNUSED_RESULT const BMLoop * l
unsigned long long int uint64_t
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
device_vector< uint > object_lookup_offset
LightTree(Scene *scene, DeviceScene *dscene, Progress &progress, const uint max_lights_in_leaf)
unique_ptr< LightTreeNode > create_node(const LightTreeMeasure &measure, const uint &bit_trial)
LightTreeNode * build(Scene *scene, DeviceScene *dscene)
size_t num_emitters() const
EmissionSampling emission_sampling
T * alloc(const size_t width, const size_t height=0)
dot(value.rgb, luminance_coefficients)") DEFINE_VALUE("REDUCE(lhs
#define CCL_NAMESPACE_END
#define assert(assertion)
VecBase< float, 3 > cross(VecOp< float, 3 >, VecOp< float, 3 >) RET
constexpr T clamp(T, U, U) RET
VecBase< float, 3 > float3
@ EMISSION_SAMPLING_FRONT
static void sort_leaf(const int start, const int end, LightTreeEmitter *emitters)
__forceinline LightTreeMeasure operator+(const LightTreeMeasure &a, const LightTreeMeasure &b)
OrientationBounds merge(const OrientationBounds &cone_a, const OrientationBounds &cone_b)
ccl_device_inline T max4(const T &a, const T &b, const T &c, const T &d)
ccl_device float fast_tanf(float x)
ccl_device float fast_atanf(const float x)
ccl_device_inline bool is_zero(const float2 a)
ccl_device_inline float2 safe_normalize(const float2 a)
ccl_device_inline float2 fabs(const float2 a)
ccl_device_inline float triangle_area(const ccl_private float3 &v1, const ccl_private float3 &v2, const ccl_private float3 &v3)
ccl_device_inline void make_orthonormals(const float3 N, ccl_private float3 *a, ccl_private float3 *b)
__forceinline float3 size() const
__forceinline void grow(const float3 &pt)
LightTreeLightLink light_link
static const int num_buckets
__forceinline bool is_triangle() const
unique_ptr< LightTreeNode > root
uint64_t light_set_membership
LightTreeEmitter(Object *object, const int object_id)
__forceinline bool is_light() const
void add(const uint64_t prim_set_membership)
bool transform(const Transform &tfm)
__forceinline void reset()
__forceinline float calculate()
__forceinline void add(const LightTreeMeasure &measure)
unique_ptr< LightTreeNode > children[2]
__forceinline Inner & get_inner()
void make_leaf(const int first_emitter_index, const int num_emitters)
LightTreeLightLink light_link
Shader * get_shader() const
float area(const Transform &tfm) const
size_t num_triangles() const
Triangle get_triangle(const size_t i) const
__forceinline bool is_empty() const
float calculate_measure() const
unique_ptr_vector< Object > objects