Browse Source

hack around DX texture problem

David Rose 23 years ago
parent
commit
b41f230f44
1 changed files with 26 additions and 2 deletions
  1. 26 2
      panda/src/pgraph/cullResult.cxx

+ 26 - 2
panda/src/pgraph/cullResult.cxx

@@ -23,6 +23,30 @@
 #include "renderState.h"
 #include "renderState.h"
 #include "clockObject.h"
 #include "clockObject.h"
 
 
+// This value is used instead of 1.0 to represent the alpha level of a
+// pixel that is to be considered "opaque" for the purposes of M_dual.
+
+// Ideally, 1.0 is the only correct value for this.  Realistically, we
+// have to fudge it lower for two reasons:
+
+// (1) The modelers tend to paint textures with very slight
+// transparency levels in places that are not intended to be
+// transparent, without realizing it.  These very faint transparency
+// regions are normally (almost) invisible, but when rendered with
+// M_dual they may be revealed as regions of poor alpha sorting.
+
+// (2) There seems to be some problem in DX where, in certain
+// circumstances apparently related to automatic texture management,
+// it spontaneously drops out the bottom two bits of an eight-bit
+// alpha channel, causing a value of 255 to become a value of 252
+// instead.
+
+// We use 256 as the denominator here (instead of, say, 255) because a
+// fractional power of two will have a terminating representation in
+// base 2, and thus will be more likely to have a precise value in
+// whatever internal representation the graphics API will use.
+static const float dual_opaque_level = 252.0f / 256.0f;
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: CullResult::make_next
 //     Function: CullResult::make_next
 //       Access: Public
 //       Access: Public
@@ -274,7 +298,7 @@ get_dual_transparent_state_decals() {
     // test of < 1.0 instead of > 0.0.  This makes us draw big empty
     // 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
     // pixels where the alpha values are 0.0, but we don't overwrite
     // the decals where the pixels are 1.0.
     // the decals where the pixels are 1.0.
-    state = RenderState::make(AlphaTestAttrib::make(AlphaTestAttrib::M_less, 1.0f),
+    state = RenderState::make(AlphaTestAttrib::make(AlphaTestAttrib::M_less, dual_opaque_level),
                               TransparencyAttrib::make(TransparencyAttrib::M_alpha),
                               TransparencyAttrib::make(TransparencyAttrib::M_alpha),
                               RenderState::get_max_priority());
                               RenderState::get_max_priority());
   }
   }
@@ -305,7 +329,7 @@ CPT(RenderState) CullResult::
 get_dual_opaque_state() {
 get_dual_opaque_state() {
   static CPT(RenderState) state = NULL;
   static CPT(RenderState) state = NULL;
   if (state == (const RenderState *)NULL) {
   if (state == (const RenderState *)NULL) {
-    state = RenderState::make(AlphaTestAttrib::make(AlphaTestAttrib::M_equal, 1.0f),
+    state = RenderState::make(AlphaTestAttrib::make(AlphaTestAttrib::M_greater_equal, dual_opaque_level),
                               TransparencyAttrib::make(TransparencyAttrib::M_none),
                               TransparencyAttrib::make(TransparencyAttrib::M_none),
                               RenderState::get_max_priority());
                               RenderState::get_max_priority());
   }
   }