Browse Source

Adding more code for shader generator and image postprocessing

Josh Yelon 18 years ago
parent
commit
da29b5e02f

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

@@ -894,12 +894,25 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name, LMatrix4f
                                  0.0);
                                  0.0);
     return &t;
     return &t;
   }
   }
-  case Shader::SMO_card_center: {
-    int px = _current_display_region->get_pixel_width();
-    int py = _current_display_region->get_pixel_height();
-    t = LMatrix4f::translate_mat((px*0.5) / Texture::up_to_power_2(px),
-                                 (py*0.5) / Texture::up_to_power_2(py),
-                                 0.0);
+  case Shader::SMO_texpad_x: {
+    Texture *tex = _target._shader->get_shader_input_texture(name);
+    nassertr(tex != 0, &LMatrix4f::zeros_mat());
+    int sx = tex->get_x_size() - tex->get_pad_x_size();
+    int sy = tex->get_y_size() - tex->get_pad_y_size();
+    int sz = tex->get_z_size() - tex->get_pad_z_size();
+    double cx = (sx * 0.5) / tex->get_x_size();
+    double cy = (sy * 0.5) / tex->get_y_size();
+    double cz = (sz * 0.5) / tex->get_z_size();
+    t = LMatrix4f(0,0,0,0,0,0,0,0,0,0,0,0,cx,cy,cz,0);
+    return &t;
+  }
+  case Shader::SMO_texpix_x: {
+    Texture *tex = _target._shader->get_shader_input_texture(name);
+    nassertr(tex != 0, &LMatrix4f::zeros_mat());
+    double px = 1.0 / tex->get_x_size();
+    double py = 1.0 / tex->get_y_size();
+    double pz = 1.0 / tex->get_z_size();
+    t = LMatrix4f(0,0,0,0,0,0,0,0,0,0,0,0,px,py,pz,0);
     return &t;
     return &t;
   }
   }
   case Shader::SMO_attr_material: {
   case Shader::SMO_attr_material: {

+ 45 - 7
panda/src/gobj/shader.cxx

@@ -348,7 +348,9 @@ cp_dependency(ShaderMatInput inp) {
       (inp == SMO_view_to_model)) {
       (inp == SMO_view_to_model)) {
     dep |= SSD_transform;
     dep |= SSD_transform;
   }
   }
-  if ((inp == SMO_alight_x)||
+  if ((inp == SMO_texpad_x)||
+      (inp == SMO_texpix_x)||
+      (inp == SMO_alight_x)||
       (inp == SMO_dlight_x)||
       (inp == SMO_dlight_x)||
       (inp == SMO_plight_x)||
       (inp == SMO_plight_x)||
       (inp == SMO_slight_x)||
       (inp == SMO_slight_x)||
@@ -789,12 +791,6 @@ compile_parameter(const ShaderArgId  &arg_id,
       }
       }
       bind._part[0] = SMO_window_size;
       bind._part[0] = SMO_window_size;
       bind._arg[0] = NULL;
       bind._arg[0] = NULL;
-    } else if (pieces[1] == "cardcenter") {
-      if (!cp_errchk_parameter_float(p, 2, 2)) {
-        return false;
-      }
-      bind._part[0] = SMO_card_center;
-      bind._arg[0] = NULL;
     } else {
     } else {
       cp_report_error(p,"unknown system parameter");
       cp_report_error(p,"unknown system parameter");
       return false;
       return false;
@@ -909,6 +905,48 @@ compile_parameter(const ShaderArgId  &arg_id,
     return true;
     return true;
   }
   }
 
 
+  // Keywords to fetch texture parameter data.
+  
+  if (pieces[0] == "texpad") {
+    if ((!cp_errchk_parameter_words(p,2)) ||
+        (!cp_errchk_parameter_in(p)) ||
+        (!cp_errchk_parameter_uniform(p))||
+        (!cp_errchk_parameter_float(p,3,4))) {
+      return false;
+    }
+    ShaderMatSpec bind;
+    bind._id = arg_id;
+    bind._piece = SMP_row3;
+    bind._func = SMF_first;
+    bind._part[0] = SMO_texpad_x;
+    bind._arg[0] = InternalName::make(pieces[1]);
+    bind._part[1] = SMO_identity;
+    bind._arg[1] = NULL;
+    cp_optimize_mat_spec(bind);
+    _mat_spec.push_back(bind);
+    return true;
+  }
+
+  if (pieces[0] == "texpix") {
+    if ((!cp_errchk_parameter_words(p,2)) ||
+        (!cp_errchk_parameter_in(p)) ||
+        (!cp_errchk_parameter_uniform(p))||
+        (!cp_errchk_parameter_float(p,2,4))) {
+      return false;
+    }
+    ShaderMatSpec bind;
+    bind._id = arg_id;
+    bind._piece = SMP_row3;
+    bind._func = SMF_first;
+    bind._part[0] = SMO_texpix_x;
+    bind._arg[0] = InternalName::make(pieces[1]);
+    bind._part[1] = SMO_identity;
+    bind._arg[1] = NULL;
+    cp_optimize_mat_spec(bind);
+    _mat_spec.push_back(bind);
+    return true;
+  }
+
   if (pieces[0] == "l") {
   if (pieces[0] == "l") {
     // IMPLEMENT THE ERROR CHECKING
     // IMPLEMENT THE ERROR CHECKING
     return true; // Cg handles this automatically.
     return true; // Cg handles this automatically.

+ 2 - 1
panda/src/gobj/shader.h

@@ -70,7 +70,8 @@ public:
 
 
     SMO_window_size,
     SMO_window_size,
     SMO_pixel_size,
     SMO_pixel_size,
-    SMO_card_center,
+    SMO_texpad_x,
+    SMO_texpix_x,
     
     
     SMO_attr_material,
     SMO_attr_material,
     SMO_attr_color,
     SMO_attr_color,

+ 1 - 0
panda/src/pgraph/attribSlots.I

@@ -27,6 +27,7 @@ clear_to_zero() {
   _alpha_test     = NULL;
   _alpha_test     = NULL;
   _antialias      = NULL;
   _antialias      = NULL;
   _audio_volume   = NULL;
   _audio_volume   = NULL;
+  _aux_bitplane   = NULL;
   _clip_plane     = NULL;
   _clip_plane     = NULL;
   _color          = NULL;
   _color          = NULL;
   _color_blend    = NULL;
   _color_blend    = NULL;

+ 28 - 23
panda/src/pgraph/attribSlots.cxx

@@ -35,6 +35,7 @@ initialize_defvals() {
   _defvals._alpha_test     = DCAST(AlphaTestAttrib,AlphaTestAttrib::make(AlphaTestAttrib::M_none, 0.0));
   _defvals._alpha_test     = DCAST(AlphaTestAttrib,AlphaTestAttrib::make(AlphaTestAttrib::M_none, 0.0));
   _defvals._antialias      = DCAST(AntialiasAttrib,AntialiasAttrib::make(AntialiasAttrib::M_none));
   _defvals._antialias      = DCAST(AntialiasAttrib,AntialiasAttrib::make(AntialiasAttrib::M_none));
   _defvals._audio_volume   = DCAST(AudioVolumeAttrib,AudioVolumeAttrib::make_identity());
   _defvals._audio_volume   = DCAST(AudioVolumeAttrib,AudioVolumeAttrib::make_identity());
+  _defvals._aux_bitplane   = DCAST(AuxBitplaneAttrib,AuxBitplaneAttrib::make());
   _defvals._clip_plane     = DCAST(ClipPlaneAttrib,ClipPlaneAttrib::make_all_off());
   _defvals._clip_plane     = DCAST(ClipPlaneAttrib,ClipPlaneAttrib::make_all_off());
   _defvals._color          = DCAST(ColorAttrib,ColorAttrib::make_off());
   _defvals._color          = DCAST(ColorAttrib,ColorAttrib::make_off());
   _defvals._color_blend    = DCAST(ColorBlendAttrib,ColorBlendAttrib::make_off());
   _defvals._color_blend    = DCAST(ColorBlendAttrib,ColorBlendAttrib::make_off());
@@ -64,6 +65,7 @@ initialize_defvals() {
   _defvals._alpha_test     = DCAST(AlphaTestAttrib,_defvals._alpha_test->make_default());
   _defvals._alpha_test     = DCAST(AlphaTestAttrib,_defvals._alpha_test->make_default());
   _defvals._antialias      = DCAST(AntialiasAttrib,_defvals._antialias->make_default());
   _defvals._antialias      = DCAST(AntialiasAttrib,_defvals._antialias->make_default());
   _defvals._audio_volume   = DCAST(AudioVolumeAttrib,_defvals._audio_volume->make_default());
   _defvals._audio_volume   = DCAST(AudioVolumeAttrib,_defvals._audio_volume->make_default());
+  _defvals._aux_bitplane   = DCAST(AuxBitplaneAttrib,_defvals._aux_bitplane->make_default());
   _defvals._clip_plane     = DCAST(ClipPlaneAttrib,_defvals._clip_plane->make_default());
   _defvals._clip_plane     = DCAST(ClipPlaneAttrib,_defvals._clip_plane->make_default());
   _defvals._color          = DCAST(ColorAttrib,_defvals._color->make_default());
   _defvals._color          = DCAST(ColorAttrib,_defvals._color->make_default());
   _defvals._color_blend    = DCAST(ColorBlendAttrib,_defvals._color_blend->make_default());
   _defvals._color_blend    = DCAST(ColorBlendAttrib,_defvals._color_blend->make_default());
@@ -108,6 +110,7 @@ AttribSlots(const AttribSlots &copy) :
   _alpha_test(copy._alpha_test),
   _alpha_test(copy._alpha_test),
   _antialias(copy._antialias),
   _antialias(copy._antialias),
   _audio_volume(copy._audio_volume),
   _audio_volume(copy._audio_volume),
+  _aux_bitplane(copy._aux_bitplane),
   _clip_plane(copy._clip_plane),
   _clip_plane(copy._clip_plane),
   _color(copy._color),
   _color(copy._color),
   _color_blend(copy._color_blend),
   _color_blend(copy._color_blend),
@@ -144,6 +147,7 @@ operator =(const AttribSlots &src) {
   _alpha_test     = src._alpha_test;
   _alpha_test     = src._alpha_test;
   _antialias      = src._antialias;
   _antialias      = src._antialias;
   _audio_volume   = src._audio_volume;
   _audio_volume   = src._audio_volume;
+  _aux_bitplane   = src._aux_bitplane;
   _clip_plane     = src._clip_plane;
   _clip_plane     = src._clip_plane;
   _color          = src._color;
   _color          = src._color;
   _color_blend    = src._color_blend;
   _color_blend    = src._color_blend;
@@ -180,29 +184,30 @@ get_slot(int n) const {
   case  0: return DCAST(RenderAttrib, _alpha_test);
   case  0: return DCAST(RenderAttrib, _alpha_test);
   case  1: return DCAST(RenderAttrib, _antialias);
   case  1: return DCAST(RenderAttrib, _antialias);
   case  2: return DCAST(RenderAttrib, _audio_volume);
   case  2: return DCAST(RenderAttrib, _audio_volume);
-  case  3: return DCAST(RenderAttrib, _clip_plane);
-  case  4: return DCAST(RenderAttrib, _color);
-  case  5: return DCAST(RenderAttrib, _color_blend);
-  case  6: return DCAST(RenderAttrib, _color_scale);
-  case  7: return DCAST(RenderAttrib, _color_write);
-  case  8: return DCAST(RenderAttrib, _cull_bin);
-  case  9: return DCAST(RenderAttrib, _cull_face);
-  case 10: return DCAST(RenderAttrib, _depth_offset);
-  case 11: return DCAST(RenderAttrib, _depth_test);
-  case 12: return DCAST(RenderAttrib, _depth_write);
-  case 13: return DCAST(RenderAttrib, _fog);
-  case 14: return DCAST(RenderAttrib, _light);
-  case 15: return DCAST(RenderAttrib, _light_ramp);
-  case 16: return DCAST(RenderAttrib, _material);
-  case 17: return DCAST(RenderAttrib, _render_mode);
-  case 18: return DCAST(RenderAttrib, _rescale_normal);
-  case 19: return DCAST(RenderAttrib, _shade_model);
-  case 20: return DCAST(RenderAttrib, _shader);
-  case 21: return DCAST(RenderAttrib, _stencil);
-  case 22: return DCAST(RenderAttrib, _tex_gen);
-  case 23: return DCAST(RenderAttrib, _tex_matrix);
-  case 24: return DCAST(RenderAttrib, _texture);
-  case 25: return DCAST(RenderAttrib, _transparency);
+  case  3: return DCAST(RenderAttrib, _aux_bitplane);
+  case  4: return DCAST(RenderAttrib, _clip_plane);
+  case  5: return DCAST(RenderAttrib, _color);
+  case  6: return DCAST(RenderAttrib, _color_blend);
+  case  7: return DCAST(RenderAttrib, _color_scale);
+  case  8: return DCAST(RenderAttrib, _color_write);
+  case  9: return DCAST(RenderAttrib, _cull_bin);
+  case 10: return DCAST(RenderAttrib, _cull_face);
+  case 11: return DCAST(RenderAttrib, _depth_offset);
+  case 12: return DCAST(RenderAttrib, _depth_test);
+  case 13: return DCAST(RenderAttrib, _depth_write);
+  case 14: return DCAST(RenderAttrib, _fog);
+  case 15: return DCAST(RenderAttrib, _light);
+  case 16: return DCAST(RenderAttrib, _light_ramp);
+  case 17: return DCAST(RenderAttrib, _material);
+  case 18: return DCAST(RenderAttrib, _render_mode);
+  case 19: return DCAST(RenderAttrib, _rescale_normal);
+  case 20: return DCAST(RenderAttrib, _shade_model);
+  case 21: return DCAST(RenderAttrib, _shader);
+  case 22: return DCAST(RenderAttrib, _stencil);
+  case 23: return DCAST(RenderAttrib, _tex_gen);
+  case 24: return DCAST(RenderAttrib, _tex_matrix);
+  case 25: return DCAST(RenderAttrib, _texture);
+  case 26: return DCAST(RenderAttrib, _transparency);
   default:
   default:
     nassertr(false, NULL);
     nassertr(false, NULL);
     return NULL;
     return NULL;

+ 3 - 1
panda/src/pgraph/attribSlots.h

@@ -27,6 +27,7 @@
 #include "alphaTestAttrib.h"
 #include "alphaTestAttrib.h"
 #include "antialiasAttrib.h"
 #include "antialiasAttrib.h"
 #include "audioVolumeAttrib.h"
 #include "audioVolumeAttrib.h"
+#include "auxBitplaneAttrib.h"
 #include "clipPlaneAttrib.h"
 #include "clipPlaneAttrib.h"
 #include "colorAttrib.h"
 #include "colorAttrib.h"
 #include "colorBlendAttrib.h"
 #include "colorBlendAttrib.h"
@@ -63,6 +64,7 @@ class EXPCL_PANDA_PGRAPH AttribSlots
   CPT(AlphaTestAttrib)       _alpha_test;
   CPT(AlphaTestAttrib)       _alpha_test;
   CPT(AntialiasAttrib)       _antialias;
   CPT(AntialiasAttrib)       _antialias;
   CPT(AudioVolumeAttrib)     _audio_volume;
   CPT(AudioVolumeAttrib)     _audio_volume;
+  CPT(AuxBitplaneAttrib)     _aux_bitplane;
   CPT(ClipPlaneAttrib)       _clip_plane;
   CPT(ClipPlaneAttrib)       _clip_plane;
   CPT(ColorAttrib)           _color;
   CPT(ColorAttrib)           _color;
   CPT(ColorBlendAttrib)      _color_blend;
   CPT(ColorBlendAttrib)      _color_blend;
@@ -97,7 +99,7 @@ class EXPCL_PANDA_PGRAPH AttribSlots
 
 
  public:
  public:
   // Each "array" reference requires a switch and a DCAST, so it's not overly fast.
   // Each "array" reference requires a switch and a DCAST, so it's not overly fast.
-  enum { slot_count=26 };
+  enum { slot_count=27 };
   const RenderAttrib *get_slot(int n) const;
   const RenderAttrib *get_slot(int n) const;
 
 
  private:
  private:

+ 41 - 0
panda/src/pgraph/auxBitplaneAttrib.I

@@ -0,0 +1,41 @@
+// Filename: auxBitplaneAttrib.I
+// Created by:  drose (04Mar02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: AuxBitplaneAttrib::Constructor
+//       Access: Private
+//  Description: Use AuxBitplaneAttrib::make() to construct a new
+//               AuxBitplaneAttrib object.
+////////////////////////////////////////////////////////////////////
+INLINE AuxBitplaneAttrib::
+AuxBitplaneAttrib(int outputs) :
+  _outputs(outputs)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AuxBitplaneAttrib::get_outputs
+//       Access: Published
+//  Description: Returns the AuxBitplaneAttrib output bits.
+////////////////////////////////////////////////////////////////////
+INLINE int AuxBitplaneAttrib::
+get_outputs() const {
+  return _outputs;
+}
+

+ 175 - 0
panda/src/pgraph/auxBitplaneAttrib.cxx

@@ -0,0 +1,175 @@
+// Filename: auxBitplaneAttrib.cxx
+// Created by:  drose (04Mar02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "auxBitplaneAttrib.h"
+#include "attribSlots.h"
+#include "graphicsStateGuardianBase.h"
+#include "dcast.h"
+#include "bamReader.h"
+#include "bamWriter.h"
+#include "datagram.h"
+#include "datagramIterator.h"
+
+TypeHandle AuxBitplaneAttrib::_type_handle;
+CPT(RenderAttrib) AuxBitplaneAttrib::_default;
+
+////////////////////////////////////////////////////////////////////
+//     Function: AuxBitplaneAttrib::make
+//       Access: Published, Static
+//  Description: Constructs a default AuxBitplaneAttrib object.
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) AuxBitplaneAttrib::
+make() {
+  if (_default == 0) {
+    AuxBitplaneAttrib *attrib = new AuxBitplaneAttrib(ABO_color);
+    _default = return_new(attrib);
+  }
+  return _default;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AuxBitplaneAttrib::make
+//       Access: Published, Static
+//  Description: Constructs a specified AuxBitplaneAttrib object.
+////////////////////////////////////////////////////////////////////
+CPT(RenderAttrib) AuxBitplaneAttrib::
+make(int outputs) {
+  AuxBitplaneAttrib *attrib = new AuxBitplaneAttrib(outputs);
+  return return_new(attrib);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AuxBitplaneAttrib::output
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void AuxBitplaneAttrib::
+output(ostream &out) const {
+  out << get_type() << "(" << _outputs << ")";
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AuxBitplaneAttrib::compare_to_impl
+//       Access: Protected, Virtual
+//  Description: Intended to be overridden by derived AuxBitplaneAttrib
+//               types to return a unique number indicating whether
+//               this AuxBitplaneAttrib is equivalent to the other one.
+//
+//               This should return 0 if the two AuxBitplaneAttrib objects
+//               are equivalent, a number less than zero if this one
+//               should be sorted before the other one, and a number
+//               greater than zero otherwise.
+//
+//               This will only be called with two AuxBitplaneAttrib
+//               objects whose get_type() functions return the same.
+////////////////////////////////////////////////////////////////////
+int AuxBitplaneAttrib::
+compare_to_impl(const RenderAttrib *other) const {
+  const AuxBitplaneAttrib *ta;
+  DCAST_INTO_R(ta, other, 0);
+  int compare_result = _outputs - ta->_outputs;
+  if (compare_result!=0) {
+    return compare_result;
+  }
+  return 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AuxBitplaneAttrib::make_default_impl
+//       Access: Protected, Virtual
+//  Description: Intended to be overridden by derived AuxBitplaneAttrib
+//               types to specify what the default property for a
+//               AuxBitplaneAttrib of this type should be.
+//
+//               This should return a newly-allocated AuxBitplaneAttrib of
+//               the same type that corresponds to whatever the
+//               standard default for this kind of AuxBitplaneAttrib is.
+////////////////////////////////////////////////////////////////////
+RenderAttrib *AuxBitplaneAttrib::
+make_default_impl() const {
+  return new AuxBitplaneAttrib(ABO_color);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AuxBitplaneAttrib::store_into_slot
+//       Access: Public, Virtual
+//  Description: Stores this attrib into the appropriate slot of
+//               an object of class AttribSlots.
+////////////////////////////////////////////////////////////////////
+void AuxBitplaneAttrib::
+store_into_slot(AttribSlots *slots) const {
+  slots->_aux_bitplane = this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AuxBitplaneAttrib::register_with_read_factory
+//       Access: Public, Static
+//  Description: Tells the BamReader how to create objects of type
+//               AuxBitplaneAttrib.
+////////////////////////////////////////////////////////////////////
+void AuxBitplaneAttrib::
+register_with_read_factory() {
+  BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AuxBitplaneAttrib::write_datagram
+//       Access: Public, Virtual
+//  Description: Writes the contents of this object to the datagram
+//               for shipping out to a Bam file.
+////////////////////////////////////////////////////////////////////
+void AuxBitplaneAttrib::
+write_datagram(BamWriter *manager, Datagram &dg) {
+  RenderAttrib::write_datagram(manager, dg);
+
+  dg.add_int32(_outputs);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AuxBitplaneAttrib::make_from_bam
+//       Access: Protected, Static
+//  Description: This function is called by the BamReader's factory
+//               when a new object of type AuxBitplaneAttrib is encountered
+//               in the Bam file.  It should create the AuxBitplaneAttrib
+//               and extract its information from the file.
+////////////////////////////////////////////////////////////////////
+TypedWritable *AuxBitplaneAttrib::
+make_from_bam(const FactoryParams &params) {
+  AuxBitplaneAttrib *attrib = new AuxBitplaneAttrib(0);
+  DatagramIterator scan;
+  BamReader *manager;
+
+  parse_params(params, scan, manager);
+  attrib->fillin(scan, manager);
+  
+  return attrib;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AuxBitplaneAttrib::fillin
+//       Access: Protected
+//  Description: This internal function is called by make_from_bam to
+//               read in all of the relevant data from the BamFile for
+//               the new AuxBitplaneAttrib.
+////////////////////////////////////////////////////////////////////
+void AuxBitplaneAttrib::
+fillin(DatagramIterator &scan, BamReader *manager) {
+  RenderAttrib::fillin(scan, manager);
+
+  _outputs = scan.get_int32();
+}

+ 95 - 0
panda/src/pgraph/auxBitplaneAttrib.h

@@ -0,0 +1,95 @@
+// Filename: auxBitplaneAttrib.h
+// Created by:  drose (04Mar02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef AUXBITPLANEATTRIB_H
+#define AUXBITPLANEATTRIB_H
+
+#include "pandabase.h"
+#include "renderAttrib.h"
+
+class FactoryParams;
+
+////////////////////////////////////////////////////////////////////
+//       Class : AuxBitplaneAttrib
+// Description : Modern frame buffers can have 'aux' bitplanes, which
+//               are additional bitplanes above and beyond the
+//               standard depth and color.  This attrib controls what
+//               gets rendered into those additional bitplanes when
+//               using the standard shader generator.
+//
+//               AuxBitplaneAttrib is relevant only when shader
+//               generation is enabled. Otherwise, it has no effect.
+//
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDA_PGRAPH AuxBitplaneAttrib : public RenderAttrib {
+private:
+  INLINE AuxBitplaneAttrib(int outputs);
+
+PUBLISHED:
+  enum AuxBitplaneOutput {
+    ABO_color = 1,     // The usual.
+    ABO_csnormal = 2,  // Camera space normal.
+  };
+  static CPT(RenderAttrib) make();
+  static CPT(RenderAttrib) make(int outputs);
+  
+  INLINE int get_outputs() const;
+  
+public:
+  virtual void output(ostream &out) const;
+  virtual void store_into_slot(AttribSlots *slots) const;
+  
+protected:
+  virtual int compare_to_impl(const RenderAttrib *other) const;
+  virtual RenderAttrib *make_default_impl() const;
+  
+private:
+  int _outputs;
+
+  static CPT(RenderAttrib) AuxBitplaneAttrib::_default;
+
+public:
+  static void register_with_read_factory();
+  virtual void write_datagram(BamWriter *manager, Datagram &dg);
+
+protected:
+  static TypedWritable *make_from_bam(const FactoryParams &params);
+  void fillin(DatagramIterator &scan, BamReader *manager);
+  
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    RenderAttrib::init_type();
+    register_type(_type_handle, "AuxBitplaneAttrib",
+                  RenderAttrib::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
+
+private:
+  static TypeHandle _type_handle;
+};
+
+#include "auxBitplaneAttrib.I"
+
+#endif
+

+ 3 - 0
panda/src/pgraph/config_pgraph.cxx

@@ -20,6 +20,7 @@
 
 
 #include "alphaTestAttrib.h"
 #include "alphaTestAttrib.h"
 #include "audioVolumeAttrib.h"
 #include "audioVolumeAttrib.h"
+#include "auxBitplaneAttrib.h"
 #include "ambientLight.h"
 #include "ambientLight.h"
 #include "antialiasAttrib.h"
 #include "antialiasAttrib.h"
 #include "auxSceneData.h"
 #include "auxSceneData.h"
@@ -373,6 +374,7 @@ init_libpgraph() {
   AmbientLight::init_type();
   AmbientLight::init_type();
   AntialiasAttrib::init_type();
   AntialiasAttrib::init_type();
   AudioVolumeAttrib::init_type();
   AudioVolumeAttrib::init_type();
+  AuxBitplaneAttrib::init_type();
   AuxSceneData::init_type();
   AuxSceneData::init_type();
   BillboardEffect::init_type();
   BillboardEffect::init_type();
   Camera::init_type();
   Camera::init_type();
@@ -462,6 +464,7 @@ init_libpgraph() {
   AmbientLight::register_with_read_factory();
   AmbientLight::register_with_read_factory();
   AntialiasAttrib::register_with_read_factory();
   AntialiasAttrib::register_with_read_factory();
   AudioVolumeAttrib::register_with_read_factory();
   AudioVolumeAttrib::register_with_read_factory();
+  AuxBitplaneAttrib::register_with_read_factory();
   BillboardEffect::register_with_read_factory();
   BillboardEffect::register_with_read_factory();
   Camera::register_with_read_factory();
   Camera::register_with_read_factory();
   ClipPlaneAttrib::register_with_read_factory();
   ClipPlaneAttrib::register_with_read_factory();

+ 1 - 2
panda/src/pgraph/lightRampAttrib.I

@@ -28,7 +28,6 @@ LightRampAttrib() {
   _mode = LRT_identity;
   _mode = LRT_identity;
   _level[0] = 0.0;
   _level[0] = 0.0;
   _level[1] = 0.0;
   _level[1] = 0.0;
-  _level[2] = 0.0;
   _threshold[0] = 0.0;
   _threshold[0] = 0.0;
   _threshold[1] = 0.0;
   _threshold[1] = 0.0;
 }
 }
@@ -50,7 +49,7 @@ get_mode() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE float LightRampAttrib::
 INLINE float LightRampAttrib::
 get_level(int n) const {
 get_level(int n) const {
-  if ((n<0)||(n>2)) return 0.0;
+  if ((n<0)||(n>1)) return 0.0;
   return _level[n];
   return _level[n];
 }
 }
 
 

+ 8 - 10
panda/src/pgraph/lightRampAttrib.cxx

@@ -48,12 +48,11 @@ make_identity() {
 //  Description: Constructs a new LightRampAttrib object.
 //  Description: Constructs a new LightRampAttrib object.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 CPT(RenderAttrib) LightRampAttrib::
 CPT(RenderAttrib) LightRampAttrib::
-make_single_threshold(float val0, float val1, float thresh0) {
+make_single_threshold(float thresh0, float val0) {
   LightRampAttrib *attrib = new LightRampAttrib();
   LightRampAttrib *attrib = new LightRampAttrib();
   attrib->_mode = LRT_single_threshold;
   attrib->_mode = LRT_single_threshold;
-  attrib->_level[0] = val0;
-  attrib->_level[1] = val1;
   attrib->_threshold[0] = thresh0;
   attrib->_threshold[0] = thresh0;
+  attrib->_level[0] = val0;
   return return_new(attrib);
   return return_new(attrib);
 }
 }
 
 
@@ -63,14 +62,13 @@ make_single_threshold(float val0, float val1, float thresh0) {
 //  Description: Constructs a new LightRampAttrib object.
 //  Description: Constructs a new LightRampAttrib object.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 CPT(RenderAttrib) LightRampAttrib::
 CPT(RenderAttrib) LightRampAttrib::
-make_double_threshold(float val0, float val1, float val2, float thresh0, float thresh1) {
+make_double_threshold(float thresh0, float val0, float thresh1, float val1) {
   LightRampAttrib *attrib = new LightRampAttrib();
   LightRampAttrib *attrib = new LightRampAttrib();
   attrib->_mode = LRT_single_threshold;
   attrib->_mode = LRT_single_threshold;
-  attrib->_level[0] = val0;
-  attrib->_level[1] = val1;
-  attrib->_level[2] = val2;
   attrib->_threshold[0] = thresh0;
   attrib->_threshold[0] = thresh0;
+  attrib->_level[0] = val0;
   attrib->_threshold[1] = thresh1;
   attrib->_threshold[1] = thresh1;
+  attrib->_level[1] = val1;
   return return_new(attrib);
   return return_new(attrib);
 }
 }
 
 
@@ -118,7 +116,7 @@ compare_to_impl(const RenderAttrib *other) const {
   if (compare_result!=0) {
   if (compare_result!=0) {
     return compare_result;
     return compare_result;
   }
   }
-  for (int i=0; i<3; i++) {
+  for (int i=0; i<2; i++) {
     compare_result = _level[i] - ta->_level[i];
     compare_result = _level[i] - ta->_level[i];
     if (compare_result!=0) {
     if (compare_result!=0) {
       return compare_result;
       return compare_result;
@@ -182,7 +180,7 @@ write_datagram(BamWriter *manager, Datagram &dg) {
   RenderAttrib::write_datagram(manager, dg);
   RenderAttrib::write_datagram(manager, dg);
 
 
   dg.add_int8(_mode);
   dg.add_int8(_mode);
-  for (int i=0; i<3; i++) {
+  for (int i=0; i<2; i++) {
     dg.add_float32(_level[i]);
     dg.add_float32(_level[i]);
   }
   }
   for (int i=0; i<2; i++) {
   for (int i=0; i<2; i++) {
@@ -222,7 +220,7 @@ fillin(DatagramIterator &scan, BamReader *manager) {
   RenderAttrib::fillin(scan, manager);
   RenderAttrib::fillin(scan, manager);
 
 
   _mode = (LightRampMode)scan.get_int8();
   _mode = (LightRampMode)scan.get_int8();
-  for (int i=0; i<3; i++) {
+  for (int i=0; i<2; i++) {
     _level[i] = scan.get_float32();
     _level[i] = scan.get_float32();
   }
   }
   for (int i=0; i<2; i++) {
   for (int i=0; i<2; i++) {

+ 6 - 4
panda/src/pgraph/lightRampAttrib.h

@@ -33,7 +33,9 @@ class FactoryParams;
 //
 //
 //               LightRampAttrib is relevant only when lighting and
 //               LightRampAttrib is relevant only when lighting and
 //               shader generation are both enabled. Otherwise, it has
 //               shader generation are both enabled. Otherwise, it has
-//               no effect.
+//               no effect.  The light ramp only affects the diffuse
+//               contribution.  Ambient light is not ramped.
+//
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDA_PGRAPH LightRampAttrib : public RenderAttrib {
 class EXPCL_PANDA_PGRAPH LightRampAttrib : public RenderAttrib {
 private:
 private:
@@ -46,8 +48,8 @@ PUBLISHED:
     LRT_double_threshold,
     LRT_double_threshold,
   };
   };
   static CPT(RenderAttrib) make_identity();
   static CPT(RenderAttrib) make_identity();
-  static CPT(RenderAttrib) make_single_threshold(float lev0, float lev1, float thresh0);
-  static CPT(RenderAttrib) make_double_threshold(float lev0, float lev1, float lev2, float thresh0, float thresh1);
+  static CPT(RenderAttrib) make_single_threshold(float thresh0, float lev0);
+  static CPT(RenderAttrib) make_double_threshold(float thresh0, float lev0, float thresh1, float lev1);
   
   
   INLINE LightRampMode get_mode() const;
   INLINE LightRampMode get_mode() const;
   INLINE float get_level(int n) const;
   INLINE float get_level(int n) const;
@@ -63,7 +65,7 @@ protected:
   
   
 private:
 private:
   LightRampMode _mode;
   LightRampMode _mode;
-  float _level[3];
+  float _level[2];
   float _threshold[2];
   float _threshold[2];
 
 
   static CPT(RenderAttrib) LightRampAttrib::_identity;
   static CPT(RenderAttrib) LightRampAttrib::_identity;

+ 1 - 0
panda/src/pgraph/pgraph_composite1.cxx

@@ -3,6 +3,7 @@
 #include "antialiasAttrib.cxx"
 #include "antialiasAttrib.cxx"
 #include "attribNodeRegistry.cxx"
 #include "attribNodeRegistry.cxx"
 #include "audioVolumeAttrib.cxx"
 #include "audioVolumeAttrib.cxx"
+#include "auxBitplaneAttrib.cxx"
 #include "auxSceneData.cxx"
 #include "auxSceneData.cxx"
 #include "attribSlots.cxx"
 #include "attribSlots.cxx"
 #include "bamFile.cxx"
 #include "bamFile.cxx"

+ 76 - 31
panda/src/pgraph/shaderGenerator.cxx

@@ -146,6 +146,16 @@ analyze_renderstate(const RenderState *rs) {
 
 
   rs->store_into_slots(&_attribs);
   rs->store_into_slots(&_attribs);
 
 
+  // Figure out which bitplane should hold which output.
+  
+  int next = 0;
+  if (_attribs._aux_bitplane->get_outputs() & AuxBitplaneAttrib::ABO_color) {
+    _bitplane_color = next++;
+  }
+  if (_attribs._aux_bitplane->get_outputs() & AuxBitplaneAttrib::ABO_csnormal) {
+    _bitplane_normal = next++;
+  }
+
   // Count number of textures.
   // Count number of textures.
 
 
   _num_textures = 0;
   _num_textures = 0;
@@ -155,7 +165,7 @@ analyze_renderstate(const RenderState *rs) {
   
   
   // Determine whether or not vertex colors or flat colors are present.
   // Determine whether or not vertex colors or flat colors are present.
 
 
-  if (_attribs._color != 0) {
+  if ((_bitplane_color >= 0)&&(_attribs._color != 0)) {
     if (_attribs._color->get_color_type() == ColorAttrib::T_vertex) {
     if (_attribs._color->get_color_type() == ColorAttrib::T_vertex) {
       _vertex_colors = true;
       _vertex_colors = true;
     } else if (_attribs._color->get_color_type() == ColorAttrib::T_flat) {
     } else if (_attribs._color->get_color_type() == ColorAttrib::T_flat) {
@@ -211,10 +221,11 @@ analyze_renderstate(const RenderState *rs) {
   
   
   // Determine whether lighting is needed.
   // Determine whether lighting is needed.
 
 
-  if (_attribs._light->get_num_on_lights() > 0) {
+  if ((_bitplane_color >= 0) &&
+      (_attribs._light->get_num_on_lights() > 0)) {
     _lighting = true;
     _lighting = true;
   }
   }
-
+  
   // Find the material.
   // Find the material.
 
 
   if (!_attribs._material->is_off()) {
   if (!_attribs._material->is_off()) {
@@ -225,7 +236,7 @@ analyze_renderstate(const RenderState *rs) {
   
   
   // Decide which material modes need to be calculated.
   // Decide which material modes need to be calculated.
   
   
-  if (_alights.size() > 0) {
+  if (_lighting && (_alights.size() > 0)) {
     if (_material->has_ambient()) {
     if (_material->has_ambient()) {
       Colorf a = _material->get_ambient();
       Colorf a = _material->get_ambient();
       if ((a[0]!=0.0)||(a[1]!=0.0)||(a[2]!=0.0)) {
       if ((a[0]!=0.0)||(a[1]!=0.0)||(a[2]!=0.0)) {
@@ -236,7 +247,7 @@ analyze_renderstate(const RenderState *rs) {
     }
     }
   }
   }
 
 
-  if (_dlights.size() + _plights.size() + _slights.size()) {
+  if (_lighting && (_dlights.size() + _plights.size() + _slights.size())) {
     if (_material->has_diffuse()) {
     if (_material->has_diffuse()) {
       Colorf d = _material->get_diffuse();
       Colorf d = _material->get_diffuse();
       if ((d[0]!=0.0)||(d[1]!=0.0)||(d[2]!=0.0)) {
       if ((d[0]!=0.0)||(d[1]!=0.0)||(d[2]!=0.0)) {
@@ -247,14 +258,14 @@ analyze_renderstate(const RenderState *rs) {
     }
     }
   }
   }
   
   
-  if (_material->has_emission()) {
+  if (_lighting && (_material->has_emission())) {
     Colorf e = _material->get_emission();
     Colorf e = _material->get_emission();
     if ((e[0]!=0.0)||(e[1]!=0.0)||(e[2]!=0.0)) {
     if ((e[0]!=0.0)||(e[1]!=0.0)||(e[2]!=0.0)) {
       _have_emission = true;
       _have_emission = true;
     }
     }
   }
   }
   
   
-  if (_dlights.size() + _plights.size() + _slights.size()) {
+  if (_lighting && (_dlights.size() + _plights.size() + _slights.size())) {
     if (_material->has_specular()) {
     if (_material->has_specular()) {
       Colorf s = _material->get_specular();
       Colorf s = _material->get_specular();
       if ((s[0]!=0.0)||(s[1]!=0.0)||(s[2]!=0.0)) {
       if ((s[0]!=0.0)||(s[1]!=0.0)||(s[2]!=0.0)) {
@@ -283,13 +294,11 @@ analyze_renderstate(const RenderState *rs) {
     }
     }
   }
   }
 
 
-  if (_attribs._light_ramp->get_mode() != LightRampAttrib::LRT_identity) {
-    if (_separate_ambient_diffuse) {
-      pgraph_cat.error() << "Light Ramp incompatible with separate ambient/diffuse\n";
-      _separate_ambient_diffuse = false;
-    }
+  if (_lighting && 
+      (_attribs._light_ramp->get_mode() != LightRampAttrib::LRT_identity)) {
+    _separate_ambient_diffuse = true;
   }
   }
-
+  
   // Does the shader need material properties as input?
   // Does the shader need material properties as input?
   
   
   _need_material_props = 
   _need_material_props = 
@@ -322,8 +331,11 @@ clear_analysis() {
   _map_index_height = -1;
   _map_index_height = -1;
   _map_index_glow = -1;
   _map_index_glow = -1;
   _map_index_gloss = -1;
   _map_index_gloss = -1;
+  _bitplane_color = -1;
+  _bitplane_normal = -1;
   _attribs.clear_to_defaults();
   _attribs.clear_to_defaults();
   _material = (Material*)NULL;
   _material = (Material*)NULL;
+  _need_material_props = false;
   _alights.clear();
   _alights.clear();
   _dlights.clear();
   _dlights.clear();
   _plights.clear();
   _plights.clear();
@@ -391,6 +403,9 @@ create_shader_attrib(const string &txt) {
 //               - other TextureStage::Modes
 //               - other TextureStage::Modes
 //               - cartoon thresholding and other special effects
 //               - cartoon thresholding and other special effects
 //
 //
+//               Potential optimizations
+//               - omit attenuation calculations if attenuation off
+//
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 CPT(RenderAttrib) ShaderGenerator::
 CPT(RenderAttrib) ShaderGenerator::
 synthesize_shader(const RenderState *rs) {
 synthesize_shader(const RenderState *rs) {
@@ -406,15 +421,16 @@ synthesize_shader(const RenderState *rs) {
   char *tangent_freg = 0;
   char *tangent_freg = 0;
   char *binormal_vreg = 0;
   char *binormal_vreg = 0;
   char *binormal_freg = 0;
   char *binormal_freg = 0;
+  char *csnormal_freg = 0;
   pvector<char *> texcoord_vreg;
   pvector<char *> texcoord_vreg;
   pvector<char *> texcoord_freg;
   pvector<char *> texcoord_freg;
   pvector<char *> tslightvec_freg;
   pvector<char *> tslightvec_freg;
-
+  
   if (_vertex_colors) {
   if (_vertex_colors) {
     _vcregs_used = 1;
     _vcregs_used = 1;
     _fcregs_used = 1;
     _fcregs_used = 1;
   }
   }
-  
+
   // Generate the shader's text.
   // Generate the shader's text.
 
 
   ostringstream text;
   ostringstream text;
@@ -450,6 +466,15 @@ synthesize_shader(const RenderState *rs) {
       text << "\t out float4 l_binormal : " << binormal_freg << ",\n";
       text << "\t out float4 l_binormal : " << binormal_freg << ",\n";
     }
     }
   }
   }
+  if (_bitplane_normal >= 0) {
+    if (normal_vreg == 0) {
+      normal_vreg = alloc_vreg();
+      text << "\t in float4 vtx_normal : " << normal_vreg << ",\n";
+    }
+    csnormal_freg = alloc_freg();
+    text << "\t uniform float4x4 itp_modelview,\n";
+    text << "\t out float4 l_csnormal : " << csnormal_freg << ",\n";
+  }
   
   
   text << "\t float4 vtx_position : POSITION,\n";
   text << "\t float4 vtx_position : POSITION,\n";
   text << "\t out float4 l_position : POSITION,\n";
   text << "\t out float4 l_position : POSITION,\n";
@@ -467,11 +492,15 @@ synthesize_shader(const RenderState *rs) {
   if (_lighting) {
   if (_lighting) {
     text << "\t l_pos = vtx_position;\n";
     text << "\t l_pos = vtx_position;\n";
     text << "\t l_normal = vtx_normal;\n";
     text << "\t l_normal = vtx_normal;\n";
-    if (_map_index_normal) {
+    if (_map_index_normal >= 0) {
       text << "\t l_tangent = vtx_tangent" << _map_index_normal << ";\n";
       text << "\t l_tangent = vtx_tangent" << _map_index_normal << ";\n";
       text << "\t l_binormal = -vtx_binormal" << _map_index_normal << ";\n";
       text << "\t l_binormal = -vtx_binormal" << _map_index_normal << ";\n";
     }
     }
   }
   }
+  if (_bitplane_normal >= 0) {
+    text << "\t l_csnormal.xyz = mul(itp_modelview, vtx_normal);\n";
+    text << "\t l_csnormal.w = 0;\n";
+  }
   text << "}\n\n";
   text << "}\n\n";
   
   
   text << "void fshader(\n";
   text << "void fshader(\n";
@@ -480,17 +509,14 @@ synthesize_shader(const RenderState *rs) {
     text << "\t in float4 l_texcoord" << i << " : " << texcoord_freg[i] << ",\n";
     text << "\t in float4 l_texcoord" << i << " : " << texcoord_freg[i] << ",\n";
     text << "\t uniform sampler2D tex_" << i << ",\n";
     text << "\t uniform sampler2D tex_" << i << ",\n";
   }
   }
-  if (_vertex_colors) {
-    text << "\t in float4 l_color : COLOR,\n";
-  } else {
-    text << "\t uniform float4 attr_color,\n";
-  }
   if (_lighting) {
   if (_lighting) {
     text << "\t in float3 l_normal : " << normal_freg << ",\n";
     text << "\t in float3 l_normal : " << normal_freg << ",\n";
-    if (_map_index_normal) {
+    if (_map_index_normal >= 0) {
       text << "\t in float3 l_tangent : " << tangent_freg << ",\n";
       text << "\t in float3 l_tangent : " << tangent_freg << ",\n";
       text << "\t in float3 l_binormal : " << binormal_freg << ",\n";
       text << "\t in float3 l_binormal : " << binormal_freg << ",\n";
     }
     }
+  }
+  if (_lighting) {
     text << "\t in float4 l_pos : " << pos_freg << ",\n";
     text << "\t in float4 l_pos : " << pos_freg << ",\n";
     for (int i=0; i<(int)_alights.size(); i++) {
     for (int i=0; i<(int)_alights.size(); i++) {
       text << "\t uniform float4 alight_alight" << i << ",\n";
       text << "\t uniform float4 alight_alight" << i << ",\n";
@@ -516,15 +542,28 @@ synthesize_shader(const RenderState *rs) {
       }
       }
     }
     }
   }
   }
-  text << "\t out float4 o_color : COLOR\n";
+  if (_bitplane_normal >= 0) {
+    text << "\t in float4 l_csnormal : " << csnormal_freg << ",\n";
+    text << "\t out float4 o_csnormal : COLOR" << _bitplane_normal << ",\n";
+  }
+  if (_bitplane_color >= 0) {
+    text << "\t out float4 o_color : COLOR" << _bitplane_color << ",\n";
+  }
+  if (_vertex_colors) {
+    text << "\t in float4 l_color : COLOR\n";
+  } else {
+    text << "\t uniform float4 attr_color\n";
+  }
   text << ") {\n";
   text << ") {\n";
+  if (_bitplane_color < 0) {
+    text << "float4 \t o_color;\n";
+  }
   text << "\t // Fetch all textures.\n";
   text << "\t // Fetch all textures.\n";
   for (int i=0; i<_num_textures; i++) {
   for (int i=0; i<_num_textures; i++) {
     text << "\t float4 tex" << i << " = tex2D(tex_" << i << ", float2(l_texcoord" << i << "));\n";
     text << "\t float4 tex" << i << " = tex2D(tex_" << i << ", float2(l_texcoord" << i << "));\n";
   }
   }
-  
   if (_lighting) {
   if (_lighting) {
-    if (_map_index_normal) {
+    if (_map_index_normal >= 0) {
       text << "\t // Translate tangent-space normal in map to model-space.\n";
       text << "\t // Translate tangent-space normal in map to model-space.\n";
       text << "\t float3 tsnormal = ((float3)tex" << _map_index_normal << " * 2) - 1;\n";
       text << "\t float3 tsnormal = ((float3)tex" << _map_index_normal << " * 2) - 1;\n";
       text << "\t l_normal = l_normal * tsnormal.z;\n";
       text << "\t l_normal = l_normal * tsnormal.z;\n";
@@ -535,6 +574,12 @@ synthesize_shader(const RenderState *rs) {
       text << "\t // Correct the surface normal for interpolation effects\n";
       text << "\t // Correct the surface normal for interpolation effects\n";
       text << "\t l_normal = normalize(l_normal);\n";
       text << "\t l_normal = normalize(l_normal);\n";
     }
     }
+  }
+  if (_bitplane_normal >= 0) {
+    text << "\t // Output the camera-space surface normal\n";
+    text << "\t o_csnormal = (normalize(l_csnormal)*0.5) + float4(0.5,0.5,0.5,0);\n";
+  }
+  if (_lighting) {
     text << "\t // Begin model-space light calculations\n";
     text << "\t // Begin model-space light calculations\n";
     text << "\t float ldist,lattenv,langle;\n";
     text << "\t float ldist,lattenv,langle;\n";
     text << "\t float4 lcolor,lspec,lvec,lpoint,latten,ldir,leye,lhalf;\n";
     text << "\t float4 lcolor,lspec,lvec,lpoint,latten,ldir,leye,lhalf;\n";
@@ -641,11 +686,10 @@ synthesize_shader(const RenderState *rs) {
       {
       {
         float t = _attribs._light_ramp->get_threshold(0);
         float t = _attribs._light_ramp->get_threshold(0);
         float l0 = _attribs._light_ramp->get_level(0);
         float l0 = _attribs._light_ramp->get_level(0);
-        float l1 = _attribs._light_ramp->get_level(1);
         text << "\t // Single-threshold light ramp\n";
         text << "\t // Single-threshold light ramp\n";
         text << "\t float lr_in = dot(tot_diffuse.rgb, float3(0.33,0.34,0.33));\n";
         text << "\t float lr_in = dot(tot_diffuse.rgb, float3(0.33,0.34,0.33));\n";
-        text << "\t float lr_out = (lr_in < " << t << ") ? " << l0 << ":" << l1 << ";\n";
-        text << "\t tot_diffuse = tot_diffuse * (lr_out / lr_in);\n";
+        text << "\t float lr_scale = (lr_in < " << t << ") ? 0.0 : (" << l0 << "/lr_in);\n";
+        text << "\t tot_diffuse = tot_diffuse * lr_scale;\n";
         break;
         break;
       }
       }
     case LightRampAttrib::LRT_double_threshold:
     case LightRampAttrib::LRT_double_threshold:
@@ -692,12 +736,13 @@ synthesize_shader(const RenderState *rs) {
         text << "\t o_color += tot_diffuse;\n";
         text << "\t o_color += tot_diffuse;\n";
       }
       }
     }
     }
+    // Use of lerp here is a workaround for a radeon driver bug.
     if (_vertex_colors) {
     if (_vertex_colors) {
-      text << "\t o_color.a = l_color.a;\n";
+      text << "\t o_color = lerp(o_color, l_color, float4(0,0,0,1));\n";
     } else if (_flat_colors) {
     } else if (_flat_colors) {
-      text << "\t o_color.a = attr_color.a;\n";
+      text << "\t o_color = lerp(o_color, attr_color, float4(0,0,0,1));\n";
     } else {
     } else {
-      text << "\t o_color.a = 1;\n";
+      text << "\t o_color.a = lerp(o_color, float4(1,1,1,1), float4(0,0,0,1));\n";
     }
     }
     text << "\t // End model-space light calculations\n";
     text << "\t // End model-space light calculations\n";
   } else {
   } else {

+ 3 - 0
panda/src/pgraph/shaderGenerator.h

@@ -118,6 +118,9 @@ protected:
   int _map_index_glow;
   int _map_index_glow;
   int _map_index_gloss;
   int _map_index_gloss;
   
   
+  int _bitplane_color;
+  int _bitplane_normal;
+  
   bool _need_material_props;
   bool _need_material_props;
   
   
   void analyze_renderstate(const RenderState *rs);
   void analyze_renderstate(const RenderState *rs);