Bladeren bron

hide/show optimization

David Rose 17 jaren geleden
bovenliggende
commit
22ecb41b4c
3 gewijzigde bestanden met toevoegingen van 90 en 27 verwijderingen
  1. 10 6
      panda/src/display/graphicsStateGuardian.cxx
  2. 8 0
      panda/src/pgraph/pandaNode.I
  3. 72 21
      panda/src/pgraph/pandaNode.cxx

+ 10 - 6
panda/src/display/graphicsStateGuardian.cxx

@@ -1766,13 +1766,17 @@ do_issue_light() {
         cur_ambient_light += light_obj->get_color();
 
       } else {
-        enable_light(num_enabled, true);
-        if (num_enabled == 0) {
-          begin_bind_lights();
+        const Colorf &color = light_obj->get_color();
+        // Don't bother binding the light if it has no color to contribute.
+        if (color[0] != 0.0 || color[1] != 0.0 || color[2] != 0.0) {
+          enable_light(num_enabled, true);
+          if (num_enabled == 0) {
+            begin_bind_lights();
+          }
+          
+          light_obj->bind(this, light, num_enabled);
+          num_enabled++;
         }
-
-        light_obj->bind(this, light, num_enabled);
-        num_enabled++;
       }
     }
   }

+ 8 - 0
panda/src/pgraph/pandaNode.I

