Browse Source

ShaderGenerator: fix toggling shadows while shader gen is on

rdb 7 years ago
parent
commit
4699dfcd5b

+ 8 - 45
panda/src/pgraphnodes/lightLensNode.I

@@ -28,51 +28,6 @@ is_shadow_caster() const {
   return _shadow_caster;
   return _shadow_caster;
 }
 }
 
 
-/**
- * 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);
-  if (caster) {
-    setup_shadow_map();
-  }
-}
-
-/**
- * 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_size[0] || buffer_ysize != _sb_size[1]) {
-    clear_shadow_buffers();
-  }
-  _shadow_caster = caster;
-  _sb_size.set(buffer_xsize, 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);
-  if (caster) {
-    setup_shadow_map();
-  }
-}
-
 /**
 /**
  * Returns the sort of the shadow buffer to be created for this light source.
  * Returns the sort of the shadow buffer to be created for this light source.
  */
  */
@@ -115,3 +70,11 @@ get_shadow_buffer(GraphicsStateGuardianBase *gsg) {
     return (*it).second;
     return (*it).second;
   }
   }
 }
 }
+
+/**
+ * Marks this light as having been used by the auto shader.
+ */
+INLINE void LightLensNode::
+mark_used_by_auto_shader() const {
+  _used_by_auto_shader = true;
+}

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

@@ -19,6 +19,7 @@
 #include "renderState.h"
 #include "renderState.h"
 #include "cullFaceAttrib.h"
 #include "cullFaceAttrib.h"
 #include "colorWriteAttrib.h"
 #include "colorWriteAttrib.h"
+#include "graphicsStateGuardianBase.h"
 
 
 TypeHandle LightLensNode::_type_handle;
 TypeHandle LightLensNode::_type_handle;
 
 
@@ -29,7 +30,8 @@ LightLensNode::
 LightLensNode(const std::string &name, Lens *lens) :
 LightLensNode(const std::string &name, Lens *lens) :
   Camera(name, lens),
   Camera(name, lens),
   _has_specular_color(false),
   _has_specular_color(false),
-  _attrib_count(0)
+  _attrib_count(0),
+  _used_by_auto_shader(false)
 {
 {
   set_active(false);
   set_active(false);
   _shadow_caster = false;
   _shadow_caster = false;
@@ -65,13 +67,67 @@ LightLensNode(const LightLensNode &copy) :
   _sb_size(copy._sb_size),
   _sb_size(copy._sb_size),
   _sb_sort(-10),
   _sb_sort(-10),
   _has_specular_color(copy._has_specular_color),
   _has_specular_color(copy._has_specular_color),
-  _attrib_count(0)
+  _attrib_count(0),
+  _used_by_auto_shader(false)
 {
 {
   if (_shadow_caster) {
   if (_shadow_caster) {
     setup_shadow_map();
     setup_shadow_map();
   }
   }
 }
 }
 
 
+/**
+ * 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.
+ */
+void LightLensNode::
+set_shadow_caster(bool caster) {
+  if (_shadow_caster && !caster) {
+    clear_shadow_buffers();
+  }
+  if (_shadow_caster != caster && _used_by_auto_shader) {
+    // Make sure any shaders using this light are regenerated.
+    GraphicsStateGuardianBase::mark_rehash_generated_shaders();
+  }
+  _shadow_caster = caster;
+  set_active(caster);
+  if (caster) {
+    setup_shadow_map();
+  }
+}
+
+/**
+ * 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.
+ */
+void LightLensNode::
+set_shadow_caster(bool caster, int buffer_xsize, int buffer_ysize, int buffer_sort) {
+  if ((_shadow_caster && !caster) || buffer_xsize != _sb_size[0] || buffer_ysize != _sb_size[1]) {
+    clear_shadow_buffers();
+  }
+  if (_shadow_caster != caster && _used_by_auto_shader) {
+    // Make sure any shaders using this light are regenerated.
+    GraphicsStateGuardianBase::mark_rehash_generated_shaders();
+  }
+  _shadow_caster = caster;
+  _sb_size.set(buffer_xsize, 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);
+  if (caster) {
+    setup_shadow_map();
+  }
+}
+
 /**
 /**
  * Clears the shadow buffers, meaning they will be automatically recreated
  * Clears the shadow buffers, meaning they will be automatically recreated
  * when the Shader Generator needs them.
  * when the Shader Generator needs them.

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

@@ -38,8 +38,8 @@ PUBLISHED:
   INLINE bool has_specular_color() const;
   INLINE bool has_specular_color() const;
 
 
   INLINE bool is_shadow_caster() const;
   INLINE bool is_shadow_caster() const;
-  INLINE void set_shadow_caster(bool caster);
-  INLINE void set_shadow_caster(bool caster, int buffer_xsize, int buffer_ysize, int sort = -10);
+  void set_shadow_caster(bool caster);
+  void set_shadow_caster(bool caster, int buffer_xsize, int buffer_ysize, int sort = -10);
 
 
   INLINE int get_shadow_buffer_sort() const;
   INLINE int get_shadow_buffer_sort() const;
 
 
@@ -52,6 +52,9 @@ PUBLISHED:
   MAKE_PROPERTY(shadow_caster, is_shadow_caster);
   MAKE_PROPERTY(shadow_caster, is_shadow_caster);
   MAKE_PROPERTY(shadow_buffer_size, get_shadow_buffer_size, set_shadow_buffer_size);
   MAKE_PROPERTY(shadow_buffer_size, get_shadow_buffer_size, set_shadow_buffer_size);
 
 
+public:
+  INLINE void mark_used_by_auto_shader() const;
+
 protected:
 protected:
   LightLensNode(const LightLensNode &copy);
   LightLensNode(const LightLensNode &copy);
   void clear_shadow_buffers();
   void clear_shadow_buffers();
@@ -61,6 +64,7 @@ protected:
   bool _shadow_caster;
   bool _shadow_caster;
   bool _has_specular_color;
   bool _has_specular_color;
   int _sb_sort;
   int _sb_sort;
+  mutable bool _used_by_auto_shader = false;
 
 
   PT(Texture) _shadow_map;
   PT(Texture) _shadow_map;
 
 

+ 8 - 2
panda/src/pgraphnodes/shaderGenerator.cxx

@@ -294,8 +294,14 @@ analyze_renderstate(ShaderKey &key, const RenderState *rs) {
 
 
       if (node->is_of_type(LightLensNode::get_class_type())) {
       if (node->is_of_type(LightLensNode::get_class_type())) {
         const LightLensNode *llnode = (const LightLensNode *)node;
         const LightLensNode *llnode = (const LightLensNode *)node;
-        if (shader_attrib->auto_shadow_on() && llnode->is_shadow_caster()) {
-          info._flags |= ShaderKey::LF_has_shadows;
+        if (shader_attrib->auto_shadow_on()) {
+          if (llnode->is_shadow_caster()) {
+            info._flags |= ShaderKey::LF_has_shadows;
+          }
+
+          // Make sure that the next time the shadows are toggled on this
+          // light, it triggers a state rehash.
+          llnode->mark_used_by_auto_shader();
         }
         }
         if (llnode->has_specular_color()) {
         if (llnode->has_specular_color()) {
           info._flags |= ShaderKey::LF_has_specular_color;
           info._flags |= ShaderKey::LF_has_specular_color;