Add derivative functions with precision to shaders
This commit is contained in:
parent
44c0bfc94d
commit
8c8c333bf2
|
@ -15,6 +15,9 @@
|
||||||
<member name="op_type" type="int" setter="set_op_type" getter="get_op_type" enum="VisualShaderNodeDerivativeFunc.OpType" default="0">
|
<member name="op_type" type="int" setter="set_op_type" getter="get_op_type" enum="VisualShaderNodeDerivativeFunc.OpType" default="0">
|
||||||
A type of operands and returned value. See [enum OpType] for options.
|
A type of operands and returned value. See [enum OpType] for options.
|
||||||
</member>
|
</member>
|
||||||
|
<member name="precision" type="int" setter="set_precision" getter="get_precision" enum="VisualShaderNodeDerivativeFunc.Precision" default="0">
|
||||||
|
Sets the level of precision to use for the derivative function. See [enum Precision] for options. When using the GL_Compatibility renderer, this setting has no effect.
|
||||||
|
</member>
|
||||||
</members>
|
</members>
|
||||||
<constants>
|
<constants>
|
||||||
<constant name="OP_TYPE_SCALAR" value="0" enum="OpType">
|
<constant name="OP_TYPE_SCALAR" value="0" enum="OpType">
|
||||||
|
@ -44,5 +47,17 @@
|
||||||
<constant name="FUNC_MAX" value="3" enum="Function">
|
<constant name="FUNC_MAX" value="3" enum="Function">
|
||||||
Represents the size of the [enum Function] enum.
|
Represents the size of the [enum Function] enum.
|
||||||
</constant>
|
</constant>
|
||||||
|
<constant name="PRECISION_NONE" value="0" enum="Precision">
|
||||||
|
No precision is specified, the GPU driver is allowed to use whatever level of precision it chooses. This is the default option and is equivalent to using [code]dFdx()[/code] or [code]dFdy()[/code] in text shaders.
|
||||||
|
</constant>
|
||||||
|
<constant name="PRECISION_COARSE" value="1" enum="Precision">
|
||||||
|
The derivative will be calculated using the current fragment's neighbors (which may not include the current fragment). This tends to be faster than using [constant PRECISION_FINE], but may not be suitable when more precision is needed. This is equivalent to using [code]dFdxCoarse()[/code] or [code]dFdyCoarse()[/code] in text shaders.
|
||||||
|
</constant>
|
||||||
|
<constant name="PRECISION_FINE" value="2" enum="Precision">
|
||||||
|
The derivative will be calculated using the current fragment and its immediate neighbors. This tends to be slower than using [constant PRECISION_COARSE], but may be necessary when more precision is needed. This is equivalent to using [code]dFdxFine()[/code] or [code]dFdyFine()[/code] in text shaders.
|
||||||
|
</constant>
|
||||||
|
<constant name="PRECISION_MAX" value="3" enum="Precision">
|
||||||
|
Represents the size of the [enum Precision] enum.
|
||||||
|
</constant>
|
||||||
</constants>
|
</constants>
|
||||||
</class>
|
</class>
|
||||||
|
|
|
@ -3690,16 +3690,47 @@ String VisualShaderNodeDerivativeFunc::get_output_port_name(int p_port) const {
|
||||||
|
|
||||||
String VisualShaderNodeDerivativeFunc::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 VisualShaderNodeDerivativeFunc::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 {
|
||||||
static const char *functions[FUNC_MAX] = {
|
static const char *functions[FUNC_MAX] = {
|
||||||
"fwidth($)",
|
"fwidth$($)",
|
||||||
"dFdx($)",
|
"dFdx$($)",
|
||||||
"dFdy($)"
|
"dFdy$($)"
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *precisions[PRECISION_MAX] = {
|
||||||
|
"",
|
||||||
|
"Coarse",
|
||||||
|
"Fine"
|
||||||
};
|
};
|
||||||
|
|
||||||
String code;
|
String code;
|
||||||
code += " " + p_output_vars[0] + " = " + String(functions[func]).replace("$", p_input_vars[0]) + ";\n";
|
if (OS::get_singleton()->get_current_rendering_method() == "gl_compatibility") {
|
||||||
|
code += " " + p_output_vars[0] + " = " + String(functions[func]).replace_first("$", "").replace_first("$", p_input_vars[0]) + ";\n";
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
code += " " + p_output_vars[0] + " = " + String(functions[func]).replace_first("$", String(precisions[precision])).replace_first("$", p_input_vars[0]) + ";\n";
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String VisualShaderNodeDerivativeFunc::get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const {
|
||||||
|
if (precision != PRECISION_NONE && OS::get_singleton()->get_current_rendering_method() == "gl_compatibility") {
|
||||||
|
String precision_str;
|
||||||
|
switch (precision) {
|
||||||
|
case PRECISION_COARSE: {
|
||||||
|
precision_str = "Coarse";
|
||||||
|
} break;
|
||||||
|
case PRECISION_FINE: {
|
||||||
|
precision_str = "Fine";
|
||||||
|
} break;
|
||||||
|
default: {
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return vformat(RTR("`%s` precision mode is not available for `gl_compatibility` profile.\nReverted to `None` precision."), precision_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
return String();
|
||||||
|
}
|
||||||
|
|
||||||
void VisualShaderNodeDerivativeFunc::set_op_type(OpType p_op_type) {
|
void VisualShaderNodeDerivativeFunc::set_op_type(OpType p_op_type) {
|
||||||
ERR_FAIL_INDEX((int)p_op_type, int(OP_TYPE_MAX));
|
ERR_FAIL_INDEX((int)p_op_type, int(OP_TYPE_MAX));
|
||||||
if (op_type == p_op_type) {
|
if (op_type == p_op_type) {
|
||||||
|
@ -3742,10 +3773,24 @@ VisualShaderNodeDerivativeFunc::Function VisualShaderNodeDerivativeFunc::get_fun
|
||||||
return func;
|
return func;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VisualShaderNodeDerivativeFunc::set_precision(Precision p_precision) {
|
||||||
|
ERR_FAIL_INDEX(int(p_precision), int(PRECISION_MAX));
|
||||||
|
if (precision == p_precision) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
precision = p_precision;
|
||||||
|
emit_changed();
|
||||||
|
}
|
||||||
|
|
||||||
|
VisualShaderNodeDerivativeFunc::Precision VisualShaderNodeDerivativeFunc::get_precision() const {
|
||||||
|
return precision;
|
||||||
|
}
|
||||||
|
|
||||||
Vector<StringName> VisualShaderNodeDerivativeFunc::get_editable_properties() const {
|
Vector<StringName> VisualShaderNodeDerivativeFunc::get_editable_properties() const {
|
||||||
Vector<StringName> props;
|
Vector<StringName> props;
|
||||||
props.push_back("op_type");
|
props.push_back("op_type");
|
||||||
props.push_back("function");
|
props.push_back("function");
|
||||||
|
props.push_back("precision");
|
||||||
return props;
|
return props;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3756,8 +3801,12 @@ void VisualShaderNodeDerivativeFunc::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("set_function", "func"), &VisualShaderNodeDerivativeFunc::set_function);
|
ClassDB::bind_method(D_METHOD("set_function", "func"), &VisualShaderNodeDerivativeFunc::set_function);
|
||||||
ClassDB::bind_method(D_METHOD("get_function"), &VisualShaderNodeDerivativeFunc::get_function);
|
ClassDB::bind_method(D_METHOD("get_function"), &VisualShaderNodeDerivativeFunc::get_function);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("set_precision", "precision"), &VisualShaderNodeDerivativeFunc::set_precision);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_precision"), &VisualShaderNodeDerivativeFunc::get_precision);
|
||||||
|
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Scalar,Vector2,Vector3,Vector4"), "set_op_type", "get_op_type");
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "op_type", PROPERTY_HINT_ENUM, "Scalar,Vector2,Vector3,Vector4"), "set_op_type", "get_op_type");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "function", PROPERTY_HINT_ENUM, "Sum,X,Y"), "set_function", "get_function");
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "function", PROPERTY_HINT_ENUM, "Sum,X,Y"), "set_function", "get_function");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "precision", PROPERTY_HINT_ENUM, "None,Coarse,Fine"), "set_precision", "get_precision");
|
||||||
|
|
||||||
BIND_ENUM_CONSTANT(OP_TYPE_SCALAR);
|
BIND_ENUM_CONSTANT(OP_TYPE_SCALAR);
|
||||||
BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_2D);
|
BIND_ENUM_CONSTANT(OP_TYPE_VECTOR_2D);
|
||||||
|
@ -3769,6 +3818,11 @@ void VisualShaderNodeDerivativeFunc::_bind_methods() {
|
||||||
BIND_ENUM_CONSTANT(FUNC_X);
|
BIND_ENUM_CONSTANT(FUNC_X);
|
||||||
BIND_ENUM_CONSTANT(FUNC_Y);
|
BIND_ENUM_CONSTANT(FUNC_Y);
|
||||||
BIND_ENUM_CONSTANT(FUNC_MAX);
|
BIND_ENUM_CONSTANT(FUNC_MAX);
|
||||||
|
|
||||||
|
BIND_ENUM_CONSTANT(PRECISION_NONE);
|
||||||
|
BIND_ENUM_CONSTANT(PRECISION_COARSE);
|
||||||
|
BIND_ENUM_CONSTANT(PRECISION_FINE);
|
||||||
|
BIND_ENUM_CONSTANT(PRECISION_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
VisualShaderNodeDerivativeFunc::VisualShaderNodeDerivativeFunc() {
|
VisualShaderNodeDerivativeFunc::VisualShaderNodeDerivativeFunc() {
|
||||||
|
|
|
@ -1536,9 +1536,17 @@ public:
|
||||||
FUNC_MAX,
|
FUNC_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum Precision {
|
||||||
|
PRECISION_NONE,
|
||||||
|
PRECISION_COARSE,
|
||||||
|
PRECISION_FINE,
|
||||||
|
PRECISION_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
OpType op_type = OP_TYPE_SCALAR;
|
OpType op_type = OP_TYPE_SCALAR;
|
||||||
Function func = FUNC_SUM;
|
Function func = FUNC_SUM;
|
||||||
|
Precision precision = PRECISION_NONE;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
|
@ -1555,6 +1563,7 @@ public:
|
||||||
virtual String get_output_port_name(int p_port) const override;
|
virtual String get_output_port_name(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;
|
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;
|
||||||
|
virtual String get_warning(Shader::Mode p_mode, VisualShader::Type p_type) const override;
|
||||||
|
|
||||||
void set_op_type(OpType p_op_type);
|
void set_op_type(OpType p_op_type);
|
||||||
OpType get_op_type() const;
|
OpType get_op_type() const;
|
||||||
|
@ -1562,6 +1571,9 @@ public:
|
||||||
void set_function(Function p_func);
|
void set_function(Function p_func);
|
||||||
Function get_function() const;
|
Function get_function() const;
|
||||||
|
|
||||||
|
void set_precision(Precision p_precision);
|
||||||
|
Precision get_precision() const;
|
||||||
|
|
||||||
virtual Vector<StringName> get_editable_properties() const override;
|
virtual Vector<StringName> get_editable_properties() const override;
|
||||||
|
|
||||||
VisualShaderNodeDerivativeFunc();
|
VisualShaderNodeDerivativeFunc();
|
||||||
|
@ -1569,6 +1581,7 @@ public:
|
||||||
|
|
||||||
VARIANT_ENUM_CAST(VisualShaderNodeDerivativeFunc::OpType)
|
VARIANT_ENUM_CAST(VisualShaderNodeDerivativeFunc::OpType)
|
||||||
VARIANT_ENUM_CAST(VisualShaderNodeDerivativeFunc::Function)
|
VARIANT_ENUM_CAST(VisualShaderNodeDerivativeFunc::Function)
|
||||||
|
VARIANT_ENUM_CAST(VisualShaderNodeDerivativeFunc::Precision)
|
||||||
|
|
||||||
///////////////////////////////////////
|
///////////////////////////////////////
|
||||||
/// FACEFORWARD
|
/// FACEFORWARD
|
||||||
|
|
|
@ -2837,6 +2837,20 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
|
||||||
{ "dFdx", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
|
{ "dFdx", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
|
||||||
{ "dFdx", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
|
{ "dFdx", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
|
||||||
|
|
||||||
|
// dFdxCoarse
|
||||||
|
|
||||||
|
{ "dFdxCoarse", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
|
||||||
|
{ "dFdxCoarse", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
|
||||||
|
{ "dFdxCoarse", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
|
||||||
|
{ "dFdxCoarse", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
|
||||||
|
|
||||||
|
// dFdxFine
|
||||||
|
|
||||||
|
{ "dFdxFine", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
|
||||||
|
{ "dFdxFine", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
|
||||||
|
{ "dFdxFine", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
|
||||||
|
{ "dFdxFine", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
|
||||||
|
|
||||||
// dFdy
|
// dFdy
|
||||||
|
|
||||||
{ "dFdy", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
|
{ "dFdy", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
|
||||||
|
@ -2844,6 +2858,20 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
|
||||||
{ "dFdy", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
|
{ "dFdy", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
|
||||||
{ "dFdy", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
|
{ "dFdy", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
|
||||||
|
|
||||||
|
// dFdyCoarse
|
||||||
|
|
||||||
|
{ "dFdyCoarse", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
|
||||||
|
{ "dFdyCoarse", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
|
||||||
|
{ "dFdyCoarse", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
|
||||||
|
{ "dFdyCoarse", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
|
||||||
|
|
||||||
|
// dFdyFine
|
||||||
|
|
||||||
|
{ "dFdyFine", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
|
||||||
|
{ "dFdyFine", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
|
||||||
|
{ "dFdyFine", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
|
||||||
|
{ "dFdyFine", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
|
||||||
|
|
||||||
// fwidth
|
// fwidth
|
||||||
|
|
||||||
{ "fwidth", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
|
{ "fwidth", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
|
||||||
|
@ -2851,6 +2879,20 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
|
||||||
{ "fwidth", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
|
{ "fwidth", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
|
||||||
{ "fwidth", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
|
{ "fwidth", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
|
||||||
|
|
||||||
|
// fwidthCoarse
|
||||||
|
|
||||||
|
{ "fwidthCoarse", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
|
||||||
|
{ "fwidthCoarse", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
|
||||||
|
{ "fwidthCoarse", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
|
||||||
|
{ "fwidthCoarse", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
|
||||||
|
|
||||||
|
// fwidthFine
|
||||||
|
|
||||||
|
{ "fwidthFine", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
|
||||||
|
{ "fwidthFine", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
|
||||||
|
{ "fwidthFine", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
|
||||||
|
{ "fwidthFine", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
|
||||||
|
|
||||||
// Sub-functions.
|
// Sub-functions.
|
||||||
// array
|
// array
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue