Browse Source

ShaderGenerator: don't generate a shader per Material

rdb 8 years ago
parent
commit
511b0c10e5

+ 17 - 13
panda/src/gobj/material.h

@@ -127,19 +127,7 @@ PUBLISHED:
   MAKE_PROPERTY(local, get_local, set_local);
   MAKE_PROPERTY(twoside, get_twoside, set_twoside);
 
-private:
-  LColor _base_color;
-  LColor _ambient;
-  LColor _diffuse;
-  LColor _specular;
-  LColor _emission;
-  PN_stdfloat _shininess;
-  PN_stdfloat _roughness;
-  PN_stdfloat _metallic;
-  PN_stdfloat _refractive_index;
-
-  static PT(Material) _default;
-
+public:
   enum Flags {
     F_ambient     = 0x001,
     F_diffuse     = 0x002,
@@ -153,8 +141,24 @@ private:
     F_base_color  = 0x200,
     F_refractive_index = 0x400,
   };
+
+private:
+  LColor _base_color;
+  LColor _ambient;
+  LColor _diffuse;
+  LColor _specular;
+  LColor _emission;
+  PN_stdfloat _shininess;
+  PN_stdfloat _roughness;
+  PN_stdfloat _metallic;
+  PN_stdfloat _refractive_index;
+
+  static PT(Material) _default;
+
   int _flags;
 
+  friend class MaterialAttrib;
+
 public:
   static void register_with_read_factory();
   virtual void write_datagram(BamWriter *manager, Datagram &me);

+ 10 - 2
panda/src/pgraph/materialAttrib.I

@@ -15,7 +15,7 @@
  * Use MaterialAttrib::make() to construct a new MaterialAttrib object.
  */
 INLINE MaterialAttrib::
