Some refactoring for visual shader texture functions

This commit is contained in:
Yuri Rubinsky 2023-01-20 11:59:05 +03:00
parent 2f2bf84890
commit 7cbe2b939e
3 changed files with 189 additions and 260 deletions

View file

@ -58,13 +58,6 @@
Sets the output port index which will be showed for preview. If set to [code]-1[/code] no port will be open for preview.
</member>
</members>
<signals>
<signal name="editor_refresh_request">
<description>
Emitted when the node requests an editor refresh. Currently called only in setter of [member VisualShaderNodeTexture.source], [VisualShaderNodeTexture], and [VisualShaderNodeCubemap] (and their derivatives).
</description>
</signal>
</signals>
<constants>
<constant name="PORT_TYPE_SCALAR" value="0" enum="PortType">
Floating-point scalar. Translated to [code]float[/code] type in shader code.

View file

@ -399,7 +399,6 @@ void VisualShaderNode::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "output_port_for_preview"), "set_output_port_for_preview", "get_output_port_for_preview");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "default_input_values", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "set_default_input_values", "get_default_input_values");
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "expanded_output_ports", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_output_ports_expanded", "_get_output_ports_expanded");
ADD_SIGNAL(MethodInfo("editor_refresh_request"));
BIND_ENUM_CONSTANT(PORT_TYPE_SCALAR);
BIND_ENUM_CONSTANT(PORT_TYPE_SCALAR_INT);

View file

