Merge pull request #49337 from Chaosus/vs_texture_func

Adds `UVFunc` for panning/scaling on UV's to VisualShader's.
This commit is contained in:
Rémi Verschelde 2021-06-07 09:38:37 +02:00 committed by GitHub
commit afbabd12f3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 274 additions and 0 deletions

View file

@ -9,6 +9,13 @@
<link title="VisualShaders">https://docs.godotengine.org/en/latest/tutorials/shading/visual_shaders.html</link>
</tutorials>
<methods>
<method name="clear_default_input_values">
<return type="void">
</return>
<description>
Clears the default input ports value.
</description>
</method>
<method name="get_default_input_values" qualifiers="const">
<return type="Array">
</return>
@ -25,6 +32,15 @@
Returns the default value of the input [code]port[/code].
</description>
</method>
<method name="remove_input_port_default_value">
<return type="void">
</return>
<argument index="0" name="port" type="int">
</argument>
<description>
Removes the default value of the input [code]port[/code].
</description>
</method>
<method name="set_default_input_values">
<return type="void">
</return>

View file

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="VisualShaderNodeUVFunc" inherits="VisualShaderNode" version="4.0">
<brief_description>
Contains functions to modify texture coordinates ([code]uv[/code]) to be used within the visual shader graph.
</brief_description>
<description>
</description>
<tutorials>
</tutorials>
<methods>
</methods>
<members>
<member name="function" type="int" setter="set_function" getter="get_function" enum="VisualShaderNodeUVFunc.Function" default="0">
A function to be applied to the texture coordinates. See [enum Function] for options.
</member>
</members>
<constants>
<constant name="FUNC_PANNING" value="0" enum="Function">
Translates [code]uv[/code] by using [code]scale[/code] and [code]offset[/code] values using the following formula: [code]uv = uv + offset * scale[/code]. [code]uv[/code] port is connected to [code]UV[/code] built-in by default.
</constant>
<constant name="FUNC_SCALING" value="1" enum="Function">
Scales [code]uv[/uv] by using [code]scale[/code] and [code]pivot[/code] values using the following formula: [code]uv = (uv - pivot) * scale + pivot[/code]. [code]uv[/code] port is connected to [code]UV[/code] built-in by default.
</constant>
<constant name="FUNC_MAX" value="2" enum="Function">
Represents the size of the [enum Function] enum.
</constant>
</constants>
</class>

View file

