Allow multiple triplanar textures to be used within one visual shader

This commit is contained in:
Chaosus 2024-11-22 18:33:41 +03:00
parent f952bfe998
commit 8e5f59500c
4 changed files with 89 additions and 23 deletions

View File

@ -38,6 +38,10 @@
#include "visual_shader_particle_nodes.h"
#include "visual_shader_sdf_nodes.h"
#ifdef MODULE_REGEX_ENABLED
#include "modules/regex/regex.h"
#endif // MODULE_REGEX_ENABLED
String make_unique_id(VisualShader::Type p_type, int p_id, const String &p_name) {
static const char *typepf[VisualShader::TYPE_MAX] = { "vtx", "frg", "lgt", "start", "process", "collide", "start_custom", "process_custom", "sky", "fog" };
return p_name + "_" + String(typepf[p_type]) + "_" + itos(p_id);
@ -381,6 +385,10 @@ String VisualShaderNode::generate_global_per_func(Shader::Mode p_mode, VisualSha
return String();
}
String VisualShaderNode::generate_global_per_func_multi(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
return String();
}
Vector<StringName> VisualShaderNode::get_editable_properties() const {
return Vector<StringName>();
}
@ -2018,6 +2026,11 @@ Error VisualShader::_write_node(Type type, StringBuilder *p_global_code, StringB
}
r_classes.insert(class_name);
}
for (int i = 0; i < TYPE_MAX; i++) {
if (p_global_code_per_func) {
(*p_global_code_per_func)[Type(i)] += vsnode->generate_global_per_func_multi(get_mode(), Type(i), p_node);
}
}
}
if (!vsnode->is_code_generated()) { // just generate globals and ignore locals
@ -4334,6 +4347,35 @@ String VisualShaderNodeParameter::get_warning(Shader::Mode p_mode, VisualShader:
return String();
}
int VisualShaderNodeParameter::get_index() const {
#ifdef MODULE_REGEX_ENABLED
RegEx regex = RegEx("\\d+$");
Ref<RegExMatch> match = regex.search(parameter_name);
if (match.is_null()) {
return 0;
}
return match->get_strings()[0].to_int();
#else
String buffer;
for (int i = 0; i < parameter_name.length(); i++) {
int index = parameter_name.length() - i - 1;
String ch = parameter_name.substr(index, 1);
if (ch.is_valid_int()) {
buffer += ch;
} else {
break;
}
}
if (buffer.is_empty()) {
return 0;
}
return buffer.reverse().to_int();
#endif
}
Vector<StringName> VisualShaderNodeParameter::get_editable_properties() const {
Vector<StringName> props;
props.push_back("qualifier");

View File

@ -377,6 +377,7 @@ public:
virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const;
virtual String generate_global_per_node(Shader::Mode p_mode, int p_id) const;
virtual String generate_global_per_func(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const;
virtual String generate_global_per_func_multi(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const;
// If no output is connected, the output var passed will be empty. If no input is connected and input is NIL, the input var passed will be empty.
virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const = 0;
@ -626,6 +627,8 @@ public:
virtual bool is_qualifier_supported(Qualifier p_qual) const = 0;
virtual bool is_convertible_to_constant() const = 0;
int get_index() const;
virtual Vector<StringName> get_editable_properties() const override;
virtual String get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const override;

View File

@ -6758,34 +6758,34 @@ String VisualShaderNodeTextureParameterTriplanar::generate_global_per_node(Shade
String code;
code += "// " + get_caption() + "\n";
code += " vec4 triplanar_texture(sampler2D p_sampler, vec3 p_weights, vec3 p_triplanar_pos) {\n";
code += " vec4 samp = vec4(0.0);\n";
code += " samp += texture(p_sampler, p_triplanar_pos.xy) * p_weights.z;\n";
code += " samp += texture(p_sampler, p_triplanar_pos.xz) * p_weights.y;\n";
code += " samp += texture(p_sampler, p_triplanar_pos.zy * vec2(-1.0, 1.0)) * p_weights.x;\n";
code += " return samp;\n";
code += " }\n";
code += "\n";
code += " uniform vec3 triplanar_scale = vec3(1.0, 1.0, 1.0);\n";
code += " uniform vec3 triplanar_offset;\n";
code += " uniform float triplanar_sharpness = 0.5;\n";
code += "\n";
code += " varying vec3 triplanar_power_normal;\n";
code += " varying vec3 triplanar_pos;\n";
code += "vec4 triplanar_texture(sampler2D p_sampler, vec3 p_weights, vec3 p_triplanar_pos) {\n";
code += " vec4 samp = vec4(0.0);\n";
code += " samp += texture(p_sampler, p_triplanar_pos.xy) * p_weights.z;\n";
code += " samp += texture(p_sampler, p_triplanar_pos.xz) * p_weights.y;\n";
code += " samp += texture(p_sampler, p_triplanar_pos.zy * vec2(-1.0, 1.0)) * p_weights.x;\n";
code += " return samp;\n";
code += "}\n";
return code;
}
String VisualShaderNodeTextureParameterTriplanar::generate_global_per_func(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
String VisualShaderNodeTextureParameterTriplanar::generate_global_per_func_multi(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
String code;
if (p_type == VisualShader::TYPE_VERTEX) {
int index = get_index();
String index_string;
if (index > 0) {
index_string = itos(index);
}
code += "// " + get_caption() + "\n";
code += " {\n";
code += " triplanar_power_normal = pow(abs(NORMAL), vec3(triplanar_sharpness));\n";
code += " triplanar_power_normal /= dot(triplanar_power_normal, vec3(1.0));\n";
code += " triplanar_pos = VERTEX * triplanar_scale + triplanar_offset;\n";
code += " triplanar_pos *= vec3(1.0, -1.0, 1.0);\n";
code += vformat(" triplanar_power_normal%s = pow(abs(NORMAL), vec3(triplanar_sharpness%s));\n", index_string, index_string);
code += vformat(" triplanar_power_normal%s /= dot(triplanar_power_normal%s, vec3(1.0));\n", index_string, index_string);
code += vformat(" triplanar_pos%s = VERTEX * triplanar_scale%s + triplanar_offset%s;\n", index_string, index_string, index_string);
code += vformat(" triplanar_pos%s *= vec3(1.0, -1.0, 1.0);\n", index_string);
code += " }\n";
}
@ -6794,21 +6794,42 @@ String VisualShaderNodeTextureParameterTriplanar::generate_global_per_func(Shade
String VisualShaderNodeTextureParameterTriplanar::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
String code = _get_qual_str() + "uniform sampler2D " + get_parameter_name();
int index = get_index();
code += get_sampler_hint(texture_type, color_default, texture_filter, texture_repeat, texture_source);
code += ";\n";
String index_string;
if (index > 0) {
index_string = itos(index);
}
code += vformat("uniform vec3 triplanar_scale%s = vec3(1.0, 1.0, 1.0);\n", index_string);
code += vformat("uniform vec3 triplanar_offset%s;\n", index_string);
code += vformat("uniform float triplanar_sharpness%s = 0.5;\n", index_string);
code += vformat("varying vec3 triplanar_power_normal%s;\n", index_string);
code += vformat("varying vec3 triplanar_pos%s;\n", index_string);
code += "\n";
return code;
}
String VisualShaderNodeTextureParameterTriplanar::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const {
String id = get_parameter_name();
int index = get_index();
String index_string;
if (index > 0) {
index_string = itos(index);
}
String code;
if (p_input_vars[0].is_empty() && p_input_vars[1].is_empty()) {
code += " " + p_output_vars[0] + " = triplanar_texture(" + id + ", triplanar_power_normal, triplanar_pos);\n";
code += " " + p_output_vars[0] + " = triplanar_texture(" + id + vformat(", triplanar_power_normal%s, triplanar_pos%s);\n", index_string, index_string);
} else if (!p_input_vars[0].is_empty() && p_input_vars[1].is_empty()) {
code += " " + p_output_vars[0] + " = triplanar_texture(" + id + ", " + p_input_vars[0] + ", triplanar_pos);\n";
code += " " + p_output_vars[0] + " = triplanar_texture(" + id + ", " + p_input_vars[0] + vformat(", triplanar_pos%s);\n", index_string);
} else if (p_input_vars[0].is_empty() && !p_input_vars[1].is_empty()) {
code += " " + p_output_vars[0] + " = triplanar_texture(" + id + ", triplanar_power_normal, " + p_input_vars[1] + ");\n";
code += " " + p_output_vars[0] + " = triplanar_texture(" + id + vformat(", triplanar_power_normal%s, ", index_string) + p_input_vars[1] + ");\n";
} else {
code += " " + p_output_vars[0] + " = triplanar_texture(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
}

View File

@ -2625,7 +2625,7 @@ public:
virtual bool is_input_port_default(int p_port, Shader::Mode p_mode) const override;
virtual String generate_global_per_node(Shader::Mode p_mode, int p_id) const override;
virtual String generate_global_per_func(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override;
virtual String generate_global_per_func_multi(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override;
virtual String generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const override;
virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override;