@@ -1238,6 +1238,7 @@ void Ray::Cpu::Scene::RebuildLightTree_nolock() {
12381238 struct additional_data_t {
12391239 Ref::fvec4 axis;
12401240 float flux, omega_n, omega_e;
1241+ uint32_t type;
12411242 };
12421243 aligned_vector<additional_data_t > additional_data;
12431244 additional_data.reserve (lights_.size ());
@@ -1375,7 +1376,7 @@ void Ray::Cpu::Scene::RebuildLightTree_nolock() {
13751376 primitives.push_back ({0 , 0 , 0 , bbox_min, bbox_max});
13761377
13771378 const float flux = lum * area;
1378- additional_data.push_back ({axis, flux, omega_n, omega_e});
1379+ additional_data.push_back ({axis, flux, omega_n, omega_e, l. type });
13791380 }
13801381
13811382 light_nodes_.clear ();
@@ -1406,6 +1407,7 @@ void Ray::Cpu::Scene::RebuildLightTree_nolock() {
14061407 light_nodes_[i].flux = additional_data[prim_index].flux ;
14071408 light_nodes_[i].omega_n = additional_data[prim_index].omega_n ;
14081409 light_nodes_[i].omega_e = additional_data[prim_index].omega_e ;
1410+ light_nodes_[i].bitmask = (1u << additional_data[prim_index].type );
14091411 }
14101412 }
14111413
@@ -1434,47 +1436,59 @@ void Ray::Cpu::Scene::RebuildLightTree_nolock() {
14341436 }
14351437
14361438 // Propagate flux and cone up the hierarchy
1439+ std::vector<bool > processed (light_nodes_.size (), false );
14371440 std::vector<uint32_t > to_process;
1438- to_process.reserve (light_nodes_.size ());
14391441 to_process.insert (end (to_process), begin (leaf_indices), end (leaf_indices));
1440- for (uint32_t i = 0 ; i < uint32_t (to_process.size ()); ++i) {
1441- const uint32_t n = to_process[i];
1442- const uint32_t parent = parent_indices[n];
1443- if (parent == 0xffffffff ) {
1444- continue ;
1445- }
1446-
1447- light_nodes_[parent].flux += light_nodes_[n].flux ;
1448- if (light_nodes_[parent].axis [0 ] == 0 .0f && light_nodes_[parent].axis [1 ] == 0 .0f &&
1449- light_nodes_[parent].axis [2 ] == 0 .0f ) {
1450- memcpy (light_nodes_[parent].axis , light_nodes_[n].axis , 3 * sizeof (float ));
1451- light_nodes_[parent].omega_n = light_nodes_[n].omega_n ;
1452- } else {
1453- auto axis1 = Ref::fvec4{light_nodes_[parent].axis }, axis2 = Ref::fvec4{light_nodes_[n].axis };
1454- axis1.set <3 >(0 .0f );
1455- axis2.set <3 >(0 .0f );
1442+ while (!to_process.empty ()) {
1443+ uint32_t next_count = 0 ;
1444+ for (uint32_t i = 0 ; i < uint32_t (to_process.size ()); ++i) {
1445+ const uint32_t n = to_process[i];
1446+ const uint32_t parent = parent_indices[n];
1447+ if (parent == 0xffffffff ) {
1448+ continue ;
1449+ }
14561450
1457- const float angle_between = acosf (clamp (dot (axis1, axis2), -1 .0f , 1 .0f ));
1451+ assert (!processed[n]);
1452+ processed[n] = true ;
14581453
1459- axis1 += axis2;
1460- const float axis_length = length (axis1);
1461- if (axis_length != 0 .0f ) {
1462- axis1 /= axis_length;
1454+ light_nodes_[parent].flux += light_nodes_[n].flux ;
1455+ light_nodes_[parent].bitmask |= light_nodes_[n].bitmask ;
1456+ if (light_nodes_[parent].axis [0 ] == 0 .0f && light_nodes_[parent].axis [1 ] == 0 .0f &&
1457+ light_nodes_[parent].axis [2 ] == 0 .0f ) {
1458+ memcpy (light_nodes_[parent].axis , light_nodes_[n].axis , 3 * sizeof (float ));
1459+ light_nodes_[parent].omega_n = light_nodes_[n].omega_n ;
14631460 } else {
1464- axis1 = Ref::fvec4{0 .0f , 1 .0f , 0 .0f , 0 .0f };
1465- }
1461+ auto axis1 = Ref::fvec4{light_nodes_[parent].axis }, axis2 = Ref::fvec4{light_nodes_[n].axis };
1462+ axis1.set <3 >(0 .0f );
1463+ axis2.set <3 >(0 .0f );
1464+
1465+ const float angle_between = acosf (clamp (dot (axis1, axis2), -1 .0f , 1 .0f ));
1466+
1467+ axis1 += axis2;
1468+ const float axis_length = length (axis1);
1469+ if (axis_length != 0 .0f ) {
1470+ axis1 /= axis_length;
1471+ } else {
1472+ axis1 = Ref::fvec4{0 .0f , 1 .0f , 0 .0f , 0 .0f };
1473+ }
14661474
1467- memcpy (light_nodes_[parent].axis , value_ptr (axis1), 3 * sizeof (float ));
1475+ memcpy (light_nodes_[parent].axis , value_ptr (axis1), 3 * sizeof (float ));
14681476
1469- light_nodes_[parent].omega_n =
1470- fminf (0 .5f * (light_nodes_[parent].omega_n +
1471- fmaxf (light_nodes_[parent].omega_n , angle_between + light_nodes_[n].omega_n )),
1472- PI);
1473- }
1474- light_nodes_[parent].omega_e = fmaxf (light_nodes_[parent].omega_e , light_nodes_[n].omega_e );
1475- if ((light_nodes_[parent].left_child & LEFT_CHILD_BITS) == n) {
1476- to_process.push_back (parent);
1477+ light_nodes_[parent].omega_n =
1478+ fminf (0 .5f * (light_nodes_[parent].omega_n +
1479+ fmaxf (light_nodes_[parent].omega_n , angle_between + light_nodes_[n].omega_n )),
1480+ PI);
1481+ }
1482+ light_nodes_[parent].omega_e = fmaxf (light_nodes_[parent].omega_e , light_nodes_[n].omega_e );
1483+
1484+ const uint32_t left_child = light_nodes_[parent].left_child & LEFT_CHILD_BITS,
1485+ right_child = light_nodes_[parent].right_child & RIGHT_CHILD_BITS;
1486+ if (processed[left_child] && processed[right_child]) {
1487+ assert (next_count <= i);
1488+ to_process[next_count++] = parent;
1489+ }
14771490 }
1491+ to_process.resize (next_count);
14781492 }
14791493
14801494 // Remove indices indirection
0 commit comments