Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add more useful Visual Shader nodes #72664

Merged
merged 1 commit into from
Jul 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions doc/classes/VisualShaderNodeRotationByAxis.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="VisualShaderNodeRotationByAxis" inherits="VisualShaderNode" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
A visual shader node that modifies the rotation of the object using a rotation matrix.
</brief_description>
<description>
RotationByAxis node will transform the vertices of a mesh with specified axis and angle in radians. It can be used to rotate an object in an arbitrary axis.
</description>
<tutorials>
</tutorials>
</class>
11 changes: 11 additions & 0 deletions doc/classes/VisualShaderNodeScreenNormalWorldSpace.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="VisualShaderNodeScreenNormalWorldSpace" inherits="VisualShaderNode" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
A visual shader node that unpacks the screen normal texture in World Space.
</brief_description>
<description>
The ScreenNormalWorldSpace node allows to create outline effects.
</description>
<tutorials>
</tutorials>
</class>
11 changes: 11 additions & 0 deletions doc/classes/VisualShaderNodeWorldPositionFromDepth.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="VisualShaderNodeWorldPositionFromDepth" inherits="VisualShaderNode" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd">
<brief_description>
A visual shader node that calculates the position of the pixel in world space using the depth texture.
</brief_description>
<description>
The WorldPositionFromDepth node reconstructs the depth position of the pixel in world space. This can be used to obtain world space UVs for projection mapping like Caustics.
</description>
<tutorials>
</tutorials>
</class>
6 changes: 6 additions & 0 deletions editor/plugins/visual_shader_editor_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5875,6 +5875,10 @@ VisualShaderEditor::VisualShaderEditor() {
add_options.push_back(AddOption("CurveXYZTexture", "Textures/Functions", "VisualShaderNodeCurveXYZTexture", TTR("Perform the three components curve texture lookup."), {}, VisualShaderNode::PORT_TYPE_VECTOR_3D));
add_options.push_back(AddOption("LinearSceneDepth", "Textures/Functions", "VisualShaderNodeLinearSceneDepth", TTR("Returns the depth value obtained from the depth prepass in a linear space."), {}, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
texture2d_node_option_idx = add_options.size();
add_options.push_back(AddOption("WorldPositionFromDepth", "Textures/Functions", "VisualShaderNodeWorldPositionFromDepth", TTR("Reconstructs the World Position of the Node from the depth texture."), {}, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
texture2d_node_option_idx = add_options.size();
add_options.push_back(AddOption("ScreenNormalWorldSpace", "Textures/Functions", "VisualShaderNodeScreenNormalWorldSpace", TTR("Unpacks the Screen Normal Texture in World Space"), {}, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
texture2d_node_option_idx = add_options.size();
add_options.push_back(AddOption("Texture2D", "Textures/Functions", "VisualShaderNodeTexture", TTR("Perform the 2D texture lookup."), {}, VisualShaderNode::PORT_TYPE_VECTOR_4D));
texture2d_array_node_option_idx = add_options.size();
add_options.push_back(AddOption("Texture2DArray", "Textures/Functions", "VisualShaderNodeTexture2DArray", TTR("Perform the 2D-array texture lookup."), {}, VisualShaderNode::PORT_TYPE_VECTOR_4D));
Expand Down Expand Up @@ -5919,6 +5923,8 @@ VisualShaderEditor::VisualShaderEditor() {
add_options.push_back(AddOption("ProximityFade", "Utility", "VisualShaderNodeProximityFade", TTR("The proximity fade effect fades out each pixel based on its distance to another object."), {}, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("RandomRange", "Utility", "VisualShaderNodeRandomRange", TTR("Returns a random value between the minimum and maximum input values."), {}, VisualShaderNode::PORT_TYPE_SCALAR));
add_options.push_back(AddOption("Remap", "Utility", "VisualShaderNodeRemap", TTR("Remaps a given input from the input range to the output range."), {}, VisualShaderNode::PORT_TYPE_SCALAR));
add_options.push_back(AddOption("RotationByAxis", "Utility", "VisualShaderNodeRotationByAxis", TTR("Rotates an input vector by a given angle."), {}, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL));
add_options.push_back(AddOption("RotationByAxis", "Utility", "VisualShaderNodeRotationByAxis", TTR("Rotates an input vector by a given angle."), {}, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL));

// VECTOR

Expand Down
3 changes: 3 additions & 0 deletions scene/register_scene_types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -675,6 +675,8 @@ void register_scene_types() {
GDREGISTER_CLASS(VisualShaderNodeTexture3DParameter);
GDREGISTER_CLASS(VisualShaderNodeCubemapParameter);
GDREGISTER_CLASS(VisualShaderNodeLinearSceneDepth);
GDREGISTER_CLASS(VisualShaderNodeWorldPositionFromDepth);
GDREGISTER_CLASS(VisualShaderNodeScreenNormalWorldSpace);
GDREGISTER_CLASS(VisualShaderNodeIf);
GDREGISTER_CLASS(VisualShaderNodeSwitch);
GDREGISTER_CLASS(VisualShaderNodeFresnel);
Expand All @@ -688,6 +690,7 @@ void register_scene_types() {
GDREGISTER_CLASS(VisualShaderNodeProximityFade);
GDREGISTER_CLASS(VisualShaderNodeRandomRange);
GDREGISTER_CLASS(VisualShaderNodeRemap);
GDREGISTER_CLASS(VisualShaderNodeRotationByAxis);
GDREGISTER_ABSTRACT_CLASS(VisualShaderNodeVarying);
GDREGISTER_CLASS(VisualShaderNodeVaryingSetter);
GDREGISTER_CLASS(VisualShaderNodeVaryingGetter);
Expand Down
226 changes: 226 additions & 0 deletions scene/resources/visual_shader_nodes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1727,6 +1727,135 @@ VisualShaderNodeLinearSceneDepth::VisualShaderNodeLinearSceneDepth() {
simple_decl = false;
}

////////////// World Position from Depth

String VisualShaderNodeWorldPositionFromDepth::get_caption() const {
return "WorldPositionFromDepth";
}

int VisualShaderNodeWorldPositionFromDepth::get_input_port_count() const {
return 1;
}

VisualShaderNodeWorldPositionFromDepth::PortType VisualShaderNodeWorldPositionFromDepth::get_input_port_type(int p_port) const {
return PORT_TYPE_VECTOR_2D;
}

String VisualShaderNodeWorldPositionFromDepth::get_input_port_name(int p_port) const {
return "screen uv";
}

bool VisualShaderNodeWorldPositionFromDepth::is_input_port_default(int p_port, Shader::Mode p_mode) const {
if (p_port == 0) {
return true;
}
return false;
}

int VisualShaderNodeWorldPositionFromDepth::get_output_port_count() const {
return 1;
}

VisualShaderNodeWorldPositionFromDepth::PortType VisualShaderNodeWorldPositionFromDepth::get_output_port_type(int p_port) const {
return PORT_TYPE_VECTOR_3D;
}

String VisualShaderNodeWorldPositionFromDepth::get_output_port_name(int p_port) const {
return "world position";
}

bool VisualShaderNodeWorldPositionFromDepth::has_output_port_preview(int p_port) const {
return false;
}

String VisualShaderNodeWorldPositionFromDepth::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
return "uniform sampler2D " + make_unique_id(p_type, p_id, "depth_tex") + " : hint_depth_texture, repeat_disable, filter_nearest;\n";
}

String VisualShaderNodeWorldPositionFromDepth::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 uv = p_input_vars[0].is_empty() ? "SCREEN_UV" : p_input_vars[0];
code += " {\n";

code += " float __log_depth = textureLod(" + make_unique_id(p_type, p_id, "depth_tex") + ", " + uv + ", 0.0).x;\n";
if (!RenderingServer::get_singleton()->is_low_end()) {
code += " vec4 __depth_view = INV_PROJECTION_MATRIX * vec4(" + uv + " * 2.0 - 1.0, __log_depth, 1.0);\n";
} else {
code += " vec4 __depth_view = INV_PROJECTION_MATRIX * vec4(vec3(" + uv + ", __log_depth) * 2.0 - 1.0, 1.0);\n";
}
code += " __depth_view.xyz /= __depth_view.w;\n";
code += vformat(" %s = (INV_VIEW_MATRIX * __depth_view).xyz;\n", p_output_vars[0]);

code += " }\n";
return code;
}

VisualShaderNodeWorldPositionFromDepth::VisualShaderNodeWorldPositionFromDepth() {
simple_decl = false;
}

////////////// Unpack Normals in World Space

String VisualShaderNodeScreenNormalWorldSpace::get_caption() const {
return "ScreenNormalWorldSpace";
}

int VisualShaderNodeScreenNormalWorldSpace::get_input_port_count() const {
return 1;
}

VisualShaderNodeScreenNormalWorldSpace::PortType VisualShaderNodeScreenNormalWorldSpace::get_input_port_type(int p_port) const {
return PORT_TYPE_VECTOR_2D;
}

String VisualShaderNodeScreenNormalWorldSpace::get_input_port_name(int p_port) const {
return "screen uv";
}

bool VisualShaderNodeScreenNormalWorldSpace::is_input_port_default(int p_port, Shader::Mode p_mode) const {
if (p_port == 0) {
return true;
}
return false;
}

int VisualShaderNodeScreenNormalWorldSpace::get_output_port_count() const {
return 1;
}

VisualShaderNodeScreenNormalWorldSpace::PortType VisualShaderNodeScreenNormalWorldSpace::get_output_port_type(int p_port) const {
return PORT_TYPE_VECTOR_3D;
}

String VisualShaderNodeScreenNormalWorldSpace::get_output_port_name(int p_port) const {
return "screen normal";
}

bool VisualShaderNodeScreenNormalWorldSpace::has_output_port_preview(int p_port) const {
return false;
}

String VisualShaderNodeScreenNormalWorldSpace::generate_global(Shader::Mode p_mode, VisualShader::Type p_type, int p_id) const {
return "uniform sampler2D " + make_unique_id(p_type, p_id, "normal_rough_tex") + " : hint_normal_roughness_texture, repeat_disable, filter_nearest;\n";
}

String VisualShaderNodeScreenNormalWorldSpace::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 uv = p_input_vars[0].is_empty() ? "SCREEN_UV" : p_input_vars[0];
code += " {\n";

code += " vec3 __normals = textureLod(" + make_unique_id(p_type, p_id, "normal_rough_tex") + ", " + uv + ", 0.0).xyz;\n";
code += " __normals = __normals * 2.0 - 1.0;\n";
code += vformat(" %s = mat3(INV_VIEW_MATRIX) * __normals;\n", p_output_vars[0]);

code += " }\n";
return code;
}

VisualShaderNodeScreenNormalWorldSpace::VisualShaderNodeScreenNormalWorldSpace() {
simple_decl = false;
}

////////////// Float Op

String VisualShaderNodeFloatOp::get_caption() const {
Expand Down Expand Up @@ -7971,3 +8100,100 @@ VisualShaderNodeRemap::VisualShaderNodeRemap() {

simple_decl = false;
}

////////////// RotationByAxis

String VisualShaderNodeRotationByAxis::get_caption() const {
return "RotationByAxis";
}

int VisualShaderNodeRotationByAxis::get_input_port_count() const {
return 3;
}

VisualShaderNodeRotationByAxis::PortType VisualShaderNodeRotationByAxis::get_input_port_type(int p_port) const {
switch (p_port) {
case 0:
return PORT_TYPE_VECTOR_3D;
case 1:
return PORT_TYPE_SCALAR;
case 2:
return PORT_TYPE_VECTOR_3D;
default:
break;
}

return PORT_TYPE_SCALAR;
}

String VisualShaderNodeRotationByAxis::get_input_port_name(int p_port) const {
switch (p_port) {
case 0:
return "input";
case 1:
return "angle";
case 2:
return "axis";
default:
break;
}

return "";
}

int VisualShaderNodeRotationByAxis::get_output_port_count() const {
return 2;
}

VisualShaderNodeRotationByAxis::PortType VisualShaderNodeRotationByAxis::get_output_port_type(int p_port) const {
switch (p_port) {
case 0:
return PORT_TYPE_VECTOR_3D;
case 1:
return PORT_TYPE_TRANSFORM;
default:
break;
}

return PORT_TYPE_SCALAR;
}

String VisualShaderNodeRotationByAxis::get_output_port_name(int p_port) const {
switch (p_port) {
case 0:
return "output";
case 1:
return "rotationMat";
default:
break;
}

return "";
}

bool VisualShaderNodeRotationByAxis::has_output_port_preview(int p_port) const {
return false;
}

String VisualShaderNodeRotationByAxis::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;
code += " {\n";
code += vformat(" float __angle = %s;\n", p_input_vars[1]);
code += vformat(" vec3 __axis = normalize(%s);\n", p_input_vars[2]);
code += vformat(" mat3 __rot_matrix = mat3(\n");
code += vformat(" vec3( cos(__angle)+__axis.x*__axis.x*(1.0 - cos(__angle)), __axis.x*__axis.y*(1.0-cos(__angle))-__axis.z*sin(__angle), __axis.x*__axis.z*(1.0-cos(__angle))+__axis.y*sin(__angle) ),\n");
code += vformat(" vec3( __axis.y*__axis.x*(1.0-cos(__angle))+__axis.z*sin(__angle), cos(__angle)+__axis.y*__axis.y*(1.0-cos(__angle)), __axis.y*__axis.z*(1.0-cos(__angle))-__axis.x*sin(__angle) ),\n");
code += vformat(" vec3( __axis.z*__axis.x*(1.0-cos(__angle))-__axis.y*sin(__angle), __axis.z*__axis.y*(1.0-cos(__angle))+__axis.x*sin(__angle), cos(__angle)+__axis.z*__axis.z*(1.0-cos(__angle)) )\n");
code += vformat(" );\n");
code += vformat(" %s = %s * __rot_matrix;\n", p_output_vars[0], p_input_vars[0]);
code += vformat(" %s = mat4(__rot_matrix);\n", p_output_vars[1]);
code += " }\n";
return code;
}

VisualShaderNodeRotationByAxis::VisualShaderNodeRotationByAxis() {
set_input_port_default_value(1, 0.0);
set_input_port_default_value(2, Vector3(0.0, 0.0, 0.0));

simple_decl = false;
}
64 changes: 64 additions & 0 deletions scene/resources/visual_shader_nodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -680,6 +680,50 @@ class VisualShaderNodeLinearSceneDepth : public VisualShaderNode {
VisualShaderNodeLinearSceneDepth();
};

class VisualShaderNodeWorldPositionFromDepth : public VisualShaderNode {
GDCLASS(VisualShaderNodeWorldPositionFromDepth, VisualShaderNode);

public:
virtual String get_caption() const override;

virtual int get_input_port_count() const override;
virtual PortType get_input_port_type(int p_port) const override;
virtual String get_input_port_name(int p_port) const override;
virtual bool is_input_port_default(int p_port, Shader::Mode p_mode) const override;

virtual int get_output_port_count() const override;
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
virtual bool has_output_port_preview(int p_port) 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;

VisualShaderNodeWorldPositionFromDepth();
};

class VisualShaderNodeScreenNormalWorldSpace : public VisualShaderNode {
GDCLASS(VisualShaderNodeScreenNormalWorldSpace, VisualShaderNode);

public:
virtual String get_caption() const override;

virtual int get_input_port_count() const override;
virtual PortType get_input_port_type(int p_port) const override;
virtual String get_input_port_name(int p_port) const override;
virtual bool is_input_port_default(int p_port, Shader::Mode p_mode) const override;

virtual int get_output_port_count() const override;
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
virtual bool has_output_port_preview(int p_port) 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;

VisualShaderNodeScreenNormalWorldSpace();
};

///////////////////////////////////////
/// OPS
///////////////////////////////////////
Expand Down Expand Up @@ -2913,4 +2957,24 @@ class VisualShaderNodeRemap : public VisualShaderNode {
VisualShaderNodeRemap();
};

class VisualShaderNodeRotationByAxis : public VisualShaderNode {
GDCLASS(VisualShaderNodeRotationByAxis, VisualShaderNode);

public:
virtual String get_caption() const override;

virtual int get_input_port_count() const override;
virtual PortType get_input_port_type(int p_port) const override;
virtual String get_input_port_name(int p_port) const override;

virtual int get_output_port_count() const override;
virtual PortType get_output_port_type(int p_port) const override;
virtual String get_output_port_name(int p_port) const override;
virtual bool has_output_port_preview(int p_port) 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;

VisualShaderNodeRotationByAxis();
};

#endif // VISUAL_SHADER_NODES_H