shader: Add additional mode-based texture inputs to GLSL shaders

This adds the following inputs:
  p3d_Texture[] (as alternative to p3d_Texture0, etc.)
  p3d_TextureFF[]
  p3d_TextureModulate[]
  p3d_TextureAdd[]
  p3d_TextureNormal[]
  p3d_TextureHeight[]
  p3d_TextureSelector[]
  p3d_TextureGloss[]
  p3d_TextureEmission[]
This commit is contained in:
rdb 2020-12-23 17:51:23 +01:00
parent 05876317cf
commit 35b7ef0dcb
3 changed files with 256 additions and 12 deletions

View File

@ -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;

View File

@ -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;
}

View File

@ -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 {