diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index a3979a6c2c..15ebcd9dc2 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -1190,14 +1190,26 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name, } return &t; } - case Shader::SMO_texmat_x: { - const TexMatrixAttrib *tma = DCAST(TexMatrixAttrib, _target_rs->get_attrib_def(TexMatrixAttrib::get_class_slot())); - const TextureAttrib *ta = DCAST(TextureAttrib, _target_rs->get_attrib_def(TextureAttrib::get_class_slot())); - int stagenr = atoi(name->get_name().c_str()); - if (stagenr >= ta->get_num_on_stages()) { + case Shader::SMO_texmat_i: { + const TexMatrixAttrib *tma; + const TextureAttrib *ta; + if (_target_rs->get_attrib(ta) && _target_rs->get_attrib(tma) && + index < ta->get_num_on_stages()) { + return &tma->get_mat(ta->get_on_stage(index)); + } else { + return &LMatrix4::ident_mat(); + } + } + case Shader::SMO_inv_texmat_i: { + const TexMatrixAttrib *tma; + const TextureAttrib *ta; + if (_target_rs->get_attrib(ta) && _target_rs->get_attrib(tma) && + index < ta->get_num_on_stages()) { + t = tma->get_transform(ta->get_on_stage(index))->get_inverse()->get_mat(); + return &t; + } else { return &LMatrix4::ident_mat(); } - return &tma->get_mat(ta->get_on_stage(stagenr)); } case Shader::SMO_plane_x: { const NodePath &np = _target_shader->get_shader_input_nodepath(name); diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index e594579d4c..6159dd5cfb 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -9217,7 +9217,6 @@ set_state_and_transform(const RenderState *target, // 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. -#ifdef SUPPORT_FIXED_FUNCTION if (_tex_gen_modifies_mat) { int tex_gen_slot = TexGenAttrib::get_class_slot(); int tex_matrix_slot = TexMatrixAttrib::get_class_slot(); @@ -9234,10 +9233,16 @@ set_state_and_transform(const RenderState *target, if (_target_rs->get_attrib(tex_matrix_slot) != _state_rs->get_attrib(tex_matrix_slot) || !_state_mask.get_bit(tex_matrix_slot)) { //PStatGPUTimer timer(this, _draw_set_state_tex_matrix_pcollector); +#ifdef SUPPORT_FIXED_FUNCTION do_issue_tex_matrix(); - _state_mask.set_bit(tex_matrix_slot); - } #endif + _state_mask.set_bit(tex_matrix_slot); +#ifndef OPENGLES_1 + if (_current_shader_context) { + _current_shader_context->issue_parameters(Shader::SSD_tex_matrix); + } +#endif + } #ifdef SUPPORT_FIXED_FUNCTION int tex_gen_slot = TexGenAttrib::get_class_slot(); diff --git a/panda/src/glstuff/glShaderContext_src.cxx b/panda/src/glstuff/glShaderContext_src.cxx index 50a40f4e30..f2f0bd8a27 100644 --- a/panda/src/glstuff/glShaderContext_src.cxx +++ b/panda/src/glstuff/glShaderContext_src.cxx @@ -690,12 +690,16 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { } else { bind._piece = Shader::SMP_transpose3x3; } - } else { + } else if (param_type == GL_FLOAT_MAT4) { if (transpose) { bind._piece = Shader::SMP_transpose; } else { bind._piece = Shader::SMP_whole; } + } else { + GLCAT.error() + << "Matrix input p3d_" << matrix_name << " should be mat3 or mat4\n"; + return; } bind._arg[0] = NULL; bind._arg[1] = NULL; @@ -731,7 +735,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { bind._part[1] = Shader::SMO_identity; if (param_type != GL_FLOAT_MAT3) { - GLCAT.error() << "p3d_NormalMatrix input should be mat3, not mat4!\n"; + GLCAT.warning() << "p3d_NormalMatrix input should be mat3, not mat4!\n"; } } else if (matrix_name == "ModelMatrix") { @@ -761,6 +765,27 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { bind._part[1] = Shader::SMO_view_to_apiclip; } + } else if (matrix_name == "TextureMatrix") { + // We may support 2-D texmats later, but let's make sure that people + // don't think they can just use a mat3 to get the 2-D version. + if (param_type != GL_FLOAT_MAT4) { + GLCAT.error() << "p3d_TextureMatrix should be mat4[], not mat3[]!\n"; + return; + } + + bind._func = Shader::SMF_first; + bind._part[0] = inverse ? Shader::SMO_inv_texmat_i + : Shader::SMO_texmat_i; + bind._part[1] = Shader::SMO_identity; + bind._dep[0] = Shader::SSD_general | Shader::SSD_tex_matrix; + bind._dep[1] = 0; + + // Add it once for each index. + for (bind._index = 0; bind._index < param_size; ++bind._index) { + _shader->_mat_spec.push_back(bind); + } + return; + } else { GLCAT.error() << "Unrecognized uniform matrix name '" << matrix_name << "'!\n"; return; diff --git a/panda/src/gobj/shader.cxx b/panda/src/gobj/shader.cxx index 8f1cc70d33..b20ac8e1b2 100644 --- a/panda/src/gobj/shader.cxx +++ b/panda/src/gobj/shader.cxx @@ -452,6 +452,9 @@ cp_dependency(ShaderMatInput inp) { (inp == SMO_apiview_clipplane_i)) { dep |= SSD_clip_planes; } + if (inp == SMO_texmat_i || inp == SMO_inv_texmat_i) { + dep |= SSD_tex_matrix; + } return dep; } @@ -1040,10 +1043,11 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) { bind._id = p._id; bind._piece = SMP_whole; bind._func = SMF_first; - bind._part[0] = SMO_texmat_x; - bind._arg[0] = InternalName::make(pieces[1]); + bind._part[0] = SMO_texmat_i; + bind._arg[0] = NULL; bind._part[1] = SMO_identity; bind._arg[1] = NULL; + bind._index = atoi(pieces[1].c_str()); cp_optimize_mat_spec(bind); _mat_spec.push_back(bind); diff --git a/panda/src/gobj/shader.h b/panda/src/gobj/shader.h index e56960b1f5..33fe43b799 100644 --- a/panda/src/gobj/shader.h +++ b/panda/src/gobj/shader.h @@ -132,7 +132,7 @@ public: SMO_plight_x, SMO_slight_x, SMO_satten_x, - SMO_texmat_x, + SMO_texmat_i, SMO_plane_x, SMO_clipplane_x, @@ -191,6 +191,8 @@ public: SMO_apiview_to_apiclip, SMO_apiclip_to_apiview, + SMO_inv_texmat_i, + SMO_INVALID }; @@ -270,6 +272,7 @@ public: SSD_fog = 0x040, SSD_light = 0x080, SSD_clip_planes = 0x100, + SSD_tex_matrix = 0x200, }; enum ShaderBug {