diff --git a/panda/src/display/graphicsEngine.cxx b/panda/src/display/graphicsEngine.cxx index 2222214e4a..22b2b876f8 100644 --- a/panda/src/display/graphicsEngine.cxx +++ b/panda/src/display/graphicsEngine.cxx @@ -1360,9 +1360,9 @@ cull_and_draw_together(const GraphicsEngine::Windows &wlist, Thread *current_thread) { PStatTimer timer(_cull_pcollector, current_thread); - Windows::const_iterator wi; - for (wi = wlist.begin(); wi != wlist.end(); ++wi) { - GraphicsOutput *win = (*wi); + size_t wlist_size = wlist.size(); + for (size_t wi = 0; wi < wlist_size; ++wi) { + GraphicsOutput *win = wlist[wi]; if (win->is_active() && win->get_gsg()->is_active()) { if (win->flip_ready()) { { @@ -1486,9 +1486,9 @@ cull_to_bins(const GraphicsEngine::Windows &wlist, Thread *current_thread) { typedef pmap AlreadyCulled; AlreadyCulled already_culled; - Windows::const_iterator wi; - for (wi = wlist.begin(); wi != wlist.end(); ++wi) { - GraphicsOutput *win = (*wi); + size_t wlist_size = wlist.size(); + for (size_t wi = 0; wi < wlist_size; ++wi) { + GraphicsOutput *win = wlist[wi]; if (win->is_active() && win->get_gsg()->is_active()) { PStatTimer timer(win->get_cull_window_pcollector(), current_thread); int num_display_regions = win->get_num_active_display_regions(); @@ -1997,6 +1997,14 @@ 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. + if (gsg->get_shader_generator() == NULL) { + gsg->set_shader_generator(new ShaderGenerator(gsg, window)); + } + return scene_setup; } diff --git a/panda/src/display/graphicsStateGuardian.I b/panda/src/display/graphicsStateGuardian.I index 703bc72c7a..a4cea5ffc3 100644 --- a/panda/src/display/graphicsStateGuardian.I +++ b/panda/src/display/graphicsStateGuardian.I @@ -214,6 +214,28 @@ get_loader() const { return _loader; } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::set_shader_generator +// Access: Public +// Description: Sets the ShaderGenerator object that will be used +// by this GSG to generate shaders when necessary. +//////////////////////////////////////////////////////////////////// +INLINE void GraphicsStateGuardian:: +set_shader_generator(ShaderGenerator *shader_generator) { + _shader_generator = shader_generator; +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::get_shader_generator +// Access: Public +// Description: Returns the ShaderGenerator object that will be used +// by this GSG to generate shaders when necessary. +//////////////////////////////////////////////////////////////////// +INLINE ShaderGenerator *GraphicsStateGuardian:: +get_shader_generator() const { + return _shader_generator; +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::get_pipe // Access: Published diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index 9760387a48..aab3814dd3 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -266,8 +266,6 @@ GraphicsStateGuardian(CoordinateSystem internal_coordinate_system, _gamma = 1.0f; _texture_quality_override = Texture::QL_default; - - _shader_generator = NULL; } //////////////////////////////////////////////////////////////////// @@ -278,12 +276,6 @@ GraphicsStateGuardian(CoordinateSystem internal_coordinate_system, GraphicsStateGuardian:: ~GraphicsStateGuardian() { remove_gsg(this); - - if (_shader_generator) { - delete _shader_generator; - _shader_generator = 0; - } - GeomMunger::unregister_mungers_for_gsg(this); } diff --git a/panda/src/display/graphicsStateGuardian.h b/panda/src/display/graphicsStateGuardian.h index 32a3e863c0..deec626996 100644 --- a/panda/src/display/graphicsStateGuardian.h +++ b/panda/src/display/graphicsStateGuardian.h @@ -49,10 +49,10 @@ #include "shaderAttrib.h" #include "texGenAttrib.h" #include "textureAttrib.h" +#include "shaderGenerator.h" class DrawableRegion; class GraphicsEngine; -class ShaderGenerator; //////////////////////////////////////////////////////////////////// // Class : GraphicsStateGuardian @@ -104,6 +104,9 @@ PUBLISHED: INLINE void set_loader(Loader *loader); INLINE Loader *get_loader() const; + INLINE void set_shader_generator(ShaderGenerator *shader_generator); + INLINE ShaderGenerator *get_shader_generator() const; + INLINE GraphicsPipe *get_pipe() const; GraphicsEngine *get_engine() const; INLINE const GraphicsThreadingModel &get_threading_model() const; @@ -546,7 +549,7 @@ protected: PN_stdfloat _gamma; Texture::QualityLevel _texture_quality_override; - ShaderGenerator* _shader_generator; + PT(ShaderGenerator) _shader_generator; #ifndef NDEBUG PT(Texture) _flash_texture; diff --git a/panda/src/display/standardMunger.cxx b/panda/src/display/standardMunger.cxx index 35c6231cd5..922150a114 100644 --- a/panda/src/display/standardMunger.cxx +++ b/panda/src/display/standardMunger.cxx @@ -43,15 +43,18 @@ StandardMunger(GraphicsStateGuardianBase *gsg, const RenderState *state, _munge_color = false; _munge_color_scale = false; + _auto_shader = false; if (!get_gsg()->get_runtime_color_scale()) { // We might need to munge the colors. - CPT(ColorAttrib) color_attrib = DCAST(ColorAttrib, state->get_attrib(ColorAttrib::get_class_slot())); - CPT(ColorScaleAttrib) color_scale_attrib = DCAST(ColorScaleAttrib, state->get_attrib(ColorScaleAttrib::get_class_slot())); + const ColorAttrib *color_attrib = (const ColorAttrib *) + state->get_attrib(ColorAttrib::get_class_slot()); + const ColorScaleAttrib *color_scale_attrib = (const ColorScaleAttrib *) + state->get_attrib(ColorScaleAttrib::get_class_slot()); if (color_attrib != (ColorAttrib *)NULL && color_attrib->get_color_type() == ColorAttrib::T_flat) { - + if (!get_gsg()->get_color_scale_via_lighting()) { // We only need to munge the color directly if the GSG says it // can't cheat the color via lighting (presumably, in this case, @@ -72,15 +75,16 @@ StandardMunger(GraphicsStateGuardianBase *gsg, const RenderState *state, color_scale_attrib->has_scale()) { _color_scale = color_scale_attrib->get_scale(); - CPT(TextureAttrib) tex_attrib = DCAST(TextureAttrib, state->get_attrib(TextureAttrib::get_class_slot())); - + const TextureAttrib *tex_attrib = (const TextureAttrib *) + state->get_attrib(TextureAttrib::get_class_slot()); + // If the GSG says it can't cheat this RGB or alpha scale, we have // to apply the color scale directly. if ((color_scale_attrib->has_rgb_scale() && !get_gsg()->get_color_scale_via_lighting()) || (color_scale_attrib->has_alpha_scale() && !get_gsg()->get_alpha_scale_via_texture(tex_attrib))) { _munge_color_scale = true; } - + // Known bug: if there is a material on an object that would // obscure the effect of color_scale, we scale the lighting // anyway, thus applying the effect even if it should be obscured. @@ -88,6 +92,12 @@ StandardMunger(GraphicsStateGuardianBase *gsg, const RenderState *state, // situation and handle it correctly. } } + + const ShaderAttrib *shader_attrib = (const ShaderAttrib *) + state->get_attrib_def(ShaderAttrib::get_class_slot()); + if (shader_attrib->auto_shader()) { + _auto_shader = true; + } } //////////////////////////////////////////////////////////////////// @@ -297,6 +307,10 @@ compare_to_impl(const GeomMunger *other) const { } } + if (_auto_shader != om->_auto_shader) { + return (int)_auto_shader - (int)om->_auto_shader; + } + return StateMunger::compare_to_impl(other); } @@ -351,5 +365,20 @@ munge_state_impl(const RenderState *state) { munged_state = munged_state->remove_attrib(ColorScaleAttrib::get_class_slot()); } + 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; + } + if (shader_state->_generated_shader == NULL) { + // Cache the generated ShaderAttrib on the shader state. + shader_state->_generated_shader = shader_generator->synthesize_shader(shader_state); + } + munged_state = munged_state->set_attrib(shader_state->_generated_shader); + } + return munged_state; } diff --git a/panda/src/display/standardMunger.h b/panda/src/display/standardMunger.h index 9b432da718..1e2b8ef024 100644 --- a/panda/src/display/standardMunger.h +++ b/panda/src/display/standardMunger.h @@ -57,6 +57,7 @@ private: bool _munge_color; bool _munge_color_scale; + bool _auto_shader; LColor _color; LVecBase4 _color_scale; diff --git a/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx b/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx index 8f3be1402d..3ab2157e18 100755 --- a/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx +++ b/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx @@ -3194,16 +3194,6 @@ set_state_and_transform(const RenderState *target, _target_rs = target; _target_shader = DCAST(ShaderAttrib, _target_rs->get_attrib_def(ShaderAttrib::get_class_slot())); - if (_target_shader->auto_shader()) { - // If we don't have a generated shader, make sure we have a ShaderGenerator, then generate the shader. - if (_target_rs->_generated_shader == NULL) { - if (_shader_generator == NULL) { - _shader_generator = new ShaderGenerator(this, _scene_setup->get_display_region()->get_window()); - } - const_cast(_target_rs.p())->_generated_shader = DCAST(ShaderAttrib, _shader_generator->synthesize_shader(_target_rs)); - } - _target_shader = DCAST(ShaderAttrib, _target_rs->_generated_shader); - } int alpha_test_slot = AlphaTestAttrib::get_class_slot(); if (_target_rs->get_attrib(alpha_test_slot) != _state_rs->get_attrib(alpha_test_slot) || diff --git a/panda/src/pgraph/renderState.h b/panda/src/pgraph/renderState.h index 7ed8a05729..035ae6fbe9 100644 --- a/panda/src/pgraph/renderState.h +++ b/panda/src/pgraph/renderState.h @@ -215,7 +215,7 @@ public: // ShaderAttrib will be synthesized by the runtime and stored here. // I can't declare this as a ShaderAttrib because that would create // a circular include-file dependency problem. Aaargh. - CPT(RenderAttrib) _generated_shader; + mutable CPT(RenderAttrib) _generated_shader; private: // This mutex protects _states. It also protects any modification diff --git a/panda/src/pgraphnodes/shaderGenerator.cxx b/panda/src/pgraphnodes/shaderGenerator.cxx index 7e8dc54040..f3c7aeaade 100644 --- a/panda/src/pgraphnodes/shaderGenerator.cxx +++ b/panda/src/pgraphnodes/shaderGenerator.cxx @@ -53,8 +53,8 @@ TypeHandle ShaderGenerator::_type_handle; // which the shader generator belongs. //////////////////////////////////////////////////////////////////// ShaderGenerator:: -ShaderGenerator(PT(GraphicsStateGuardianBase) gsg, PT(GraphicsOutputBase) host) : - _gsg (gsg), _host (host) { +ShaderGenerator(GraphicsStateGuardianBase *gsg, GraphicsOutputBase *host) : + _gsg(gsg), _host(host) { } //////////////////////////////////////////////////////////////////// @@ -566,7 +566,7 @@ update_shadow_buffer(NodePath light_np) { } // See if we already have a buffer. If not, create one. - PT(Texture) tex; + Texture *tex; if (light->_sbuffers.count(_gsg) == 0) { // Nope, the light doesn't have a buffer for our GSG. Make one. tex = _gsg->make_shadow_buffer(light_np, _host); @@ -612,7 +612,7 @@ update_shadow_buffer(NodePath light_np) { // - omit attenuation calculations if attenuation off // //////////////////////////////////////////////////////////////////// -CPT(RenderAttrib) ShaderGenerator:: +CPT(ShaderAttrib) ShaderGenerator:: synthesize_shader(const RenderState *rs) { analyze_renderstate(rs); reset_register_allocator(); @@ -1462,7 +1462,7 @@ synthesize_shader(const RenderState *rs) { } clear_analysis(); reset_register_allocator(); - return shattr; + return DCAST(ShaderAttrib, shattr); } //////////////////////////////////////////////////////////////////// @@ -1636,4 +1636,3 @@ texture_type_as_string(Texture::TextureType ttype) { return "2D"; } } - diff --git a/panda/src/pgraphnodes/shaderGenerator.h b/panda/src/pgraphnodes/shaderGenerator.h index d08a3976a8..9028149e92 100644 --- a/panda/src/pgraphnodes/shaderGenerator.h +++ b/panda/src/pgraphnodes/shaderGenerator.h @@ -63,12 +63,11 @@ class LightAttrib; // Thanks to them! // //////////////////////////////////////////////////////////////////// - -class EXPCL_PANDA_PGRAPHNODES ShaderGenerator : public TypedObject { +class EXPCL_PANDA_PGRAPHNODES ShaderGenerator : public TypedReferenceCount { PUBLISHED: - ShaderGenerator(PT(GraphicsStateGuardianBase) gsg, PT(GraphicsOutputBase) host); + ShaderGenerator(GraphicsStateGuardianBase *gsg, GraphicsOutputBase *host); virtual ~ShaderGenerator(); - virtual CPT(RenderAttrib) synthesize_shader(const RenderState *rs); + virtual CPT(ShaderAttrib) synthesize_shader(const RenderState *rs); protected: CPT(RenderAttrib) create_shader_attrib(const string &txt); @@ -152,9 +151,9 @@ protected: void analyze_renderstate(const RenderState *rs); void clear_analysis(); - PT(GraphicsStateGuardianBase) _gsg; - PT(GraphicsOutputBase) _host; - pmap _generated_shaders; + // This is not a PT() to prevent a circular reference. + GraphicsStateGuardianBase *_gsg; + GraphicsOutputBase *_host; public: static TypeHandle get_class_type() { @@ -177,4 +176,3 @@ public: #include "shaderGenerator.I" #endif // SHADERGENERATOR_H -