From 962f43800d236f120346a1b0771897e20d927572 Mon Sep 17 00:00:00 2001 From: David Rose Date: Tue, 10 Oct 2006 17:58:08 +0000 Subject: [PATCH] add alpha-scale-via-texture --- panda/src/display/config_display.cxx | 14 +++- panda/src/display/config_display.h | 1 + panda/src/display/graphicsStateGuardian.I | 45 ++++++++++ panda/src/display/graphicsStateGuardian.cxx | 37 +++++++++ panda/src/display/graphicsStateGuardian.h | 17 ++++ panda/src/display/standardMunger.cxx | 23 ++--- .../glstuff/glGraphicsStateGuardian_src.cxx | 83 ++++++++++++------- panda/src/gobj/texture.cxx | 25 ++++++ panda/src/gobj/texture.h | 1 + panda/src/gobj/texturePool.I | 16 ++++ panda/src/gobj/texturePool.cxx | 17 ++++ panda/src/gobj/texturePool.h | 3 + panda/src/pgraph/colorScaleAttrib.I | 41 +++++---- panda/src/pgraph/colorScaleAttrib.cxx | 21 +++++ panda/src/pgraph/colorScaleAttrib.h | 6 +- panda/src/pgraph/nodePath.cxx | 30 +++++++ panda/src/pgraph/nodePath.h | 3 + panda/src/pgraph/renderAttrib.h | 5 ++ panda/src/pgraph/stateMunger.h | 2 +- panda/src/pgraph/texGenAttrib.I | 7 +- panda/src/pgraph/texGenAttrib.cxx | 79 +++++++++++++++++- panda/src/pgraph/texGenAttrib.h | 8 +- 22 files changed, 421 insertions(+), 63 deletions(-) diff --git a/panda/src/display/config_display.cxx b/panda/src/display/config_display.cxx index 54e7a12343..4e39e0d413 100644 --- a/panda/src/display/config_display.cxx +++ b/panda/src/display/config_display.cxx @@ -201,7 +201,19 @@ ConfigVariableBool color_scale_via_lighting "avoids the need to munge the vertex data to change each vertex's " "color. Set this false to avoid this trickery, so that lighting " "is only enabled when the application specifically enables " - "it.")); + "it. See also alpha-scale-via-texture.")); + +ConfigVariableBool alpha_scale_via_texture +("alpha-scale-via-texture", false, + PRC_DESC("When this is true, Panda will try to implement " + "ColorScaleAttribs that affect alpha by " + "creating an additional Texture layer over the geometry " + "with a uniform alpha scale applied everywhere, if there " + "is at least one available Texture slot available on the " + "multitexture pipeline. Set this false to avoid this " + "trickery, so that texturing is only enabled when the " + "application specifically enables it. See also " + "color-scale-via-lighting.")); ConfigVariableInt win_size ("win-size", "640 480", diff --git a/panda/src/display/config_display.h b/panda/src/display/config_display.h index ee78961ce1..4b5fd0fb9d 100644 --- a/panda/src/display/config_display.h +++ b/panda/src/display/config_display.h @@ -61,6 +61,7 @@ extern EXPCL_PANDA ConfigVariableString red_blue_stereo_colors; extern EXPCL_PANDA ConfigVariableBool depth_offset_decals; extern EXPCL_PANDA ConfigVariableBool auto_generate_mipmaps; extern EXPCL_PANDA ConfigVariableBool color_scale_via_lighting; +extern EXPCL_PANDA ConfigVariableBool alpha_scale_via_texture; extern EXPCL_PANDA ConfigVariableInt win_size; extern EXPCL_PANDA ConfigVariableInt win_origin; diff --git a/panda/src/display/graphicsStateGuardian.I b/panda/src/display/graphicsStateGuardian.I index 573898f48e..4d7d0273a2 100644 --- a/panda/src/display/graphicsStateGuardian.I +++ b/panda/src/display/graphicsStateGuardian.I @@ -573,6 +573,51 @@ get_color_scale_via_lighting() const { return _color_scale_via_lighting; } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::get_alpha_scale_via_texture +// Access: Published +// Description: Returns true if this particular GSG can implement (or +// would prefer to implement) an alpha scale via an +// additional Texture layer, or false if we need to +// actually munge the alpha. +//////////////////////////////////////////////////////////////////// +INLINE bool GraphicsStateGuardian:: +get_alpha_scale_via_texture() const { + return _alpha_scale_via_texture; +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::get_alpha_scale_via_texture +// Access: Published +// Description: This variant of get_alpha_scale_via_texture() answers +// the question of whether the GSG can implement an +// alpha scale via an additional Texture layer, +// considering the current TextureAttrib that will be in +// effect. This considers whether there is at least one +// additional texture slot available on the GSG. +//////////////////////////////////////////////////////////////////// +INLINE bool GraphicsStateGuardian:: +get_alpha_scale_via_texture(const TextureAttrib *tex_attrib) const { + return _alpha_scale_via_texture && + (tex_attrib->get_num_on_stages() < get_max_texture_stages()); +} + +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::get_alpha_scale_texture_stage +// Access: Published, Static +// Description: Returns the TextureStage that will be used to apply +// an alpha scale, if get_alpha_scale_via_texture() +// returns true. +//////////////////////////////////////////////////////////////////// +INLINE TextureStage *GraphicsStateGuardian:: +get_alpha_scale_texture_stage() { + if (_alpha_scale_texture_stage == (TextureStage *)NULL) { + _alpha_scale_texture_stage = new TextureStage("alpha-scale"); + _alpha_scale_texture_stage->set_sort(1000000000); + } + return _alpha_scale_texture_stage; +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::get_coordinate_system // Access: Published diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index 68ba94c7b7..9d660c9ec2 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -38,6 +38,7 @@ #include "drawableRegion.h" #include "displayRegion.h" #include "graphicsOutput.h" +#include "texturePool.h" #include #include @@ -68,6 +69,7 @@ PStatCollector GraphicsStateGuardian::_draw_primitive_pcollector("Draw:Primitive PStatCollector GraphicsStateGuardian::_clear_pcollector("Draw:Clear"); PStatCollector GraphicsStateGuardian::_flush_pcollector("Draw:Flush"); +PT(TextureStage) GraphicsStateGuardian::_alpha_scale_texture_stage = NULL; GraphicsStateGuardian *GraphicsStateGuardian::_global_gsg = NULL; TypeHandle GraphicsStateGuardian::_type_handle; @@ -163,6 +165,10 @@ GraphicsStateGuardian(CoordinateSystem internal_coordinate_system, // enabling lighting even without a LightAttrib). _color_scale_via_lighting = color_scale_via_lighting; + // Similarly for applying a texture to achieve uniform alpha + // scaling. + _alpha_scale_via_texture = alpha_scale_via_texture; + _stencil_render_states = 0; // The default is no shader support. @@ -311,6 +317,7 @@ reset() { _color_scale_enabled = false; _current_color_scale.set(1.0f, 1.0f, 1.0f, 1.0f); + _has_texture_alpha_scale = false; _has_material_force_color = false; _material_force_color.set(1.0f, 1.0f, 1.0f, 1.0f); @@ -1564,6 +1571,7 @@ do_issue_color_scale() { const ColorScaleAttrib *attrib = _target._color_scale; _color_scale_enabled = attrib->has_scale(); _current_color_scale = attrib->get_scale(); + _has_texture_alpha_scale = false; if (_color_blend_involves_color_scale) { _state_rs = 0; @@ -1580,6 +1588,13 @@ do_issue_color_scale() { determine_light_color_scale(); } + if (_alpha_scale_via_texture && !_has_scene_graph_color && + attrib->has_alpha_scale()) { + _state._texture = 0; + _state._tex_matrix = 0; + + _has_texture_alpha_scale = true; + } } //////////////////////////////////////////////////////////////////// @@ -1909,6 +1924,28 @@ void GraphicsStateGuardian:: end_bind_clip_planes() { } +//////////////////////////////////////////////////////////////////// +// Function: GraphicsStateGuardian::determine_effective_texture +// Access: Protected +// Description: Assigns _effective_texture and _effective_tex_gen +// based on the current settings of _target._texture and +// _target._color_scale. +//////////////////////////////////////////////////////////////////// +void GraphicsStateGuardian:: +determine_effective_texture() { + _effective_texture = _target._texture->filter_to_max(_max_texture_stages); + _effective_tex_gen = _target._tex_gen; + + if (_has_texture_alpha_scale) { + PT(TextureStage) stage = get_alpha_scale_texture_stage(); + PT(Texture) texture = TexturePool::get_alpha_scale_map(); + + _effective_texture = DCAST(TextureAttrib, _effective_texture->add_on_stage(stage, texture)); + _effective_tex_gen = DCAST(TexGenAttrib, _effective_tex_gen->add_stage + (stage, TexGenAttrib::M_constant, TexCoord3f(_current_color_scale[3], 0.0f, 0.0f))); + } +} + //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::free_pointers // Access: Protected, Virtual diff --git a/panda/src/display/graphicsStateGuardian.h b/panda/src/display/graphicsStateGuardian.h index d818a12709..30fcc6ec1a 100644 --- a/panda/src/display/graphicsStateGuardian.h +++ b/panda/src/display/graphicsStateGuardian.h @@ -139,6 +139,10 @@ PUBLISHED: virtual int get_supported_geom_rendering() const; INLINE bool get_color_scale_via_lighting() const; + INLINE bool get_alpha_scale_via_texture() const; + INLINE bool get_alpha_scale_via_texture(const TextureAttrib *tex_attrib) const; + + INLINE static TextureStage *get_alpha_scale_texture_stage(); void set_coordinate_system(CoordinateSystem cs); INLINE CoordinateSystem get_coordinate_system() const; @@ -268,6 +272,8 @@ protected: virtual void bind_clip_plane(const NodePath &plane, int plane_id); virtual void end_bind_clip_planes(); + void determine_effective_texture(); + virtual void free_pointers(); virtual void close_gsg(); void panic_deactivate(); @@ -292,6 +298,13 @@ protected: CPT(RenderState) _target_rs; CPT(TransformState) _internal_transform; + // The current TextureAttrib is a special case; we may further + // restrict it (according to graphics cards limits) or extend it + // (according to ColorScaleAttribs in effect) beyond what is + // specifically requested in the scene graph. + CPT(TextureAttrib) _effective_texture; + CPT(TexGenAttrib) _effective_tex_gen; + // These are set by begin_draw_primitives(), and are only valid // between begin_draw_primitives() and end_draw_primitives(). CPT(GeomMunger) _munger; @@ -329,6 +342,7 @@ protected: bool _has_material_force_color; Colorf _material_force_color; LVecBase4f _light_color_scale; + bool _has_texture_alpha_scale; bool _tex_gen_modifies_mat; bool _tex_gen_point_sprite; @@ -383,6 +397,7 @@ protected: int _supported_geom_rendering; bool _color_scale_via_lighting; + bool _alpha_scale_via_texture; int _stereo_buffer_mask; @@ -391,6 +406,8 @@ protected: int _auto_detect_shader_model; int _shader_model; + static PT(TextureStage) _alpha_scale_texture_stage; + public: // Statistics static PStatCollector _vertex_buffer_switch_pcollector; diff --git a/panda/src/display/standardMunger.cxx b/panda/src/display/standardMunger.cxx index c2b4718362..d5cda2c1ae 100644 --- a/panda/src/display/standardMunger.cxx +++ b/panda/src/display/standardMunger.cxx @@ -73,20 +73,21 @@ StandardMunger(GraphicsStateGuardianBase *gsg, const RenderState *state, } else if (color_scale_attrib != (ColorScaleAttrib *)NULL && color_scale_attrib->has_scale()) { _color_scale = color_scale_attrib->get_scale(); - if (!_gsg->get_color_scale_via_lighting() || _color_scale[3] < 0.999f) { - // We only need to apply the color scale by directly munging the - // color if the GSG says it can't cheat this via lighting (for - // instance, by applying an ambient light). Or, since we assume - // lighting can't scale the alpha component, if the color scale - // involves alpha. - // 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. It doesn't seem worth the effort to detect this - // contrived situation and handle it correctly. + CPT(TextureAttrib) tex_attrib = state->get_texture(); + + // 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() && !_gsg->get_color_scale_via_lighting()) || + (color_scale_attrib->has_alpha_scale() && !_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. + // It doesn't seem worth the effort to detect this contrived + // situation and handle it correctly. } } diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 6e7df6fd0a..6ec756c3b3 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -5676,23 +5676,6 @@ set_state_and_transform(const RenderState *target, _state._texture = 0; } - if (_target._texture != _state._texture) { - do_issue_texture(); - _state._texture = _target._texture; - _state._tex_gen = 0; - _state._tex_matrix = 0; - } - - if (_target._material != _state._material) { - do_issue_material(); - _state._material = _target._material; - } - - if (_target._light != _state._light) { - do_issue_light(); - _state._light = _target._light; - } - // If one of the previously-loaded TexGen modes modified the texture // matrix, then if either state changed, we have to change both of // them now. @@ -5704,14 +5687,29 @@ set_state_and_transform(const RenderState *target, } } + if (_target._texture != _state._texture || + _target._tex_gen != _state._tex_gen) { + determine_effective_texture(); + do_issue_texture(); + do_issue_tex_gen(); + _state._texture = _target._texture; + _state._tex_gen = _target._tex_gen; + _state._tex_matrix = 0; + } + if (_target._tex_matrix != _state._tex_matrix) { do_issue_tex_matrix(); _state._tex_matrix = _target._tex_matrix; } - if (_target._tex_gen != _state._tex_gen) { - do_issue_tex_gen(); - _state._tex_gen = _target._tex_gen; + if (_target._material != _state._material) { + do_issue_material(); + _state._material = _target._material; + } + + if (_target._light != _state._light) { + do_issue_light(); + _state._light = _target._light; } if (_target._stencil != _state._stencil) { @@ -5822,7 +5820,7 @@ do_issue_texture() { //////////////////////////////////////////////////////////////////// void CLP(GraphicsStateGuardian):: update_standard_texture_bindings() { - int num_stages = _target._texture->get_num_on_stages(); + int num_stages = _effective_texture->get_num_on_stages(); int num_old_stages = _max_texture_stages; if (_state._texture != (TextureAttrib *)NULL) { num_old_stages = _state._texture->get_num_on_stages(); @@ -5837,8 +5835,8 @@ update_standard_texture_bindings() { int last_stage = -1; int i; for (i = 0; i < num_stages; i++) { - TextureStage *stage = _target._texture->get_on_stage(i); - Texture *texture = _target._texture->get_on_texture(stage); + TextureStage *stage = _effective_texture->get_on_stage(i); + Texture *texture = _effective_texture->get_on_texture(stage); nassertv(texture != (Texture *)NULL); if (i >= num_old_stages || @@ -6057,11 +6055,11 @@ disable_standard_texture_bindings() { //////////////////////////////////////////////////////////////////// void CLP(GraphicsStateGuardian):: do_issue_tex_matrix() { - int num_stages = _target._texture->get_num_on_stages(); + int num_stages = _effective_texture->get_num_on_stages(); nassertv(num_stages <= _max_texture_stages); for (int i = 0; i < num_stages; i++) { - TextureStage *stage = _target._texture->get_on_stage(i); + TextureStage *stage = _effective_texture->get_on_stage(i); _glActiveTexture(GL_TEXTURE0 + i); GLP(MatrixMode)(GL_TEXTURE); @@ -6091,7 +6089,7 @@ void CLP(GraphicsStateGuardian):: do_issue_tex_gen() { bool force_normal = false; - int num_stages = _target._texture->get_num_on_stages(); + int num_stages = _effective_texture->get_num_on_stages(); nassertv(num_stages <= _max_texture_stages); // These are passed in for the four OBJECT_PLANE or EYE_PLANE @@ -6109,7 +6107,7 @@ do_issue_tex_gen() { bool got_point_sprites = false; for (int i = 0; i < num_stages; i++) { - TextureStage *stage = _target._texture->get_on_stage(i); + TextureStage *stage = _effective_texture->get_on_stage(i); _glActiveTexture(GL_TEXTURE0 + i); GLP(Disable)(GL_TEXTURE_GEN_S); GLP(Disable)(GL_TEXTURE_GEN_T); @@ -6119,7 +6117,7 @@ do_issue_tex_gen() { GLP(TexEnvi)(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_FALSE); } - TexGenAttrib::Mode mode = _target._tex_gen->get_mode(stage); + TexGenAttrib::Mode mode = _effective_tex_gen->get_mode(stage); switch (mode) { case TexGenAttrib::M_off: case TexGenAttrib::M_light_vector: @@ -6301,6 +6299,35 @@ do_issue_tex_gen() { } break; + case TexGenAttrib::M_constant: + // To generate a constant UV(w) coordinate everywhere, we use + // EYE_LINEAR mode, but we construct a special matrix that + // flattens the vertex position to zero and then adds our + // desired value. + { + const TexCoord3f &v = _effective_tex_gen->get_constant_value(stage); + + GLP(TexGeni)(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + GLP(TexGeni)(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + GLP(TexGeni)(GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + GLP(TexGeni)(GL_Q, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + + LVecBase4f s(0.0f, 0.0f, 0.0f, v[0]); + LVecBase4f t(0.0f, 0.0f, 0.0f, v[1]); + LVecBase4f r(0.0f, 0.0f, 0.0f, v[2]); + + GLP(TexGenfv)(GL_S, GL_OBJECT_PLANE, s.get_data()); + GLP(TexGenfv)(GL_T, GL_OBJECT_PLANE, t.get_data()); + GLP(TexGenfv)(GL_R, GL_OBJECT_PLANE, r.get_data()); + GLP(TexGenfv)(GL_Q, GL_OBJECT_PLANE, q_data); + + GLP(Enable)(GL_TEXTURE_GEN_S); + GLP(Enable)(GL_TEXTURE_GEN_T); + GLP(Enable)(GL_TEXTURE_GEN_R); + GLP(Enable)(GL_TEXTURE_GEN_Q); + } + break; + case TexGenAttrib::M_unused: break; } diff --git a/panda/src/gobj/texture.cxx b/panda/src/gobj/texture.cxx index 290a5e8c6c..0cddfd4b74 100644 --- a/panda/src/gobj/texture.cxx +++ b/panda/src/gobj/texture.cxx @@ -350,6 +350,31 @@ generate_normalization_cube_map(int size) { } } +//////////////////////////////////////////////////////////////////// +// Function: Texture::generate_alpha_scale_map +// Access: Published +// Description: Generates a special 256x1 1-d texture that can be +// used to apply an arbitrary alpha scale to objects by +// judicious use of texture matrix. The texture is a +// gradient, with an alpha of 0 on the left (U = 0), and +// 255 on the right (U = 1). +//////////////////////////////////////////////////////////////////// +void Texture:: +generate_alpha_scale_map() { + setup_1d_texture(256, T_unsigned_byte, F_alpha); + set_wrap_u(WM_clamp); + set_minfilter(FT_nearest); + set_magfilter(FT_nearest); + + PTA_uchar image = make_ram_image(); + _keep_ram_image = true; + + unsigned char *p = image; + for (int xi = 0; xi < 256; ++xi) { + *p++ = xi; + } +} + //////////////////////////////////////////////////////////////////// // Function: Texture::estimate_texture_memory // Access: Published diff --git a/panda/src/gobj/texture.h b/panda/src/gobj/texture.h index a1902a7884..39c93826f9 100644 --- a/panda/src/gobj/texture.h +++ b/panda/src/gobj/texture.h @@ -199,6 +199,7 @@ PUBLISHED: ComponentType component_type, Format format); void generate_normalization_cube_map(int size); + void generate_alpha_scale_map(); INLINE bool read(const Filename &fullpath); INLINE bool read(const Filename &fullpath, const Filename &alpha_fullpath, diff --git a/panda/src/gobj/texturePool.I b/panda/src/gobj/texturePool.I index 802d4304a1..2875f743de 100644 --- a/panda/src/gobj/texturePool.I +++ b/panda/src/gobj/texturePool.I @@ -143,6 +143,22 @@ get_normalization_cube_map(int size) { return get_global_ptr()->ns_get_normalization_cube_map(size); } +//////////////////////////////////////////////////////////////////// +// Function: TexturePool::get_alpha_scale_map +// Access: Published, Static +// Description: Returns a standard Texture object that has been +// created with Texture::generate_alpha_scale_map(). +// +// This Texture object is used internally by Panda to +// apply an alpha scale to an object (instead of munging +// its vertices) when gsg->get_alpha_scale_via_texture() +// returns true. +//////////////////////////////////////////////////////////////////// +INLINE Texture *TexturePool:: +get_alpha_scale_map() { + return get_global_ptr()->ns_get_alpha_scale_map(); +} + //////////////////////////////////////////////////////////////////// // Function: TexturePool::add_texture // Access: Published, Static diff --git a/panda/src/gobj/texturePool.cxx b/panda/src/gobj/texturePool.cxx index 13498eeec6..f9871e1c34 100644 --- a/panda/src/gobj/texturePool.cxx +++ b/panda/src/gobj/texturePool.cxx @@ -657,6 +657,23 @@ ns_get_normalization_cube_map(int size) { return _normalization_cube_map; } +//////////////////////////////////////////////////////////////////// +// Function: TexturePool::ns_get_alpha_scale_map +// Access: Private +// Description: The nonstatic implementation of get_alpha_scale_map(). +//////////////////////////////////////////////////////////////////// +Texture *TexturePool:: +ns_get_alpha_scale_map() { + MutexHolder holder(_lock); + + if (_alpha_scale_map == (Texture *)NULL) { + _alpha_scale_map = new Texture("alpha_scale_map"); + _alpha_scale_map->generate_alpha_scale_map(); + } + + return _alpha_scale_map; +} + //////////////////////////////////////////////////////////////////// // Function: TexturePool::ns_add_texture // Access: Private diff --git a/panda/src/gobj/texturePool.h b/panda/src/gobj/texturePool.h index 67e7d28c63..d579e7505d 100644 --- a/panda/src/gobj/texturePool.h +++ b/panda/src/gobj/texturePool.h @@ -57,6 +57,7 @@ PUBLISHED: bool read_mipmaps = false); INLINE static Texture *get_normalization_cube_map(int size); + INLINE static Texture *get_alpha_scale_map(); INLINE static void add_texture(Texture *texture); INLINE static void release_texture(Texture *texture); @@ -101,6 +102,7 @@ private: Texture *ns_load_cube_map(const Filename &filename_pattern, bool read_mipmaps); Texture *ns_get_normalization_cube_map(int size); + Texture *ns_get_alpha_scale_map(); void ns_add_texture(Texture *texture); void ns_release_texture(Texture *texture); @@ -128,6 +130,7 @@ private: string _fake_texture_image; PT(Texture) _normalization_cube_map; + PT(Texture) _alpha_scale_map; typedef pmap TypeRegistry; TypeRegistry _type_registry; diff --git a/panda/src/pgraph/colorScaleAttrib.I b/panda/src/pgraph/colorScaleAttrib.I index fe7fd02928..ad5a186c02 100644 --- a/panda/src/pgraph/colorScaleAttrib.I +++ b/panda/src/pgraph/colorScaleAttrib.I @@ -17,21 +17,6 @@ //////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////// -// Function: ColorScaleAttrib::Constructor -// Access: Protected -// Description: Use ColorScaleAttrib::make() to construct a new -// ColorScaleAttrib object. -//////////////////////////////////////////////////////////////////// -INLINE ColorScaleAttrib:: -ColorScaleAttrib(bool off, const LVecBase4f &scale) : - _off(off), - _scale(scale) -{ - quantize_scale(); - _has_scale = !_scale.almost_equal(LVecBase4f(1.0f, 1.0f, 1.0f, 1.0f)); -} - //////////////////////////////////////////////////////////////////// // Function: ColorScaleAttrib::Copy Constructor // Access: Protected @@ -42,6 +27,8 @@ INLINE ColorScaleAttrib:: ColorScaleAttrib(const ColorScaleAttrib ©) : _off(copy._off), _has_scale(copy._has_scale), + _has_rgb_scale(copy._has_rgb_scale), + _has_alpha_scale(copy._has_alpha_scale), _scale(copy._scale) { } @@ -84,6 +71,30 @@ has_scale() const { return _has_scale; } +//////////////////////////////////////////////////////////////////// +// Function: ColorScaleAttrib::has_rgb_scale +// Access: Published +// Description: Returns true if the ColorScaleAttrib has a +// non-identity scale in the RGB components (ignoring +// alpha), or false otherwise. +//////////////////////////////////////////////////////////////////// +INLINE bool ColorScaleAttrib:: +has_rgb_scale() const { + return _has_rgb_scale; +} + +//////////////////////////////////////////////////////////////////// +// Function: ColorScaleAttrib::has_alpha_scale +// Access: Published +// Description: Returns true if the ColorScaleAttrib has a +// non-identity scale in the alpha component (ignoring +// RGB), or false otherwise. +//////////////////////////////////////////////////////////////////// +INLINE bool ColorScaleAttrib:: +has_alpha_scale() const { + return _has_alpha_scale; +} + //////////////////////////////////////////////////////////////////// // Function: ColorScaleAttrib::get_scale // Access: Published diff --git a/panda/src/pgraph/colorScaleAttrib.cxx b/panda/src/pgraph/colorScaleAttrib.cxx index 207ce75d40..a455cbe17b 100644 --- a/panda/src/pgraph/colorScaleAttrib.cxx +++ b/panda/src/pgraph/colorScaleAttrib.cxx @@ -29,6 +29,23 @@ TypeHandle ColorScaleAttrib::_type_handle; CPT(RenderAttrib) ColorScaleAttrib::_identity_attrib; +//////////////////////////////////////////////////////////////////// +// Function: ColorScaleAttrib::Constructor +// Access: Protected +// Description: Use ColorScaleAttrib::make() to construct a new +// ColorScaleAttrib object. +//////////////////////////////////////////////////////////////////// +ColorScaleAttrib:: +ColorScaleAttrib(bool off, const LVecBase4f &scale) : + _off(off), + _scale(scale) +{ + quantize_scale(); + _has_scale = !_scale.almost_equal(LVecBase4f(1.0f, 1.0f, 1.0f, 1.0f)); + _has_rgb_scale = !LVecBase3f(_scale[0], _scale[1], _scale[2]).almost_equal(LVecBase3f(1.0f, 1.0f, 1.0f)); + _has_alpha_scale = !IS_NEARLY_EQUAL(_scale[3], 1.0f); +} + //////////////////////////////////////////////////////////////////// // Function: ColorScaleAttrib::make_identity // Access: Published, Static @@ -85,6 +102,8 @@ set_scale(const LVecBase4f &scale) const { attrib->_scale = scale; attrib->quantize_scale(); attrib->_has_scale = !scale.almost_equal(LVecBase4f(1.0f, 1.0f, 1.0f, 1.0f)); + attrib->_has_rgb_scale = !LVecBase3f(scale[0], scale[1], scale[2]).almost_equal(LVecBase3f(1.0f, 1.0f, 1.0f)); + attrib->_has_alpha_scale = !IS_NEARLY_EQUAL(scale[3], 1.0f); return return_new(attrib); } @@ -346,4 +365,6 @@ fillin(DatagramIterator &scan, BamReader *manager) { _scale.read_datagram(scan); quantize_scale(); _has_scale = !_scale.almost_equal(LVecBase4f(1.0f, 1.0f, 1.0f, 1.0f)); + _has_rgb_scale = !LVecBase3f(_scale[0], _scale[1], _scale[2]).almost_equal(LVecBase3f(1.0f, 1.0f, 1.0f)); + _has_alpha_scale = !IS_NEARLY_EQUAL(_scale[3], 1.0f); } diff --git a/panda/src/pgraph/colorScaleAttrib.h b/panda/src/pgraph/colorScaleAttrib.h index e4dd3f6214..fd1f14da45 100644 --- a/panda/src/pgraph/colorScaleAttrib.h +++ b/panda/src/pgraph/colorScaleAttrib.h @@ -33,7 +33,7 @@ class FactoryParams; //////////////////////////////////////////////////////////////////// class EXPCL_PANDA ColorScaleAttrib : public RenderAttrib { protected: - INLINE ColorScaleAttrib(bool off, const LVecBase4f &scale); + ColorScaleAttrib(bool off, const LVecBase4f &scale); INLINE ColorScaleAttrib(const ColorScaleAttrib ©); PUBLISHED: @@ -44,6 +44,8 @@ PUBLISHED: INLINE bool is_off() const; INLINE bool is_identity() const; INLINE bool has_scale() const; + INLINE bool has_rgb_scale() const; + INLINE bool has_alpha_scale() const; INLINE const LVecBase4f &get_scale() const; CPT(RenderAttrib) set_scale(const LVecBase4f &scale) const; @@ -64,6 +66,8 @@ private: private: bool _off; bool _has_scale; + bool _has_rgb_scale; + bool _has_alpha_scale; LVecBase4f _scale; static CPT(RenderAttrib) _identity_attrib; diff --git a/panda/src/pgraph/nodePath.cxx b/panda/src/pgraph/nodePath.cxx index b85cebd065..7bbc717c92 100644 --- a/panda/src/pgraph/nodePath.cxx +++ b/panda/src/pgraph/nodePath.cxx @@ -3576,6 +3576,36 @@ set_tex_gen(TextureStage *stage, RenderAttrib::TexGenMode mode, node()->set_attrib(tga->add_stage(stage, mode, source_name, light), priority); } +//////////////////////////////////////////////////////////////////// +// Function: NodePath::set_tex_gen +// Access: Published +// Description: Enables automatic texture coordinate generation for +// the indicated texture stage. This version of this +// method is useful when setting M_constant, which +// requires a constant texture coordinate value. +//////////////////////////////////////////////////////////////////// +void NodePath:: +set_tex_gen(TextureStage *stage, RenderAttrib::TexGenMode mode, + const TexCoord3f &constant_value, int priority) { + nassertv_always(!is_empty()); + + const RenderAttrib *attrib = + node()->get_attrib(TexGenAttrib::get_class_type()); + + CPT(TexGenAttrib) tga; + + if (attrib != (const RenderAttrib *)NULL) { + priority = max(priority, + node()->get_state()->get_override(TextureAttrib::get_class_type())); + tga = DCAST(TexGenAttrib, attrib); + + } else { + tga = DCAST(TexGenAttrib, TexGenAttrib::make()); + } + + node()->set_attrib(tga->add_stage(stage, mode, constant_value), priority); +} + //////////////////////////////////////////////////////////////////// // Function: NodePath::clear_tex_gen // Access: Published diff --git a/panda/src/pgraph/nodePath.h b/panda/src/pgraph/nodePath.h index 91fc456b0a..ab64bcd76f 100644 --- a/panda/src/pgraph/nodePath.h +++ b/panda/src/pgraph/nodePath.h @@ -636,6 +636,9 @@ PUBLISHED: void set_tex_gen(TextureStage *stage, RenderAttrib::TexGenMode mode, const string &source_name, const NodePath &light, int priority = 0); + void set_tex_gen(TextureStage *stage, RenderAttrib::TexGenMode mode, + const TexCoord3f &constant_value, + int priority = 0); void clear_tex_gen(); void clear_tex_gen(TextureStage *stage); bool has_tex_gen(TextureStage *stage) const; diff --git a/panda/src/pgraph/renderAttrib.h b/panda/src/pgraph/renderAttrib.h index 142e27ce54..be00594dfe 100644 --- a/panda/src/pgraph/renderAttrib.h +++ b/panda/src/pgraph/renderAttrib.h @@ -164,6 +164,11 @@ PUBLISHED: // tangent and binormal for the particular named texture // coordinate set. M_light_vector, + + // M_constant generates the same fixed texture coordinates at each + // vertex. Not terribly useful, of course, except for certain + // special effects involving moving a flat color over an object. + M_constant, }; protected: diff --git a/panda/src/pgraph/stateMunger.h b/panda/src/pgraph/stateMunger.h index 375e635de2..c6e29cbdaa 100644 --- a/panda/src/pgraph/stateMunger.h +++ b/panda/src/pgraph/stateMunger.h @@ -37,7 +37,7 @@ public: CPT(RenderState) munge_state(const RenderState *state); protected: - CPT(RenderState) munge_state_impl(const RenderState *state); + virtual CPT(RenderState) munge_state_impl(const RenderState *state); typedef pmap< WCPT(RenderState), WCPT(RenderState) > StateMap; StateMap _state_map; diff --git a/panda/src/pgraph/texGenAttrib.I b/panda/src/pgraph/texGenAttrib.I index 94794c17d9..48fa8723d4 100755 --- a/panda/src/pgraph/texGenAttrib.I +++ b/panda/src/pgraph/texGenAttrib.I @@ -117,6 +117,11 @@ compare_to(const TexGenAttrib::ModeDef &other) const { if (compare != 0) { return compare; } - return strcmp(_source_name.c_str(), other._source_name.c_str()); + compare = strcmp(_source_name.c_str(), other._source_name.c_str()); + if (compare != 0) { + return compare; + } + compare = _constant_value.compare_to(other._constant_value); + return compare; } diff --git a/panda/src/pgraph/texGenAttrib.cxx b/panda/src/pgraph/texGenAttrib.cxx index 75b6ad4a56..34c48e56d8 100755 --- a/panda/src/pgraph/texGenAttrib.cxx +++ b/panda/src/pgraph/texGenAttrib.cxx @@ -62,9 +62,8 @@ make() { // indicated stage. //////////////////////////////////////////////////////////////////// CPT(RenderAttrib) TexGenAttrib:: -make(TextureStage *stage, TexGenAttrib::Mode mode, - const string &source_name, const NodePath &light) { - return DCAST(TexGenAttrib, make())->add_stage(stage, mode, source_name, light); +make(TextureStage *stage, TexGenAttrib::Mode mode) { + return DCAST(TexGenAttrib, make())->add_stage(stage, mode); } //////////////////////////////////////////////////////////////////// @@ -76,8 +75,35 @@ make(TextureStage *stage, TexGenAttrib::Mode mode, // replaced. //////////////////////////////////////////////////////////////////// CPT(RenderAttrib) TexGenAttrib:: +add_stage(TextureStage *stage, TexGenAttrib::Mode mode) const { + nassertr(mode != M_light_vector && mode != M_constant, this); + + CPT(RenderAttrib) removed = remove_stage(stage); + TexGenAttrib *attrib = new TexGenAttrib(*DCAST(TexGenAttrib, removed)); + + ModeDef &mode_def = attrib->_stages[stage]; + mode_def._mode = mode; + attrib->record_stage(stage, mode_def); + + return return_new(attrib); +} + +//////////////////////////////////////////////////////////////////// +// Function: TexGenAttrib::add_stage +// Access: Published, Static +// Description: Returns a new TexGenAttrib just like this one, +// with the indicated generation mode for the given +// stage. If this stage already exists, its mode is +// replaced. +// +// This variant also accepts source_name and light, +// which are only meaningful if mode is M_light_vector. +//////////////////////////////////////////////////////////////////// +CPT(RenderAttrib) TexGenAttrib:: add_stage(TextureStage *stage, TexGenAttrib::Mode mode, const string &source_name, const NodePath &light) const { + nassertr(mode == M_light_vector, this); + CPT(RenderAttrib) removed = remove_stage(stage); TexGenAttrib *attrib = new TexGenAttrib(*DCAST(TexGenAttrib, removed)); @@ -90,6 +116,33 @@ add_stage(TextureStage *stage, TexGenAttrib::Mode mode, return return_new(attrib); } +//////////////////////////////////////////////////////////////////// +// Function: TexGenAttrib::add_stage +// Access: Published, Static +// Description: Returns a new TexGenAttrib just like this one, +// with the indicated generation mode for the given +// stage. If this stage already exists, its mode is +// replaced. +// +// This variant also accepts constant_value, which is +// only meaningful if mode is M_constant. +//////////////////////////////////////////////////////////////////// +CPT(RenderAttrib) TexGenAttrib:: +add_stage(TextureStage *stage, TexGenAttrib::Mode mode, + const TexCoord3f &constant_value) const { + nassertr(mode == M_constant, this); + + CPT(RenderAttrib) removed = remove_stage(stage); + TexGenAttrib *attrib = new TexGenAttrib(*DCAST(TexGenAttrib, removed)); + + ModeDef &mode_def = attrib->_stages[stage]; + mode_def._mode = mode; + mode_def._constant_value = constant_value; + attrib->record_stage(stage, mode_def); + + return return_new(attrib); +} + //////////////////////////////////////////////////////////////////// // Function: TexGenAttrib::remove_stage // Access: Published, Static @@ -200,6 +253,22 @@ get_light(TextureStage *stage) const { return NodePath(); } +//////////////////////////////////////////////////////////////////// +// Function: TexGenAttrib::get_constant_value +// Access: Published +// Description: Returns the constant value associated with the named +// texture stage. This is only meaningful if the mode +// is M_constant. +//////////////////////////////////////////////////////////////////// +const TexCoord3f &TexGenAttrib:: +get_constant_value(TextureStage *stage) const { + Stages::const_iterator mi = _stages.find(stage); + if (mi != _stages.end()) { + return (*mi).second._constant_value; + } + return TexCoord3f::zero(); +} + //////////////////////////////////////////////////////////////////// // Function: TexGenAttrib::output // Access: Public, Virtual @@ -253,6 +322,10 @@ output(ostream &out) const { << mode_def._light; break; + case M_constant: + out << "constant: " << mode_def._constant_value; + break; + case M_unused: break; } diff --git a/panda/src/pgraph/texGenAttrib.h b/panda/src/pgraph/texGenAttrib.h index b9de2a9fe0..010be32c6a 100755 --- a/panda/src/pgraph/texGenAttrib.h +++ b/panda/src/pgraph/texGenAttrib.h @@ -54,9 +54,11 @@ public: PUBLISHED: static CPT(RenderAttrib) make(); - static CPT(RenderAttrib) make(TextureStage *stage, Mode mode, const string &source_name = string(), const NodePath &light = NodePath()); + static CPT(RenderAttrib) make(TextureStage *stage, Mode mode); - CPT(RenderAttrib) add_stage(TextureStage *stage, Mode mode, const string &source_name = string(), const NodePath &light = NodePath()) const; + CPT(RenderAttrib) add_stage(TextureStage *stage, Mode mode) const; + CPT(RenderAttrib) add_stage(TextureStage *stage, Mode mode, const string &source_name, const NodePath &light) const; + CPT(RenderAttrib) add_stage(TextureStage *stage, Mode mode, const TexCoord3f &constant_value) const; CPT(RenderAttrib) remove_stage(TextureStage *stage) const; bool is_empty() const; @@ -64,6 +66,7 @@ PUBLISHED: Mode get_mode(TextureStage *stage) const; string get_source_name(TextureStage *stage) const; NodePath get_light(TextureStage *stage) const; + const TexCoord3f &get_constant_value(TextureStage *stage) const; INLINE int get_geom_rendering(int geom_rendering) const; @@ -94,6 +97,7 @@ private: Mode _mode; string _source_name; NodePath _light; + TexCoord3f _constant_value; }; typedef pmap Stages; Stages _stages;