From 751299d65a0dd75278dce33a32321210285c204c Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 20 Jun 2017 15:45:21 +0200 Subject: [PATCH 1/9] makepanda: don't build with OpenCV if we have ffmpeg enabled (except on macOS, where we use OpenCV to provide webcam support) --- makepanda/makepanda.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index a2df279c0d..4c06fc4706 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -835,13 +835,16 @@ if (COMPILER=="GCC"): # Needed when linking ffmpeg statically on Linux. LibName("FFMPEG", "-Wl,-Bsymbolic") - cv_lib = ChooseLib(("opencv_core", "cv"), "OPENCV") - if cv_lib == "opencv_core": - OPENCV_VER_23 = True - SmartPkgEnable("OPENCV", "opencv", ("opencv_core", "opencv_highgui"), ("opencv2/core/core.hpp")) + if PkgSkip("FFMPEG") or GetTarget() == "darwin": + cv_lib = ChooseLib(("opencv_core", "cv"), "OPENCV") + if cv_lib == "opencv_core": + OPENCV_VER_23 = True + SmartPkgEnable("OPENCV", "opencv", ("opencv_core", "opencv_highgui"), ("opencv2/core/core.hpp")) + else: + SmartPkgEnable("OPENCV", "opencv", ("cv", "highgui", "cvaux", "ml", "cxcore"), + ("opencv", "opencv/cv.h", "opencv/cxcore.h", "opencv/highgui.h")) else: - SmartPkgEnable("OPENCV", "opencv", ("cv", "highgui", "cvaux", "ml", "cxcore"), - ("opencv", "opencv/cv.h", "opencv/cxcore.h", "opencv/highgui.h")) + PkgDisable("OPENCV") rocket_libs = ("RocketCore", "RocketControls") if (GetOptimize() <= 3): From b781995ef135fdaea6d2479f8b3b7e6213e9d9f3 Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 20 Jun 2017 16:14:00 +0200 Subject: [PATCH 2/9] ShaderGenerator: prepare_scene now invokes shader generator. This also necessarily removes ShaderGenerator's dependency on a host window. --- panda/src/display/graphicsEngine.cxx | 10 --------- panda/src/display/standardMunger.cxx | 10 ++++----- panda/src/pgraph/geomNode.cxx | 26 +++++++++++------------ panda/src/pgraphnodes/shaderGenerator.cxx | 4 ++-- panda/src/pgraphnodes/shaderGenerator.h | 3 +-- 5 files changed, 21 insertions(+), 32 deletions(-) diff --git a/panda/src/display/graphicsEngine.cxx b/panda/src/display/graphicsEngine.cxx index 045c534ebe..a9ce3abbcb 100644 --- a/panda/src/display/graphicsEngine.cxx +++ b/panda/src/display/graphicsEngine.cxx @@ -1849,16 +1849,6 @@ setup_scene(GraphicsStateGuardian *gsg, DisplayRegionPipelineReader *dr) { CPT(TransformState) cs_world_transform = cs_transform->compose(world_transform); scene_setup->set_cs_world_transform(cs_world_transform); - // Make sure that the GSG has a ShaderGenerator for the munger to use. We - // have to do this here because the ShaderGenerator needs a host window - // pointer. Hopefully we'll be able to eliminate that requirement in the - // future. -#ifdef HAVE_CG - if (gsg->get_shader_generator() == NULL) { - gsg->set_shader_generator(new ShaderGenerator(gsg, window)); - } -#endif - return scene_setup; } diff --git a/panda/src/display/standardMunger.cxx b/panda/src/display/standardMunger.cxx index b6bc1ada2a..4b6aa01f67 100644 --- a/panda/src/display/standardMunger.cxx +++ b/panda/src/display/standardMunger.cxx @@ -344,11 +344,11 @@ munge_state_impl(const RenderState *state) { #ifdef HAVE_CG if (_auto_shader) { CPT(RenderState) shader_state = munged_state->get_auto_shader_state(); - ShaderGenerator *shader_generator = get_gsg()->get_shader_generator(); - if (shader_generator == NULL) { - pgraph_cat.error() - << "auto_shader enabled, but GSG has no shader generator assigned!\n"; - return munged_state; + GraphicsStateGuardian *gsg = get_gsg(); + ShaderGenerator *shader_generator = gsg->get_shader_generator(); + if (shader_generator == nullptr) { + shader_generator = new ShaderGenerator(gsg); + gsg->set_shader_generator(shader_generator); } if (shader_state->_generated_shader == NULL) { // Cache the generated ShaderAttrib on the shader state. diff --git a/panda/src/pgraph/geomNode.cxx b/panda/src/pgraph/geomNode.cxx index 7b850fafc6..11d319212f 100644 --- a/panda/src/pgraph/geomNode.cxx +++ b/panda/src/pgraph/geomNode.cxx @@ -15,6 +15,7 @@ #include "geom.h" #include "geomTransformer.h" #include "sceneGraphReducer.h" +#include "stateMunger.h" #include "accumulatedAttribs.h" #include "colorAttrib.h" #include "colorScaleAttrib.h" @@ -391,33 +392,32 @@ r_prepare_scene(GraphicsStateGuardianBase *gsg, const RenderState *node_state, ((GeomPrimitive *)prim.p())->prepare(prepared_objects); } + if (munger->is_of_type(StateMunger::get_class_type())) { + StateMunger *state_munger = (StateMunger *)munger.p(); + geom_state = state_munger->munge_state(geom_state); + } + // And now prepare each of the textures. - const RenderAttrib *attrib = - geom_state->get_attrib(TextureAttrib::get_class_slot()); - if (attrib != (const RenderAttrib *)NULL) { - const TextureAttrib *ta; - DCAST_INTO_V(ta, attrib); + const TextureAttrib *ta; + if (geom_state->get_attrib(ta)) { int num_stages = ta->get_num_on_stages(); for (int i = 0; i < num_stages; ++i) { Texture *texture = ta->get_on_texture(ta->get_on_stage(i)); // TODO: prepare the sampler states, if specified. - if (texture != (Texture *)NULL) { + if (texture != nullptr) { texture->prepare(prepared_objects); } } } // As well as the shaders. - attrib = geom_state->get_attrib(ShaderAttrib::get_class_slot()); - if (attrib != (const RenderAttrib *)NULL) { - const ShaderAttrib *sa; - DCAST_INTO_V(sa, attrib); + const ShaderAttrib *sa; + if (geom_state->get_attrib(sa)) { Shader *shader = (Shader *)sa->get_shader(); - if (shader != (Shader *)NULL) { + if (shader != nullptr) { shader->prepare(prepared_objects); } - // TODO: prepare the shader inputs. TODO: Invoke the shader generator - // if enabled. + // TODO: prepare the shader inputs. } } diff --git a/panda/src/pgraphnodes/shaderGenerator.cxx b/panda/src/pgraphnodes/shaderGenerator.cxx index 63973c6bc3..f5c15f136c 100644 --- a/panda/src/pgraphnodes/shaderGenerator.cxx +++ b/panda/src/pgraphnodes/shaderGenerator.cxx @@ -55,8 +55,8 @@ TypeHandle ShaderGenerator::_type_handle; * shader generator belongs. */ ShaderGenerator:: -ShaderGenerator(GraphicsStateGuardianBase *gsg, GraphicsOutputBase *host) : - _gsg(gsg), _host(host) { +ShaderGenerator(GraphicsStateGuardianBase *gsg) : + _gsg(gsg) { // The ATTR# input semantics seem to map to generic vertex attributes in // both arbvp1 and glslv, which behave more consistently. However, they diff --git a/panda/src/pgraphnodes/shaderGenerator.h b/panda/src/pgraphnodes/shaderGenerator.h index a1d83f0919..1fd597b215 100644 --- a/panda/src/pgraphnodes/shaderGenerator.h +++ b/panda/src/pgraphnodes/shaderGenerator.h @@ -60,7 +60,7 @@ class GeomVertexAnimationSpec; */ class EXPCL_PANDA_PGRAPHNODES ShaderGenerator : public TypedReferenceCount { PUBLISHED: - ShaderGenerator(GraphicsStateGuardianBase *gsg, GraphicsOutputBase *host); + ShaderGenerator(GraphicsStateGuardianBase *gsg); virtual ~ShaderGenerator(); virtual CPT(ShaderAttrib) synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim); @@ -144,7 +144,6 @@ protected: // This is not a PT() to prevent a circular reference. GraphicsStateGuardianBase *_gsg; - GraphicsOutputBase *_host; public: static TypeHandle get_class_type() { From af57c829d2c15530f72395895353c004a7440a35 Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 20 Jun 2017 18:42:44 +0200 Subject: [PATCH 3/9] ShaderGenerator: reduce combinatoric explosion of shaders This is done by: * Not considering the texture pointer when looking up a generated shader, only type * Not requiring different shaders based on RescaleNormalAttrib * Not looking at AlphaTestAttrib unless it is going to be relevant This should dramatically reduce the number of shaders that are being generated for many scenes, especially since the only thing that differs from object to object is often just the texture. These changes are also necessary to make b781995ef135fdaea6d2479f8b3b7e6213e9d9f3 more usable, since prepare_scene may see a slightly different state than is encountered at render time due to code in CullResult adding in an AlphaTestAttrib or RescaleNormalAttrib. --- panda/src/pgraph/alphaTestAttrib.cxx | 11 +++- panda/src/pgraph/rescaleNormalAttrib.cxx | 7 ++- panda/src/pgraph/shaderAttrib.cxx | 9 +-- panda/src/pgraph/textureAttrib.I | 40 ++++++++++++ panda/src/pgraph/textureAttrib.cxx | 74 ++++++++++++++++++++++- panda/src/pgraph/textureAttrib.h | 8 +++ panda/src/pgraph/transparencyAttrib.cxx | 9 ++- panda/src/pgraphnodes/shaderGenerator.cxx | 45 +++++++------- 8 files changed, 170 insertions(+), 33 deletions(-) diff --git a/panda/src/pgraph/alphaTestAttrib.cxx b/panda/src/pgraph/alphaTestAttrib.cxx index 5a37a23531..8d31c57b12 100644 --- a/panda/src/pgraph/alphaTestAttrib.cxx +++ b/panda/src/pgraph/alphaTestAttrib.cxx @@ -18,6 +18,7 @@ #include "bamWriter.h" #include "datagram.h" #include "datagramIterator.h" +#include "auxBitplaneAttrib.h" TypeHandle AlphaTestAttrib::_type_handle; int AlphaTestAttrib::_attrib_slot; @@ -98,7 +99,15 @@ get_hash_impl() const { */ CPT(RenderAttrib) AlphaTestAttrib:: get_auto_shader_attrib_impl(const RenderState *state) const { - return this; + // This is only important if the shader subsumes the alpha test, which only + // happens if there is an AuxBitplaneAttrib with ABO_glow. + const AuxBitplaneAttrib *aux; + if (!state->get_attrib(aux) || + (aux->get_outputs() & AuxBitplaneAttrib::ABO_glow) == 0) { + return nullptr; + } else { + return this; + } } /** diff --git a/panda/src/pgraph/rescaleNormalAttrib.cxx b/panda/src/pgraph/rescaleNormalAttrib.cxx index 36af8ebafb..e9d081e43c 100644 --- a/panda/src/pgraph/rescaleNormalAttrib.cxx +++ b/panda/src/pgraph/rescaleNormalAttrib.cxx @@ -86,11 +86,14 @@ get_hash_impl() const { CPT(RenderAttrib) RescaleNormalAttrib:: get_auto_shader_attrib_impl(const RenderState *state) const { // We currently only support M_normalize in the ShaderGenerator. - if (_mode == M_none || _mode == M_normalize) { + /*if (_mode == M_none || _mode == M_normalize) { return this; } else { return RescaleNormalAttrib::make(M_normalize); - } + }*/ + // Actually, we currently ignore this attribute in the shader generator, + // and always normalize the normals. It's too much of a bother. + return nullptr; } /** diff --git a/panda/src/pgraph/shaderAttrib.cxx b/panda/src/pgraph/shaderAttrib.cxx index 6435ceed5d..04d6196aa2 100644 --- a/panda/src/pgraph/shaderAttrib.cxx +++ b/panda/src/pgraph/shaderAttrib.cxx @@ -523,14 +523,15 @@ void ShaderAttrib:: output(ostream &out) const { out << "ShaderAttrib:"; - if (_has_shader) { - if (_shader == NULL) { + if (_auto_shader) { + out << "auto"; + return; + } else if (_has_shader) { + if (_shader == nullptr) { out << "off"; } else { out << _shader->get_filename().get_basename(); } - } else if (_auto_shader) { - out << "auto"; } out << "," << _inputs.size() << " inputs"; diff --git a/panda/src/pgraph/textureAttrib.I b/panda/src/pgraph/textureAttrib.I index da1feca0be..2b008b2f51 100644 --- a/panda/src/pgraph/textureAttrib.I +++ b/panda/src/pgraph/textureAttrib.I @@ -140,6 +140,26 @@ get_on_texture(TextureStage *stage) const { return NULL; } +/** + * Returns the type of the texture associated with the indicated stage. It is + * an error to call this if has_on_stage(stage) returns false. + * + * This method is no different than get_on_texture(stage)->get_texture_type(); + * it merely exists to address a corner case for the shader generator. + */ +INLINE Texture::TextureType TextureAttrib:: +get_on_texture_type(TextureStage *stage) const { + Stages::const_iterator si; + si = _on_stages.find(StageNode(stage)); + nassertr(si != _on_stages.end(), Texture::TT_2d_texture); + + if ((*si)._texture == nullptr) { + return (*si)._texture_type; + } else { + return (*si)._texture->get_texture_type(); + } +} + /** * Returns the sampler associated with the indicated stage, or the one * associated with its texture if no custom stage has been specified. It is @@ -215,6 +235,26 @@ is_identity() const { return _on_stages.empty() && _off_stages.empty() && !_off_all_stages; } +/** + * Call only on a state returned by get_auto_shader_attrib. + */ +bool TextureAttrib:: +on_stage_affects_rgb(size_t n) const { + nassertr(n < _render_stages.size(), false); + StageNode *stage = _render_stages[n]; + return stage->_texture_affects_rgb; +} + +/** + * Call only on a state returned by get_auto_shader_attrib. + */ +bool TextureAttrib:: +on_stage_affects_alpha(size_t n) const { + nassertr(n < _render_stages.size(), false); + StageNode *stage = _render_stages[n]; + return stage->_texture_affects_alpha; +} + /** * Confirms whether the _on_stages list is still sorted. It will become * unsorted if someone calls TextureStage::set_sort(). diff --git a/panda/src/pgraph/textureAttrib.cxx b/panda/src/pgraph/textureAttrib.cxx index 157bf1d146..09e9f7ce7e 100644 --- a/panda/src/pgraph/textureAttrib.cxx +++ b/panda/src/pgraph/textureAttrib.cxx @@ -106,6 +106,8 @@ find_on_stage(const TextureStage *stage) const { */ CPT(RenderAttrib) TextureAttrib:: add_on_stage(TextureStage *stage, Texture *tex, int override) const { + nassertr(tex != nullptr, this); + TextureAttrib *attrib = new TextureAttrib(*this); Stages::iterator si = attrib->_on_stages.insert(StageNode(stage)).first; (*si)._override = override; @@ -127,6 +129,8 @@ add_on_stage(TextureStage *stage, Texture *tex, int override) const { */ CPT(RenderAttrib) TextureAttrib:: add_on_stage(TextureStage *stage, Texture *tex, const SamplerState &sampler, int override) const { + nassertr(tex != nullptr, this); + TextureAttrib *attrib = new TextureAttrib(*this); Stages::iterator si = attrib->_on_stages.insert(StageNode(stage)).first; (*si)._override = override; @@ -381,10 +385,19 @@ output(ostream &out) const { const StageNode &sn = *(*ri); TextureStage *stage = sn._stage; Texture *tex = sn._texture; - if (tex != NULL) { + if (tex != nullptr) { out << " " << stage->get_name() << ":" << tex->get_name(); } else { - out << " " << stage->get_name(); + out << " " << stage->get_name() << ":(" << sn._texture_type; + if (sn._texture_affects_rgb) { + out << " rgb"; + if (sn._texture_affects_alpha) { + out << "a"; + } + } else if (sn._texture_affects_alpha) { + out << " alpha"; + } + out << ")"; } if (sn._override != 0) { out << "^" << sn._override; @@ -500,6 +513,19 @@ compare_to_impl(const RenderAttrib *other) const { } } + if (texture == nullptr) { + // This is an attribute returned by get_auto_shader_attrib_impl. + if ((*si)._texture_type != (*osi)._texture_type) { + return (*si)._texture_type < (*osi)._texture_type ? -1 : 1; + } + if ((*si)._texture_affects_rgb != (*osi)._texture_affects_rgb) { + return (*si)._texture_affects_rgb < (*osi)._texture_affects_rgb ? -1 : 1; + } + if ((*si)._texture_affects_alpha != (*osi)._texture_affects_alpha) { + return (*si)._texture_affects_alpha < (*osi)._texture_affects_alpha ? -1 : 1; + } + } + ++si; ++osi; } @@ -563,6 +589,13 @@ get_hash_impl() const { hash = pointer_hash::add_hash(hash, sn._texture); hash = int_hash::add_hash(hash, (int)sn._implicit_sort); hash = int_hash::add_hash(hash, sn._override); + + if (sn._texture == nullptr) { + // This is an attribute returned by get_auto_shader_attrib_impl. + hash = int_hash::add_hash(hash, (int)sn._texture_type); + hash = int_hash::add_hash(hash, (int)sn._texture_affects_rgb); + hash = int_hash::add_hash(hash, (int)sn._texture_affects_alpha); + } } // This bool value goes here, between the two lists, to differentiate @@ -739,7 +772,42 @@ invert_compose_impl(const RenderAttrib *other) const { */ CPT(RenderAttrib) TextureAttrib:: get_auto_shader_attrib_impl(const RenderState *state) const { - return this; + if (_on_stages.empty()) { + // Having no stages is the same as not applying a texture attribute. + return nullptr; + } + + // We make a texture attribute that does not store the texture and sampler, + // so that we don't have to generate a shader for every possible texture. + // We do have to store the few texture properties that do affect the + // generated shader. + PT(TextureAttrib) attrib = new TextureAttrib; + attrib->_on_stages = _on_stages; + attrib->sort_on_stages(); + + Stages::iterator si; + for (si = attrib->_on_stages.begin(); si != attrib->_on_stages.end(); ++si) { + Texture::Format format = (*si)._texture->get_format(); + (*si)._texture_type = (*si)._texture->get_texture_type(); + (*si)._texture_affects_rgb = (format != Texture::F_alpha); + (*si)._texture_affects_alpha = Texture::has_alpha(format); + (*si)._texture = nullptr; + (*si)._has_sampler = false; + + // We will no longer be composing or sorting this state so we can get rid + // of these values. + (*si)._override = 0; + (*si)._implicit_sort = 0; + + // Exception to optimize a common case: if the first texture is an RGB + // texture, we don't care about whether it affects the alpha channel. + if (attrib->_render_stages[0] == &(*si) && + (*si)._texture_affects_rgb && !(*si)._texture_affects_alpha) { + (*si)._texture_affects_alpha = true; + } + } + + return return_new(attrib); } /** diff --git a/panda/src/pgraph/textureAttrib.h b/panda/src/pgraph/textureAttrib.h index 2cc5270536..9f1c13e3c8 100644 --- a/panda/src/pgraph/textureAttrib.h +++ b/panda/src/pgraph/textureAttrib.h @@ -59,6 +59,7 @@ PUBLISHED: INLINE int get_ff_tc_index(int n) const; INLINE bool has_on_stage(TextureStage *stage) const; INLINE Texture *get_on_texture(TextureStage *stage) const; + INLINE Texture::TextureType get_on_texture_type(TextureStage *stage) const; INLINE const SamplerState &get_on_sampler(TextureStage *stage) const; INLINE int get_on_stage_override(TextureStage *stage) const; @@ -81,6 +82,8 @@ PUBLISHED: CPT(RenderAttrib) unify_texture_stages(TextureStage *stage) const; public: + INLINE bool on_stage_affects_rgb(size_t n) const; + INLINE bool on_stage_affects_alpha(size_t n) const; CPT(TextureAttrib) filter_to_max(int max_texture_stages) const; virtual bool lower_attrib_can_override() const; @@ -114,6 +117,11 @@ private: int _ff_tc_index; unsigned int _implicit_sort; int _override; + + // These fields are used by the shader generator. + Texture::TextureType _texture_type : 16; + bool _texture_affects_rgb : 8; + bool _texture_affects_alpha : 8; }; class CompareTextureStagePriorities { diff --git a/panda/src/pgraph/transparencyAttrib.cxx b/panda/src/pgraph/transparencyAttrib.cxx index 4dd7d0a1c2..d998004f09 100644 --- a/panda/src/pgraph/transparencyAttrib.cxx +++ b/panda/src/pgraph/transparencyAttrib.cxx @@ -114,7 +114,14 @@ get_hash_impl() const { */ CPT(RenderAttrib) TransparencyAttrib:: get_auto_shader_attrib_impl(const RenderState *state) const { - return this; + if (_mode == TransparencyAttrib::M_alpha) { + return this; + } else if (_mode == TransparencyAttrib::M_premultiplied_alpha || + _mode == TransparencyAttrib::M_dual) { + return return_new(new TransparencyAttrib(M_alpha)); + } else { + return nullptr; + } } /** diff --git a/panda/src/pgraphnodes/shaderGenerator.cxx b/panda/src/pgraphnodes/shaderGenerator.cxx index f5c15f136c..46b9701d3c 100644 --- a/panda/src/pgraphnodes/shaderGenerator.cxx +++ b/panda/src/pgraphnodes/shaderGenerator.cxx @@ -357,10 +357,14 @@ analyze_renderstate(const RenderState *rs) { } // Determine whether we should normalize the normals. - const RescaleNormalAttrib *rescale; + /*const RescaleNormalAttrib *rescale; rs->get_attrib_def(rescale); _normalize_normals = (rescale->get_mode() != RescaleNormalAttrib::M_none); + */ + // Actually, let's always normalize the normals for now. This helps to + // reduce combinatoric explosion of shaders. + _normalize_normals = true; // Decide which material modes need to be calculated. @@ -823,11 +827,10 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) { text << "\t in float4 l_" << it->first->join("_") << " : " << it->second << ",\n"; } const TexMatrixAttrib *tex_matrix = DCAST(TexMatrixAttrib, rs->get_attrib_def(TexMatrixAttrib::get_class_slot())); - for (int i=0; i<_num_textures; i++) { + for (int i = 0; i < _num_textures; ++i) { TextureStage *stage = texture->get_on_stage(i); - Texture *tex = texture->get_on_texture(stage); - nassertr(tex != NULL, NULL); - text << "\t uniform sampler" << texture_type_as_string(tex->get_texture_type()) << " tex_" << i << ",\n"; + Texture::TextureType type = texture->get_on_texture_type(stage); + text << "\t uniform sampler" << texture_type_as_string(type) << " tex_" << i << ",\n"; if (tex_matrix->has_stage(stage)) { text << "\t uniform float4x4 texmat_" << i << ",\n"; } @@ -935,11 +938,10 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) { } text << "\t // Fetch all textures.\n"; if (_map_index_height >= 0 && parallax_mapping_samples > 0) { - Texture *tex = texture->get_on_texture(texture->get_on_stage(_map_index_height)); - nassertr(tex != NULL, NULL); - text << "\t float4 tex" << _map_index_height << " = tex" << texture_type_as_string(tex->get_texture_type()); + Texture::TextureType type = texture->get_on_texture_type(texture->get_on_stage(_map_index_height)); + text << "\t float4 tex" << _map_index_height << " = tex" << texture_type_as_string(type); text << "(tex_" << _map_index_height << ", texcoord" << _map_index_height << "."; - switch (tex->get_texture_type()) { + switch (type) { case Texture::TT_cube_map: case Texture::TT_3d_texture: case Texture::TT_2d_texture_array: @@ -972,18 +974,17 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) { text << " * 2.0 - 1.0)) * " << 0.5 * parallax_mapping_scale << ";\n"; } } - for (int i=0; i<_num_textures; i++) { + for (int i = 0; i < _num_textures; ++i) { if (i != _map_index_height) { - Texture *tex = texture->get_on_texture(texture->get_on_stage(i)); - nassertr(tex != NULL, NULL); + Texture::TextureType type = texture->get_on_texture_type(texture->get_on_stage(i)); // Parallax mapping pushes the texture coordinates of the other textures // away from the camera. if (_map_index_height >= 0 && parallax_mapping_samples > 0) { text << "\t texcoord" << i << ".xyz -= parallax_offset;\n"; } - text << "\t float4 tex" << i << " = tex" << texture_type_as_string(tex->get_texture_type()); + text << "\t float4 tex" << i << " = tex" << texture_type_as_string(type); text << "(tex_" << i << ", texcoord" << i << "."; - switch(tex->get_texture_type()) { + switch (type) { case Texture::TT_cube_map: case Texture::TT_3d_texture: case Texture::TT_2d_texture_array: @@ -1263,20 +1264,20 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) { } // Now loop through the textures to compose our magic blending formulas. - for (int i=0; i<_num_textures; i++) { + for (int i = 0; i < _num_textures; ++i) { TextureStage *stage = texture->get_on_stage(i); switch (stage->get_mode()) { case TextureStage::M_modulate: { - int num_components = texture->get_on_texture(texture->get_on_stage(i))->get_num_components(); + bool affects_rgb = texture->on_stage_affects_rgb(i); + bool affects_alpha = texture->on_stage_affects_alpha(i); - if (num_components == 1) { - text << "\t result.a *= tex" << i << ".a;\n"; - } else if (num_components == 3) { - text << "\t result.rgb *= tex" << i << ".rgb;\n"; - } else { + if (affects_rgb && affects_alpha) { text << "\t result.rgba *= tex" << i << ".rgba;\n"; + } else if (affects_alpha) { + text << "\t result.a *= tex" << i << ".a;\n"; + } else if (affects_rgb) { + text << "\t result.rgb *= tex" << i << ".rgb;\n"; } - break; } case TextureStage::M_modulate_glow: case TextureStage::M_modulate_gloss: From b41496b17aec40604b9da4fdd011869e50415e65 Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 20 Jun 2017 19:15:12 +0200 Subject: [PATCH 4/9] Fix texpad/texpix inputs not updating (fixes CommonFilters resize issue) --- panda/src/gobj/shader.cxx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/panda/src/gobj/shader.cxx b/panda/src/gobj/shader.cxx index f0cb8e0506..7147a108c0 100644 --- a/panda/src/gobj/shader.cxx +++ b/panda/src/gobj/shader.cxx @@ -428,7 +428,9 @@ cp_dependency(ShaderMatInput inp) { (inp == SMO_view_to_apiclip_x)) { dep |= SSD_shaderinputs; - if ((inp == SMO_alight_x) || + if ((inp == SMO_texpad_x) || + (inp == SMO_texpix_x) || + (inp == SMO_alight_x) || (inp == SMO_dlight_x) || (inp == SMO_plight_x) || (inp == SMO_slight_x) || From 3eb91e38b51b4f7b699213514f60f99b1bafc80f Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 20 Jun 2017 19:37:57 +0200 Subject: [PATCH 5/9] CommonFilters: fix edge bleeding when using POT textures (LP 424640) --- direct/src/filter/filter-bloomx.sha | 5 +++-- direct/src/filter/filter-bloomy.sha | 5 +++-- direct/src/filter/filter-blurx.sha | 10 ++++++---- direct/src/filter/filter-blury.sha | 10 ++++++---- 4 files changed, 18 insertions(+), 12 deletions(-) diff --git a/direct/src/filter/filter-bloomx.sha b/direct/src/filter/filter-bloomx.sha index 6819936fc4..300ffeff2e 100644 --- a/direct/src/filter/filter-bloomx.sha +++ b/direct/src/filter/filter-bloomx.sha @@ -12,8 +12,9 @@ void vshader(float4 vtx_position : POSITION, l_position=mul(mat_modelproj, vtx_position); float2 c=(vtx_position.xz * texpad_src.xy) + texpad_src.xy; float offset = texpix_src.x; - l_texcoord0 = float4(c.x-offset* -4, c.x-offset* -3, c.x-offset* -2, c.y); - l_texcoord1 = float4(c.x-offset* -1, c.x-offset* 0, c.x-offset* 1, c.y); + float pad = texpad_src.x * 2; + l_texcoord0 = float4(min(c.x-offset* -4, pad), min(c.x-offset* -3, pad), min(c.x-offset* -2, pad), c.y); + l_texcoord1 = float4(min(c.x-offset* -1, pad), c.x-offset* 0, c.x-offset* 1, c.y); l_texcoord2 = float4(c.x-offset* 2, c.x-offset* 3, c.x-offset* 4, c.y); } diff --git a/direct/src/filter/filter-bloomy.sha b/direct/src/filter/filter-bloomy.sha index 2351c70dd3..51912b8b60 100644 --- a/direct/src/filter/filter-bloomy.sha +++ b/direct/src/filter/filter-bloomy.sha @@ -12,8 +12,9 @@ void vshader(float4 vtx_position : POSITION, l_position=mul(mat_modelproj, vtx_position); float2 c=(vtx_position.xz * texpad_src.xy) + texpad_src.xy; float offset = texpix_src.y; - l_texcoord0 = float4(c.y-offset* -4, c.y-offset* -3, c.y-offset* -2, c.x); - l_texcoord1 = float4(c.y-offset* -1, c.y-offset* 0, c.y-offset* 1, c.x); + float pad = texpad_src.y * 2; + l_texcoord0 = float4(min(c.y-offset* -4, pad), min(c.y-offset* -3, pad), min(c.y-offset* -2, pad), c.x); + l_texcoord1 = float4(min(c.y-offset* -1, pad), c.y-offset* 0, c.y-offset* 1, c.x); l_texcoord2 = float4(c.y-offset* 2, c.y-offset* 3, c.y-offset* 4, c.x); } diff --git a/direct/src/filter/filter-blurx.sha b/direct/src/filter/filter-blurx.sha index 2cb6c1512d..47a2217af3 100644 --- a/direct/src/filter/filter-blurx.sha +++ b/direct/src/filter/filter-blurx.sha @@ -2,7 +2,7 @@ // //Cg profile arbvp1 arbfp1 -void vshader(float4 vtx_position : POSITION, +void vshader(float4 vtx_position : POSITION, float2 vtx_texcoord0 : TEXCOORD0, out float4 l_position : POSITION, out float2 l_texcoord0 : TEXCOORD0, @@ -17,16 +17,18 @@ void vshader(float4 vtx_position : POSITION, void fshader(float2 l_texcoord0 : TEXCOORD0, out float4 o_color : COLOR, uniform float2 texpix_src, + uniform float4 texpad_src, uniform sampler2D k_src : TEXUNIT0) { + float pad = texpad_src.x * 2; float3 offset = float3(1.0*texpix_src.x, 2.0*texpix_src.x, 3.0*texpix_src.x); o_color = tex2D(k_src, l_texcoord0); o_color += tex2D(k_src, float2(l_texcoord0.x - offset.z, l_texcoord0.y)); o_color += tex2D(k_src, float2(l_texcoord0.x - offset.y, l_texcoord0.y)); o_color += tex2D(k_src, float2(l_texcoord0.x - offset.x, l_texcoord0.y)); - o_color += tex2D(k_src, float2(l_texcoord0.x + offset.x, l_texcoord0.y)); - o_color += tex2D(k_src, float2(l_texcoord0.x + offset.y, l_texcoord0.y)); - o_color += tex2D(k_src, float2(l_texcoord0.x + offset.z, l_texcoord0.y)); + o_color += tex2D(k_src, float2(min(l_texcoord0.x + offset.x, pad), l_texcoord0.y)); + o_color += tex2D(k_src, float2(min(l_texcoord0.x + offset.y, pad), l_texcoord0.y)); + o_color += tex2D(k_src, float2(min(l_texcoord0.x + offset.z, pad), l_texcoord0.y)); o_color /= 7; o_color.w = 1; } diff --git a/direct/src/filter/filter-blury.sha b/direct/src/filter/filter-blury.sha index b927cf0329..ab135c363a 100644 --- a/direct/src/filter/filter-blury.sha +++ b/direct/src/filter/filter-blury.sha @@ -2,7 +2,7 @@ // //Cg profile arbvp1 arbfp1 -void vshader(float4 vtx_position : POSITION, +void vshader(float4 vtx_position : POSITION, float2 vtx_texcoord0 : TEXCOORD0, out float4 l_position : POSITION, out float2 l_texcoord0 : TEXCOORD0, @@ -17,16 +17,18 @@ void vshader(float4 vtx_position : POSITION, void fshader(float2 l_texcoord0 : TEXCOORD0, out float4 o_color : COLOR, uniform float2 texpix_src, + uniform float4 texpad_src, uniform sampler2D k_src : TEXUNIT0) { + float pad = texpad_src.y * 2; float3 offset = float3(1.0*texpix_src.y, 2.0*texpix_src.y, 3.0*texpix_src.y); o_color = tex2D(k_src, l_texcoord0); o_color += tex2D(k_src, float2(l_texcoord0.x, l_texcoord0.y - offset.z)); o_color += tex2D(k_src, float2(l_texcoord0.x, l_texcoord0.y - offset.y)); o_color += tex2D(k_src, float2(l_texcoord0.x, l_texcoord0.y - offset.x)); - o_color += tex2D(k_src, float2(l_texcoord0.x, l_texcoord0.y + offset.x)); - o_color += tex2D(k_src, float2(l_texcoord0.x, l_texcoord0.y + offset.y)); - o_color += tex2D(k_src, float2(l_texcoord0.x, l_texcoord0.y + offset.z)); + o_color += tex2D(k_src, float2(l_texcoord0.x, min(l_texcoord0.y + offset.x, pad))); + o_color += tex2D(k_src, float2(l_texcoord0.x, min(l_texcoord0.y + offset.y, pad))); + o_color += tex2D(k_src, float2(l_texcoord0.x, min(l_texcoord0.y + offset.z, pad))); o_color /= 7; o_color.w = 1; } From c6dda2a44a929f46ca86c5b197e0efe8bf9d0b37 Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 20 Jun 2017 21:52:04 +0200 Subject: [PATCH 6/9] vfs: Show IOError instead of AssertionError if read_file fails The methods are marked non-BLOCKING since the GIL needs to be held while throwing exceptions. We handle the GIL in the extension functions instead. --- panda/src/express/virtualFile.h | 4 +-- panda/src/express/virtualFileSystem.h | 4 +-- panda/src/express/virtualFileSystem_ext.cxx | 15 +++++++++++- panda/src/express/virtualFile_ext.cxx | 27 ++++++++++++++++++++- 4 files changed, 44 insertions(+), 6 deletions(-) diff --git a/panda/src/express/virtualFile.h b/panda/src/express/virtualFile.h index 0719f3f8d1..5322fce670 100644 --- a/panda/src/express/virtualFile.h +++ b/panda/src/express/virtualFile.h @@ -56,12 +56,12 @@ PUBLISHED: BLOCKING void ls(ostream &out = cout) const; BLOCKING void ls_all(ostream &out = cout) const; - EXTENSION(BLOCKING PyObject *read_file(bool auto_unwrap) const); + EXTENSION(PyObject *read_file(bool auto_unwrap) const); BLOCKING virtual istream *open_read_file(bool auto_unwrap) const; BLOCKING virtual void close_read_file(istream *stream) const; virtual bool was_read_successful() const; - EXTENSION(BLOCKING PyObject *write_file(PyObject *data, bool auto_wrap)); + EXTENSION(PyObject *write_file(PyObject *data, bool auto_wrap)); BLOCKING virtual ostream *open_write_file(bool auto_wrap, bool truncate); BLOCKING virtual ostream *open_append_file(); BLOCKING virtual void close_write_file(ostream *stream); diff --git a/panda/src/express/virtualFileSystem.h b/panda/src/express/virtualFileSystem.h index 22d6316ce7..2ff1fa4e95 100644 --- a/panda/src/express/virtualFileSystem.h +++ b/panda/src/express/virtualFileSystem.h @@ -95,11 +95,11 @@ PUBLISHED: static VirtualFileSystem *get_global_ptr(); - EXTENSION(BLOCKING PyObject *read_file(const Filename &filename, bool auto_unwrap) const); + EXTENSION(PyObject *read_file(const Filename &filename, bool auto_unwrap) const); BLOCKING istream *open_read_file(const Filename &filename, bool auto_unwrap) const; BLOCKING static void close_read_file(istream *stream); - EXTENSION(BLOCKING PyObject *write_file(const Filename &filename, PyObject *data, bool auto_wrap)); + EXTENSION(PyObject *write_file(const Filename &filename, PyObject *data, bool auto_wrap)); BLOCKING ostream *open_write_file(const Filename &filename, bool auto_wrap, bool truncate); BLOCKING ostream *open_append_file(const Filename &filename); BLOCKING static void close_write_file(ostream *stream); diff --git a/panda/src/express/virtualFileSystem_ext.cxx b/panda/src/express/virtualFileSystem_ext.cxx index dc50751c52..6bc375c0d9 100644 --- a/panda/src/express/virtualFileSystem_ext.cxx +++ b/panda/src/express/virtualFileSystem_ext.cxx @@ -26,9 +26,22 @@ */ PyObject *Extension:: read_file(const Filename &filename, bool auto_unwrap) const { + // Release the GIL while we do this potentially slow operation. +#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS) + PyThreadState *_save; + Py_UNBLOCK_THREADS +#endif + vector_uchar pv; bool okflag = _this->read_file(filename, pv, auto_unwrap); - nassertr(okflag, NULL); + +#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS) + Py_BLOCK_THREADS +#endif + + if (!okflag) { + return PyErr_Format(PyExc_IOError, "Failed to read file: '%s'", filename.c_str()); + } #if PY_MAJOR_VERSION >= 3 if (pv.empty()) { diff --git a/panda/src/express/virtualFile_ext.cxx b/panda/src/express/virtualFile_ext.cxx index d81672cc50..db1a9a62ab 100644 --- a/panda/src/express/virtualFile_ext.cxx +++ b/panda/src/express/virtualFile_ext.cxx @@ -26,9 +26,23 @@ */ PyObject *Extension:: read_file(bool auto_unwrap) const { + // Release the GIL while we do this potentially slow operation. +#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS) + PyThreadState *_save; + Py_UNBLOCK_THREADS +#endif + vector_uchar pv; bool okflag = _this->read_file(pv, auto_unwrap); - nassertr(okflag, NULL); + +#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS) + Py_BLOCK_THREADS +#endif + + if (!okflag) { + Filename fn = _this->get_filename(); + return PyErr_Format(PyExc_IOError, "Failed to read file: '%s'", fn.c_str()); + } #if PY_MAJOR_VERSION >= 3 if (pv.empty()) { @@ -68,7 +82,18 @@ write_file(PyObject *data, bool auto_wrap) { } #endif + // Release the GIL while we do this potentially slow operation. +#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS) + PyThreadState *_save; + Py_UNBLOCK_THREADS +#endif + bool result = _this->write_file((const unsigned char *)buffer, length, auto_wrap); + +#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS) + Py_BLOCK_THREADS +#endif + return PyBool_FromLong(result); } From 40c6f41da2864b4ddcd006373b831421001b93e7 Mon Sep 17 00:00:00 2001 From: wezu Date: Tue, 20 Jun 2017 21:53:57 +0200 Subject: [PATCH 7/9] direct: provide snake_case functions for some classes Closes #147 --- direct/src/actor/Actor.py | 94 +++++++++++++++++++++++++++ direct/src/controls/InputState.py | 13 ++++ direct/src/filter/CommonFilters.py | 21 ++++++ direct/src/filter/FilterManager.py | 12 ++++ direct/src/showbase/Audio3DManager.py | 24 +++++++ direct/src/showbase/DirectObject.py | 12 ++++ direct/src/showbase/Messenger.py | 13 ++++ 7 files changed, 189 insertions(+) diff --git a/direct/src/actor/Actor.py b/direct/src/actor/Actor.py index 29db4290bd..5a64c1fe2a 100644 --- a/direct/src/actor/Actor.py +++ b/direct/src/actor/Actor.py @@ -50,6 +50,10 @@ class Actor(DirectObject, NodePath): def __repr__(self): return 'Actor.PartDef(%s, %s)' % (repr(self.partBundleNP), repr(self.partModel)) + + #snake_case alias: + get_bundle = getBundle + class AnimDef: """Instances of this class are stored within the @@ -72,6 +76,10 @@ class Actor(DirectObject, NodePath): def __repr__(self): return 'Actor.AnimDef(%s)' % (repr(self.filename)) + + #snake_case alias: + make_copy = makeCopy + class SubpartDef: """Instances of this class are stored within the SubpartDict @@ -2549,3 +2557,89 @@ class Actor(DirectObject, NodePath): for partBundleDict in self.__partBundleDict.values(): partDef = partBundleDict.get(subpartDef.truePartName) partDef.getBundle().setName(newBundleName) + + #snake_case alias: + control_joint = controlJoint + set_lod_animation = setLODAnimation + get_anim_control_dict = getAnimControlDict + get_actor_info = getActorInfo + clear_lod_animation = clearLODAnimation + reset_lod = resetLOD + fix_bounds = fixBounds + get_anim_filename = getAnimFilename + get_subparts_complete = getSubpartsComplete + verify_subparts_complete = verifySubpartsComplete + get_play_rate = getPlayRate + clear_python_data = clearPythonData + load_anims = loadAnims + set_subparts_complete = setSubpartsComplete + draw_in_front = drawInFront + get_lod_node = getLODNode + hide_part = hidePart + get_joint_transform_state = getJointTransformState + set_control_effect = setControlEffect + get_anim_controls = getAnimControls + release_joint = releaseJoint + print_anim_blends = printAnimBlends + get_lod = getLOD + disable_blend = disableBlend + show_part = showPart + get_joint_transform = getJointTransform + face_away_from_viewer = faceAwayFromViewer + set_lod = setLOD + osd_anim_blends = osdAnimBlends + get_current_frame = getCurrentFrame + set_play_rate = setPlayRate + bind_all_anims = bindAllAnims + unload_anims = unloadAnims + remove_part = removePart + use_lod = useLOD + get_anim_blends = getAnimBlends + get_lod_index = getLODIndex + get_num_frames = getNumFrames + post_flatten = postFlatten + get_lod_names = getLODNames + list_joints = listJoints + make_subpart = makeSubpart + get_anim_control = getAnimControl + get_part_bundle = getPartBundle + get_part_bundle_dict = getPartBundleDict + get_duration = getDuration + has_lod = hasLOD + print_lod = printLOD + fix_bounds_old = fixBounds_old + get_anim_names = getAnimNames + get_part_bundles = getPartBundles + anim_panel = animPanel + stop_joint = stopJoint + actor_interval = actorInterval + hide_all_bounds = hideAllBounds + show_all_bounds = showAllBounds + init_anims_on_all_lods = initAnimsOnAllLODs + get_part = getPart + add_lod = addLOD + show_all_parts = showAllParts + get_joints = getJoints + get_overlapping_joints = getOverlappingJoints + enable_blend = enableBlend + face_towards_viewer = faceTowardsViewer + bind_anim = bindAnim + set_blend = setBlend + get_frame_time = getFrameTime + remove_node = removeNode + wait_pending = waitPending + expose_joint = exposeJoint + set_lod_node = setLODNode + get_frame_rate = getFrameRate + get_current_anim = getCurrentAnim + get_part_names = getPartNames + freeze_joint = freezeJoint + set_center = setCenter + rename_part_bundles = renamePartBundles + get_geom_node = getGeomNode + set_geom_node = setGeomNode + load_model = loadModel + copy_actor = copyActor + get_base_frame_rate = getBaseFrameRate + remove_anim_control_dict = removeAnimControlDict + load_anims_on_all_lods = loadAnimsOnAllLODs diff --git a/direct/src/controls/InputState.py b/direct/src/controls/InputState.py index 38b0d78892..68608e9bea 100755 --- a/direct/src/controls/InputState.py +++ b/direct/src/controls/InputState.py @@ -21,6 +21,9 @@ class InputStateToken: def __hash__(self): return self._hash + #snake_case alias: + is_valid = isValid + class InputStateWatchToken(InputStateToken, DirectObject.DirectObject): def release(self): self._inputState._ignore(self) @@ -39,6 +42,9 @@ class InputStateTokenGroup: token.release() self._tokens = [] + #snake_case alias: + add_token = addToken + class InputState(DirectObject.DirectObject): """ InputState is for tracking the on/off state of some events. @@ -235,3 +241,10 @@ class InputState(DirectObject.DirectObject): """for debugging""" return self.notify.debug( "%s (%s) %s"%(id(self), len(self._state), message)) + + #snake_case alias: + watch_with_modifiers = watchWithModifiers + is_set = isSet + get_event_name = getEventName + debug_print = debugPrint + release_inputs = releaseInputs diff --git a/direct/src/filter/CommonFilters.py b/direct/src/filter/CommonFilters.py index 9cfe72d987..493f2d9794 100644 --- a/direct/src/filter/CommonFilters.py +++ b/direct/src/filter/CommonFilters.py @@ -536,3 +536,24 @@ class CommonFilters: del self.configuration["GammaAdjust"] return self.reconfigure((old_gamma != 1.0), "GammaAdjust") return True + + #snake_case alias: + del_cartoon_ink = delCartoonInk + set_half_pixel_shift = setHalfPixelShift + del_half_pixel_shift = delHalfPixelShift + set_inverted = setInverted + del_inverted = delInverted + del_view_glow = delViewGlow + set_volumetric_lighting = setVolumetricLighting + del_gamma_adjust = delGammaAdjust + set_bloom = setBloom + set_view_glow = setViewGlow + set_ambient_occlusion = setAmbientOcclusion + set_cartoon_ink = setCartoonInk + del_bloom = delBloom + del_ambient_occlusion = delAmbientOcclusion + load_shader = loadShader + set_blur_sharpen = setBlurSharpen + del_blur_sharpen = delBlurSharpen + del_volumetric_lighting = delVolumetricLighting + set_gamma_adjust = setGammaAdjust diff --git a/direct/src/filter/FilterManager.py b/direct/src/filter/FilterManager.py index bf35abf3c9..1de63c702d 100644 --- a/direct/src/filter/FilterManager.py +++ b/direct/src/filter/FilterManager.py @@ -349,3 +349,15 @@ class FilterManager(DirectObject): self.nextsort = self.win.getSort() - 1000 self.basex = 0 self.basey = 0 + + #snake_case alias: + is_fullscreen = isFullscreen + resize_buffers = resizeBuffers + set_stacked_clears = setStackedClears + render_scene_into = renderSceneInto + get_scaled_size = getScaledSize + render_quad_into = renderQuadInto + get_clears = getClears + set_clears = setClears + create_buffer = createBuffer + window_event = windowEvent diff --git a/direct/src/showbase/Audio3DManager.py b/direct/src/showbase/Audio3DManager.py index 07407c822b..463d3b5bf0 100644 --- a/direct/src/showbase/Audio3DManager.py +++ b/direct/src/showbase/Audio3DManager.py @@ -289,3 +289,27 @@ class Audio3DManager: for sound in self.sound_dict[object]: self.detachSound(sound) + #snake_case alias: + get_doppler_factor = getDopplerFactor + set_listener_velocity_auto = setListenerVelocityAuto + attach_listener = attachListener + set_distance_factor = setDistanceFactor + attach_sound_to_object = attachSoundToObject + get_drop_off_factor = getDropOffFactor + set_doppler_factor = setDopplerFactor + get_sounds_on_object = getSoundsOnObject + set_sound_velocity_auto = setSoundVelocityAuto + get_sound_max_distance = getSoundMaxDistance + load_sfx = loadSfx + get_distance_factor = getDistanceFactor + set_listener_velocity = setListenerVelocity + set_sound_max_distance = setSoundMaxDistance + get_sound_velocity = getSoundVelocity + get_listener_velocity = getListenerVelocity + set_sound_velocity = setSoundVelocity + set_sound_min_distance = setSoundMinDistance + get_sound_min_distance = getSoundMinDistance + detach_listener = detachListener + set_drop_off_factor = setDropOffFactor + detach_sound = detachSound + diff --git a/direct/src/showbase/DirectObject.py b/direct/src/showbase/DirectObject.py index 9106637134..778328ea50 100644 --- a/direct/src/showbase/DirectObject.py +++ b/direct/src/showbase/DirectObject.py @@ -101,3 +101,15 @@ class DirectObject: func = choice(getRepository()._crashOnProactiveLeakDetect, self.notify.error, self.notify.warning) func('destroyed %s instance is still %s%s' % (self.__class__.__name__, estr, tstr)) + + #snake_case alias: + add_task = addTask + do_method_later = doMethodLater + detect_leaks = detectLeaks + accept_once = acceptOnce + ignore_all = ignoreAll + get_all_accepting = getAllAccepting + is_ignoring = isIgnoring + remove_all_tasks = removeAllTasks + remove_task = removeTask + is_accepting = isAccepting diff --git a/direct/src/showbase/Messenger.py b/direct/src/showbase/Messenger.py index 09ceb9cd0a..08062e4a3e 100644 --- a/direct/src/showbase/Messenger.py +++ b/direct/src/showbase/Messenger.py @@ -635,3 +635,16 @@ class Messenger: str = str + '='*50 + '\n' return str + #snake_case alias: + get_events = getEvents + is_ignoring = isIgnoring + who_accepts = whoAccepts + find_all = findAll + replace_method = replaceMethod + ignore_all = ignoreAll + is_accepting = isAccepting + is_empty = isEmpty + detailed_repr = detailedRepr + get_all_accepting = getAllAccepting + toggle_verbose = toggleVerbose + From 511b0c10e570a31a3454c36b2dad7631570aac2d Mon Sep 17 00:00:00 2001 From: rdb Date: Thu, 22 Jun 2017 13:35:46 +0200 Subject: [PATCH 8/9] 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; From 9c4151cb0f167feea43e74ed003a8c1f98e09f5b Mon Sep 17 00:00:00 2001 From: rdb Date: Thu, 22 Jun 2017 13:36:23 +0200 Subject: [PATCH 9/9] ShaderGenerator: fix TextureAttrib assertion This was caused by af57c829d2c15530f72395895353c004a7440a35 and was triggered by a change in TextureStage sort. --- panda/src/pgraph/textureAttrib.I | 2 +- panda/src/pgraph/textureAttrib.cxx | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/panda/src/pgraph/textureAttrib.I b/panda/src/pgraph/textureAttrib.I index 2b008b2f51..6649c8d87a 100644 --- a/panda/src/pgraph/textureAttrib.I +++ b/panda/src/pgraph/textureAttrib.I @@ -263,7 +263,7 @@ on_stage_affects_alpha(size_t n) const { */ INLINE void TextureAttrib:: check_sorted() const { - if (_sort_seq != TextureStage::get_sort_seq()) { + if (_sort_seq != TextureStage::get_sort_seq() && !_sort_seq.is_fresh()) { ((TextureAttrib *)this)->sort_on_stages(); } } diff --git a/panda/src/pgraph/textureAttrib.cxx b/panda/src/pgraph/textureAttrib.cxx index 09e9f7ce7e..8c1b4833ff 100644 --- a/panda/src/pgraph/textureAttrib.cxx +++ b/panda/src/pgraph/textureAttrib.cxx @@ -807,6 +807,9 @@ get_auto_shader_attrib_impl(const RenderState *state) const { } } + // Prevent check_sorted() from being called on this state. + attrib->_sort_seq = UpdateSeq::fresh(); + return return_new(attrib); }