diff --git a/panda/src/pgraph/camera.cxx b/panda/src/pgraph/camera.cxx index 3819f7f821..dae3ee3a89 100644 --- a/panda/src/pgraph/camera.cxx +++ b/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()) diff --git a/panda/src/pgraph/camera.h b/panda/src/pgraph/camera.h index 36bb0fb853..4573584550 100644 --- a/panda/src/pgraph/camera.h +++ b/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 ©); public: diff --git a/panda/src/pgraphnodes/directionalLight.cxx b/panda/src/pgraphnodes/directionalLight.cxx index d2795d7876..41fbb0415e 100644 --- a/panda/src/pgraphnodes/directionalLight.cxx +++ b/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 ©) : - 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 ¶ms) { //////////////////////////////////////////////////////////////////// void DirectionalLight:: fillin(DatagramIterator &scan, BamReader *manager) { - LightNode::fillin(scan, manager); + LightLensNode::fillin(scan, manager); manager->read_cdata(scan, _cycler); } diff --git a/panda/src/pgraphnodes/directionalLight.h b/panda/src/pgraphnodes/directionalLight.h index a8a3bfe25b..ae6c562066 100644 --- a/panda/src/pgraphnodes/directionalLight.h +++ b/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(); diff --git a/panda/src/pgraphnodes/lightLensNode.I b/panda/src/pgraphnodes/lightLensNode.I index 373048db36..75a37ea900 100644 --- a/panda/src/pgraphnodes/lightLensNode.I +++ b/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; +} diff --git a/panda/src/pgraphnodes/lightLensNode.cxx b/panda/src/pgraphnodes/lightLensNode.cxx index 1ecaa40f3a..9a8336f079 100644 --- a/panda/src/pgraphnodes/lightLensNode.cxx +++ b/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 ©) : +LightLensNode(const LightLensNode ©) : 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()); } diff --git a/panda/src/pgraphnodes/lightLensNode.h b/panda/src/pgraphnodes/lightLensNode.h index 082fe9d013..23c155c0de 100644 --- a/panda/src/pgraphnodes/lightLensNode.h +++ b/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 ©); + void clear_shadow_buffers(); + + bool _shadow_caster; + int _sb_xsize, _sb_ysize, _sb_sort; + double _push_bias; + typedef pmap 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) {