diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index 43074a2234..9ea3ab1f90 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -1798,6 +1798,10 @@ fetch_specified_member(const NodePath &np, CPT_InternalName attrib, LMatrix4 &t) PT(Texture) GraphicsStateGuardian:: fetch_specified_texture(Shader::ShaderTexSpec &spec, SamplerState &sampler, int &view) { + + static PT(Texture) default_add_tex; + static PT(Texture) default_normal_height_tex; + switch (spec._part) { case Shader::STO_named_input: // Named texture input. @@ -1895,6 +1899,199 @@ fetch_specified_texture(Shader::ShaderTexSpec &spec, SamplerState &sampler, } break; + case Shader::STO_ff_stage_i: + { + // We get the TextureAttrib directly from the _target_rs, not the + // filtered TextureAttrib in _target_texture. + const TextureAttrib *texattrib; + _target_rs->get_attrib_def(texattrib); + + if (spec._stage < texattrib->get_num_on_ff_stages()) { + TextureStage *stage = texattrib->get_on_ff_stage(spec._stage); + sampler = texattrib->get_on_sampler(stage); + view += stage->get_tex_view_offset(); + return texattrib->get_on_texture(stage); + } + } + break; + + case Shader::STO_stage_modulate_i: + { + const TextureAttrib *texattrib; + if (_target_rs->get_attrib(texattrib)) { + size_t si = 0; + for (int i = 0; i < texattrib->get_num_on_stages(); ++i) { + TextureStage *stage = texattrib->get_on_stage(i); + TextureStage::Mode mode = stage->get_mode(); + + if (mode == TextureStage::M_modulate || + mode == TextureStage::M_modulate_glow || + mode == TextureStage::M_modulate_gloss) { + if (si++ == spec._stage) { + sampler = texattrib->get_on_sampler(stage); + view += stage->get_tex_view_offset(); + return texattrib->get_on_texture(stage); + } + } + } + } + } + break; + + case Shader::STO_stage_add_i: + { + const TextureAttrib *texattrib; + if (_target_rs->get_attrib(texattrib)) { + size_t si = 0; + for (int i = 0; i < texattrib->get_num_on_stages(); ++i) { + TextureStage *stage = texattrib->get_on_stage(i); + TextureStage::Mode mode = stage->get_mode(); + + if (mode == TextureStage::M_add) { + if (si++ == spec._stage) { + sampler = texattrib->get_on_sampler(stage); + view += stage->get_tex_view_offset(); + return texattrib->get_on_texture(stage); + } + } + } + } + + if (default_add_tex == nullptr) { + PT(Texture) tex = new Texture("default-add"); + tex->setup_2d_texture(1, 1, Texture::T_unsigned_byte, Texture::F_luminance); + tex->set_clear_color(LColor(0, 0, 0, 1)); + default_add_tex = std::move(tex); + } + return default_add_tex; + } + break; + + case Shader::STO_stage_normal_i: + { + const TextureAttrib *texattrib; + if (_target_rs->get_attrib(texattrib)) { + size_t si = 0; + for (int i = 0; i < texattrib->get_num_on_stages(); ++i) { + TextureStage *stage = texattrib->get_on_stage(i); + TextureStage::Mode mode = stage->get_mode(); + + if (mode == TextureStage::M_normal || + mode == TextureStage::M_normal_height) { + if (si++ == spec._stage) { + sampler = texattrib->get_on_sampler(stage); + view += stage->get_tex_view_offset(); + return texattrib->get_on_texture(stage); + } + } + } + } + + if (default_normal_height_tex == nullptr) { + PT(Texture) tex = new Texture("default-normal-height"); + tex->setup_2d_texture(1, 1, Texture::T_unsigned_byte, Texture::F_rgba); + tex->set_clear_color(LColor(0.5, 0.5, 1, 0)); + default_normal_height_tex = std::move(tex); + } + return default_normal_height_tex; + } + break; + + case Shader::STO_stage_gloss_i: + { + const TextureAttrib *texattrib; + if (_target_rs->get_attrib(texattrib)) { + size_t si = 0; + for (int i = 0; i < texattrib->get_num_on_stages(); ++i) { + TextureStage *stage = texattrib->get_on_stage(i); + TextureStage::Mode mode = stage->get_mode(); + + if (mode == TextureStage::M_gloss || + mode == TextureStage::M_modulate_gloss || + mode == TextureStage::M_normal_gloss) { + if (si++ == spec._stage) { + sampler = texattrib->get_on_sampler(stage); + view += stage->get_tex_view_offset(); + return texattrib->get_on_texture(stage); + } + } + } + } + } + break; + + case Shader::STO_stage_height_i: + { + const TextureAttrib *texattrib; + if (_target_rs->get_attrib(texattrib)) { + size_t si = 0; + for (int i = 0; i < texattrib->get_num_on_stages(); ++i) { + TextureStage *stage = texattrib->get_on_stage(i); + TextureStage::Mode mode = stage->get_mode(); + + if (mode == TextureStage::M_height || + mode == TextureStage::M_normal_height) { + if (si++ == spec._stage) { + sampler = texattrib->get_on_sampler(stage); + view += stage->get_tex_view_offset(); + return texattrib->get_on_texture(stage); + } + } + } + } + + if (default_normal_height_tex == nullptr) { + PT(Texture) tex = new Texture("default-normal-height"); + tex->setup_2d_texture(1, 1, Texture::T_unsigned_byte, Texture::F_rgba); + tex->set_clear_color(LColor(0.5, 0.5, 1, 0)); + default_normal_height_tex = std::move(tex); + } + return default_normal_height_tex; + } + break; + + case Shader::STO_stage_selector_i: + { + const TextureAttrib *texattrib; + if (_target_rs->get_attrib(texattrib)) { + size_t si = 0; + for (int i = 0; i < texattrib->get_num_on_stages(); ++i) { + TextureStage *stage = texattrib->get_on_stage(i); + TextureStage::Mode mode = stage->get_mode(); + + if (mode == TextureStage::M_selector) { + if (si++ == spec._stage) { + sampler = texattrib->get_on_sampler(stage); + view += stage->get_tex_view_offset(); + return texattrib->get_on_texture(stage); + } + } + } + } + } + break; + + case Shader::STO_stage_emission_i: + { + const TextureAttrib *texattrib; + if (_target_rs->get_attrib(texattrib)) { + size_t si = 0; + for (int i = 0; i < texattrib->get_num_on_stages(); ++i) { + TextureStage *stage = texattrib->get_on_stage(i); + TextureStage::Mode mode = stage->get_mode(); + + if (mode == TextureStage::M_emission) { + if (si++ == spec._stage) { + sampler = texattrib->get_on_sampler(stage); + view += stage->get_tex_view_offset(); + return texattrib->get_on_texture(stage); + } + } + } + } + } + break; + default: nassertr(false, nullptr); break; diff --git a/panda/src/glstuff/glShaderContext_src.cxx b/panda/src/glstuff/glShaderContext_src.cxx index 28429941c4..b0dfd4531b 100644 --- a/panda/src/glstuff/glShaderContext_src.cxx +++ b/panda/src/glstuff/glShaderContext_src.cxx @@ -953,27 +953,65 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { _shader->_mat_deps |= bind._dep[0] | bind._dep[1]; return; } - if (size > 7 && noprefix.substr(0, 7) == "Texture") { + if (noprefix.compare(0, 7, "Texture") == 0) { Shader::ShaderTexSpec bind; bind._id = arg_id; - bind._part = Shader::STO_stage_i; - bind._name = 0; - string tail; - bind._stage = string_to_int(noprefix.substr(7), tail); - if (!tail.empty()) { + if (!get_sampler_texture_type(bind._desired_type, param_type)) { GLCAT.error() - << "Error parsing shader input name: unexpected '" - << tail << "' in '" << param_name << "'\n"; + << "Could not bind texture input " << param_name << "\n"; return; } - if (get_sampler_texture_type(bind._desired_type, param_type)) { + if (size > 7 && isdigit(noprefix[7])) { + // p3d_Texture0, p3d_Texture1, etc. + bind._part = Shader::STO_stage_i; + + string tail; + bind._stage = string_to_int(noprefix.substr(7), tail); + if (!tail.empty()) { + GLCAT.error() + << "Error parsing shader input name: unexpected '" + << tail << "' in '" << param_name << "'\n"; + return; + } _glgsg->_glUniform1i(p, _shader->_tex_spec.size()); _shader->_tex_spec.push_back(bind); - } else { - GLCAT.error() - << "Could not bind texture input " << param_name << "\n"; + } + else { + // p3d_Texture[] or p3d_TextureModulate[], etc. + if (size == 7) { + bind._part = Shader::STO_stage_i; + } + else if (noprefix.compare(7, string::npos, "FF") == 0) { + bind._part = Shader::STO_ff_stage_i; + } + else if (noprefix.compare(7, string::npos, "Modulate") == 0) { + bind._part = Shader::STO_stage_modulate_i; + } + else if (noprefix.compare(7, string::npos, "Add") == 0) { + bind._part = Shader::STO_stage_add_i; + } + else if (noprefix.compare(7, string::npos, "Normal") == 0) { + bind._part = Shader::STO_stage_normal_i; + } + else if (noprefix.compare(7, string::npos, "Height") == 0) { + bind._part = Shader::STO_stage_height_i; + } + else if (noprefix.compare(7, string::npos, "Selector") == 0) { + bind._part = Shader::STO_stage_selector_i; + } + else if (noprefix.compare(7, string::npos, "Gloss") == 0) { + bind._part = Shader::STO_stage_gloss_i; + } + else if (noprefix.compare(7, string::npos, "Emission") == 0) { + bind._part = Shader::STO_stage_emission_i; + } + + for (bind._stage = 0; bind._stage < param_size; ++bind._stage) { + _glgsg->_glUniform1i(p + bind._stage, _shader->_tex_spec.size()); + _shader->_tex_spec.push_back(bind); + } } return; } diff --git a/panda/src/gobj/shader.h b/panda/src/gobj/shader.h index 940e2d0ccf..d2035a26ea 100644 --- a/panda/src/gobj/shader.h +++ b/panda/src/gobj/shader.h @@ -225,6 +225,15 @@ public: STO_stage_i, STO_light_i_shadow_map, + + STO_ff_stage_i, + STO_stage_modulate_i, + STO_stage_add_i, + STO_stage_normal_i, + STO_stage_height_i, + STO_stage_selector_i, + STO_stage_gloss_i, + STO_stage_emission_i, }; enum ShaderArgClass {