@ -756,194 +756,157 @@ Vector<VisualShader::DefaultTextureParam> VisualShaderNodeTexture::get_default_t
}
String VisualShaderNodeTexture::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
if (source == SOURCE_TEXTURE) {
String u = "uniform sampler2D " + make_unique_id(p_type, p_id, "tex");
switch (texture_type) {
case TYPE_DATA:
break;
case TYPE_COLOR:
u += " : source_color";
break;
case TYPE_NORMAL_MAP:
u += " : hint_normal";
break;
default:
break;
}
return u + ";\n";
} else if (source == SOURCE_SCREEN && (p_mode == Shader::MODE_SPATIAL || p_mode == Shader::MODE_CANVAS_ITEM) && p_type == VisualShader::TYPE_FRAGMENT) {
String u = "uniform sampler2D " + make_unique_id(p_type, p_id, "screen_tex");
return u + " : hint_screen_texture;\n";
} else if (source == SOURCE_DEPTH || source == SOURCE_3D_NORMAL || source == SOURCE_ROUGHNESS) {
String sampler_name = "";
String hint = " : ";
if (source == SOURCE_DEPTH) {
sampler_name = "depth_tex";
hint += "hint_depth_texture;\n";
} else if (source == SOURCE_3D_NORMAL) {
sampler_name = "screen_normal_tex";
hint += "hint_normal_roughness_texture;\n";
} else if (source == SOURCE_ROUGHNESS) {
sampler_name = "screen_roughness_tex";
hint += "hint_normal_roughness_texture;\n";
}
return "uniform sampler2D " + make_unique_id(p_type, p_id, sampler_name) + hint;
String code;
switch (source) {
case SOURCE_TEXTURE: {
code += "uniform sampler2D " + make_unique_id(p_type, p_id, "tex");
switch (texture_type) {
case TYPE_DATA: {
} break;
case TYPE_COLOR: {
code += " : source_color";
} break;
case TYPE_NORMAL_MAP: {
code += " : hint_normal";
} break;
default: {
} break;
}
code += ";\n";
} break;
case SOURCE_SCREEN: {
if ((p_mode == Shader::MODE_SPATIAL || p_mode == Shader::MODE_CANVAS_ITEM) && p_type == VisualShader::TYPE_FRAGMENT) {
code += "uniform sampler2D " + make_unique_id(p_type, p_id, "screen_tex") + " : hint_screen_texture;\n";
}
} break;
case SOURCE_DEPTH:
case SOURCE_3D_NORMAL:
case SOURCE_ROUGHNESS: {
if (p_mode == Shader::MODE_SPATIAL && p_type == VisualShader::TYPE_FRAGMENT) {
String sampler_name = "";
String hint = " : ";
if (source == SOURCE_DEPTH) {
sampler_name = "depth_tex";
hint += "hint_depth_texture;\n";
} else {
sampler_name = source == SOURCE_ROUGHNESS ? "roughness_tex" : "normal_roughness_tex";
hint += "hint_normal_roughness_texture;\n";
}
code += "uniform sampler2D " + make_unique_id(p_type, p_id, sampler_name) + hint;
}
} break;
default: {
} break;
}
return String();
return code;
}
String VisualShaderNodeTexture::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 default_uv;
if (p_mode == Shader::MODE_CANVAS_ITEM || p_mode == Shader::MODE_SPATIAL) {
default_uv = "UV";
if (source == SOURCE_SCREEN) {
default_uv = "SCREEN_UV";
} else {
default_uv = "UV";
}
} else {
default_uv = "vec2(0.0)";
}
String code;
if (source == SOURCE_TEXTURE) {
String id = make_unique_id(p_type, p_id, "tex");
if (p_input_vars[0].is_empty()) { // Use UV by default.
if (p_input_vars[1].is_empty()) {
code += " " + p_output_vars[0] + " = texture(" + id + ", " + default_uv + ");\n";
} else {
code += " " + p_output_vars[0] + " = textureLod(" + id + ", " + default_uv + ", " + p_input_vars[1] + ");\n";
}
} else if (p_input_vars[1].is_empty()) {
//no lod
code += " " + p_output_vars[0] + " = texture(" + id + ", " + p_input_vars[0] + ");\n";
} else {
code += " " + p_output_vars[0] + " = textureLod(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
}
return code;
}
String uv = p_input_vars[0].is_empty() ? default_uv : p_input_vars[0];
if (source == SOURCE_PORT) {
String id = p_input_vars[2];
if (id.is_empty()) {
code += " " + p_output_vars[0] + " = vec4(0.0);\n";
} else {
if (p_input_vars[0].is_empty()) { // Use UV by default.
if (p_input_vars[1].is_empty()) {
code += " " + p_output_vars[0] + " = texture(" + id + ", " + default_uv + ");\n";
} else {
code += " " + p_output_vars[0] + " = textureLod(" + id + ", " + default_uv + ", " + p_input_vars[1] + ");\n";
switch (source) {
case SOURCE_PORT:
case SOURCE_TEXTURE: {
String id;
if (source == SOURCE_PORT) {
id = p_input_vars[2];
if (id.is_empty()) {
break;
}
} else if (p_input_vars[1].is_empty()) {
//no lod
code += " " + p_output_vars[0] + " = texture(" + id + ", " + p_input_vars[0] + ");\n";
} else {
code += " " + p_output_vars[0] + " = textureLod(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
} else { // SOURCE_TEXTURE
id = make_unique_id(p_type, p_id, "tex");
}
}
return code;
}
if (source == SOURCE_SCREEN && (p_mode == Shader::MODE_SPATIAL || p_mode == Shader::MODE_CANVAS_ITEM) && p_type == VisualShader::TYPE_FRAGMENT) {
String id = make_unique_id(p_type, p_id, "screen_tex");
if (p_input_vars[0].is_empty() || p_for_preview) { // Use UV by default.
if (p_input_vars[1].is_empty()) {
code += " " + p_output_vars[0] + " = textureLod(" + id + ", " + default_uv + ", 0.0);\n";
code += " " + p_output_vars[0] + " = texture(" + id + ", " + uv + ");\n";
} else {
code += " " + p_output_vars[0] + " = textureLod(" + id + ", " + default_uv + ", " + p_input_vars[1] + ");\n";
code += " " + p_output_vars[0] + " = textureLod(" + id + ", " + uv + ", " + p_input_vars[1] + ");\n";
}
} else if (p_input_vars[1].is_empty()) {
//no lod
code += " " + p_output_vars[0] + " = textureLod(" + id + ", " + p_input_vars[0] + ", 0.0);\n";
} else {
code += " " + p_output_vars[0] + " = textureLod(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
}
return code;
}
if (source == SOURCE_2D_TEXTURE && p_mode == Shader::MODE_CANVAS_ITEM && p_type == VisualShader::TYPE_FRAGMENT) {
if (p_input_vars[0].is_empty()) { // Use UV by default.
if (p_input_vars[1].is_empty()) {
code += " " + p_output_vars[0] + " = texture(TEXTURE, " + default_uv + ");\n";
} else {
code += " " + p_output_vars[0] + " = textureLod(TEXTURE, " + default_uv + ", " + p_input_vars[1] + ");\n";
}
} else if (p_input_vars[1].is_empty()) {
//no lod
code += " " + p_output_vars[0] + " = texture(TEXTURE, " + p_input_vars[0] + ");\n";
} else {
code += " " + p_output_vars[0] + " = textureLod(TEXTURE, " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
}
return code;
}
if (source == SOURCE_2D_NORMAL && p_mode == Shader::MODE_CANVAS_ITEM && p_type == VisualShader::TYPE_FRAGMENT) {
if (p_input_vars[0].is_empty()) { // Use UV by default.
if (p_input_vars[1].is_empty()) {
code += " " + p_output_vars[0] + " = texture(NORMAL_TEXTURE, " + default_uv + ");\n";
} else {
code += " " + p_output_vars[0] + " = textureLod(NORMAL_TEXTURE, " + default_uv + ", " + p_input_vars[1] + ");\n";
}
} else if (p_input_vars[1].is_empty()) {
//no lod
code += " " + p_output_vars[0] + " = texture(NORMAL_TEXTURE, " + p_input_vars[0] + ".xy);\n";
} else {
code += " " + p_output_vars[0] + " = textureLod(NORMAL_TEXTURE, " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ");\n";
}
return code;
}
if (source == SOURCE_DEPTH || source == SOURCE_ROUGHNESS) {
if (!p_for_preview && p_mode == Shader::MODE_SPATIAL && p_type == VisualShader::TYPE_FRAGMENT) {
String var_name = "";
String sampler_name = "";
if (source == SOURCE_DEPTH) {
var_name = "_depth";
sampler_name = "depth_tex";
} else if (source == SOURCE_ROUGHNESS) {
var_name = "_screen_roughness";
sampler_name = "screen_roughness_tex";
}
String id = make_unique_id(p_type, p_id, sampler_name);
code += " {\n";
if (p_input_vars[0].is_empty()) { // Use UV by default.
if (p_input_vars[1].is_empty()) {
code += " float " + var_name + " = texture(" + id + ", " + default_uv + ").r;\n";
} else {
code += " float " + var_name + " = textureLod(" + id + ", " + default_uv + ", " + p_input_vars[1] + ").r;\n";
}
} else if (p_input_vars[1].is_empty()) {
//no lod
code += " float " + var_name + " = texture(" + id + ", " + p_input_vars[0] + ".xy).r;\n";
} else {
code += " float " + var_name + " = textureLod(" + id + ", " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ").r;\n";
}
code += " " + p_output_vars[0] + " = vec4(" + var_name + ", " + var_name + ", " + var_name + ", 1.0);\n";
code += " }\n";
return code;
}
}
if (source == SOURCE_3D_NORMAL) {
if (!p_for_preview && p_mode == Shader::MODE_SPATIAL && p_type == VisualShader::TYPE_FRAGMENT) {
String id = make_unique_id(p_type, p_id, "screen_normal_tex");
code += " {\n";
if (p_input_vars[0].is_empty()) { // Use UV by default.
} break;
case SOURCE_SCREEN: {
if ((p_mode == Shader::MODE_SPATIAL || p_mode == Shader::MODE_CANVAS_ITEM) && p_type == VisualShader::TYPE_FRAGMENT) {
String id = make_unique_id(p_type, p_id, "screen_tex");
if (p_input_vars[1].is_empty()) {
code += " vec3 _screen_normal = texture(" + id + ", " + default_uv + ").xyz;\n";
code += " " + p_output_vars[0] + " = texture(" + id + ", " + uv + ");\n";
} else {
code += " vec3 _screen_normal = textureLod(" + id + ", " + default_uv + ", " + p_input_vars[1] + ").xyz;\n";
code += " " + p_output_vars[0] + " = textureLod(" + id + ", " + uv + ", " + p_input_vars[1] + ");\n";
}
} else if (p_input_vars[1].is_empty()) {
//no lod
code += " vec3 _screen_normal = texture(" + id + ", " + p_input_vars[0] + ".xy).xyz;\n";
} else {
code += " vec3 _screen_normal = textureLod(" + id + ", " + p_input_vars[0] + ".xy, " + p_input_vars[1] + ").xyz;\n";
return code;
}
} break;
case SOURCE_2D_NORMAL:
case SOURCE_2D_TEXTURE: {
if (p_mode == Shader::MODE_CANVAS_ITEM && p_type == VisualShader::TYPE_FRAGMENT) {
String id = source == SOURCE_2D_TEXTURE ? "TEXTURE" : "NORMAL_TEXTURE";
code += " " + p_output_vars[0] + " = vec4(_screen_normal, 1.0);\n";
code += " }\n";
return code;
}
if (p_input_vars[1].is_empty()) {
code += " " + p_output_vars[0] + " = texture(" + id + ", " + uv + ");\n";
} else {
code += " " + p_output_vars[0] + " = textureLod(" + id + ", " + uv + ", " + p_input_vars[1] + ");\n";
}
return code;
}
} break;
case SOURCE_3D_NORMAL:
case SOURCE_ROUGHNESS:
case SOURCE_DEPTH: {
if (!p_for_preview && p_mode == Shader::MODE_SPATIAL && p_type == VisualShader::TYPE_FRAGMENT) {
String var_name = "";
String sampler_name = "";
switch (source) {
case SOURCE_DEPTH: {
var_name = "_depth";
sampler_name = "depth_tex";
} break;
case SOURCE_ROUGHNESS: {
var_name = "_roughness";
sampler_name = "roughness_tex";
} break;
case SOURCE_3D_NORMAL: {
var_name = "_normal";
sampler_name = "normal_roughness_tex";
} break;
default: {
} break;
}
String id = make_unique_id(p_type, p_id, sampler_name);
String type = source == SOURCE_3D_NORMAL ? "vec3" : "float";
String components = source == SOURCE_3D_NORMAL ? "rgb" : "r";
code += " {\n";
if (p_input_vars[1].is_empty()) {
code += " " + type + " " + var_name + " = texture(" + id + ", " + uv + ")." + components + ";\n";
} else {
code += " " + type + " " + var_name + " = textureLod(" + id + ", " + uv + ", " + p_input_vars[1] + ")." + components + ";\n";
}
if (source == SOURCE_3D_NORMAL) {
code += " " + p_output_vars[0] + " = vec4(" + var_name + ", 1.0);\n";
} else {
code += " " + p_output_vars[0] + " = vec4(" + var_name + ", " + var_name + ", " + var_name + ", 1.0);\n";
}
code += " }\n";
return code;
}
} break;
default: {
} break;
}
code += " " + p_output_vars[0] + " = vec4(0.0);\n";
@ -985,7 +948,6 @@ void VisualShaderNodeTexture::set_source(Source p_source) {
}
source = p_source;
emit_changed();
emit_signal(SNAME("editor_refresh_request"));
}
VisualShaderNodeTexture::Source VisualShaderNodeTexture::get_source() const {
@ -1029,31 +991,34 @@ String VisualShaderNodeTexture::get_warning(Shader::Mode p_mode, VisualShader::T
return RTR("The sampler port is connected but not used. Consider changing the source to 'SamplerPort'.");
}
if (source == SOURCE_TEXTURE) {
return String(); // all good
}
if (source == SOURCE_PORT) {
return String(); // all good
}
if (source == SOURCE_SCREEN && (p_mode == Shader::MODE_SPATIAL || p_mode == Shader::MODE_CANVAS_ITEM) && p_type == VisualShader::TYPE_FRAGMENT) {
return String(); // all good
}
if (source == SOURCE_2D_TEXTURE && p_mode == Shader::MODE_CANVAS_ITEM && p_type == VisualShader::TYPE_FRAGMENT) {
return String(); // all good
}
if (source == SOURCE_2D_NORMAL && p_mode == Shader::MODE_CANVAS_ITEM) {
return String(); // all good
}
if ((source == SOURCE_DEPTH || source == SOURCE_3D_NORMAL || source == SOURCE_ROUGHNESS) && p_mode == Shader::MODE_SPATIAL && p_type == VisualShader::TYPE_FRAGMENT) {
if (get_output_port_for_preview() == 0) { // DEPTH_TEXTURE and NORMAL_ROUGHNESS_TEXTURE are not supported in preview(canvas_item) shader
return RTR("Invalid source for preview.");
}
return String(); // all good
switch (source) {
case SOURCE_TEXTURE:
case SOURCE_PORT: {
return String(); // All good.
} break;
case SOURCE_SCREEN: {
if ((p_mode == Shader::MODE_SPATIAL || p_mode == Shader::MODE_CANVAS_ITEM) && p_type == VisualShader::TYPE_FRAGMENT) {
return String(); // All good.
}
} break;
case SOURCE_2D_NORMAL:
case SOURCE_2D_TEXTURE: {
if (p_mode == Shader::MODE_CANVAS_ITEM && p_type == VisualShader::TYPE_FRAGMENT) {
return String(); // All good.
}
} break;
case SOURCE_3D_NORMAL:
case SOURCE_ROUGHNESS:
case SOURCE_DEPTH: {
if (p_mode == Shader::MODE_SPATIAL && p_type == VisualShader::TYPE_FRAGMENT) {
if (get_output_port_for_preview() == 0) { // Not supported in preview(canvas_item) shader.
return RTR("Invalid source for preview.");
}
return String(); // All good.
}
} break;
default: {
} break;
}
return RTR("Invalid source for shader.");
@ -1321,6 +1286,17 @@ bool VisualShaderNodeSample3D::is_input_port_default(int p_port, Shader::Mode p_
}
String VisualShaderNodeSample3D::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 code;
String id;
if (source == SOURCE_TEXTURE) {
id = make_unique_id(p_type, p_id, "tex3d");
} else { // SOURCE_PORT
id = p_input_vars[2];
if (id.is_empty()) {
code += " " + p_output_vars[0] + " = vec4(0.0);\n";
return code;
}
}
String default_uv;
if (p_mode == Shader::MODE_CANVAS_ITEM || p_mode == Shader::MODE_SPATIAL) {
default_uv = "vec3(UV, 0.0)";
@ -1328,33 +1304,12 @@ String VisualShaderNodeSample3D::generate_code(Shader::Mode p_mode, VisualShader
default_uv = "vec3(0.0)";
}
String code;
if (source == SOURCE_TEXTURE || source == SOURCE_PORT) {
String id;
if (source == SOURCE_TEXTURE) {
id = make_unique_id(p_type, p_id, "tex3d");
} else {
id = p_input_vars[2];
}
if (!id.is_empty()) {
if (p_input_vars[0].is_empty()) { // Use UV by default.
if (p_input_vars[1].is_empty()) {
code += " " + p_output_vars[0] + " = texture(" + id + ", " + default_uv + ");\n";
} else {
code += " " + p_output_vars[0] + " = textureLod(" + id + ", " + default_uv + ", " + p_input_vars[1] + ");\n";
}
} else if (p_input_vars[1].is_empty()) {
//no lod
code += " " + p_output_vars[0] + " = texture(" + id + ", " + p_input_vars[0] + ");\n";
} else {
code += " " + p_output_vars[0] + " = textureLod(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
}
} else {
code += " " + p_output_vars[0] + " = vec4(0.0);\n";
}
return code;
String uv = p_input_vars[0].is_empty() ? default_uv : p_input_vars[0];
if (p_input_vars[1].is_empty()) {
code += " " + p_output_vars[0] + " = texture(" + id + ", " + uv + ");\n";
} else {
code += " " + p_output_vars[0] + " = textureLod(" + id + ", " + uv + ", " + p_input_vars[1] + ");\n";
}
code += " " + p_output_vars[0] + " = vec4(0.0);\n";
return code;
}
@ -1365,7 +1320,6 @@ void VisualShaderNodeSample3D::set_source(Source p_source) {
}
source = p_source;
emit_changed();
emit_signal(SNAME("editor_refresh_request"));
}
VisualShaderNodeSample3D::Source VisualShaderNodeSample3D::get_source() const {
@ -1387,14 +1341,7 @@ String VisualShaderNodeSample3D::get_warning(Shader::Mode p_mode, VisualShader::
if (is_input_port_connected(2) && source != SOURCE_PORT) {
return RTR("The sampler port is connected but not used. Consider changing the source to 'SamplerPort'.");
}
if (source == SOURCE_TEXTURE) {
return String(); // all good
}
if (source == SOURCE_PORT) {
return String(); // all good
}
return RTR("Invalid source for shader.");
return String();
}
VisualShaderNodeSample3D::VisualShaderNodeSample3D() {
@ -1600,6 +1547,19 @@ String VisualShaderNodeCubemap::generate_global(Shader::Mode p_mode, VisualShade
}
String VisualShaderNodeCubemap::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 code;
String id;
if (source == SOURCE_TEXTURE) {
id = make_unique_id(p_type, p_id, "cube");
} else { // SOURCE_PORT
id = p_input_vars[2];
if (id.is_empty()) {
code += " " + p_output_vars[0] + " = vec4(0.0);\n";
return code;
}
}
String default_uv;
if (p_mode == Shader::MODE_CANVAS_ITEM || p_mode == Shader::MODE_SPATIAL) {
default_uv = "vec3(UV, 0.0)";
@ -1607,35 +1567,13 @@ String VisualShaderNodeCubemap::generate_code(Shader::Mode p_mode, VisualShader:
default_uv = "vec3(0.0)";
}
String code;
String id;
if (source == SOURCE_TEXTURE) {
id = make_unique_id(p_type, p_id, "cube");
} else if (source == SOURCE_PORT) {
id = p_input_vars[2];
String uv = p_input_vars[0].is_empty() ? default_uv : p_input_vars[0];
if (p_input_vars[1].is_empty()) {
code += " " + p_output_vars[0] + " = texture(" + id + ", " + uv + ");\n";
} else {
return code;
code += " " + p_output_vars[0] + " = textureLod(" + id + ", " + uv + ", " + p_input_vars[1] + ");\n";
}
if (id.is_empty()) {
code += " " + p_output_vars[0] + " = vec4(0.0);\n";
return code;
}
if (p_input_vars[0].is_empty()) { // Use UV by default.
if (p_input_vars[1].is_empty()) {
code += " " + p_output_vars[0] + " = texture(" + id + ", " + default_uv + ");\n";
} else {
code += " " + p_output_vars[0] + " = textureLod(" + id + ", " + default_uv + ", " + p_input_vars[1] + ");\n";
}
} else if (p_input_vars[1].is_empty()) {
//no lod
code += " " + p_output_vars[0] + " = texture(" + id + ", " + p_input_vars[0] + ");\n";
} else {
code += " " + p_output_vars[0] + " = textureLod(" + id + ", " + p_input_vars[0] + ", " + p_input_vars[1] + ");\n";
}
return code;
}
@ -1655,7 +1593,6 @@ void VisualShaderNodeCubemap::set_source(Source p_source) {
}
source = p_source;
emit_changed();
emit_signal(SNAME("editor_refresh_request"));
}
VisualShaderNodeCubemap::Source VisualShaderNodeCubemap::get_source() const {