2
0
Эх сурвалжийг харах

support decals on M_dual objects

David Rose 23 жил өмнө
parent
commit
8ab41304fd

+ 51 - 1
panda/src/pgraph/cullResult.cxx

@@ -87,7 +87,10 @@ add_object(CullableObject *object) {
 #endif
           {
             CullableObject *transparent_part = new CullableObject(*object);
-            transparent_part->_state = state->compose(get_dual_transparent_state());
+            CPT(RenderState) transparent_state = object->has_decals() ? 
+              get_dual_transparent_state_decals() : 
+              get_dual_transparent_state();
+            transparent_part->_state = state->compose(transparent_state);
             CullBin *bin = get_bin(transparent_part->_state->get_bin_index());
             nassertv(bin != (CullBin *)NULL);
             bin->add_object(transparent_part);
@@ -219,16 +222,63 @@ static const double m_dual_flash_rate = 1.0;  // 1 state change per second
 //       Access: Private
 //  Description: Returns a RenderState that renders only the
 //               transparent parts of an object, in support of M_dual.
+//               This state is suitable only for objects that do not
+//               contain decals.
 ////////////////////////////////////////////////////////////////////
 CPT(RenderState) CullResult::
 get_dual_transparent_state() {
   static CPT(RenderState) state = NULL;
   if (state == (const RenderState *)NULL) {
+    // The alpha test for > 0 prevents us from drawing empty pixels,
+    // and hence filling up the depth buffer with large empty spaces
+    // that may obscure other things.  However, this does mean we draw
+    // pixels twice where the alpha == 1.0 (since they were already
+    // drawn in the opaque pass).  This is not normally a problem,
+    // except when we are using decals; in the case of decals, we
+    // don't want to draw the 1.0 pixels again, since these are the
+    // ones that may have been decaled onto.
     state = RenderState::make(AlphaTestAttrib::make(AlphaTestAttrib::M_greater, 0.0f),
                               TransparencyAttrib::make(TransparencyAttrib::M_alpha),
                               RenderState::get_max_priority());
   }
 
+#ifndef NDEBUG
+  if (m_dual_flash) {
+    int cycle = (int)(ClockObject::get_global_clock()->get_real_time() * m_dual_flash_rate);
+    if ((cycle & 1) == 0) {
+      static CPT(RenderState) flash_state = NULL;
+      if (flash_state == (const RenderState *)NULL) {
+        flash_state = state->add_attrib(ColorScaleAttrib::make(LVecBase4f(0.8f, 0.2f, 0.2f, 1.0f)));
+        flash_state = flash_state->add_attrib(AlphaTestAttrib::make(AlphaTestAttrib::M_less, 1.0f));
+      }
+      return flash_state;
+    }
+  }
+#endif  // NDEBUG
+
+  return state;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CullResult::get_dual_transparent_state_decals
+//       Access: Private
+//  Description: Returns a RenderState that renders only the
+//               transparent parts of an object, but suitable for
+//               objects that contain decals.
+////////////////////////////////////////////////////////////////////
+CPT(RenderState) CullResult::
+get_dual_transparent_state_decals() {
+  static CPT(RenderState) state = NULL;
+  if (state == (const RenderState *)NULL) {
+    // This is exactly the same as above except here we make the alpha
+    // test of < 1.0 instead of > 0.0.  This makes us draw big empty
+    // pixels where the alpha values are 0.0, but we don't overwrite
+    // the decals where the pixels are 1.0.
+    state = RenderState::make(AlphaTestAttrib::make(AlphaTestAttrib::M_less, 1.0f),
+                              TransparencyAttrib::make(TransparencyAttrib::M_alpha),
+                              RenderState::get_max_priority());
+  }
+
 #ifndef NDEBUG
   if (m_dual_flash) {
     int cycle = (int)(ClockObject::get_global_clock()->get_real_time() * m_dual_flash_rate);

+ 1 - 0
panda/src/pgraph/cullResult.h

@@ -65,6 +65,7 @@ private:
 
   static CPT(RenderState) get_binary_state();
   static CPT(RenderState) get_dual_transparent_state();
+  static CPT(RenderState) get_dual_transparent_state_decals();
   static CPT(RenderState) get_dual_opaque_state();
 
   GraphicsStateGuardianBase *_gsg;

+ 11 - 1
panda/src/pgraph/cullableObject.I

@@ -81,7 +81,6 @@ CullableObject(const CullableObject &copy) :
 
 ////////////////////////////////////////////////////////////////////
 //     Function: CullableObject::Copy Assignment Operator
-//       Access: Private
 //       Access: Public
 //  Description: Copies the CullableObject, but does not copy its
 //               children (decals).
@@ -93,6 +92,17 @@ operator = (const CullableObject &copy) {
   _transform = copy._transform;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: CullableObject::has_decals
+//       Access: Public
+//  Description: Returns true if the object has one or more decals
+//               placed on it, false otherwise.
+////////////////////////////////////////////////////////////////////
+INLINE bool CullableObject::
+has_decals() const {
+  return (_next != (CullableObject *)NULL);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: CullableObject::operator new
 //       Access: Public

+ 2 - 0
panda/src/pgraph/cullableObject.h

@@ -49,6 +49,8 @@ public:
   INLINE CullableObject(const CullableObject &copy);
   INLINE void operator = (const CullableObject &copy);
 
+  INLINE bool has_decals() const;
+
 public:
   ~CullableObject();