@@ -1437,6 +1437,14 @@ compare_draw_mask(DrawMask running_draw_mask, DrawMask camera_mask) const {
   nassertr(_cdata != (PandaNode::CData *)NULL, false);
   nassertr(_cdata->_last_update == _cdata->_next_update, false);
 
+  // As a special case, if net_draw_show_mask is all 0, it means
+  // either that all nodes under this node are hidden to all cameras,
+  // or that none of them are renderable nodes (or some combination).
+  // In either case, we might as well short-circuit.
+  if (_cdata->_net_draw_show_mask.is_zero()) {
+    return false;
+  }
+
   DrawMask net_draw_control_mask, net_draw_show_mask;
   net_draw_control_mask = _cdata->_net_draw_control_mask;
   net_draw_show_mask = _cdata->_net_draw_show_mask;

+ 72 - 21
panda/src/pgraph/pandaNode.cxx

@@ -3710,29 +3710,68 @@ update_bounds(int pipeline_stage, PandaNode::CDLockedStageReader &cdata) {
       
         net_collide_mask |= child_cdataw->_net_collide_mask;
 
+        if (drawmask_cat.is_debug()) {
+          drawmask_cat.debug(false)
+            << "\nchild update " << *child << ":\n";
+        }
+
         DrawMask child_control_mask = child_cdataw->_net_draw_control_mask;
         DrawMask child_show_mask = child_cdataw->_net_draw_show_mask;
-        if (child_control_mask != DrawMask::all_off() ||
-            child_show_mask != DrawMask::all_off()) {
+        if (!(child_control_mask | child_show_mask).is_zero()) {
           // This child includes a renderable node or subtree.  Thus,
           // we should propagate its draw masks.
           renderable = true;
 
-          // Compute the set of control bits that are defined on this
-          // node, but not on the child node.
-          DrawMask new_control_mask = draw_control_mask & ~child_control_mask;
-          // Anywhere we have a control bit that our child does not,
-          // the child inherits our show bit.
-          DrawMask new_child_show_mask = (child_show_mask & ~new_control_mask) | (draw_show_mask & new_control_mask);
-          DrawMask new_child_control_mask = child_control_mask | new_control_mask;
-          // Now merge that result with our accumulated draw masks.
-          net_draw_control_mask |= new_child_control_mask;
-          net_draw_show_mask |= new_child_show_mask;
+          // For each bit position in the masks, we have assigned the
+          // following semantic meaning.  The number on the left
+          // represents the pairing of the corresponding bit from the
+          // control mask and from the show mask:
+          
+          //   00 : not a renderable node   (control 0, show 0)
+          //   01 : a normally visible node (control 0, show 1)
+          //   10 : a hidden node           (control 1, show 0)
+          //   11 : a show-through node     (control 1, show 1)
+
+          // Now, when we accumulate these masks, we want to do so
+          // according to the following table, for each bit position:
+
+          //          00   01   10   11     (child)
+          //        ---------------------
+          //     00 | 00   01   10   11
+          //     01 | 01   01   01*  11
+          //     10 | 10   01*  10   11
+          //     11 | 11   11   11   11
+          // (parent)
+
+          // This table is almost the same as the union of both masks,
+          // with one exception, marked with a * in the above table:
+          // if one is 10 and the other is 01--that is, one is hidden
+          // and the other is normally visible--then the result should
+          // be 01, normally visible.  This is because we only want to
+          // propagate the hidden bit upwards if *all* renderable
+          // nodes are hidden.
+
+          // Get the set of exception bits for which the above rule
+          // applies.  These are the bits for which both bits have
+          // flipped, but which were not the same in the original.
+          DrawMask exception_mask = (net_draw_control_mask ^ child_control_mask) & (net_draw_show_mask ^ child_show_mask);
+          exception_mask &= (net_draw_control_mask ^ net_draw_show_mask);
+
+          if (drawmask_cat.is_debug()) {
+            drawmask_cat.debug(false)
+              << "exception_mask = " << exception_mask << "\n";
+          }
+
+          // Now compute the union, applying the above exception.
+          net_draw_control_mask |= child_control_mask;
+          net_draw_show_mask |= child_show_mask;
+          
+          net_draw_control_mask &= ~exception_mask;
+          net_draw_show_mask |= exception_mask;
         }
 
         if (drawmask_cat.is_debug()) {
           drawmask_cat.debug(false)
-            << "\nchild update " << *child << ":\n"
             << "child_control_mask = " << child_control_mask
             << "\nchild_show_mask = " << child_show_mask
             << "\nnet_draw_control_mask = " << net_draw_control_mask
@@ -3758,21 +3797,33 @@ update_bounds(int pipeline_stage, PandaNode::CDLockedStageReader &cdata) {
         net_collide_mask |= child_cdata->_net_collide_mask;
 
         // See comments in similar block above.
+        if (drawmask_cat.is_debug()) {
+          drawmask_cat.debug(false)
+            << "\nchild fresh " << *child << ":\n";
+        }
         DrawMask child_control_mask = child_cdata->_net_draw_control_mask;
         DrawMask child_show_mask = child_cdata->_net_draw_show_mask;
-        if (child_control_mask != DrawMask::all_off() ||
-            child_show_mask != DrawMask::all_off()) {
+        if (!(child_control_mask | child_show_mask).is_zero()) {
           renderable = true;
-          DrawMask new_control_mask = draw_control_mask & ~child_control_mask;
-          DrawMask new_child_show_mask = (child_show_mask & ~new_control_mask) | (draw_show_mask & new_control_mask);
-          DrawMask new_child_control_mask = child_control_mask | new_control_mask;
-          net_draw_control_mask |= new_child_control_mask;
-          net_draw_show_mask |= new_child_show_mask;
+
+          DrawMask exception_mask = (net_draw_control_mask ^ child_control_mask) & (net_draw_show_mask ^ child_show_mask);
+          exception_mask &= (net_draw_control_mask ^ net_draw_show_mask);
+
+          if (drawmask_cat.is_debug()) {
+            drawmask_cat.debug(false)
+              << "exception_mask = " << exception_mask << "\n";
+          }
+
+          // Now compute the union, applying the above exception.
+          net_draw_control_mask |= child_control_mask;
+          net_draw_show_mask |= child_show_mask;
+          
+          net_draw_control_mask &= ~exception_mask;
+          net_draw_show_mask |= exception_mask;
         }
 
         if (drawmask_cat.is_debug()) {
           drawmask_cat.debug(false)
-            << "\nchild fresh " << *child << ":\n"
             << "child_control_mask = " << child_control_mask
             << "\nchild_show_mask = " << child_show_mask
             << "\nnet_draw_control_mask = " << net_draw_control_mask