diff --git a/doc/classes/VisualShaderNodeIntParameter.xml b/doc/classes/VisualShaderNodeIntParameter.xml
index ba17da49a821..d3d77f040fa1 100644
--- a/doc/classes/VisualShaderNodeIntParameter.xml
+++ b/doc/classes/VisualShaderNodeIntParameter.xml
@@ -15,9 +15,12 @@
 		<member name="default_value_enabled" type="bool" setter="set_default_value_enabled" getter="is_default_value_enabled" default="false">
 			If [code]true[/code], the node will have a custom default value.
 		</member>
-		<member name="enum_names" type="PackedStringArray" setter="set_enum_names" getter="get_enum_names" default="PackedStringArray()">
+		<member name="enum_names" type="PackedStringArray" setter="set_hint_names" getter="get_hint_names" default="PackedStringArray()">
 			The names used for the enum select in the editor. [member hint] must be [constant HINT_ENUM] for this to take effect.
 		</member>
+		<member name="flag_names" type="PackedStringArray" setter="set_hint_names" getter="get_hint_names" default="PackedStringArray()">
+			The names used for the bit flags in the editor. [member hint] must be [constant HINT_FLAGS] for this to take effect.
+		</member>
 		<member name="hint" type="int" setter="set_hint" getter="get_hint" enum="VisualShaderNodeIntParameter.Hint" default="0">
 			Range hint of this node. Use it to customize valid parameter range.
 		</member>
@@ -44,7 +47,10 @@
 		<constant name="HINT_ENUM" value="3" enum="Hint">
 			The parameter uses an enum to associate preset values to names in the editor.
 		</constant>
-		<constant name="HINT_MAX" value="4" enum="Hint">
+		<constant name="HINT_FLAGS" value="4" enum="Hint">
+			The parameter is configured using named bit flags in the editor.
+		</constant>
+		<constant name="HINT_MAX" value="5" enum="Hint">
 			Represents the size of the [enum Hint] enum.
 		</constant>
 	</constants>
diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp
index 5e148c9276da..d431163fffc5 100644
--- a/scene/resources/visual_shader_nodes.cpp
+++ b/scene/resources/visual_shader_nodes.cpp
@@ -5368,11 +5368,12 @@ String VisualShaderNodeIntParameter::generate_global(Shader::Mode p_mode, Visual
 		code += _get_qual_str() + "uniform int " + get_parameter_name() + " : hint_range(" + itos(hint_range_min) + ", " + itos(hint_range_max) + ")";
 	} else if (hint == HINT_RANGE_STEP) {
 		code += _get_qual_str() + "uniform int " + get_parameter_name() + " : hint_range(" + itos(hint_range_min) + ", " + itos(hint_range_max) + ", " + itos(hint_range_step) + ")";
-	} else if (hint == HINT_ENUM) {
-		code += _get_qual_str() + "uniform int " + get_parameter_name() + " : hint_enum(";
+	} else if (hint == HINT_ENUM || hint == HINT_FLAGS) {
+		const char *hint_gdshader_name = hint == HINT_ENUM ? "hint_enum" : "hint_flags";
+		code += _get_qual_str() + "uniform int " + get_parameter_name() + " : " + hint_gdshader_name + "(";
 
 		bool first = true;
-		for (const String &_name : hint_enum_names) {
+		for (const String &_name : hint_names) {
 			if (first) {
 				first = false;
 			} else {
@@ -5453,16 +5454,16 @@ int VisualShaderNodeIntParameter::get_step() const {
 	return hint_range_step;
 }
 
-void VisualShaderNodeIntParameter::set_enum_names(const PackedStringArray &p_names) {
-	if (hint_enum_names == p_names) {
+void VisualShaderNodeIntParameter::set_hint_names(const PackedStringArray &p_names) {
+	if (hint_names == p_names) {
 		return;
 	}
-	hint_enum_names = p_names;
+	hint_names = p_names;
 	emit_changed();
 }
 
-PackedStringArray VisualShaderNodeIntParameter::get_enum_names() const {
-	return hint_enum_names;
+PackedStringArray VisualShaderNodeIntParameter::get_hint_names() const {
+	return hint_names;
 }
 
 void VisualShaderNodeIntParameter::set_default_value_enabled(bool p_default_value_enabled) {
@@ -5502,8 +5503,8 @@ void VisualShaderNodeIntParameter::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("set_step", "value"), &VisualShaderNodeIntParameter::set_step);
 	ClassDB::bind_method(D_METHOD("get_step"), &VisualShaderNodeIntParameter::get_step);
 
-	ClassDB::bind_method(D_METHOD("set_enum_names", "names"), &VisualShaderNodeIntParameter::set_enum_names);
-	ClassDB::bind_method(D_METHOD("get_enum_names"), &VisualShaderNodeIntParameter::get_enum_names);
+	ClassDB::bind_method(D_METHOD("set_hint_names", "names"), &VisualShaderNodeIntParameter::set_hint_names);
+	ClassDB::bind_method(D_METHOD("get_hint_names"), &VisualShaderNodeIntParameter::get_hint_names);
 
 	ClassDB::bind_method(D_METHOD("set_default_value_enabled", "enabled"), &VisualShaderNodeIntParameter::set_default_value_enabled);
 	ClassDB::bind_method(D_METHOD("is_default_value_enabled"), &VisualShaderNodeIntParameter::is_default_value_enabled);
@@ -5511,11 +5512,12 @@ void VisualShaderNodeIntParameter::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("set_default_value", "value"), &VisualShaderNodeIntParameter::set_default_value);
 	ClassDB::bind_method(D_METHOD("get_default_value"), &VisualShaderNodeIntParameter::get_default_value);
 
-	ADD_PROPERTY(PropertyInfo(Variant::INT, "hint", PROPERTY_HINT_ENUM, "None,Range,Range + Step,Enum"), "set_hint", "get_hint");
+	ADD_PROPERTY(PropertyInfo(Variant::INT, "hint", PROPERTY_HINT_ENUM, "None,Range,Range + Step,Enum,Flags"), "set_hint", "get_hint");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "min"), "set_min", "get_min");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "max"), "set_max", "get_max");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "step"), "set_step", "get_step");
-	ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "enum_names"), "set_enum_names", "get_enum_names");
+	ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "enum_names"), "set_hint_names", "get_hint_names");
+	ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "flag_names"), "set_hint_names", "get_hint_names");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "default_value_enabled"), "set_default_value_enabled", "is_default_value_enabled");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "default_value"), "set_default_value", "get_default_value");
 
@@ -5523,6 +5525,7 @@ void VisualShaderNodeIntParameter::_bind_methods() {
 	BIND_ENUM_CONSTANT(HINT_RANGE);
 	BIND_ENUM_CONSTANT(HINT_RANGE_STEP);
 	BIND_ENUM_CONSTANT(HINT_ENUM);
+	BIND_ENUM_CONSTANT(HINT_FLAGS);
 	BIND_ENUM_CONSTANT(HINT_MAX);
 }
 
@@ -5547,6 +5550,9 @@ Vector<StringName> VisualShaderNodeIntParameter::get_editable_properties() const
 	if (hint == HINT_ENUM) {
 		props.push_back("enum_names");
 	}