@ -2081,6 +2081,16 @@ void VisualShaderEditor::_setup_node(VisualShaderNode *p_node, int p_op_idx) {
}
}
//UV_FUNC
{
VisualShaderNodeUVFunc *uvFunc = Object::cast_to<VisualShaderNodeUVFunc>(p_node);
if (uvFunc) {
uvFunc->set_function((VisualShaderNodeUVFunc::Function)p_op_idx);
return;
}
}
// IS
{
VisualShaderNodeIs *is = Object::cast_to<VisualShaderNodeIs>(p_node);
@ -4244,6 +4254,8 @@ VisualShaderEditor::VisualShaderEditor() {
// TEXTURES
add_options.push_back(AddOption("UVFunc", "Textures", "Common", "VisualShaderNodeUVFunc", TTR("Function to be applied on texture coordinates."), -1, VisualShaderNode::PORT_TYPE_VECTOR));
cubemap_node_option_idx = add_options.size();
add_options.push_back(AddOption("CubeMap", "Textures", "Functions", "VisualShaderNodeCubemap", TTR("Perform the cubic texture lookup."), -1, -1));
curve_node_option_idx = add_options.size();
@ -4254,6 +4266,8 @@ VisualShaderEditor::VisualShaderEditor() {
add_options.push_back(AddOption("Texture2DArray", "Textures", "Functions", "VisualShaderNodeTexture2DArray", TTR("Perform the 2D-array texture lookup."), -1, -1, -1, -1, -1));
texture3d_node_option_idx = add_options.size();
add_options.push_back(AddOption("Texture3D", "Textures", "Functions", "VisualShaderNodeTexture3D", TTR("Perform the 3D texture lookup."), -1, -1));
add_options.push_back(AddOption("UVPanning", "Textures", "Functions", "VisualShaderNodeUVFunc", TTR("Apply panning function on texture coordinates."), VisualShaderNodeUVFunc::FUNC_PANNING, VisualShaderNode::PORT_TYPE_VECTOR));
add_options.push_back(AddOption("UVScaling", "Textures", "Functions", "VisualShaderNodeUVFunc", TTR("Apply scaling function on texture coordinates."), VisualShaderNodeUVFunc::FUNC_SCALING, VisualShaderNode::PORT_TYPE_VECTOR));
add_options.push_back(AddOption("CubeMapUniform", "Textures", "Variables", "VisualShaderNodeCubemapUniform", TTR("Cubic texture uniform lookup."), -1, -1));
add_options.push_back(AddOption("TextureUniform", "Textures", "Variables", "VisualShaderNodeTextureUniform", TTR("2D texture uniform lookup."), -1, -1));

View file

@ -560,6 +560,7 @@ void register_scene_types() {
ClassDB::register_class<VisualShaderNodeVectorFunc>();
ClassDB::register_class<VisualShaderNodeColorFunc>();
ClassDB::register_class<VisualShaderNodeTransformFunc>();
ClassDB::register_class<VisualShaderNodeUVFunc>();
ClassDB::register_class<VisualShaderNodeDotProduct>();
ClassDB::register_class<VisualShaderNodeVectorLen>();
ClassDB::register_class<VisualShaderNodeDeterminant>();

View file

@ -60,6 +60,20 @@ Variant VisualShaderNode::get_input_port_default_value(int p_port) const {
return Variant();
}
void VisualShaderNode::remove_input_port_default_value(int p_port) {
if (default_input_values.has(p_port)) {
default_input_values.erase(p_port);
emit_changed();
}
}
void VisualShaderNode::clear_default_input_values() {
if (!default_input_values.is_empty()) {
default_input_values.clear();
emit_changed();
}
}
bool VisualShaderNode::is_port_separator(int p_index) const {
return false;
}
@ -220,6 +234,9 @@ void VisualShaderNode::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_input_port_default_value", "port", "value"), &VisualShaderNode::set_input_port_default_value);
ClassDB::bind_method(D_METHOD("get_input_port_default_value", "port"), &VisualShaderNode::get_input_port_default_value);
ClassDB::bind_method(D_METHOD("remove_input_port_default_value", "port"), &VisualShaderNode::remove_input_port_default_value);
ClassDB::bind_method(D_METHOD("clear_default_input_values"), &VisualShaderNode::clear_default_input_values);
ClassDB::bind_method(D_METHOD("set_default_input_values", "values"), &VisualShaderNode::set_default_input_values);
ClassDB::bind_method(D_METHOD("get_default_input_values"), &VisualShaderNode::get_default_input_values);
@ -373,6 +390,18 @@ void VisualShaderNodeCustom::set_default_input_values(const Array &p_values) {
}
}
void VisualShaderNodeCustom::remove_input_port_default_value(int p_port) {
if (!is_initialized) {
VisualShaderNode::remove_input_port_default_value(p_port);
}
}
void VisualShaderNodeCustom::clear_default_input_values() {
if (!is_initialized) {
VisualShaderNode::clear_default_input_values();
}
}
void VisualShaderNodeCustom::_set_input_port_default_value(int p_port, const Variant &p_value) {
VisualShaderNode::set_input_port_default_value(p_port, p_value);
}

View file

@ -230,6 +230,8 @@ public:
Variant get_input_port_default_value(int p_port) const; // if NIL (default if node does not set anything) is returned, it means no default value is wanted if disconnected, thus no input var must be supplied (empty string will be supplied)
Array get_default_input_values() const;
virtual void set_default_input_values(const Array &p_values);
virtual void remove_input_port_default_value(int p_port);
virtual void clear_default_input_values();
virtual int get_output_port_count() const = 0;
virtual PortType get_output_port_type(int p_port) const = 0;
@ -305,6 +307,8 @@ protected:
virtual void set_input_port_default_value(int p_port, const Variant &p_value) override;
virtual void set_default_input_values(const Array &p_values) override;
virtual void remove_input_port_default_value(int p_port) override;
virtual void clear_default_input_values() override;
protected:
void _set_input_port_default_value(int p_port, const Variant &p_value);

View file

@ -2499,6 +2499,143 @@ VisualShaderNodeTransformFunc::VisualShaderNodeTransformFunc() {
set_input_port_default_value(0, Transform3D());
}
////////////// UV Func
String VisualShaderNodeUVFunc::get_caption() const {
return "UVFunc";
}
int VisualShaderNodeUVFunc::get_input_port_count() const {
return 3;
}
VisualShaderNodeUVFunc::PortType VisualShaderNodeUVFunc::get_input_port_type(int p_port) const {
switch (p_port) {
case 0:
[[fallthrough]]; // uv
case 1:
return PORT_TYPE_VECTOR; // scale
case 2:
return PORT_TYPE_VECTOR; // offset & pivot
default:
break;
}
return PORT_TYPE_SCALAR;
}
String VisualShaderNodeUVFunc::get_input_port_name(int p_port) const {
switch (p_port) {
case 0:
return "uv";
case 1:
return "scale";
case 2:
switch (func) {
case FUNC_PANNING:
return "offset";
case FUNC_SCALING:
return "pivot";
case FUNC_MAX:
break;
default:
break;
}
break;
default:
break;
}
return "";
}
String VisualShaderNodeUVFunc::get_input_port_default_hint(int p_port) const {
if (p_port == 0) {
return "UV";
}
return "";
}
int VisualShaderNodeUVFunc::get_output_port_count() const {
return 1;
}
VisualShaderNodeUVFunc::PortType VisualShaderNodeUVFunc::get_output_port_type(int p_port) const {
return PORT_TYPE_VECTOR;
}
String VisualShaderNodeUVFunc::get_output_port_name(int p_port) const {
return "uv";
}
bool VisualShaderNodeUVFunc::is_show_prop_names() const {
return true;
}
String VisualShaderNodeUVFunc::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;
if (p_input_vars[0].is_empty()) {
uv = "vec3(UV.xy, 0.0)";
} else {
uv = vformat("%s", p_input_vars[0]);
}
String scale = vformat("%s", p_input_vars[1]);
String offset_pivot = vformat("%s", p_input_vars[2]);
switch (func) {
case FUNC_PANNING: {
code += vformat("\t%s = fma(%s, %s, %s);\n", p_output_vars[0], offset_pivot, scale, uv);
} break;
case FUNC_SCALING: {
code += vformat("\t%s = fma((%s - %s), %s, %s);\n", p_output_vars[0], uv, offset_pivot, scale, offset_pivot);
} break;
case FUNC_MAX:
break;
}
return code;
}
void VisualShaderNodeUVFunc::set_function(VisualShaderNodeUVFunc::Function p_func) {
ERR_FAIL_INDEX(int(p_func), FUNC_MAX);
if (func == p_func) {
return;
}
func = p_func;
if (p_func == FUNC_PANNING) {
set_input_port_default_value(2, Vector3()); // offset
} else { // FUNC_SCALING
set_input_port_default_value(2, Vector3(0.5, 0.5, 0.0)); // pivot
}
emit_changed();
}
VisualShaderNodeUVFunc::Function VisualShaderNodeUVFunc::get_function() const {
return func;
}
Vector<StringName> VisualShaderNodeUVFunc::get_editable_properties() const {
Vector<StringName> props;
props.push_back("function");
return props;
}
void VisualShaderNodeUVFunc::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_function", "func"), &VisualShaderNodeUVFunc::set_function);
ClassDB::bind_method(D_METHOD("get_function"), &VisualShaderNodeUVFunc::get_function);
ADD_PROPERTY(PropertyInfo(Variant::INT, "function", PROPERTY_HINT_ENUM, "Panning,Scaling"), "set_function", "get_function");
BIND_ENUM_CONSTANT(FUNC_PANNING);
BIND_ENUM_CONSTANT(FUNC_SCALING);
BIND_ENUM_CONSTANT(FUNC_MAX);
}
VisualShaderNodeUVFunc::VisualShaderNodeUVFunc() {
set_input_port_default_value(1, Vector3(1.0, 1.0, 0.0)); // scale
set_input_port_default_value(2, Vector3()); // offset
}
////////////// Dot Product
String VisualShaderNodeDotProduct::get_caption() const {

View file

@ -1018,6 +1018,51 @@ public:
VARIANT_ENUM_CAST(VisualShaderNodeTransformFunc::Function)
///////////////////////////////////////
/// UV FUNC
///////////////////////////////////////
class VisualShaderNodeUVFunc : public VisualShaderNode {
GDCLASS(VisualShaderNodeUVFunc, VisualShaderNode);
public:
enum Function {
FUNC_PANNING,
FUNC_SCALING,
FUNC_MAX,
};
protected:
Function func = FUNC_PANNING;
static void _bind_methods();
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 String get_input_port_default_hint(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 is_show_prop_names() 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;
void set_function(Function p_op);
Function get_function() const;
virtual Vector<StringName> get_editable_properties() const override;
VisualShaderNodeUVFunc();
};
VARIANT_ENUM_CAST(VisualShaderNodeUVFunc::Function)
///////////////////////////////////////
/// DOT
///////////////////////////////////////