From 511b0c10e570a31a3454c36b2dad7631570aac2d Mon Sep 17 00:00:00 2001 From: rdb Date: Thu, 22 Jun 2017 13:35:46 +0200 Subject: [PATCH] ShaderGenerator: don't generate a shader per Material --- panda/src/gobj/material.h | 30 +++++---- panda/src/pgraph/materialAttrib.I | 12 +++- panda/src/pgraph/materialAttrib.cxx | 49 +++++++++++++-- panda/src/pgraph/materialAttrib.h | 4 ++ panda/src/pgraphnodes/shaderGenerator.cxx | 75 +++++++---------------- panda/src/pgraphnodes/shaderGenerator.h | 2 +- 6 files changed, 99 insertions(+), 73 deletions(-) diff --git a/panda/src/gobj/material.h b/panda/src/gobj/material.h index 1a37415294..eb1a36747e 100644 --- a/panda/src/gobj/material.h +++ b/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); diff --git a/panda/src/pgraph/materialAttrib.I b/panda/src/pgraph/materialAttrib.I index 2f2652f43c..3cb7f9e6be 100644 --- a/panda/src/pgraph/materialAttrib.I +++ b/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; +} diff --git a/panda/src/pgraph/materialAttrib.cxx b/panda/src/pgraph/materialAttrib.cxx index c3facc7bb4..d8eee605d7 100644 --- a/panda/src/pgraph/materialAttrib.cxx +++ b/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; diff --git a/panda/src/pgraph/materialAttrib.h b/panda/src/pgraph/materialAttrib.h index f984b699b3..28bd90f8bd 100644 --- a/panda/src/pgraph/materialAttrib.h +++ b/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() { diff --git a/panda/src/pgraphnodes/shaderGenerator.cxx b/panda/src/pgraphnodes/shaderGenerator.cxx index 46b9701d3c..e78ac65f3a 100644 --- a/panda/src/pgraphnodes/shaderGenerator.cxx +++ b/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) { diff --git a/panda/src/pgraphnodes/shaderGenerator.h b/panda/src/pgraphnodes/shaderGenerator.h index 1fd597b215..9042291631 100644 --- a/panda/src/pgraphnodes/shaderGenerator.h +++ b/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 _lights;