Browse Source

DepthOffsetAttrib::min_value, max_value

David Rose 14 years ago
parent
commit
3a75ebde9a

+ 1 - 1
panda/src/glstuff/glGeomContext_src.cxx

@@ -85,7 +85,7 @@ release_display_lists() {
 
     if (GLCAT.is_debug()) {
       GLCAT.debug()
-        << "releasing index " << dl._index << "\n";
+        << "releasing index " << (int)dl._index << "\n";
     }
     GLP(DeleteLists)(dl._index, 1);
   }

+ 2 - 2
panda/src/glstuff/glGraphicsBuffer_src.cxx

@@ -216,7 +216,7 @@ check_fbo() {
       GLCAT.error() << "FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT"; break;
 #endif
     default:
-      GLCAT.error() << "UNKNOWN PROBLEM " << status; break;
+      GLCAT.error() << "UNKNOWN PROBLEM " << (int)status; break;
     }
     GLCAT.error(false) << " for " << get_name() << "\n";
 
@@ -1080,7 +1080,7 @@ report_my_errors(int line, const char *file) {
   if (_gsg == 0) {
     GLenum error_code = glGetError();
     if (error_code != GL_NO_ERROR) {
-      GLCAT.error() << file << ", line " << line << ": GL error " << error_code << "\n";
+      GLCAT.error() << file << ", line " << line << ": GL error " << (int)error_code << "\n";
     }
   } else {
     CLP(GraphicsStateGuardian) *glgsg;

+ 53 - 27
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -1915,6 +1915,10 @@ clear(DrawableRegion *clearable) {
 #else
     GLP(ClearDepth)(clearable->get_clear_depth());
 #endif  // OPENGLES
+#ifdef GSG_VERBOSE
+    GLCAT.spam()
+      << "glDepthMask(GL_TRUE)" << endl;
+#endif
     GLP(DepthMask)(GL_TRUE);
     _state_mask.clear_bit(DepthWriteAttrib::get_class_slot());
     mask |= GL_DEPTH_BUFFER_BIT;
@@ -2244,7 +2248,7 @@ end_frame(Thread *current_thread) {
            ++ddli) {
         if (GLCAT.is_debug()) {
           GLCAT.debug()
-            << "releasing display list index " << (*ddli) << "\n";
+            << "releasing display list index " << (int)(*ddli) << "\n";
         }
         GLP(DeleteLists)((*ddli), 1);
       }
@@ -2259,7 +2263,7 @@ end_frame(Thread *current_thread) {
            ++ddli) {
         if (GLCAT.is_debug()) {
           GLCAT.debug()
-            << "releasing query index " << (*ddli) << "\n";
+            << "releasing query index " << (int)(*ddli) << "\n";
         }
         _glDeleteQueries(1, &(*ddli));
       }
@@ -2458,7 +2462,7 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader,
       // If it hasn't been modified, just play the display list again.
       if (GLCAT.is_spam()) {
         GLCAT.spam()
-          << "calling display list " << _geom_display_list << "\n";
+          << "calling display list " << (int)_geom_display_list << "\n";
       }
 
       GLP(CallList)(_geom_display_list);
@@ -2479,7 +2483,7 @@ begin_draw_primitives(const GeomPipelineReader *geom_reader,
 
     if (GLCAT.is_debug()) {
       GLCAT.debug()
-        << "compiling display list " << _geom_display_list << "\n";
+        << "compiling display list " << (int)_geom_display_list << "\n";
     }
 
     // If it has been modified, or this is the first time, then we
@@ -3589,7 +3593,7 @@ prepare_vertex_buffer(GeomVertexArrayData *data) {
 
     if (GLCAT.is_debug() && CLP(debug_buffers)) {
       GLCAT.debug()
-        << "creating vertex buffer " << gvbc->_index << ": "
+        << "creating vertex buffer " << (int)gvbc->_index << ": "
         << data->get_num_rows() << " vertices "
         << *data->get_array_format() << "\n";
     }
@@ -3622,7 +3626,7 @@ apply_vertex_buffer(VertexBufferContext *vbc,
   if (_current_vbuffer_index != gvbc->_index) {
     if (GLCAT.is_spam() && CLP(debug_buffers)) {
       GLCAT.spam()
-        << "binding vertex buffer " << gvbc->_index << "\n";
+        << "binding vertex buffer " << (int)gvbc->_index << "\n";
     }
     _glBindBuffer(GL_ARRAY_BUFFER, gvbc->_index);
     _current_vbuffer_index = gvbc->_index;
@@ -3634,7 +3638,7 @@ apply_vertex_buffer(VertexBufferContext *vbc,
     if (GLCAT.is_debug() && CLP(debug_buffers)) {
       GLCAT.debug()
         << "copying " << num_bytes
-        << " bytes into vertex buffer " << gvbc->_index << "\n";
+        << " bytes into vertex buffer " << (int)gvbc->_index << "\n";
     }
     if (num_bytes != 0) {
       const unsigned char *client_pointer = reader->get_read_pointer(force);
@@ -3678,7 +3682,7 @@ release_vertex_buffer(VertexBufferContext *vbc) {
 
   if (GLCAT.is_debug() && CLP(debug_buffers)) {
     GLCAT.debug()
-      << "deleting vertex buffer " << gvbc->_index << "\n";
+      << "deleting vertex buffer " << (int)gvbc->_index << "\n";
   }
 
   // Make sure the buffer is unbound before we delete it.  Not
@@ -3778,7 +3782,7 @@ prepare_index_buffer(GeomPrimitive *data) {
 
     if (GLCAT.is_debug() && CLP(debug_buffers)) {
       GLCAT.debug()
-        << "creating index buffer " << gibc->_index << ": "
+        << "creating index buffer " << (int)gibc->_index << ": "
         << data->get_num_vertices() << " indices ("
         << data->get_vertices()->get_array_format()->get_column(0)->get_numeric_type()
         << ")\n";
@@ -3814,7 +3818,7 @@ apply_index_buffer(IndexBufferContext *ibc,
   if (_current_ibuffer_index != gibc->_index) {
     if (GLCAT.is_spam() && CLP(debug_buffers)) {
       GLCAT.spam()
-        << "binding index buffer " << gibc->_index << "\n";
+        << "binding index buffer " << (int)gibc->_index << "\n";
     }
     _glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gibc->_index);
     _current_ibuffer_index = gibc->_index;
@@ -3826,7 +3830,7 @@ apply_index_buffer(IndexBufferContext *ibc,
     if (GLCAT.is_debug() && CLP(debug_buffers)) {
       GLCAT.debug()
         << "copying " << num_bytes
-        << " bytes into index buffer " << gibc->_index << "\n";
+        << " bytes into index buffer " << (int)gibc->_index << "\n";
     }
     if (num_bytes != 0) {
       const unsigned char *client_pointer = reader->get_read_pointer(force);
@@ -3870,7 +3874,7 @@ release_index_buffer(IndexBufferContext *ibc) {
 
   if (GLCAT.is_debug() && CLP(debug_buffers)) {
     GLCAT.debug()
-      << "deleting index buffer " << gibc->_index << "\n";
+      << "deleting index buffer " << (int)gibc->_index << "\n";
   }
 
   // Make sure the buffer is unbound before we delete it.  Not
@@ -3979,7 +3983,7 @@ begin_occlusion_query() {
 
   if (GLCAT.is_debug()) {
     GLCAT.debug()
-      << "beginning occlusion query index " << query->_index << "\n";
+      << "beginning occlusion query index " << (int)query->_index << "\n";
   }
 
   _glBeginQuery(GL_SAMPLES_PASSED, query->_index);
@@ -4012,7 +4016,7 @@ end_occlusion_query() {
     
   if (GLCAT.is_debug()) {
     GLCAT.debug()
-      << "ending occlusion query index " << index << "\n";
+      << "ending occlusion query index " << (int)index << "\n";
   }
 
   _current_occlusion_query = NULL;
@@ -4709,8 +4713,16 @@ do_issue_depth_write() {
   const DepthWriteAttrib *target_depth_write = DCAST(DepthWriteAttrib, _target_rs->get_attrib_def(DepthWriteAttrib::get_class_slot()));
   DepthWriteAttrib::Mode mode = target_depth_write->get_mode();
   if (mode == DepthWriteAttrib::M_off) {
+#ifdef GSG_VERBOSE
+    GLCAT.spam()
+      << "glDepthMask(GL_FALSE)" << endl;
+#endif
     GLP(DepthMask)(GL_FALSE);
   } else {
+#ifdef GSG_VERBOSE
+    GLCAT.spam()
+      << "glDepthMask(GL_TRUE)" << endl;
+#endif
     GLP(DepthMask)(GL_TRUE);
   }
   report_my_gl_errors();
@@ -4785,6 +4797,20 @@ do_issue_depth_offset() {
     enable_polygon_offset(false);
   }
 
+  PN_stdfloat min_value = target_depth_offset->get_min_value();
+  PN_stdfloat max_value = target_depth_offset->get_max_value();
+#ifdef GSG_VERBOSE
+    GLCAT.spam()
+      << "glDepthRange(" << min_value << ", " << max_value << ")" << endl;
+#endif
+#ifdef OPENGLES
+  // OpenGL ES uses a single-precision call.
+  GLP(DepthRangef)((GLclampf)min_value, (GLclampf)max_value);
+#else
+  // Mainline OpenGL uses a double-precision call.
+  GLP(DepthRange)((GLclampd)min_value, (GLclampd)max_value);
+#endif  // OPENGLES
+
   report_my_gl_errors();
 }
 
@@ -10090,19 +10116,19 @@ do_issue_stencil() {
     if (false) {
       GLCAT.debug() << "STENCIL STATE CHANGE\n";
       GLCAT.debug() << "\n"
-                    << "SRS_front_enable " << stencil -> get_render_state (StencilAttrib::SRS_front_enable) << "\n"
-                    << "SRS_back_enable " << stencil -> get_render_state (StencilAttrib::SRS_back_enable) << "\n"
-                    << "SRS_front_comparison_function " << stencil -> get_render_state (StencilAttrib::SRS_front_comparison_function) << "\n"
-                    << "SRS_front_stencil_fail_operation " << stencil -> get_render_state (StencilAttrib::SRS_front_stencil_fail_operation) << "\n"
-                    << "SRS_front_stencil_pass_z_fail_operation " << stencil -> get_render_state (StencilAttrib::SRS_front_stencil_pass_z_fail_operation) << "\n"
-                    << "SRS_front_stencil_pass_z_pass_operation " << stencil -> get_render_state (StencilAttrib::SRS_front_stencil_pass_z_pass_operation) << "\n"
-                    << "SRS_reference " << stencil -> get_render_state (StencilAttrib::SRS_reference) << "\n"
-                    << "SRS_read_mask " << stencil -> get_render_state (StencilAttrib::SRS_read_mask) << "\n"
-                    << "SRS_write_mask " << stencil -> get_render_state (StencilAttrib::SRS_write_mask) << "\n"
-                    << "SRS_back_comparison_function " << stencil -> get_render_state (StencilAttrib::SRS_back_comparison_function) << "\n"
-                    << "SRS_back_stencil_fail_operation " << stencil -> get_render_state (StencilAttrib::SRS_back_stencil_fail_operation) << "\n"
-                    << "SRS_back_stencil_pass_z_fail_operation " << stencil -> get_render_state (StencilAttrib::SRS_back_stencil_pass_z_fail_operation) << "\n"
-                    << "SRS_back_stencil_pass_z_pass_operation " << stencil -> get_render_state (StencilAttrib::SRS_back_stencil_pass_z_pass_operation) << "\n";
+                    << "SRS_front_enable " << (int)stencil -> get_render_state (StencilAttrib::SRS_front_enable) << "\n"
+                    << "SRS_back_enable " << (int)stencil -> get_render_state (StencilAttrib::SRS_back_enable) << "\n"
+                    << "SRS_front_comparison_function " << (int)stencil -> get_render_state (StencilAttrib::SRS_front_comparison_function) << "\n"
+                    << "SRS_front_stencil_fail_operation " << (int)stencil -> get_render_state (StencilAttrib::SRS_front_stencil_fail_operation) << "\n"
+                    << "SRS_front_stencil_pass_z_fail_operation " << (int)stencil -> get_render_state (StencilAttrib::SRS_front_stencil_pass_z_fail_operation) << "\n"
+                    << "SRS_front_stencil_pass_z_pass_operation " << (int)stencil -> get_render_state (StencilAttrib::SRS_front_stencil_pass_z_pass_operation) << "\n"
+                    << "SRS_reference " << (int)stencil -> get_render_state (StencilAttrib::SRS_reference) << "\n"
+                    << "SRS_read_mask " << (int)stencil -> get_render_state (StencilAttrib::SRS_read_mask) << "\n"
+                    << "SRS_write_mask " << (int)stencil -> get_render_state (StencilAttrib::SRS_write_mask) << "\n"
+                    << "SRS_back_comparison_function " << (int)stencil -> get_render_state (StencilAttrib::SRS_back_comparison_function) << "\n"
+                    << "SRS_back_stencil_fail_operation " << (int)stencil -> get_render_state (StencilAttrib::SRS_back_stencil_fail_operation) << "\n"
+                    << "SRS_back_stencil_pass_z_fail_operation " << (int)stencil -> get_render_state (StencilAttrib::SRS_back_stencil_pass_z_fail_operation) << "\n"
+                    << "SRS_back_stencil_pass_z_pass_operation " << (int)stencil -> get_render_state (StencilAttrib::SRS_back_stencil_pass_z_pass_operation) << "\n";
     }
 
     {

+ 2 - 2
panda/src/glstuff/glOcclusionQueryContext_src.cxx

@@ -57,7 +57,7 @@ is_answer_ready() const {
 
   if (GLCAT.is_debug()) {
     GLCAT.debug()
-      << "occlusion query " << _index << " ready = " << result << "\n";
+      << "occlusion query " << (int)_index << " ready = " << (int)result << "\n";
   }
 
   return (result != 0);
@@ -106,7 +106,7 @@ get_num_fragments() const {
 
   if (GLCAT.is_debug()) {
     GLCAT.debug()
-      << "occlusion query " << _index << " reports " << result
+      << "occlusion query " << (int)_index << " reports " << (int)result
       << " fragments.\n";
   }
 

+ 28 - 2
panda/src/pgraph/depthOffsetAttrib.I

@@ -20,8 +20,10 @@
 //               DepthOffsetAttrib object.
 ////////////////////////////////////////////////////////////////////
 INLINE DepthOffsetAttrib::
-DepthOffsetAttrib(int offset) :
-  _offset(offset)
+DepthOffsetAttrib(int offset, PN_stdfloat min_value, PN_stdfloat max_value) :
+  _offset(offset),
+  _min_value(min_value),
+  _max_value(max_value)
 {
 }
 
@@ -34,3 +36,27 @@ INLINE int DepthOffsetAttrib::
 get_offset() const {
   return _offset;
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: DepthOffsetAttrib::get_min_value
+//       Access: Published
+//  Description: Returns the value for the minimum (closest) depth
+//               value to be stored in the buffer, in the range 0
+//               .. 1.
+////////////////////////////////////////////////////////////////////
+INLINE PN_stdfloat DepthOffsetAttrib::
+get_min_value() const {
+  return _min_value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DepthOffsetAttrib::get_max_value
+//       Access: Published
+//  Description: Returns the value for the maximum (farthest) depth
+//               value to be stored in the buffer, in the range 0
+//               .. 1.
+////////////////////////////////////////////////////////////////////
+INLINE PN_stdfloat DepthOffsetAttrib::
+get_max_value() const {
+  return _max_value;
+}

+ 46 - 7
panda/src/pgraph/depthOffsetAttrib.cxx

@@ -32,7 +32,26 @@ int DepthOffsetAttrib::_attrib_slot;
 ////////////////////////////////////////////////////////////////////
 CPT(RenderAttrib) DepthOffsetAttrib::
 make(int offset) {
-  DepthOffsetAttrib *attrib = new DepthOffsetAttrib(offset);
+  DepthOffsetAttrib *attrib = new DepthOffsetAttrib(offset, 0.0f, 1.0f);
+  return return_new(attrib);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DepthOffsetAttrib::make
+//       Access: Published, Static
+//  Description: Constructs a new DepthOffsetAttrib object that
+//               indicates the bias, and also specifies a minimum and
+//               maximum (or, more precisely, nearest and farthest)
+//               values to write to the depth buffer, in the range 0
+//               .. 1.  This range is 0, 1 by default; setting it to
+//               some other range can be used to create additional
+//               depth buffer effects.
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) DepthOffsetAttrib::
+make(int offset, PN_stdfloat min_value, PN_stdfloat max_value) {
+  nassertr(min_value >= 0.0f && min_value <= 1.0f, NULL);
+  nassertr(max_value >= 0.0f && max_value <= 1.0f, NULL);
+  DepthOffsetAttrib *attrib = new DepthOffsetAttrib(offset, min_value, max_value);
   return return_new(attrib);
 }
 
@@ -45,7 +64,7 @@ make(int offset) {
 ////////////////////////////////////////////////////////////////////
 CPT(RenderAttrib) DepthOffsetAttrib::
 make_default() {
-  return return_new(new DepthOffsetAttrib(0));
+  return return_new(new DepthOffsetAttrib(0, 0.0f, 1.0f));
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -55,7 +74,8 @@ make_default() {
 ////////////////////////////////////////////////////////////////////
 void DepthOffsetAttrib::
 output(ostream &out) const {
-  out << get_type() << ":(" << get_offset() << ")";
+  out << get_type() << ":(" << get_offset() << ", " << get_min_value()
+      << ", " << get_max_value() << ")";
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -77,7 +97,16 @@ int DepthOffsetAttrib::
 compare_to_impl(const RenderAttrib *other) const {
   const DepthOffsetAttrib *ta;
   DCAST_INTO_R(ta, other, 0);
-  return _offset - ta->_offset;
+  if (_offset != ta->_offset) {
+    return _offset - ta->_offset;
+  }
+  if (_min_value != ta->_min_value) {
+    return _min_value < ta->_min_value ? -1 : 1;
+  }
+  if (_max_value != ta->_max_value) {
+    return _max_value < ta->_max_value ? -1 : 1;
+  }
+  return 0;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -94,6 +123,8 @@ size_t DepthOffsetAttrib::
 get_hash_impl() const {
   size_t hash = 0;
   hash = int_hash::add_hash(hash, _offset);
+  hash = float_hash().add_hash(hash, _min_value);
+  hash = float_hash().add_hash(hash, _max_value);
   return hash;
 }
 
@@ -120,7 +151,7 @@ compose_impl(const RenderAttrib *other) const {
   DCAST_INTO_R(ta, other, 0);
   int new_offset = ta->_offset + _offset;
 
-  DepthOffsetAttrib *attrib = new DepthOffsetAttrib(new_offset);
+  DepthOffsetAttrib *attrib = new DepthOffsetAttrib(new_offset, ta->_min_value, ta->_max_value);
   return return_new(attrib);
 }
 
@@ -139,7 +170,7 @@ invert_compose_impl(const RenderAttrib *other) const {
   DCAST_INTO_R(ta, other, 0);
   int new_offset = ta->_offset - _offset;
 
-  DepthOffsetAttrib *attrib = new DepthOffsetAttrib(new_offset);
+  DepthOffsetAttrib *attrib = new DepthOffsetAttrib(new_offset, ta->_min_value, ta->_max_value);
   return return_new(attrib);
 }
 
@@ -165,6 +196,8 @@ write_datagram(BamWriter *manager, Datagram &dg) {
   RenderAttrib::write_datagram(manager, dg);
 
   dg.add_int32(_offset);
+  dg.add_stdfloat(_min_value);
+  dg.add_stdfloat(_max_value);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -177,7 +210,7 @@ write_datagram(BamWriter *manager, Datagram &dg) {
 ////////////////////////////////////////////////////////////////////
 TypedWritable *DepthOffsetAttrib::
 make_from_bam(const FactoryParams &params) {
-  DepthOffsetAttrib *attrib = new DepthOffsetAttrib(0);
+  DepthOffsetAttrib *attrib = new DepthOffsetAttrib(0, 0.0f, 1.0f);
   DatagramIterator scan;
   BamReader *manager;
 
@@ -199,4 +232,10 @@ fillin(DatagramIterator &scan, BamReader *manager) {
   RenderAttrib::fillin(scan, manager);
 
   _offset = scan.get_int32();
+  _min_value = 0.0f;
+  _max_value = 1.0f;
+  if (manager->get_file_minor_ver() >= 31) {
+    _min_value = scan.get_stdfloat();
+    _max_value = scan.get_stdfloat();
+  }
 }

+ 12 - 1
panda/src/pgraph/depthOffsetAttrib.h

@@ -49,16 +49,25 @@ class FactoryParams;
 //               lower override parameter.)  The net value should
 //               probably not exceed 16 or drop below 0 for maximum
 //               portability.
+//
+//               Also, and only tangentially related, the
+//               DepthOffsetAttrib can be used to constrain the Z
+//               output value to a subset of the usual [0, 1] range
+//               (or reversing its direction) by specifying a new
+//               min_value and max_value.
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDA_PGRAPH DepthOffsetAttrib : public RenderAttrib {
 private:
-  INLINE DepthOffsetAttrib(int offset);
+  INLINE DepthOffsetAttrib(int offset, PN_stdfloat min_value, PN_stdfloat max_value);
 
 PUBLISHED:
   static CPT(RenderAttrib) make(int offset = 1);
+  static CPT(RenderAttrib) make(int offset, PN_stdfloat min_value, PN_stdfloat max_value);
   static CPT(RenderAttrib) make_default();
 
   INLINE int get_offset() const;
+  INLINE PN_stdfloat get_min_value() const;
+  INLINE PN_stdfloat get_max_value() const;
 
 public:
   virtual void output(ostream &out) const;
@@ -71,6 +80,8 @@ protected:
 
 private:
   int _offset;
+  PN_stdfloat _min_value;
+  PN_stdfloat _max_value;
 
 PUBLISHED:
   static int get_class_slot() {

+ 2 - 1
panda/src/putil/bam.h

@@ -33,7 +33,7 @@ static const unsigned short _bam_major_ver = 6;
 // Bumped to major version 6 on 2/11/06 to factor out PandaNode::CData.
 
 static const unsigned short _bam_first_minor_ver = 14;
-static const unsigned short _bam_minor_ver = 30;
+static const unsigned short _bam_minor_ver = 31;
 // Bumped to minor version 14 on 12/19/07 to change default ColorAttrib.
 // Bumped to minor version 15 on 4/9/08 to add TextureAttrib::_implicit_sort.
 // Bumped to minor version 16 on 5/13/08 to add Texture::_quality_level.
@@ -51,6 +51,7 @@ static const unsigned short _bam_minor_ver = 30;
 // Bumped to minor version 28 on 11/28/11 to add Texture::_auto_texture_scale.
 // Bumped to minor version 29 on 12/17/11 to add GeomVertexColumn::_column_alignment.
 // Bumped to minor version 30 on 1/22/12 to add Texture::_pad_*_size.
+// Bumped to minor version 31 on 2/16/12 to add DepthOffsetAttrib::_min_value, _max_value
 
 
 #endif

+ 1 - 1
panda/src/putil/updateSeq.I

@@ -286,7 +286,7 @@ output(ostream &out) const {
     break;
 
   default:
-    out << (unsigned int)seq;
+    out << (int)seq;
   }
 }
 

+ 7 - 0
panda/src/tinydisplay/clip.cxx

@@ -33,6 +33,13 @@ void gl_transform_to_viewport(GLContext *c,GLVertex *v)
   } else {
     v->zp.z = z;
   }
+  if (c->has_zrange) {
+    // Rescale the Z value into the specified range.
+    static const int z_range = (1 << (ZB_Z_BITS + ZB_POINT_Z_FRAC_BITS)) - 1;
+    double z = 1.0 - (double)(v->zp.z) / (double)(z_range);
+    z = z * c->zrange + c->zmin;
+    v->zp.z = (int)((1.0 - z) * (double)(z_range)) + 1;
+  }
 
   /* color */
   v->zp.r=(int)(v->color.v[0] * (ZB_POINT_RED_MAX - ZB_POINT_RED_MIN) 

+ 3 - 0
panda/src/tinydisplay/init.cxx

@@ -57,6 +57,9 @@ void glInit(GLContext *c, ZBuffer *zbuffer)
   /* depth test */
   c->depth_test = 0;
   c->zbias = 0;
+  c->has_zrange = 0;
+  c->zmin = 0.0;
+  c->zrange = 1.0;
 }
 
 void glClose(GLContext *c)

+ 10 - 0
panda/src/tinydisplay/tinyGraphicsStateGuardian.cxx

@@ -2117,6 +2117,16 @@ do_issue_depth_offset() {
   const DepthOffsetAttrib *target_depth_offset = DCAST(DepthOffsetAttrib, _target_rs->get_attrib_def(DepthOffsetAttrib::get_class_slot()));
   int offset = target_depth_offset->get_offset();
   _c->zbias = offset;
+
+  PN_stdfloat min_value = target_depth_offset->get_min_value();
+  PN_stdfloat max_value = target_depth_offset->get_max_value();
+  if (min_value == 0.0f && max_value == 1.0f) {
+    _c->has_zrange = false;
+  } else {
+    _c->has_zrange = true;
+    _c->zmin = min_value;
+    _c->zrange = max_value - min_value;
+  }
 }
 
 ////////////////////////////////////////////////////////////////////

+ 2 - 0
panda/src/tinydisplay/zgl.h

@@ -185,6 +185,8 @@ typedef struct GLContext {
   /* depth test */
   int depth_test;
   int zbias;
+  bool has_zrange;
+  double zmin, zrange;
   
   /* specular buffer. could probably be shared between contexts, 
     but that wouldn't be 100% thread safe */