-MaterialAttrib() {
+MaterialAttrib() : _flags(0) {
 }
 
 /**
@@ -24,7 +24,7 @@ MaterialAttrib() {
  */
 INLINE bool MaterialAttrib::
 is_off() const {
-  return _material == (const Material *)NULL;
+  return _flags == 0;
 }
 
 /**
@@ -35,3 +35,11 @@ INLINE Material *MaterialAttrib::
 get_material() const {
   return _material;
 }
+
+/**
+ * Equivalent to get_material()->get_flags().
+ */
+INLINE int MaterialAttrib::
+get_material_flags() const {
+  return _flags;
+}

+ 44 - 5
panda/src/pgraph/materialAttrib.cxx

@@ -30,6 +30,8 @@ make(Material *material) {
   MaterialAttrib *attrib = new MaterialAttrib;
   attrib->_material = material;
   material->set_attrib_lock();
+  attrib->_flags = material->_flags;
+  nassertr(attrib->_flags & Material::F_attrib_lock, nullptr);
   return return_new(attrib);
 }
 
@@ -58,10 +60,34 @@ make_default() {
 void MaterialAttrib::
 output(ostream &out) const {
   out << get_type() << ":";
-  if (is_off()) {
+  if (_material != nullptr) {
+    out << *_material;
+  } else if (is_off()) {
     out << "(off)";
   } else {
-    out << *_material;
+    // This is a state returned from get_auto_shader_attrib().
+    out << "(on";
+#ifndef NDEBUG
+    if (_flags & Material::F_ambient) {
+      out << " amb";
+    }
+    if (_flags & Material::F_diffuse) {
+      out << " diff";
+    }
+    if (_flags & Material::F_specular) {
+      out << " spec";
+    }
+    if (_flags & Material::F_emission) {
+      out << " emit";
+    }
+    if (_flags & Material::F_local) {
+      out << " local";
+    }
+    if (_flags & Material::F_twoside) {
+      out << " twoside";
+    }
+#endif
+    out << ")";
   }
 }
 
@@ -87,7 +113,7 @@ compare_to_impl(const RenderAttrib *other) const {
   if (_material != ta->_material) {
     return _material < ta->_material ? -1 : 1;
   }
-  return 0;
+  return _flags < ta->_flags;
 }
 
 /**
@@ -100,6 +126,7 @@ size_t MaterialAttrib::
 get_hash_impl() const {
   size_t hash = 0;
   hash = pointer_hash::add_hash(hash, _material);
+  hash = int_hash::add_hash(hash, _flags);
   return hash;
 }
 
@@ -108,7 +135,15 @@ get_hash_impl() const {
  */
 CPT(RenderAttrib) MaterialAttrib::
 get_auto_shader_attrib_impl(const RenderState *state) const {
-  return this;
+  if (_material == nullptr) {
+    return this;
+  } else {
+    // Make a copy, but only with the flags, not with the material itself.
+    MaterialAttrib *attrib = new MaterialAttrib();
+    attrib->_material = nullptr;
+    attrib->_flags = _flags;
+    return return_new(attrib);
+  }
 }
 
 /**
@@ -139,8 +174,12 @@ complete_pointers(TypedWritable **p_list, BamReader *manager) {
   int pi = RenderAttrib::complete_pointers(p_list, manager);
 
   TypedWritable *material = p_list[pi++];
-  if (material != (TypedWritable *)NULL) {
+  if (material != nullptr) {
     _material = DCAST(Material, material);
+    _flags = _material->_flags | Material::F_attrib_lock;
+  } else {
+    _material = nullptr;
+    _flags = 0;
   }
 
   return pi;

+ 4 - 0
panda/src/pgraph/materialAttrib.h

@@ -36,6 +36,9 @@ PUBLISHED:
   INLINE bool is_off() const;
   INLINE Material *get_material() const;
 
+public:
+  INLINE int get_material_flags() const;
+
 PUBLISHED:
   MAKE_PROPERTY(material, get_material);
 
@@ -49,6 +52,7 @@ protected:
 
 private:
   PT(Material) _material;
+  int _flags;
 
 PUBLISHED:
   static int get_class_slot() {

+ 23 - 52
panda/src/pgraphnodes/shaderGenerator.cxx

@@ -265,12 +265,7 @@ analyze_renderstate(const RenderState *rs) {
 
   const MaterialAttrib *material;
   rs->get_attrib_def(material);
-
-  if (!material->is_off()) {
-    _material = material->get_material();
-  } else {
-    _material = Material::get_default();
-  }
+  _material_flags = material->get_material_flags();
 
   // Break out the lights by type.
 
@@ -285,14 +280,7 @@ analyze_renderstate(const RenderState *rs) {
     nassertv(light_obj != (PandaNode *)NULL);
 
     if (light_obj->is_ambient_light()) {
-      if (_material->has_ambient()) {
-        LColor a = _material->get_ambient();
-        if ((a[0]!=0.0)||(a[1]!=0.0)||(a[2]!=0.0)) {
-          _have_ambient = true;
-        }
-      } else {
-        _have_ambient = true;
-      }
+      _have_ambient = true;
       _lighting = true;
 
     } else if (light_obj->is_of_type(LightLensNode::get_class_type())) {
@@ -369,29 +357,16 @@ analyze_renderstate(const RenderState *rs) {
   // Decide which material modes need to be calculated.
 
   if (_lighting) {
-    if (_material->has_diffuse()) {
-      LColor d = _material->get_diffuse();
-      if ((d[0]!=0.0)||(d[1]!=0.0)||(d[2]!=0.0)) {
-        _have_diffuse = true;
-      }
-    } else {
-      _have_diffuse = true;
-    }
+    _have_diffuse = true;
   }
 
-  if (_lighting && (_material->has_emission())) {
-    LColor e = _material->get_emission();
-    if ((e[0]!=0.0)||(e[1]!=0.0)||(e[2]!=0.0)) {
-      _have_emission = true;
-    }
+  if (_lighting && (_material_flags & Material::F_emission) != 0) {
+    _have_emission = true;
   }
 
   if (_lighting) {
-    if (_material->has_specular()) {
-      LColor s = _material->get_specular();
-      if ((s[0]!=0.0)||(s[1]!=0.0)||(s[2]!=0.0)) {
-        _have_specular = true;
-      }
+    if (_material_flags & Material::F_specular) {
+      _have_specular = true;
     } else if (_map_index_gloss >= 0) {
       _have_specular = true;
     }
@@ -402,14 +377,10 @@ analyze_renderstate(const RenderState *rs) {
   // Decide whether to separate ambient and diffuse calculations.
 
   if (_have_ambient && _have_diffuse) {
-    if (_material->has_ambient()) {
-      if (_material->has_diffuse()) {
-        _separate_ambient_diffuse = _material->get_ambient() != _material->get_diffuse();
-      } else {
-        _separate_ambient_diffuse = true;
-      }
+    if (_material_flags & Material::F_ambient) {
+      _separate_ambient_diffuse = true;
     } else {
-      if (_material->has_diffuse()) {
+      if (_material_flags & Material::F_diffuse) {
         _separate_ambient_diffuse = true;
       } else {
         _separate_ambient_diffuse = false;
@@ -431,10 +402,10 @@ analyze_renderstate(const RenderState *rs) {
   // Does the shader need material properties as input?
 
   _need_material_props =
-    (_have_ambient  && (_material->has_ambient()))||
-    (_have_diffuse  && (_material->has_diffuse()))||
-    (_have_emission && (_material->has_emission()))||
-    (_have_specular && (_material->has_specular()));
+    (_have_ambient  && (_material_flags & Material::F_ambient) != 0) ||
+    (_have_diffuse  && (_material_flags & Material::F_diffuse) != 0) ||
+    (_have_emission && (_material_flags & Material::F_emission) != 0) ||
+    (_have_specular && (_material_flags & Material::F_specular) != 0);
 
   // Check for clip planes.
 
@@ -494,7 +465,7 @@ clear_analysis() {
   _out_aux_normal   = false;
   _out_aux_glow     = false;
   _out_aux_any      = false;
-  _material = (Material*)NULL;
+  _material_flags = 0;
   _need_material_props = false;
   _need_world_position = false;
   _need_world_normal = false;
@@ -867,7 +838,7 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
       text << "\t uniform float4x4 attr_material,\n";
     }
     if (_have_specular) {
-      if (_material->get_local()) {
+      if (_material_flags & Material::F_local) {
         text << "\t uniform float4 mspos_view,\n";
       } else {
         text << "\t uniform float4 row1_view_to_model,\n";
@@ -1041,7 +1012,7 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
     }
     if (_have_specular) {
       text << "\t float4 tot_specular = float4(0,0,0,0);\n";
-      if (_material->has_specular()) {
+      if (_material_flags & Material::F_specular) {
         text << "\t float shininess = attr_material[3].w;\n";
       } else {
         text << "\t float shininess = 50; // no shininess specified, using default\n";
@@ -1073,7 +1044,7 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
         text << "\t tot_diffuse += lcolor;\n";
       }
       if (_have_specular) {
-        if (_material->get_local()) {
+        if (_material_flags & Material::F_local) {
           text << "\t lhalf = normalize(lvec - normalize(l_eye_position.xyz));\n";
         } else {
           text << "\t lhalf = dlight_light" << i << "_rel_view[3].xyz;\n";
@@ -1103,7 +1074,7 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
         text << "\t tot_diffuse += lcolor;\n";
       }
       if (_have_specular) {
-        if (_material->get_local()) {
+        if (_material_flags & Material::F_local) {
           text << "\t lhalf = normalize(lvec - normalize(l_eye_position.xyz));\n";
         } else {
           text << "\t lhalf = normalize(lvec - float3(0, 1, 0));\n";
@@ -1141,7 +1112,7 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
         text << "\t tot_diffuse += lcolor;\n";
       }
       if (_have_specular) {
-        if (_material->get_local()) {
+        if (_material_flags & Material::F_local) {
           text << "\t lhalf = normalize(lvec - normalize(l_eye_position.xyz));\n";
         } else {
           text << "\t lhalf = normalize(lvec - float3(0,1,0));\n";
@@ -1199,7 +1170,7 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
       }
     }
     if ((_have_ambient)&&(_separate_ambient_diffuse)) {
-      if (_material->has_ambient()) {
+      if (_material_flags & Material::F_ambient) {
         text << "\t result += tot_ambient * attr_material[0];\n";
       } else if (_vertex_colors) {
         text << "\t result += tot_ambient * l_color;\n";
@@ -1210,7 +1181,7 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
       }
     }
     if (_have_diffuse) {
-      if (_material->has_diffuse()) {
+      if (_material_flags & Material::F_diffuse) {
         text << "\t result += tot_diffuse * attr_material[1];\n";
       } else if (_vertex_colors) {
         text << "\t result += tot_diffuse * l_color;\n";
@@ -1389,7 +1360,7 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) {
 
   if (_lighting) {
     if (_have_specular) {
-      if (_material->has_specular()) {
+      if (_material_flags & Material::F_specular) {
         text << "\t tot_specular *= attr_material[3];\n";
       }
       if (_map_index_gloss >= 0 && _auto_gloss_on) {

+ 1 - 1
panda/src/pgraphnodes/shaderGenerator.h

@@ -87,7 +87,7 @@ protected:
   // RenderState analysis information.  Created by analyze_renderstate:
 
   CPT(RenderState) _state;
-  Material *_material;
+  int _material_flags;
   int _num_textures;
 
   pvector<LightLensNode *> _lights;