Browse Source

Changes to light inheritance to allow shadows

rdb 16 years ago
parent
commit
801ddc8bb8

+ 2 - 2
panda/src/pgraph/camera.cxx

@@ -25,8 +25,8 @@ TypeHandle Camera::_type_handle;
 //  Description:
 ////////////////////////////////////////////////////////////////////
 Camera::
-Camera(const string &name) :
-  LensNode(name),
+Camera(const string &name, Lens *lens) :
+  LensNode(name, lens),
   _active(true),
   _camera_mask(~PandaNode::get_overall_bit()),
   _initial_state(RenderState::make_empty())

+ 2 - 1
panda/src/pgraph/camera.h

@@ -18,6 +18,7 @@
 #include "pandabase.h"
 
 #include "lensNode.h"
+#include "perspectiveLens.h"
 #include "nodePath.h"
 #include "weakNodePath.h"
 #include "drawMask.h"
@@ -35,7 +36,7 @@
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDA_PGRAPH Camera : public LensNode {
 PUBLISHED:
-  Camera(const string &name);
+  Camera(const string &name, Lens *lens = new PerspectiveLens());
   Camera(const Camera &copy);
 
 public:

+ 6 - 5
panda/src/pgraphnodes/directionalLight.cxx

@@ -13,6 +13,7 @@
 ////////////////////////////////////////////////////////////////////
 
 #include "directionalLight.h"
+#include "orthographicLens.h"
 #include "graphicsStateGuardianBase.h"
 #include "bamWriter.h"
 #include "bamReader.h"
@@ -65,7 +66,7 @@ fillin(DatagramIterator &scan, BamReader *) {
 ////////////////////////////////////////////////////////////////////
 DirectionalLight::
 DirectionalLight(const string &name) : 
-  LightNode(name) 
+  LightLensNode(name, new OrthographicLens())
 {
 }
 
@@ -78,7 +79,7 @@ DirectionalLight(const string &name) :
 ////////////////////////////////////////////////////////////////////
 DirectionalLight::
 DirectionalLight(const DirectionalLight &copy) :
-  LightNode(copy),
+  LightLensNode(copy),
   _cycler(copy._cycler)
 {
 }
@@ -106,7 +107,7 @@ make_copy() const {
 ////////////////////////////////////////////////////////////////////
 void DirectionalLight::
 xform(const LMatrix4f &mat) {
-  LightNode::xform(mat);
+  LightLensNode::xform(mat);
   CDWriter cdata(_cycler);
   cdata->_point = cdata->_point * mat;
   cdata->_direction = cdata->_direction * mat;
@@ -199,7 +200,7 @@ register_with_read_factory() {
 ////////////////////////////////////////////////////////////////////
 void DirectionalLight::
 write_datagram(BamWriter *manager, Datagram &dg) {
-  LightNode::write_datagram(manager, dg);
+  LightLensNode::write_datagram(manager, dg);
   manager->write_cdata(dg, _cycler);
 }
 
@@ -232,6 +233,6 @@ make_from_bam(const FactoryParams &params) {
 ////////////////////////////////////////////////////////////////////
 void DirectionalLight::
 fillin(DatagramIterator &scan, BamReader *manager) {
-  LightNode::fillin(scan, manager);
+  LightLensNode::fillin(scan, manager);
   manager->read_cdata(scan, _cycler);
 }

+ 4 - 4
panda/src/pgraphnodes/directionalLight.h

@@ -17,14 +17,14 @@
 
 #include "pandabase.h"
 
-#include "lightNode.h"
+#include "lightLensNode.h"
 
 ////////////////////////////////////////////////////////////////////
 //       Class : DirectionalLight
 // Description : A light shining from infinitely far away in a
 //               particular direction, like sunlight.
 ////////////////////////////////////////////////////////////////////
-class EXPCL_PANDA_PGRAPHNODES DirectionalLight : public LightNode {
+class EXPCL_PANDA_PGRAPHNODES DirectionalLight : public LightLensNode {
 PUBLISHED:
   DirectionalLight(const string &name);
 
@@ -91,9 +91,9 @@ public:
     return _type_handle;
   }
   static void init_type() {
-    LightNode::init_type();
+    LightLensNode::init_type();
     register_type(_type_handle, "DirectionalLight",
-                  LightNode::get_class_type());
+                  LightLensNode::get_class_type());
   }
   virtual TypeHandle get_type() const {
     return get_class_type();

+ 70 - 0
panda/src/pgraphnodes/lightLensNode.I

@@ -11,3 +11,73 @@
 // with this source code in a file named "LICENSE."
 //
 ////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////
+//     Function: LightLensNode::is_shadow_caster
+//       Access: Published
+//  Description: Returns whether this light is configured to cast
+//               shadows or not.
+////////////////////////////////////////////////////////////////////
+INLINE bool LightLensNode::
+is_shadow_caster() {
+  return _shadow_caster;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LightLensNode::set_shadow_caster
+//       Access: Published
+//  Description: Sets the flag indicating whether this light should
+//               cast shadows or not. This is the variant without
+//               buffer size, meaning that the current buffer size
+//               will be kept (512x512 is the default).
+//               Note that enabling shadows will require the shader
+//               generator to be enabled on the scene.
+////////////////////////////////////////////////////////////////////
+INLINE void LightLensNode::
+set_shadow_caster(bool caster) {
+  if (_shadow_caster && !caster) {
+    clear_shadow_buffers();
+  }
+  _shadow_caster = caster;
+  set_active(caster);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LightLensNode::set_shadow_caster
+//       Access: Published
+//  Description: Sets the flag indicating whether this light should
+//               cast shadows or not. The xsize and ysize parameters
+//               specify the size of the shadow buffer that will be
+//               set up, the sort parameter specifies the sort.
+//               Note that enabling shadows will require the shader
+//               generator to be enabled on the scene.
+////////////////////////////////////////////////////////////////////
+INLINE void LightLensNode::
+set_shadow_caster(bool caster, int buffer_xsize, int buffer_ysize, int buffer_sort) {
+  if ((_shadow_caster && !caster) || buffer_xsize != _sb_xsize || buffer_ysize != _sb_ysize) {
+    clear_shadow_buffers();
+  }
+  _shadow_caster = caster;
+  _sb_xsize = buffer_xsize;
+  _sb_ysize = buffer_ysize;
+  if (buffer_sort != _sb_sort) {
+    ShadowBuffers::iterator it;
+    for(it = _sbuffers.begin(); it != _sbuffers.end(); ++it) {
+      it->second->set_sort(buffer_sort);
+    }
+    _sb_sort = buffer_sort;
+  }
+  set_active(caster);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LightLensNode::set_push_bias
+//       Access: Published
+//  Description: Sets the push bias value, this is used to eliminate
+//               depth texture precision errors in shadows. Change
+//               this value if your shadows look strange.
+////////////////////////////////////////////////////////////////////
+INLINE void LightLensNode::
+set_push_bias(float push_bias) {
+  _push_bias = push_bias;
+}

+ 58 - 6
panda/src/pgraphnodes/lightLensNode.cxx

@@ -17,6 +17,7 @@
 #include "bamReader.h"
 #include "datagram.h"
 #include "datagramIterator.h"
+#include "graphicsEngine.h"
 
 TypeHandle LightLensNode::_type_handle;
 
@@ -26,9 +27,26 @@ TypeHandle LightLensNode::_type_handle;
 //  Description:
 ////////////////////////////////////////////////////////////////////
 LightLensNode::
-LightLensNode(const string &name) : 
-  LensNode(name) 
+LightLensNode(const string &name, Lens *lens) :
+  Camera(name, lens)
 {
+  set_active(false);
+  _shadow_caster = false;
+  _sb_xsize = 512;
+  _sb_ysize = 512;
+  _sb_sort = -10;
+  _push_bias = 0.5;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LightLensNode::Destructor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+LightLensNode::
+~LightLensNode() {
+  set_active(false);
+  clear_shadow_buffers();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -37,10 +55,31 @@ LightLensNode(const string &name) :
 //  Description:
 ////////////////////////////////////////////////////////////////////
 LightLensNode::
-LightLensNode(const LightLensNode &copy) : 
+LightLensNode(const LightLensNode &copy) :
   Light(copy),
-  LensNode(copy)
+  Camera(copy)
 {
+  _shadow_caster = false;
+  _sb_xsize = 512;
+  _sb_ysize = 512;
+  _sb_sort = -10;
+  _push_bias = 0.5;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: LightLensNode::clear_shadow_buffers
+//       Access: Protected
+//  Description: Clears the shadow buffers, meaning they will be
+//               automatically recreated when the Shader Generator
+//               needs them.
+////////////////////////////////////////////////////////////////////
+void LightLensNode::
+clear_shadow_buffers() {
+  ShadowBuffers::iterator it;
+  for(it = _sbuffers.begin(); it != _sbuffers.end(); ++it) {
+    it->first->get_engine()->remove_window(it->second);
+  }
+  _sbuffers.clear();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -93,8 +132,14 @@ write(ostream &out, int indent_level) const {
 ////////////////////////////////////////////////////////////////////
 void LightLensNode::
 write_datagram(BamWriter *manager, Datagram &dg) {
-  LensNode::write_datagram(manager, dg);
+  Camera::write_datagram(manager, dg);
   Light::write_datagram(manager, dg);
+  
+  dg.add_bool(_shadow_caster);
+  dg.add_int32(_sb_xsize);
+  dg.add_int32(_sb_ysize);
+  dg.add_int32(_sb_sort);
+  dg.add_float64(_push_bias);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -106,6 +151,13 @@ write_datagram(BamWriter *manager, Datagram &dg) {
 ////////////////////////////////////////////////////////////////////
 void LightLensNode::
 fillin(DatagramIterator &scan, BamReader *manager) {
-  LensNode::fillin(scan, manager);
+  Camera::fillin(scan, manager);
   Light::fillin(scan, manager);
+  
+  bool shadow_caster = scan.get_bool();
+  int sb_xsize = scan.get_int32();
+  int sb_ysize = scan.get_int32();
+  int sb_sort = scan.get_int32();
+  set_shadow_caster(shadow_caster, sb_xsize, sb_ysize, sb_sort);
+  set_push_bias(scan.get_float64());
 }

+ 28 - 6
panda/src/pgraphnodes/lightLensNode.h

@@ -18,18 +18,38 @@
 #include "pandabase.h"
 
 #include "light.h"
-#include "lensNode.h"
+#include "camera.h"
+#include "graphicsStateGuardian.h"
+#include "graphicsOutput.h"
+
+class ShaderGenerator;
 
 ////////////////////////////////////////////////////////////////////
 //       Class : LightLensNode
-// Description : A derivative of Light and of LensNode.  
+// Description : A derivative of Light and of Camera. The name might
+//               be misleading: it does not directly derive from
+//               LensNode, but through the Camera class. The Camera
+//               serves no purpose unless shadows are enabled.
 ////////////////////////////////////////////////////////////////////
-class EXPCL_PANDA_PGRAPHNODES LightLensNode : public Light, public LensNode {
+class EXPCL_PANDA_PGRAPHNODES LightLensNode : public Light, public Camera {
 PUBLISHED:
-  LightLensNode(const string &name);
+  LightLensNode(const string &name, Lens *lens = new PerspectiveLens());
+  virtual ~LightLensNode();
+
+  INLINE bool is_shadow_caster();
+  INLINE void set_shadow_caster(bool caster);
+  INLINE void set_shadow_caster(bool caster, int buffer_xsize, int buffer_ysize, int sort = -10);
+  INLINE void set_push_bias(float push_bias);
 
 protected:
   LightLensNode(const LightLensNode &copy);
+  void clear_shadow_buffers();
+
+  bool _shadow_caster;
+  int _sb_xsize, _sb_ysize, _sb_sort;
+  double _push_bias;
+  typedef pmap<CPT(GraphicsStateGuardian), PT(GraphicsOutput) > ShadowBuffers;
+  ShadowBuffers _sbuffers;
 
 public:
   virtual PandaNode *as_node();
@@ -53,10 +73,10 @@ public:
   }
   static void init_type() {
     Light::init_type();
-    LensNode::init_type();
+    Camera::init_type();
     register_type(_type_handle, "LightLensNode",
                   Light::get_class_type(),
-                  LensNode::get_class_type());
+                  Camera::get_class_type());
   }
   virtual TypeHandle get_type() const {
     return get_class_type();
@@ -65,6 +85,8 @@ public:
 
 private:
   static TypeHandle _type_handle;
+
+  friend class ShaderGenerator;
 };
 
 INLINE ostream &operator << (ostream &out, const LightLensNode &light) {