+	if (hint == HINT_FLAGS) {
+		props.push_back("flag_names");
+	}
 	props.push_back("default_value_enabled");
 	if (default_value_enabled) {
 		props.push_back("default_value");
diff --git a/scene/resources/visual_shader_nodes.h b/scene/resources/visual_shader_nodes.h
index 279599ef9c70..5ab063431e69 100644
--- a/scene/resources/visual_shader_nodes.h
+++ b/scene/resources/visual_shader_nodes.h
@@ -2116,6 +2116,7 @@ class VisualShaderNodeIntParameter : public VisualShaderNodeParameter {
 		HINT_RANGE,
 		HINT_RANGE_STEP,
 		HINT_ENUM,
+		HINT_FLAGS,
 		HINT_MAX,
 	};
 
@@ -2124,7 +2125,7 @@ class VisualShaderNodeIntParameter : public VisualShaderNodeParameter {
 	int hint_range_min = 0;
 	int hint_range_max = 100;
 	int hint_range_step = 1;
-	PackedStringArray hint_enum_names;
+	PackedStringArray hint_names;
 	bool default_value_enabled = false;
 	int default_value = 0;
 
@@ -2160,8 +2161,8 @@ class VisualShaderNodeIntParameter : public VisualShaderNodeParameter {
 	void set_step(int p_value);
 	int get_step() const;
 
-	void set_enum_names(const PackedStringArray &p_names);
-	PackedStringArray get_enum_names() const;
+	void set_hint_names(const PackedStringArray &p_names);
+	PackedStringArray get_hint_names() const;
 
 	void set_default_value_enabled(bool p_enabled);
 	bool is_default_value_enabled() const;
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index f8d00ba7ecbc..f53b0c696e61 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -214,6 +214,7 @@ const char *ShaderLanguage::token_names[TK_MAX] = {
 	"HINT_SOURCE_COLOR",
 	"HINT_RANGE",
 	"HINT_ENUM",
+	"HINT_FLAGS",
 	"HINT_INSTANCE_INDEX",
 	"HINT_SCREEN_TEXTURE",
 	"HINT_NORMAL_ROUGHNESS_TEXTURE",
@@ -368,6 +369,7 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = {
 	{ TK_HINT_SOURCE_COLOR, "source_color", CF_UNSPECIFIED, {}, {} },
 	{ TK_HINT_RANGE, "hint_range", CF_UNSPECIFIED, {}, {} },
 	{ TK_HINT_ENUM, "hint_enum", CF_UNSPECIFIED, {}, {} },
+	{ TK_HINT_FLAGS, "hint_flags", CF_UNSPECIFIED, {}, {} },
 	{ TK_HINT_INSTANCE_INDEX, "instance_index", CF_UNSPECIFIED, {}, {} },
 
 	// sampler hints
@@ -1180,6 +1182,9 @@ String ShaderLanguage::get_uniform_hint_name(ShaderNode::Uniform::Hint p_hint) {
 		case ShaderNode::Uniform::HINT_ENUM: {
 			result = "hint_enum";
 		} break;
+		case ShaderNode::Uniform::HINT_FLAGS: {
+			result = "hint_flags";
+		} break;
 		case ShaderNode::Uniform::HINT_SOURCE_COLOR: {
 			result = "source_color";
 		} break;
@@ -4199,11 +4204,11 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform
 			if (p_uniform.array_size > 0) {
 				pi.type = Variant::PACKED_INT32_ARRAY;
 				// TODO: Handle range and encoding for for unsigned values.
-			} else if (p_uniform.hint == ShaderLanguage::ShaderNode::Uniform::HINT_ENUM) {
+			} else if (p_uniform.hint == ShaderLanguage::ShaderNode::Uniform::HINT_ENUM || p_uniform.hint == ShaderLanguage::ShaderNode::Uniform::HINT_FLAGS) {
 				pi.type = Variant::INT;
-				pi.hint = PROPERTY_HINT_ENUM;
+				pi.hint = p_uniform.hint == ShaderLanguage::ShaderNode::Uniform::HINT_ENUM ? PROPERTY_HINT_ENUM : PROPERTY_HINT_FLAGS;
 				String hint_string;
-				pi.hint_string = String(",").join(p_uniform.hint_enum_names);
+				pi.hint_string = String(",").join(p_uniform.hint_names);
 			} else {
 				pi.type = Variant::INT;
 				pi.hint = PROPERTY_HINT_RANGE;
@@ -9046,15 +9051,24 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
 
 									new_hint = ShaderNode::Uniform::HINT_RANGE;
 								} break;
-								case TK_HINT_ENUM: {
+								case TK_HINT_ENUM:
+								case TK_HINT_FLAGS: {
+									bool is_hint_enum = tk.type == TK_HINT_ENUM;
+
 									if (type != TYPE_INT) {
-										_set_error(vformat(RTR("Enum hint is for '%s' only."), "int"));
+										String err;
+										if (is_hint_enum) {
+											err = RTR("Enum hint is for '%s' only.");
+										} else {
+											err = RTR("Flags hint is for '%s' only.");
+										}
+										_set_error(vformat(err, "int"));
 										return ERR_PARSE_ERROR;
 									}
 
 									tk = _get_token();
 									if (tk.type != TK_PARENTHESIS_OPEN) {
-										_set_expected_after_error("(", "hint_enum");
+										_set_expected_after_error("(", is_hint_enum ? "hint_enum" : "hint_flags");
 										return ERR_PARSE_ERROR;
 									}
 
@@ -9066,7 +9080,7 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
 											return ERR_PARSE_ERROR;
 										}
 
-										uniform.hint_enum_names.push_back(tk.text);
+										uniform.hint_names.push_back(tk.text);
 
 										tk = _get_token();
 
@@ -9078,7 +9092,7 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
 										}
 									}
 
-									new_hint = ShaderNode::Uniform::HINT_ENUM;
+									new_hint = is_hint_enum ? ShaderNode::Uniform::HINT_ENUM : ShaderNode::Uniform::HINT_FLAGS;
 								} break;
 								case TK_HINT_INSTANCE_INDEX: {
 									if (custom_instance_index != -1) {
@@ -9175,7 +9189,7 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
 									break;
 							}
 
-							bool is_sampler_hint = new_hint != ShaderNode::Uniform::HINT_NONE && new_hint != ShaderNode::Uniform::HINT_SOURCE_COLOR && new_hint != ShaderNode::Uniform::HINT_RANGE && new_hint != ShaderNode::Uniform::HINT_ENUM;
+							bool is_sampler_hint = new_hint != ShaderNode::Uniform::HINT_NONE && new_hint != ShaderNode::Uniform::HINT_SOURCE_COLOR && new_hint != ShaderNode::Uniform::HINT_RANGE && new_hint != ShaderNode::Uniform::HINT_ENUM && new_hint != ShaderNode::Uniform::HINT_FLAGS;
 							if (((new_filter != FILTER_DEFAULT || new_repeat != REPEAT_DEFAULT) || is_sampler_hint) && !is_sampler_type(type)) {
 								_set_error(RTR("This hint is only for sampler types."));
 								return ERR_PARSE_ERROR;
@@ -10884,6 +10898,7 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
 					if (completion_base == DataType::TYPE_INT) {
 						options.push_back("hint_range(0, 100, 1)");
 						options.push_back("hint_enum(\"Zero\", \"One\", \"Two\")");
+						options.push_back("hint_flags(\"Flag1\", \"Flag2\")");
 					} else {
 						options.push_back("hint_range(0.0, 1.0, 0.1)");
 					}
diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h
index 1b5df7e90f3c..ff1abb2b65ca 100644
--- a/servers/rendering/shader_language.h
+++ b/servers/rendering/shader_language.h
@@ -177,6 +177,7 @@ class ShaderLanguage {
 		TK_HINT_SOURCE_COLOR,
 		TK_HINT_RANGE,
 		TK_HINT_ENUM,
+		TK_HINT_FLAGS,
 		TK_HINT_INSTANCE_INDEX,
 		TK_HINT_SCREEN_TEXTURE,
 		TK_HINT_NORMAL_ROUGHNESS_TEXTURE,
@@ -626,6 +627,7 @@ class ShaderLanguage {
 				HINT_NONE,
 				HINT_RANGE,
 				HINT_ENUM,
+				HINT_FLAGS,
 				HINT_SOURCE_COLOR,
 				HINT_NORMAL,
 				HINT_ROUGHNESS_NORMAL,
@@ -664,7 +666,7 @@ class ShaderLanguage {
 			TextureFilter filter = FILTER_DEFAULT;
 			TextureRepeat repeat = REPEAT_DEFAULT;
 			float hint_range[3];
-			PackedStringArray hint_enum_names;
+			PackedStringArray hint_names;
 			int instance_index = 0;
 			String group;
 			String subgroup;