diff --git a/doc/classes/VisualShaderNodeColorFunc.xml b/doc/classes/VisualShaderNodeColorFunc.xml index edb523832585..aa2dcca1d580 100644 --- a/doc/classes/VisualShaderNodeColorFunc.xml +++ b/doc/classes/VisualShaderNodeColorFunc.xml @@ -40,7 +40,32 @@ return vec3(r, g, b); [/codeblock] - + + Converts color from linear color space to sRGB color space using the following formula: + [codeblock] + vec3 c = clamp(c, vec3(0.0), vec3(1.0)); + const vec3 a = vec3(0.055f); + return mix((vec3(1.0f) + a) * pow(c.rgb, vec3(1.0f / 2.4f)) - a, 12.92f * c.rgb, lessThan(c.rgb, vec3(0.0031308f))); + [/codeblock] + The Compatibility renderer uses a simpler formula: + [codeblock] + vec3 c = input; + return max(vec3(1.055) * pow(c, vec3(0.416666667)) - vec3(0.055), vec3(0.0)); + [/codeblock] + + + Converts color from sRGB color space to linear color space using the following formula: + [codeblock] + vec3 c = input; + return mix(pow((c.rgb + vec3(0.055)) * (1.0 / (1.0 + 0.055)), vec3(2.4)), c.rgb * (1.0 / 12.92), lessThan(c.rgb, vec3(0.04045))); + [/codeblock] + The Compatibility renderer uses a simpler formula: + [codeblock] + vec3 c = input; + return c * (c * (c * 0.305306011 + 0.682171111) + 0.012522878); + [/codeblock] + + Represents the size of the [enum Function] enum. diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index 987002f472de..31e158bba73e 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -6879,8 +6879,10 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("Grayscale", "Color/Functions", "VisualShaderNodeColorFunc", TTR("Grayscale function."), { VisualShaderNodeColorFunc::FUNC_GRAYSCALE }, VisualShaderNode::PORT_TYPE_VECTOR_3D)); add_options.push_back(AddOption("HSV2RGB", "Color/Functions", "VisualShaderNodeColorFunc", TTR("Converts HSV vector to RGB equivalent."), { VisualShaderNodeColorFunc::FUNC_HSV2RGB, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D)); + add_options.push_back(AddOption("LinearToSRGB", "Color/Functions", "VisualShaderNodeColorFunc", TTR("Converts color from linear to sRGB color space."), { VisualShaderNodeColorFunc::FUNC_LINEAR_TO_SRGB }, VisualShaderNode::PORT_TYPE_VECTOR_3D)); add_options.push_back(AddOption("RGB2HSV", "Color/Functions", "VisualShaderNodeColorFunc", TTR("Converts RGB vector to HSV equivalent."), { VisualShaderNodeColorFunc::FUNC_RGB2HSV, VisualShaderNodeVectorFunc::OP_TYPE_VECTOR_3D }, VisualShaderNode::PORT_TYPE_VECTOR_3D)); add_options.push_back(AddOption("Sepia", "Color/Functions", "VisualShaderNodeColorFunc", TTR("Sepia function."), { VisualShaderNodeColorFunc::FUNC_SEPIA }, VisualShaderNode::PORT_TYPE_VECTOR_3D)); + add_options.push_back(AddOption("SRGBToLinear", "Color/Functions", "VisualShaderNodeColorFunc", TTR("Converts color from sRGB to linear color space."), { VisualShaderNodeColorFunc::FUNC_SRGB_TO_LINEAR }, VisualShaderNode::PORT_TYPE_VECTOR_3D)); add_options.push_back(AddOption("Burn", "Color/Operators", "VisualShaderNodeColorOp", TTR("Burn operator."), { VisualShaderNodeColorOp::OP_BURN }, VisualShaderNode::PORT_TYPE_VECTOR_3D)); add_options.push_back(AddOption("Darken", "Color/Operators", "VisualShaderNodeColorOp", TTR("Darken operator."), { VisualShaderNodeColorOp::OP_DARKEN }, VisualShaderNode::PORT_TYPE_VECTOR_3D)); diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp index 3db1ab93380f..5350672a8638 100644 --- a/scene/resources/visual_shader_nodes.cpp +++ b/scene/resources/visual_shader_nodes.cpp @@ -3243,6 +3243,29 @@ String VisualShaderNodeColorFunc::generate_code(Shader::Mode p_mode, VisualShade code += " " + p_output_vars[0] + " = vec3(r, g, b);\n"; code += " }\n"; break; + case FUNC_LINEAR_TO_SRGB: + code += " {\n"; + if (RenderingServer::get_singleton()->is_low_end()) { + code += " vec3 c = " + p_input_vars[0] + ";\n"; + code += " " + p_output_vars[0] + " = max(vec3(1.055) * pow(c, vec3(0.416666667)) - vec3(0.055), vec3(0.0));\n"; + } else { + code += " vec3 c = clamp(" + p_input_vars[0] + ", vec3(0.0), vec3(1.0));\n"; + code += " const vec3 a = vec3(0.055f);\n"; + code += " " + p_output_vars[0] + " = mix((vec3(1.0f) + a) * pow(c.rgb, vec3(1.0f / 2.4f)) - a, 12.92f * c.rgb, lessThan(c.rgb, vec3(0.0031308f)));\n"; + } + code += " }\n"; + break; + case FUNC_SRGB_TO_LINEAR: + code += " {\n"; + if (RenderingServer::get_singleton()->is_low_end()) { + code += " vec3 c = " + p_input_vars[0] + ";\n"; + code += " " + p_output_vars[0] + " = c * (c * (c * 0.305306011 + 0.682171111) + 0.012522878);\n"; + } else { + code += " vec3 c = " + p_input_vars[0] + ";\n"; + code += " " + p_output_vars[0] + " = mix(pow((c.rgb + vec3(0.055)) * (1.0 / (1.0 + 0.055)), vec3(2.4)), c.rgb * (1.0 / 12.92), lessThan(c.rgb, vec3(0.04045)));\n"; + } + code += " }\n"; + break; default: break; } @@ -3273,12 +3296,14 @@ void VisualShaderNodeColorFunc::_bind_methods() { ClassDB::bind_method(D_METHOD("set_function", "func"), &VisualShaderNodeColorFunc::set_function); ClassDB::bind_method(D_METHOD("get_function"), &VisualShaderNodeColorFunc::get_function); - ADD_PROPERTY(PropertyInfo(Variant::INT, "function", PROPERTY_HINT_ENUM, "Grayscale,HSV2RGB,RGB2HSV,Sepia"), "set_function", "get_function"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "function", PROPERTY_HINT_ENUM, "Grayscale,HSV2RGB,RGB2HSV,Sepia,LinearToSRGB,SRGBToLinear"), "set_function", "get_function"); BIND_ENUM_CONSTANT(FUNC_GRAYSCALE); BIND_ENUM_CONSTANT(FUNC_HSV2RGB); BIND_ENUM_CONSTANT(FUNC_RGB2HSV); BIND_ENUM_CONSTANT(FUNC_SEPIA); + BIND_ENUM_CONSTANT(FUNC_LINEAR_TO_SRGB); + BIND_ENUM_CONSTANT(FUNC_SRGB_TO_LINEAR); BIND_ENUM_CONSTANT(FUNC_MAX); } diff --git a/scene/resources/visual_shader_nodes.h b/scene/resources/visual_shader_nodes.h index 67dc8f735374..36b9560ced47 100644 --- a/scene/resources/visual_shader_nodes.h +++ b/scene/resources/visual_shader_nodes.h @@ -1353,6 +1353,8 @@ class VisualShaderNodeColorFunc : public VisualShaderNode { FUNC_HSV2RGB, FUNC_RGB2HSV, FUNC_SEPIA, + FUNC_LINEAR_TO_SRGB, + FUNC_SRGB_TO_LINEAR, FUNC_MAX, };