diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index 80de97ac50..81f1498acc 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -815,79 +815,59 @@ clear(DrawableRegion *clearable) { // shoehorning them into a matrix. In this way, we avoid // the need for a separate routine to fetch these values. // -// If "altered" is false, that means you promise that -// this ShaderMatSpec has been evaluated before, and that -// since the last time this ShaderMatSpec was evaluated, -// that no part of the render state has changed except -// the external and internal transforms. +// The "altered" bits indicate what parts of the +// state_and_transform have changed since the last +// time this particular ShaderMatSpec was evaluated. +// This may allow data to be cached and not reevaluated. // //////////////////////////////////////////////////////////////////// const LMatrix4f *GraphicsStateGuardian:: -fetch_specified_value(Shader::ShaderMatSpec &spec, bool altered) { - static LMatrix4f acc; - const LMatrix4f *val1; - const LMatrix4f *val2; - static LMatrix4f t1; - static LMatrix4f t2; +fetch_specified_value(Shader::ShaderMatSpec &spec, int altered) { LVecBase3f v; + if (altered & spec._dep[0]) { + const LMatrix4f *t = fetch_specified_part(spec._part[0], spec._arg[0], spec._cache[0]); + if (t != &spec._cache[0]) { + spec._cache[0] = *t; + } + } + if (altered & spec._dep[1]) { + const LMatrix4f *t = fetch_specified_part(spec._part[1], spec._arg[1], spec._cache[1]); + if (t != &spec._cache[1]) { + spec._cache[1] = *t; + } + } + switch(spec._func) { case Shader::SMF_compose: - val1 = fetch_specified_part(spec._part[0], spec._arg[0], t1); - val2 = fetch_specified_part(spec._part[1], spec._arg[1], t2); - acc.multiply(*val1, *val2); - return &acc; - case Shader::SMF_compose_cache_first: - if (altered) { - spec._cache = *fetch_specified_part(spec._part[0], spec._arg[0], t1); - } - val2 = fetch_specified_part(spec._part[1], spec._arg[1], t2); - acc.multiply(spec._cache, *val2); - return &acc; - case Shader::SMF_compose_cache_second: - if (altered) { - spec._cache = *fetch_specified_part(spec._part[1], spec._arg[1], t2); - } - val1 = fetch_specified_part(spec._part[0], spec._arg[0], t1); - acc.multiply(*val1, spec._cache); - return &acc; + spec._value.multiply(spec._cache[0], spec._cache[1]); + return &spec._value; case Shader::SMF_transform_dlight: - if (altered) { - spec._cache = *fetch_specified_part(spec._part[0], spec._arg[0], t1); - } - val2 = fetch_specified_part(spec._part[1], spec._arg[1], t2); - acc = spec._cache; - v = val2->xform_vec(spec._cache.get_row3(2)); + spec._value = spec._cache[0]; + v = spec._cache[1].xform_vec(spec._cache[0].get_row3(2)); v.normalize(); - acc.set_row(2, v); - v = val2->xform_vec(spec._cache.get_row3(3)); + spec._value.set_row(2, v); + v = spec._cache[1].xform_vec(spec._cache[0].get_row3(3)); v.normalize(); - acc.set_row(3, v); - return &acc; + spec._value.set_row(3, v); + return &spec._value; case Shader::SMF_transform_plight: - if (altered) { - spec._cache = *fetch_specified_part(spec._part[0], spec._arg[0], t1); - } - val2 = fetch_specified_part(spec._part[1], spec._arg[1], t2); - acc = spec._cache; - acc.set_row(2, val2->xform_point(spec._cache.get_row3(2))); - return &acc; + spec._value = spec._cache[0]; + spec._value.set_row(2, spec._cache[1].xform_point(spec._cache[0].get_row3(2))); + return &spec._value; case Shader::SMF_transform_slight: - if (altered) { - spec._cache = *fetch_specified_part(spec._part[0], spec._arg[0], t1); - } - val2 = fetch_specified_part(spec._part[1], spec._arg[1], t2); - acc = spec._cache; - acc.set_row(2, val2->xform_point(spec._cache.get_row3(2))); - v = val2->xform_vec(spec._cache.get_row3(3)); + spec._value = spec._cache[0]; + spec._value.set_row(2, spec._cache[1].xform_point(spec._cache[0].get_row3(2))); + v = spec._cache[1].xform_vec(spec._cache[0].get_row3(3)); v.normalize(); - acc.set_row(3, v); - return &acc; + spec._value.set_row(3, v); + return &spec._value; case Shader::SMF_first: - return fetch_specified_part(spec._part[0], spec._arg[0], t1); + return &spec._cache[0]; default: // should never get here - return &LMatrix4f::ident_mat(); + spec._value = LMatrix4f::ident_mat(); + return &spec._value; } } diff --git a/panda/src/display/graphicsStateGuardian.h b/panda/src/display/graphicsStateGuardian.h index f6e786cdd4..3b8e0863c1 100644 --- a/panda/src/display/graphicsStateGuardian.h +++ b/panda/src/display/graphicsStateGuardian.h @@ -195,9 +195,9 @@ public: void clear(DrawableRegion *clearable); - const LMatrix4f *fetch_specified_value(Shader::ShaderMatSpec &spec, bool altered); + const LMatrix4f *fetch_specified_value(Shader::ShaderMatSpec &spec, int altered); const LMatrix4f *fetch_specified_part(Shader::ShaderMatInput input, InternalName *name, LMatrix4f &t); - + virtual void prepare_display_region(DisplayRegionPipelineReader *dr, Lens::StereoChannel stereo_channel); diff --git a/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx b/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx index 083ca02e2d..a0b4313736 100644 --- a/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx +++ b/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx @@ -3335,7 +3335,8 @@ void DXGraphicsStateGuardian8:: set_texture_blend_mode(int i, const TextureStage *stage) { switch (stage->get_mode()) { case TextureStage::M_modulate: - case TextureStage::M_modulate_glow_map: + case TextureStage::M_modulate_glow: + case TextureStage::M_modulate_gloss: // emulates GL_MODULATE glTexEnv mode _d3d_device->SetTextureStageState(i, D3DTSS_COLOROP, D3DTOP_MODULATE); _d3d_device->SetTextureStageState(i, D3DTSS_COLORARG1, D3DTA_TEXTURE); diff --git a/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx b/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx index 37f58499ac..f877e033a2 100755 --- a/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx +++ b/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx @@ -3095,7 +3095,7 @@ do_issue_transform() { if (_current_shader_context) { // _current_shader_context->issue_transform(this); - _current_shader_context->issue_parameters(this, false); + _current_shader_context->issue_parameters(this, Shader::SSD_transform); // ??? NO NEED TO SET THE D3D TRANSFORM VIA SetTransform SINCE THE TRANSFORM IS ONLY USED IN THE SHADER const D3DMATRIX *d3d_mat = (const D3DMATRIX *)transform->get_mat().get_data(); @@ -3191,7 +3191,7 @@ do_issue_shader() { } } else { // Use the same shader as before, but with new input arguments. - context->issue_parameters(this, true); + context->issue_parameters(this, Shader::SSD_shaderinputs); } } @@ -3469,6 +3469,9 @@ set_state_and_transform(const RenderState *target, do_issue_color_scale(); _state._color = _target._color; _state._color_scale = _target._color_scale; + if (_current_shader_context) { + _current_shader_context->issue_parameters(this, Shader::SSD_color); + } } if (_target._cull_face != _state._cull_face) { @@ -3542,6 +3545,9 @@ set_state_and_transform(const RenderState *target, if (_target._material != _state._material) { do_issue_material(); _state._material = _target._material; + if (_current_shader_context) { + _current_shader_context->issue_parameters(this, Shader::SSD_material); + } } if (_target._light != _state._light) { @@ -4614,7 +4620,8 @@ void DXGraphicsStateGuardian9:: set_texture_blend_mode(int i, const TextureStage *stage) { switch (stage->get_mode()) { case TextureStage::M_modulate: - case TextureStage::M_modulate_glow_map: + case TextureStage::M_modulate_glow: + case TextureStage::M_modulate_gloss: // emulates GL_MODULATE glTexEnv mode set_texture_stage_state(i, D3DTSS_COLOROP, D3DTOP_MODULATE); set_texture_stage_state(i, D3DTSS_COLORARG1, D3DTA_TEXTURE); diff --git a/panda/src/dxgsg9/dxShaderContext9.cxx b/panda/src/dxgsg9/dxShaderContext9.cxx index 68b0e8a4a5..e39a004aa4 100644 --- a/panda/src/dxgsg9/dxShaderContext9.cxx +++ b/panda/src/dxgsg9/dxShaderContext9.cxx @@ -210,7 +210,7 @@ bind(GSG *gsg) { gsg -> _last_fvf = 0; // Pass in k-parameters and transform-parameters - issue_parameters(gsg, true); + issue_parameters(gsg, Shader::SSD_general); HRESULT hr; @@ -297,12 +297,12 @@ InternalName *global_internal_name_1 = 0; #endif void CLP(ShaderContext):: -issue_parameters(GSG *gsg, bool altered) +issue_parameters(GSG *gsg, int altered) { #ifdef HAVE_CG if (_cg_context) { for (int i=0; i<(int)_shader->_mat_spec.size(); i++) { - if (altered || _shader->_mat_spec[i]._trans_dependent) { + if (altered & (_shader->_mat_spec[i]._dep[0] | _shader->_mat_spec[i]._dep[1])) { CGparameter p = _cg_parameter_map[_shader->_mat_spec[i]._id._seqno]; if (p == NULL) { continue; diff --git a/panda/src/dxgsg9/dxShaderContext9.h b/panda/src/dxgsg9/dxShaderContext9.h index 9f5a4a54da..5b7837c7a0 100644 --- a/panda/src/dxgsg9/dxShaderContext9.h +++ b/panda/src/dxgsg9/dxShaderContext9.h @@ -77,7 +77,7 @@ public: INLINE bool valid(GSG *gsg); bool bind(GSG *gsg); void unbind(GSG *gsg); - void issue_parameters(GSG *gsg, bool altered); + void issue_parameters(GSG *gsg, int altered); void issue_transform(GSG *gsg); void disable_shader_vertex_arrays(GSG *gsg); void update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg); diff --git a/panda/src/egg/eggTexture.cxx b/panda/src/egg/eggTexture.cxx index 0ad648ae43..bed4167f68 100644 --- a/panda/src/egg/eggTexture.cxx +++ b/panda/src/egg/eggTexture.cxx @@ -562,14 +562,15 @@ affects_polygon_alpha() const { case ET_add: case ET_blend_color_scale: return false; - case ET_modulate_glow_map: - case ET_normal_map: - case ET_gloss_map: - case ET_glow_map: - case ET_normal_gloss_map: + case ET_modulate_glow: + case ET_modulate_gloss: + case ET_normal: + case ET_normal_height: + case ET_glow: + case ET_gloss: return false; - case ET_selector_map: + case ET_selector: return true; case ET_unspecified: @@ -881,23 +882,29 @@ string_env_type(const string &string) { } else if (cmp_nocase_uh(string, "blend_color_scale") == 0) { return ET_blend_color_scale; - } else if (cmp_nocase_uh(string, "modulate_glow_map") == 0) { - return ET_modulate_glow_map; + } else if (cmp_nocase_uh(string, "modulate_glow") == 0) { + return ET_modulate_glow; - } else if (cmp_nocase_uh(string, "normal_map") == 0) { - return ET_normal_map; + } else if (cmp_nocase_uh(string, "modulate_gloss") == 0) { + return ET_modulate_gloss; - } else if (cmp_nocase_uh(string, "gloss_map") == 0) { - return ET_gloss_map; + } else if (cmp_nocase_uh(string, "normal") == 0) { + return ET_normal; - } else if (cmp_nocase_uh(string, "glow_map") == 0) { - return ET_glow_map; + } else if (cmp_nocase_uh(string, "normal_height") == 0) { + return ET_normal_height; - } else if (cmp_nocase_uh(string, "normal_gloss_map") == 0) { - return ET_normal_gloss_map; + } else if (cmp_nocase_uh(string, "glow") == 0) { + return ET_glow; - } else if (cmp_nocase_uh(string, "selector_map") == 0) { - return ET_selector_map; + } else if (cmp_nocase_uh(string, "gloss") == 0) { + return ET_gloss; + + } else if (cmp_nocase_uh(string, "height") == 0) { + return ET_height; + + } else if (cmp_nocase_uh(string, "selector") == 0) { + return ET_selector; } else { return ET_unspecified; @@ -1298,23 +1305,29 @@ ostream &operator << (ostream &out, EggTexture::EnvType type) { case EggTexture::ET_blend_color_scale: return out << "blend_color_scale"; - case EggTexture::ET_modulate_glow_map: - return out << "modulate_glow_map"; + case EggTexture::ET_modulate_glow: + return out << "modulate_glow"; - case EggTexture::ET_normal_map: - return out << "normal_map"; + case EggTexture::ET_modulate_gloss: + return out << "modulate_gloss"; - case EggTexture::ET_gloss_map: - return out << "gloss_map"; + case EggTexture::ET_normal: + return out << "normal"; + + case EggTexture::ET_normal_height: + return out << "normal_height"; + + case EggTexture::ET_glow: + return out << "glow"; - case EggTexture::ET_glow_map: - return out << "glow_map"; + case EggTexture::ET_gloss: + return out << "gloss"; - case EggTexture::ET_normal_gloss_map: - return out << "normal_gloss_map"; + case EggTexture::ET_height: + return out << "height"; - case EggTexture::ET_selector_map: - return out << "selector_map"; + case EggTexture::ET_selector: + return out << "selector"; } nassertr(false, out); diff --git a/panda/src/egg/eggTexture.h b/panda/src/egg/eggTexture.h index 514e450fc4..9f45b88cc2 100644 --- a/panda/src/egg/eggTexture.h +++ b/panda/src/egg/eggTexture.h @@ -102,12 +102,14 @@ PUBLISHED: ET_replace, ET_add, ET_blend_color_scale, - ET_modulate_glow_map, - ET_normal_map, - ET_gloss_map, - ET_glow_map, - ET_normal_gloss_map, - ET_selector_map, + ET_modulate_glow, + ET_modulate_gloss, + ET_normal, + ET_normal_height, + ET_glow, + ET_gloss, + ET_height, + ET_selector, }; enum CombineMode { CM_unspecified, diff --git a/panda/src/egg2pg/eggLoader.cxx b/panda/src/egg2pg/eggLoader.cxx index 6a5dd7e438..8e04469443 100644 --- a/panda/src/egg2pg/eggLoader.cxx +++ b/panda/src/egg2pg/eggLoader.cxx @@ -1393,28 +1393,36 @@ make_texture_stage(const EggTexture *egg_tex) { stage->set_mode(TextureStage::M_blend_color_scale); break; - case EggTexture::ET_modulate_glow_map: - stage->set_mode(TextureStage::M_modulate_glow_map); + case EggTexture::ET_modulate_glow: + stage->set_mode(TextureStage::M_modulate_glow); break; - case EggTexture::ET_normal_map: - stage->set_mode(TextureStage::M_normal_map); + case EggTexture::ET_modulate_gloss: + stage->set_mode(TextureStage::M_modulate_gloss); break; - case EggTexture::ET_gloss_map: - stage->set_mode(TextureStage::M_gloss_map); + case EggTexture::ET_normal: + stage->set_mode(TextureStage::M_normal); break; - case EggTexture::ET_glow_map: - stage->set_mode(TextureStage::M_glow_map); + case EggTexture::ET_normal_height: + stage->set_mode(TextureStage::M_normal_height); break; - case EggTexture::ET_normal_gloss_map: - stage->set_mode(TextureStage::M_normal_gloss_map); + case EggTexture::ET_glow: + stage->set_mode(TextureStage::M_glow); break; - case EggTexture::ET_selector_map: - stage->set_mode(TextureStage::M_selector_map); + case EggTexture::ET_gloss: + stage->set_mode(TextureStage::M_gloss); + break; + + case EggTexture::ET_height: + stage->set_mode(TextureStage::M_height); + break; + + case EggTexture::ET_selector: + stage->set_mode(TextureStage::M_selector); break; case EggTexture::ET_unspecified: diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 6a3ae092d2..96982175da 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -3494,7 +3494,7 @@ do_issue_transform() { } if (_current_shader_context) { - _current_shader_context->issue_parameters(this, false); + _current_shader_context->issue_parameters(this, Shader::SSD_transform); } report_my_gl_errors(); @@ -3555,7 +3555,7 @@ do_issue_shader() { _current_shader_context = context; } else { // Use the same shader as before, but with new input arguments. - context->issue_parameters(this, true); + context->issue_parameters(this, Shader::SSD_shaderinputs); } } @@ -5284,7 +5284,8 @@ get_texture_apply_mode_type(TextureStage::Mode am) { case TextureStage::M_add: return GL_ADD; case TextureStage::M_combine: return GL_COMBINE; case TextureStage::M_blend_color_scale: return GL_BLEND; - case TextureStage::M_modulate_glow_map: return GL_MODULATE; + case TextureStage::M_modulate_glow: return GL_MODULATE; + case TextureStage::M_modulate_gloss: return GL_MODULATE; } GLCAT.error() @@ -5867,6 +5868,9 @@ set_state_and_transform(const RenderState *target, do_issue_color_scale(); _state._color = _target._color; _state._color_scale = _target._color_scale; + if (_current_shader_context) { + _current_shader_context->issue_parameters(this, Shader::SSD_color); + } } if (_target._cull_face != _state._cull_face) { @@ -5970,6 +5974,9 @@ set_state_and_transform(const RenderState *target, PStatTimer timer(_draw_set_state_material_pcollector); do_issue_material(); _state._material = _target._material; + if (_current_shader_context) { + _current_shader_context->issue_parameters(this, Shader::SSD_material); + } } if (_target._light != _state._light) { diff --git a/panda/src/glstuff/glShaderContext_src.cxx b/panda/src/glstuff/glShaderContext_src.cxx index 4ab6fd048b..e394ff80bd 100755 --- a/panda/src/glstuff/glShaderContext_src.cxx +++ b/panda/src/glstuff/glShaderContext_src.cxx @@ -110,7 +110,7 @@ bind(GSG *gsg) { if (_cg_context != 0) { // Pass in k-parameters and transform-parameters - issue_parameters(gsg, true); + issue_parameters(gsg, Shader::SSD_general); // Bind the shaders. cgGLEnableProfile(cgGetProgramProfile(_cg_vprogram)); @@ -154,14 +154,14 @@ unbind() { // transforms. //////////////////////////////////////////////////////////////////// void CLP(ShaderContext):: -issue_parameters(GSG *gsg, bool altered) { +issue_parameters(GSG *gsg, int altered) { #ifdef HAVE_CG if (_cg_context == 0) { return; } for (int i=0; i<(int)_shader->_mat_spec.size(); i++) { - if (altered || _shader->_mat_spec[i]._trans_dependent) { + if (altered & (_shader->_mat_spec[i]._dep[0] | _shader->_mat_spec[i]._dep[1])) { CGparameter p = _cg_parameter_map[_shader->_mat_spec[i]._id._seqno]; const LMatrix4f *val = gsg->fetch_specified_value(_shader->_mat_spec[i], altered); if (val) { diff --git a/panda/src/glstuff/glShaderContext_src.h b/panda/src/glstuff/glShaderContext_src.h index 23312110dc..17c4cc19b6 100755 --- a/panda/src/glstuff/glShaderContext_src.h +++ b/panda/src/glstuff/glShaderContext_src.h @@ -41,7 +41,7 @@ public: INLINE bool valid(void); void bind(GSG *gsg); void unbind(); - void issue_parameters(GSG *gsg, bool all); + void issue_parameters(GSG *gsg, int altered); void disable_shader_vertex_arrays(GSG *gsg); bool update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg, bool force); diff --git a/panda/src/gobj/shader.cxx b/panda/src/gobj/shader.cxx index 52a000472d..ca2d2f9546 100755 --- a/panda/src/gobj/shader.cxx +++ b/panda/src/gobj/shader.cxx @@ -323,6 +323,52 @@ cp_parse_coord_sys(ShaderArgInfo &p, return true; } +//////////////////////////////////////////////////////////////////// +// Function: Shader::cp_dependency +// Access: Public +// Description: Given ShaderMatInput, returns an indication of what +// part or parts of the state_and_transform the +// ShaderMatInput depends upon. +//////////////////////////////////////////////////////////////////// +int Shader:: +cp_dependency(ShaderMatInput inp) { + + int dep = SSD_general; + + if (inp == SMO_INVALID) { + return SSD_NONE; + } + if (inp == SMO_attr_material) { + dep |= SSD_material; + } + if (inp == SMO_attr_color) { + dep |= SSD_color; + } + if ((inp == SMO_model_to_view)|| + (inp == SMO_view_to_model)) { + dep |= SSD_transform; + } + if ((inp == SMO_alight_x)|| + (inp == SMO_dlight_x)|| + (inp == SMO_plight_x)|| + (inp == SMO_slight_x)|| + (inp == SMO_satten_x)|| + (inp == SMO_mat_constant_x)|| + (inp == SMO_vec_constant_x)|| + (inp == SMO_view_x_to_view)|| + (inp == SMO_view_to_view_x)|| + (inp == SMO_apiview_x_to_view)|| + (inp == SMO_view_to_apiview_x)|| + (inp == SMO_clip_x_to_view)|| + (inp == SMO_view_to_clip_x)|| + (inp == SMO_apiclip_x_to_view)|| + (inp == SMO_view_to_apiclip_x)) { + dep |= SSD_shaderinputs; + } + + return dep; +} + //////////////////////////////////////////////////////////////////// // Function: Shader::cp_optimize_mat_spec // Access: Public @@ -336,6 +382,11 @@ void Shader:: cp_optimize_mat_spec(ShaderMatSpec &spec) { // If we're composing with identity, simplify. + + if (spec._func == SMF_first) { + spec._part[1] = SMO_INVALID; + spec._arg[1] = 0; + } if (spec._func == SMF_compose) { if (spec._part[1] == SMO_identity) { spec._func = SMF_first; @@ -349,33 +400,10 @@ cp_optimize_mat_spec(ShaderMatSpec &spec) { } } - // See if either half can be cached. - bool can_cache_part0 = true; - bool can_cache_part1 = true; - if ((spec._part[0] == SMO_model_to_view)|| - (spec._part[0] == SMO_view_to_model)) { - can_cache_part0 = false; - } - if ((spec._part[1] == SMO_model_to_view)|| - (spec._part[1] == SMO_view_to_model)) { - can_cache_part1 = false; - } + // Calculate state and transform dependencies. - // See if we can use a compose-with-cache variant. - if (spec._func == SMF_compose) { - if (can_cache_part0) { - spec._func = SMF_compose_cache_first; - } else if (can_cache_part1) { - spec._func = SMF_compose_cache_second; - } - } - - // Determine transform-dependence. - if (can_cache_part0 && can_cache_part1) { - spec._trans_dependent = false; - } else { - spec._trans_dependent = true; - } + spec._dep[0] = cp_dependency(spec._part[0]); + spec._dep[1] = cp_dependency(spec._part[1]); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/gobj/shader.h b/panda/src/gobj/shader.h index dd797b3436..5a62c6bb09 100755 --- a/panda/src/gobj/shader.h +++ b/panda/src/gobj/shader.h @@ -111,10 +111,6 @@ public: SMO_apiclip_x_to_view, SMO_view_to_apiclip_x, - SMO_light_vector, - SMO_light_color, - SMO_light_spec, - SMO_INVALID }; @@ -150,6 +146,15 @@ public: SMP_col2, SMP_col3, }; + + enum ShaderStateDep { + SSD_NONE = 0, + SSD_general = 1, + SSD_transform = 2, + SSD_color = 4, + SSD_material = 8, + SSD_shaderinputs = 16, + }; enum ShaderBug { SBUG_ati_draw_buffers, @@ -157,8 +162,6 @@ public: enum ShaderMatFunc { SMF_compose, - SMF_compose_cache_first, - SMF_compose_cache_second, SMF_transform_dlight, SMF_transform_plight, SMF_transform_slight, @@ -176,9 +179,10 @@ public: ShaderMatFunc _func; ShaderMatInput _part[2]; PT(InternalName) _arg[2]; - LMatrix4f _cache; + int _dep[2]; + LMatrix4f _cache[2]; + LMatrix4f _value; ShaderMatPiece _piece; - bool _trans_dependent; }; struct ShaderTexSpec { @@ -241,6 +245,7 @@ public: bool cp_parse_coord_sys(ShaderArgInfo &arg, vector_string &pieces, int &next, ShaderMatSpec &spec, bool fromflag); + int cp_dependency(ShaderMatInput inp); void cp_optimize_mat_spec(ShaderMatSpec &spec); bool compile_parameter(const ShaderArgId &arg_id, diff --git a/panda/src/gobj/textureStage.I b/panda/src/gobj/textureStage.I index 5eefa32aeb..ed93479ba4 100755 --- a/panda/src/gobj/textureStage.I +++ b/panda/src/gobj/textureStage.I @@ -197,7 +197,7 @@ get_mode() const { //////////////////////////////////////////////////////////////////// INLINE bool TextureStage:: is_fixed_function() const { - return (_mode < M_normal_map); + return (_mode < M_normal); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/gobj/textureStage.cxx b/panda/src/gobj/textureStage.cxx index c737a5b6e8..648aa6d05a 100755 --- a/panda/src/gobj/textureStage.cxx +++ b/panda/src/gobj/textureStage.cxx @@ -397,23 +397,29 @@ operator << (ostream &out, TextureStage::Mode mode) { case TextureStage::M_blend_color_scale: return out << "blend_color_scale"; - case TextureStage::M_modulate_glow_map: - return out << "modulate_glow_map"; + case TextureStage::M_modulate_glow: + return out << "modulate_glow"; - case TextureStage::M_normal_map: - return out << "normal_map"; + case TextureStage::M_modulate_gloss: + return out << "modulate_gloss"; + + case TextureStage::M_normal: + return out << "normal"; - case TextureStage::M_gloss_map: - return out << "gloss_map"; + case TextureStage::M_normal_height: + return out << "normal_height"; - case TextureStage::M_glow_map: - return out << "glow_map"; + case TextureStage::M_glow: + return out << "glow"; + + case TextureStage::M_gloss: + return out << "gloss"; - case TextureStage::M_normal_gloss_map: - return out << "normal_gloss_map"; - - case TextureStage::M_selector_map: - return out << "selector_map"; + case TextureStage::M_height: + return out << "height"; + + case TextureStage::M_selector: + return out << "selector"; } return out << "**invalid Mode(" << (int)mode << ")**"; diff --git a/panda/src/gobj/textureStage.h b/panda/src/gobj/textureStage.h index d5137d82f0..fe73ec6d92 100644 --- a/panda/src/gobj/textureStage.h +++ b/panda/src/gobj/textureStage.h @@ -57,15 +57,18 @@ PUBLISHED: M_add, M_combine, M_blend_color_scale, - M_modulate_glow_map, // When fixed-function, equivalent to modulate. + + M_modulate_glow, // When fixed-function, equivalent to modulate. + M_modulate_gloss, // When fixed-function, equivalent to modulate. // Modes that are only relevant to shader-based rendering. - M_normal_map, - M_gloss_map, - M_glow_map, - M_normal_gloss_map, - M_selector_map, + M_normal, + M_normal_height, + M_glow, // Rarely used: modulate_glow is more efficient. + M_gloss, // Rarely used: modulate_gloss is more efficient. + M_height, // Rarely used: normal_height is more efficient. + M_selector, }; enum CombineMode { diff --git a/panda/src/grutil/multitexReducer.cxx b/panda/src/grutil/multitexReducer.cxx index e41dc19c00..d6f840cf26 100644 --- a/panda/src/grutil/multitexReducer.cxx +++ b/panda/src/grutil/multitexReducer.cxx @@ -742,14 +742,18 @@ make_texture_layer(const NodePath &render, CPT(RenderAttrib) cba; switch (stage_info._stage->get_mode()) { - case TextureStage::M_normal_map: - case TextureStage::M_gloss_map: - case TextureStage::M_normal_gloss_map: - case TextureStage::M_selector_map: + case TextureStage::M_normal: + case TextureStage::M_normal_height: + case TextureStage::M_glow: + case TextureStage::M_gloss: + case TextureStage::M_height: + case TextureStage::M_selector: // Don't know what to do with these funny modes. We should // probably raise an exception or something. Fall through for // now. + case TextureStage::M_modulate_glow: + case TextureStage::M_modulate_gloss: case TextureStage::M_modulate: cba = ColorBlendAttrib::make (ColorBlendAttrib::M_add, ColorBlendAttrib::O_fbuffer_color, diff --git a/panda/src/pgraph/shaderGenerator.cxx b/panda/src/pgraph/shaderGenerator.cxx index f965cc0b92..a3eb2cb2c1 100644 --- a/panda/src/pgraph/shaderGenerator.cxx +++ b/panda/src/pgraph/shaderGenerator.cxx @@ -186,7 +186,7 @@ analyze_renderstate(const RenderState *rs) { if (_attribs._texture) { _num_textures = _attribs._texture->get_num_on_stages(); } - + // Determine whether or not vertex colors or flat colors are present. if (_attribs._color != 0) { if (_attribs._color->get_color_type() == ColorAttrib::T_vertex) { @@ -223,10 +223,29 @@ analyze_renderstate(const RenderState *rs) { } } + // See if there is a normal map, height map, gloss map, or glow map. + + for (int i=0; i<_num_textures; i++) { + TextureStage *stage = _attribs._texture->get_on_stage(i); + TextureStage::Mode mode = stage->get_mode(); + if ((mode == TextureStage::M_normal)||(mode == TextureStage::M_normal_height)) { + _map_index_normal = i; + } + if ((mode == TextureStage::M_height)||(mode == TextureStage::M_normal_height)) { + _map_index_height = i; + } + if ((mode == TextureStage::M_glow)||(mode == TextureStage::M_modulate_glow)) { + _map_index_glow = i; + } + if ((mode == TextureStage::M_gloss)||(mode == TextureStage::M_modulate_gloss)) { + _map_index_gloss = i; + } + } + // Determine whether model-space or tangent-space lighting is recommended. if (_attribs._light->get_num_on_lights() > 0) { - _ms_lighting = true; + _lighting = true; } // Find the material. @@ -299,12 +318,15 @@ void ShaderGenerator:: clear_analysis() { _vertex_colors = false; _flat_colors = false; - _ms_lighting = false; - _ts_lighting = false; + _lighting = false; _have_ambient = false; _have_diffuse = false; _have_emission = false; _have_specular = false; + _map_index_normal = -1; + _map_index_height = -1; + _map_index_glow = -1; + _map_index_gloss = -1; _attribs.clear_to_defaults(); _material = (Material*)NULL; _alights.clear(); @@ -329,7 +351,7 @@ create_shader_attrib(const string &txt) { PT(Shader) shader = Shader::make(txt); CPT(RenderAttrib) shattr = ShaderAttrib::make(); shattr=DCAST(ShaderAttrib, shattr)->set_shader(shader); - if (_ms_lighting) { + if (_lighting) { for (int i=0; i<(int)_alights.size(); i++) { shattr=DCAST(ShaderAttrib, shattr)->set_shader_input(InternalName::make("alight", i), _alights_np[i]); } @@ -377,10 +399,11 @@ synthesize_shader(const RenderState *rs) { char *pos_freg = 0; char *normal_vreg = 0; - // char *tangent_vreg = 0; - // char *binormal_vreg = 0; char *normal_freg = 0; - // char *eyevec_freg = 0; + char *tangent_vreg = 0; + char *tangent_freg = 0; + char *binormal_vreg = 0; + char *binormal_freg = 0; pvector texcoord_vreg; pvector texcoord_freg; pvector tslightvec_freg; @@ -407,15 +430,25 @@ synthesize_shader(const RenderState *rs) { text << "\t in float4 vtx_color : COLOR,\n"; text << "\t out float4 l_color : COLOR,\n"; } - if (_ms_lighting) { + if (_lighting) { pos_freg = alloc_freg(); normal_vreg = alloc_vreg(); normal_freg = alloc_freg(); text << "\t in float4 vtx_normal : " << normal_vreg << ",\n"; text << "\t out float4 l_normal : " << normal_freg << ",\n"; text << "\t out float4 l_pos : " << pos_freg << ",\n"; + if (_map_index_normal >= 0) { + tangent_vreg = alloc_vreg(); + tangent_freg = alloc_freg(); + binormal_vreg = alloc_vreg(); + binormal_freg = alloc_freg(); + text << "\t in float4 vtx_tangent" << _map_index_normal << " : " << tangent_vreg << ",\n"; + text << "\t in float4 vtx_binormal" << _map_index_normal << " : " << binormal_vreg << ",\n"; + text << "\t out float4 l_tangent : " << tangent_freg << ",\n"; + text << "\t out float4 l_binormal : " << binormal_freg << ",\n"; + } } - + text << "\t float4 vtx_position : POSITION,\n"; text << "\t out float4 l_position : POSITION,\n"; text << "\t uniform float4x4 mat_modelproj\n"; @@ -429,12 +462,16 @@ synthesize_shader(const RenderState *rs) { if (_vertex_colors) { text << "\t l_color = vtx_color;\n"; } - if (_ms_lighting) { - text << "\t l_normal = vtx_normal;\n"; + if (_lighting) { text << "\t l_pos = vtx_position;\n"; + text << "\t l_normal = vtx_normal;\n"; + if (_map_index_normal) { + text << "\t l_tangent = vtx_tangent" << _map_index_normal << ";\n"; + text << "\t l_binormal = vtx_binormal" << _map_index_normal << ";\n"; + } } text << "}\n\n"; - + text << "void fshader(\n"; for (int i=0; i<_num_textures; i++) { @@ -446,8 +483,12 @@ synthesize_shader(const RenderState *rs) { } else { text << "\t uniform float4 attr_color,\n"; } - if (_ms_lighting) { + if (_lighting) { text << "\t in float3 l_normal : " << normal_freg << ",\n"; + if (_map_index_normal) { + text << "\t in float3 l_tangent : " << tangent_freg << ",\n"; + text << "\t in float3 l_binormal : " << binormal_freg << ",\n"; + } text << "\t in float4 l_pos : " << pos_freg << ",\n"; for (int i=0; i<(int)_alights.size(); i++) { text << "\t uniform float4 alight_alight" << i << ",\n"; @@ -475,8 +516,13 @@ synthesize_shader(const RenderState *rs) { } text << "\t out float4 o_color : COLOR\n"; text << ") {\n"; + text << "\t // Fetch all textures.\n"; + for (int i=0; i<_num_textures; i++) { + text << "\t float4 tex" << i << " = tex2D(tex_" << i << ", float2(l_texcoord" << i << "));\n"; + } - if (_ms_lighting) { + if (_lighting) { + text << "\t // Begin model-space light calculations\n"; if (_have_ambient) { text << "\t float4 tot_ambient = float4(0,0,0,0);\n"; } @@ -486,7 +532,16 @@ synthesize_shader(const RenderState *rs) { if (_have_specular) { text << "\t float4 tot_specular = float4(0,0,0,0);\n"; } - text << "\t l_normal = normalize(l_normal);\n"; + if (_map_index_normal) { + text << "\t // Translate tangent-space normal in map to model-space.\n"; + text << "\t float3 tsnormal = ((float3)tex" << _map_index_normal << " * 2) - 1;\n"; + text << "\t l_normal = l_normal * tsnormal.z;\n"; + text << "\t l_normal+= l_tangent * tsnormal.x;\n"; + text << "\t l_normal+= l_binormal * tsnormal.y;\n"; + text << "\t l_normal = normalize(l_normal);\n"; + } else { + text << "\t l_normal = normalize(l_normal);\n"; + } text << "\t float ldist,lattenv,langle;\n"; text << "\t float4 lcolor,lspec,lvec,lpoint,latten,ldir,leye,lhalf;\n"; for (int i=0; i<(int)_alights.size(); i++) { @@ -561,11 +616,12 @@ synthesize_shader(const RenderState *rs) { text << "\t tot_specular += lspec;\n"; } } + text << "\t // Begin model-space light summation\n"; if (_have_emission) { text << "\t o_color = attr_material[2];\n"; } else { - text << "\t o_color = float4(0,0,0,1);\n"; + text << "\t o_color = float4(0,0,0,0);\n"; } if (_have_ambient) { if (_material->has_ambient()) { @@ -589,6 +645,14 @@ synthesize_shader(const RenderState *rs) { text << "\t o_color += tot_diffuse;\n"; } } + if (_vertex_colors) { + text << "\t o_color.a = l_color.a;\n"; + } else if (_flat_colors) { + text << "\t o_color.a = attr_color.a;\n"; + } else { + text << "\t o_color.a = 1;\n"; + } + text << "\t // End model-space light calculations\n"; } else { if (_vertex_colors) { text << "\t o_color = l_color;\n"; @@ -599,9 +663,12 @@ synthesize_shader(const RenderState *rs) { } } for (int i=0; i<_num_textures; i++) { - text << "\t o_color *= tex2D(tex_" << i << ", float2(l_texcoord" << i << "));\n"; + TextureStage *stage = _attribs._texture->get_on_stage(i); + if (stage->get_mode() != TextureStage::M_normal) { + text << "\t o_color *= tex" << i << ";\n"; + } } - if (_ms_lighting) { + if (_lighting) { if (_have_specular) { text << "\t o_color += tot_specular;\n"; } diff --git a/panda/src/pgraph/shaderGenerator.h b/panda/src/pgraph/shaderGenerator.h index a910c09408..31b45b81c4 100644 --- a/panda/src/pgraph/shaderGenerator.h +++ b/panda/src/pgraph/shaderGenerator.h @@ -104,14 +104,18 @@ protected: bool _vertex_colors; bool _flat_colors; - bool _ms_lighting; - bool _ts_lighting; + bool _lighting; bool _have_ambient; bool _have_diffuse; bool _have_emission; bool _have_specular; + int _map_index_normal; + int _map_index_height; + int _map_index_glow; + int _map_index_gloss; + bool _need_material_props; void analyze_renderstate(const RenderState *rs); diff --git a/pandatool/src/maya/mayaShader.cxx b/pandatool/src/maya/mayaShader.cxx index 8e99452068..265b95995a 100644 --- a/pandatool/src/maya/mayaShader.cxx +++ b/pandatool/src/maya/mayaShader.cxx @@ -175,13 +175,16 @@ collect_maps() { for (size_t i=0; i<_normal_maps.size(); i++) { _all_maps.push_back(_normal_maps[i]); } - for (size_t i=0; i<_gloss_maps.size(); i++) { - _all_maps.push_back(_gloss_maps[i]); - } for (size_t i=0; i<_glow_maps.size(); i++) { _all_maps.push_back(_glow_maps[i]); } - + for (size_t i=0; i<_gloss_maps.size(); i++) { + _all_maps.push_back(_gloss_maps[i]); + } + for (size_t i=0; i<_height_maps.size(); i++) { + _all_maps.push_back(_height_maps[i]); + } + for (size_t i=0; i<_color.size(); i++) { if (_color[i]->_has_texture) { _all_maps.push_back(_color[i]); @@ -236,6 +239,10 @@ find_textures_modern(MObject shader) { if (_glow_maps.size() == 0) { MayaShaderColorDef::find_textures_modern(n, _glow_maps, shader_fn.findPlug("incandescenceR"), true); } + MayaShaderColorDef::find_textures_modern(n, _height_maps, shader_fn.findPlug("surfaceThickness"), true); + if (_height_maps.size() == 0) { + MayaShaderColorDef::find_textures_modern(n, _height_maps, shader_fn.findPlug("surfaceThicknessR"), true); + } collect_maps(); @@ -292,47 +299,82 @@ calculate_pairings() { _all_maps[i]->_opposite = 0; } + bool using_color_alpha = (_trans_maps.size() > 0); + for (size_t i=0; i<_color_maps.size(); i++) { + if ((_color_maps[i]->_blend_type != MayaShaderColorDef::BT_modulate)&& + (_color_maps[i]->_blend_type != MayaShaderColorDef::BT_unspecified)) { + using_color_alpha = true; + } + } + for (int retry=0; retry<2; retry++) { bool perfect=(retry==0); for (size_t i=0; i<_color_maps.size(); i++) { - if ((_color_maps[i]->_blend_type == MayaShaderColorDef::BT_modulate)|| - (_color_maps[i]->_blend_type == MayaShaderColorDef::BT_unspecified)) { + if ((_color_maps[i]->_blend_type != MayaShaderColorDef::BT_modulate)&& + (_color_maps[i]->_blend_type != MayaShaderColorDef::BT_unspecified)) { for (size_t j=0; j<_trans_maps.size(); j++) { try_pair(_color_maps[i], _trans_maps[j], perfect); } } } - for (size_t i=0; i<_normal_maps.size(); i++) { - for (size_t j=0; j<_gloss_maps.size(); j++) { - try_pair(_normal_maps[i], _gloss_maps[j], perfect); - } - } - if (_trans_maps.size() == 0) { + } + + if (!using_color_alpha) { + for (int retry=0; retry<2; retry++) { + bool perfect=(retry==0); for (size_t i=0; i<_color_maps.size(); i++) { for (size_t j=0; j<_glow_maps.size(); j++) { try_pair(_color_maps[i], _glow_maps[j], perfect); } + for (size_t j=0; j<_gloss_maps.size(); j++) { + try_pair(_color_maps[i], _gloss_maps[j], perfect); + } } } } - for (size_t i=0; i<_normal_maps.size(); i++) { - _normal_maps[i]->_blend_type = MayaShaderColorDef::BT_normal_map; - } - for (size_t i=0; i<_gloss_maps.size(); i++) { - if (_gloss_maps[i]->_opposite) { - _gloss_maps[i]->_blend_type = MayaShaderColorDef::BT_unspecified; - _gloss_maps[i]->_opposite->_blend_type = MayaShaderColorDef::BT_normal_gloss_map; - } else { - _gloss_maps[i]->_blend_type = MayaShaderColorDef::BT_gloss_map; + for (int retry=0; retry<2; retry++) { + bool perfect=(retry==0); + for (size_t i=0; i<_normal_maps.size(); i++) { + for (size_t j=0; j<_height_maps.size(); j++) { + try_pair(_normal_maps[i], _height_maps[j], perfect); + } } } + + for (size_t i=0; i<_normal_maps.size(); i++) { + _normal_maps[i]->_blend_type = MayaShaderColorDef::BT_normal; + } for (size_t i=0; i<_glow_maps.size(); i++) { if (_glow_maps[i]->_opposite) { _glow_maps[i]->_blend_type = MayaShaderColorDef::BT_unspecified; - _glow_maps[i]->_opposite->_blend_type = MayaShaderColorDef::BT_modulate_glow_map; + _glow_maps[i]->_opposite->_blend_type = MayaShaderColorDef::BT_modulate_glow; } else { - _glow_maps[i]->_blend_type = MayaShaderColorDef::BT_glow_map; + _glow_maps[i]->_blend_type = MayaShaderColorDef::BT_glow; + } + } + for (size_t i=0; i<_gloss_maps.size(); i++) { + if (_gloss_maps[i]->_opposite) { + _gloss_maps[i]->_blend_type = MayaShaderColorDef::BT_unspecified; + _gloss_maps[i]->_opposite->_blend_type = MayaShaderColorDef::BT_modulate_gloss; + } else { + _gloss_maps[i]->_blend_type = MayaShaderColorDef::BT_gloss; + } + } + for (size_t i=0; i<_height_maps.size(); i++) { + if (_height_maps[i]->_opposite) { + _height_maps[i]->_blend_type = MayaShaderColorDef::BT_unspecified; + _height_maps[i]->_opposite->_blend_type = MayaShaderColorDef::BT_normal_height; + } else { + _height_maps[i]->_blend_type = MayaShaderColorDef::BT_height; + } + } + for (size_t i=0; i<_trans_maps.size(); i++) { + if (_trans_maps[i]->_opposite) { + _trans_maps[i]->_blend_type = MayaShaderColorDef::BT_unspecified; + _trans_maps[i]->_opposite->_blend_type = MayaShaderColorDef::BT_modulate; + } else { + _trans_maps[i]->_blend_type = MayaShaderColorDef::BT_modulate; } } } @@ -342,24 +384,24 @@ calculate_pairings() { // Access: Private // Description: Try to associate an RGB tex with an Alpha tex. //////////////////////////////////////////////////////////////////// -void MayaShader::try_pair(MayaShaderColorDef *map1, +bool MayaShader::try_pair(MayaShaderColorDef *map1, MayaShaderColorDef *map2, bool perfect) { if ((map1->_opposite)||(map2->_opposite)) { // one of the maps is already paired - return; + return false; } if (perfect) { if (map1->_texture_filename != map2->_texture_filename) { // perfect mode requires a filename match. - return; + return false; } } else { string pre1 = get_file_prefix(map1->_texture_filename); string pre2 = get_file_prefix(map2->_texture_filename); if (pre1 != pre2) { // imperfect mode requires a filename prefix match. - return; + return false; } } @@ -375,11 +417,12 @@ void MayaShader::try_pair(MayaShaderColorDef *map1, (map1->_repeat_uv != map2->_repeat_uv) || (map1->_offset != map2->_offset) || (map1->_rotate_uv != map2->_rotate_uv)) { - return; + return false; } // Pairing successful. map1->_opposite = map2; map2->_opposite = map1; + return true; } //////////////////////////////////////////////////////////////////// diff --git a/pandatool/src/maya/mayaShader.h b/pandatool/src/maya/mayaShader.h index 4fe5115505..cc8496bc4f 100644 --- a/pandatool/src/maya/mayaShader.h +++ b/pandatool/src/maya/mayaShader.h @@ -61,14 +61,15 @@ public: // relevant only to modern mode. MayaShaderColorList _color_maps; MayaShaderColorList _trans_maps; MayaShaderColorList _normal_maps; - MayaShaderColorList _gloss_maps; MayaShaderColorList _glow_maps; - + MayaShaderColorList _gloss_maps; + MayaShaderColorList _height_maps; + void bind_uvsets(MayaFileToUVSetMap &map); private: void calculate_pairings(); - void try_pair(MayaShaderColorDef *map1, + bool try_pair(MayaShaderColorDef *map1, MayaShaderColorDef *map2, bool perfect); string get_file_prefix(const string &fn); diff --git a/pandatool/src/maya/mayaShaderColorDef.cxx b/pandatool/src/maya/mayaShaderColorDef.cxx index 2c4398b2a6..ed887311b2 100644 --- a/pandatool/src/maya/mayaShaderColorDef.cxx +++ b/pandatool/src/maya/mayaShaderColorDef.cxx @@ -624,7 +624,7 @@ find_textures_modern(const string &shadername, MayaShaderColorList &list, MPlug MPlug inputsPlug = sourceFn.findPlug("inputs"); size_t nlayers = inputsPlug.numElements(); - for (int layer=0; layer