Przeglądaj źródła

Merge pull request #99676 from BlueCube3310/tex-import-vram-specified

Add Channel Remap settings to ResourceImporterTexture
Thaddeus Crews 2 miesięcy temu
rodzic
commit
93140c0f76

+ 57 - 1
doc/classes/ResourceImporterTexture.xml

@@ -73,6 +73,62 @@
 		<member name="mipmaps/limit" type="int" setter="" getter="" default="-1">
 			Unimplemented. This currently has no effect when changed.
 		</member>
+		<member name="process/channel_remap/alpha" type="int" setter="" getter="" default="3">
+			Specifies the data source of the output image's alpha channel.
+			[b]Red:[/b] Use the values from the source image's red channel.
+			[b]Green:[/b] Use the values from the source image's green channel.
+			[b]Blue:[/b] Use the values from the source image's blue channel.
+			[b]Alpha:[/b] Use the values from the source image's alpha channel.
+			[b]Red Inverted:[/b] Use inverted values from the source image's red channel ([code]1.0 - R[/code]).
+			[b]Green Inverted:[/b] Use inverted values from the source image's green channel ([code]1.0 - G[/code]).
+			[b]Blue Inverted:[/b] Use inverted values from the source image's blue channel ([code]1.0 - B[/code]).
+			[b]Alpha Inverted:[/b] Use inverted values from the source image's alpha channel ([code]1.0 - A[/code]).
+			[b]Unused:[/b] Set the color channel's value to the default ([code]1.0[/code] for alpha, [code]0.0[/code] for red, green or blue).
+			[b]Zero:[/b] Set the color channel's value to [code]0.0[/code].
+			[b]One:[/b] Set the color channel's value to [code]1.0[/code].
+		</member>
+		<member name="process/channel_remap/blue" type="int" setter="" getter="" default="2">
+			Specifies the data source of the output image's blue channel.
+			[b]Red:[/b] Use the values from the source image's red channel.
+			[b]Green:[/b] Use the values from the source image's green channel.
+			[b]Blue:[/b] Use the values from the source image's blue channel.
+			[b]Alpha:[/b] Use the values from the source image's alpha channel.
+			[b]Red Inverted:[/b] Use inverted values from the source image's red channel ([code]1.0 - R[/code]).
+			[b]Green Inverted:[/b] Use inverted values from the source image's green channel ([code]1.0 - G[/code]).
+			[b]Blue Inverted:[/b] Use inverted values from the source image's blue channel ([code]1.0 - B[/code]).
+			[b]Alpha Inverted:[/b] Use inverted values from the source image's alpha channel ([code]1.0 - A[/code]).
+			[b]Unused:[/b] Set the color channel's value to the default ([code]1.0[/code] for alpha, [code]0.0[/code] for red, green or blue).
+			[b]Zero:[/b] Set the color channel's value to [code]0.0[/code].
+			[b]One:[/b] Set the color channel's value to [code]1.0[/code].
+		</member>
+		<member name="process/channel_remap/green" type="int" setter="" getter="" default="1">
+			Specifies the data source of the output image's green channel.
+			[b]Red:[/b] Use the values from the source image's red channel.
+			[b]Green:[/b] Use the values from the source image's green channel.
+			[b]Blue:[/b] Use the values from the source image's blue channel.
+			[b]Alpha:[/b] Use the values from the source image's alpha channel.
+			[b]Red Inverted:[/b] Use inverted values from the source image's red channel ([code]1.0 - R[/code]).
+			[b]Green Inverted:[/b] Use inverted values from the source image's green channel ([code]1.0 - G[/code]).
+			[b]Blue Inverted:[/b] Use inverted values from the source image's blue channel ([code]1.0 - B[/code]).
+			[b]Alpha Inverted:[/b] Use inverted values from the source image's alpha channel ([code]1.0 - A[/code]).
+			[b]Unused:[/b] Set the color channel's value to the default ([code]1.0[/code] for alpha, [code]0.0[/code] for red, green or blue).
+			[b]Zero:[/b] Set the color channel's value to [code]0.0[/code].
+			[b]One:[/b] Set the color channel's value to [code]1.0[/code].
+		</member>
+		<member name="process/channel_remap/red" type="int" setter="" getter="" default="0">
+			Specifies the data source of the output image's red channel.
+			[b]Red:[/b] Use the values from the source image's red channel.
+			[b]Green:[/b] Use the values from the source image's green channel.
+			[b]Blue:[/b] Use the values from the source image's blue channel.
+			[b]Alpha:[/b] Use the values from the source image's alpha channel.
+			[b]Red Inverted:[/b] Use inverted values from the source image's red channel ([code]1.0 - R[/code]).
+			[b]Green Inverted:[/b] Use inverted values from the source image's green channel ([code]1.0 - G[/code]).
+			[b]Blue Inverted:[/b] Use inverted values from the source image's blue channel ([code]1.0 - B[/code]).
+			[b]Alpha Inverted:[/b] Use inverted values from the source image's alpha channel ([code]1.0 - A[/code]).
+			[b]Unused:[/b] Set the color channel's value to the default ([code]1.0[/code] for alpha, [code]0.0[/code] for red, green or blue).
+			[b]Zero:[/b] Set the color channel's value to [code]0.0[/code].
+			[b]One:[/b] Set the color channel's value to [code]1.0[/code].
+		</member>
 		<member name="process/fix_alpha_border" type="bool" setter="" getter="" default="true">
 			If [code]true[/code], puts pixels of the same surrounding color in transition from transparent to opaque areas. For textures displayed with bilinear filtering, this helps to reduce the outline effect when exporting images from an image editor.
 			It's recommended to leave this enabled (as it is by default), unless this causes issues for a particular image.
@@ -86,7 +142,7 @@
 			Some HDR panorama images you can find online may contain extremely bright pixels, due to being taken from real life sources without any clipping.
 			While these HDR panorama images are accurate to real life, this can cause the radiance map generated by Godot to contain sparkles when used as a background sky. This can be seen in material reflections (even on rough materials in extreme cases). Enabling [member process/hdr_clamp_exposure] can resolve this.
 		</member>
-		<member name="process/normal_map_invert_y" type="bool" setter="" getter="" default="false">
+		<member name="process/normal_map_invert_y" type="bool" setter="" getter="" default="false" deprecated="The same result can be achieved by setting [member process/channel_remap/green] to [code]Green Inverted[/code].">
 			If [code]true[/code], convert the normal map from Y- (DirectX-style) to Y+ (OpenGL-style) by inverting its green color channel. This is the normal map convention expected by Godot.
 			More information about normal maps (including a coordinate order table for popular engines) can be found [url=http://wiki.polycount.com/wiki/Normal_Map_Technical_Details]here[/url].
 		</member>

+ 112 - 0
editor/import/resource_importer_texture.cpp

@@ -245,6 +245,10 @@ void ResourceImporterTexture::get_import_options(const String &p_path, List<Impo
 	r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "mipmaps/limit", PROPERTY_HINT_RANGE, "-1,256"), -1));
 	r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "roughness/mode", PROPERTY_HINT_ENUM, "Detect,Disabled,Red,Green,Blue,Alpha,Gray"), 0));
 	r_options->push_back(ImportOption(PropertyInfo(Variant::STRING, "roughness/src_normal", PROPERTY_HINT_FILE, "*.bmp,*.dds,*.exr,*.jpeg,*.jpg,*.hdr,*.png,*.svg,*.tga,*.webp"), ""));
+	r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "process/channel_remap/red", PROPERTY_HINT_ENUM, "Red,Green,Blue,Alpha,Inverted Red,Inverted Green,Inverted Blue,Inverted Alpha,Unused,Zero,One"), 0));
+	r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "process/channel_remap/green", PROPERTY_HINT_ENUM, "Red,Green,Blue,Alpha,Inverted Red,Inverted Green,Inverted Blue,Inverted Alpha,Unused,Zero,One"), 1));
+	r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "process/channel_remap/blue", PROPERTY_HINT_ENUM, "Red,Green,Blue,Alpha,Inverted Red,Inverted Green,Inverted Blue,Inverted Alpha,Unused,Zero,One"), 2));
+	r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "process/channel_remap/alpha", PROPERTY_HINT_ENUM, "Red,Green,Blue,Alpha,Inverted Red,Inverted Green,Inverted Blue,Inverted Alpha,Unused,Zero,One"), 3));
 	r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "process/fix_alpha_border"), p_preset != PRESET_3D));
 	r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "process/premult_alpha"), false));
 	r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "process/normal_map_invert_y"), false));
@@ -443,6 +447,99 @@ Dictionary ResourceImporterTexture::_load_editor_meta(const String &p_path) cons
 	return f->get_var();
 }
 
+void ResourceImporterTexture::_remap_channels(Ref<Image> &r_image, ChannelRemap p_options[4]) {
+	bool attempted_hdr_inverted = false;
+
+	if (r_image->get_format() >= Image::FORMAT_RF && r_image->get_format() <= Image::FORMAT_RGBE9995) {
+		// Formats which can hold HDR data cannot be inverted the same way as unsigned normalized ones (1.0 - channel).
+		for (int i = 0; i < 4; i++) {
+			switch (p_options[i]) {
+				case REMAP_INV_R:
+					attempted_hdr_inverted = true;
+					p_options[i] = REMAP_R;
+					break;
+				case REMAP_INV_G:
+					attempted_hdr_inverted = true;
+					p_options[i] = REMAP_G;
+					break;
+				case REMAP_INV_B:
+					attempted_hdr_inverted = true;
+					p_options[i] = REMAP_B;
+					break;
+				case REMAP_INV_A:
+					attempted_hdr_inverted = true;
+					p_options[i] = REMAP_A;
+					break;
+				default:
+					break;
+			}
+		}
+	}
+
+	if (attempted_hdr_inverted) {
+		WARN_PRINT("Attempted to use an inverted channel remap on an HDR image. The remap has been changed to its uninverted equivalent.");
+	}
+
+	if (p_options[0] == REMAP_R && p_options[1] == REMAP_G && p_options[2] == REMAP_B && p_options[3] == REMAP_A) {
+		// Default color map, do nothing.
+		return;
+	}
+
+	for (int x = 0; x < r_image->get_width(); x++) {
+		for (int y = 0; y < r_image->get_height(); y++) {
+			Color src = r_image->get_pixel(x, y);
+			Color dst;
+
+			for (int i = 0; i < 4; i++) {
+				switch (p_options[i]) {
+					case REMAP_R:
+						dst[i] = src.r;
+						break;
+					case REMAP_G:
+						dst[i] = src.g;
+						break;
+					case REMAP_B:
+						dst[i] = src.b;
+						break;
+					case REMAP_A:
+						dst[i] = src.a;
+						break;
+
+					case REMAP_INV_R:
+						dst[i] = 1.0f - src.r;
+						break;
+					case REMAP_INV_G:
+						dst[i] = 1.0f - src.g;
+						break;
+					case REMAP_INV_B:
+						dst[i] = 1.0f - src.b;
+						break;
+					case REMAP_INV_A:
+						dst[i] = 1.0f - src.a;
+						break;
+
+					case REMAP_UNUSED:
+						// For Alpha the unused value is 1, for other channels it's 0.
+						dst[i] = (i == 3) ? 1.0f : 0.0f;
+						break;
+
+					case REMAP_0:
+						dst[i] = 0.0f;
+						break;
+					case REMAP_1:
+						dst[i] = 1.0f;
+						break;
+
+					default:
+						break;
+				}
+			}
+
+			r_image->set_pixel(x, y, dst);
+		}
+	}
+}
+
 void ResourceImporterTexture::_invert_y_channel(Ref<Image> &r_image) {
 	// Inverting the green channel can be used to flip a normal map's direction.
 	// There's no standard when it comes to normal map Y direction, so this is
@@ -508,6 +605,10 @@ Error ResourceImporterTexture::import(ResourceUID::ID p_source_id, const String
 	const String normal_map = p_options["roughness/src_normal"];
 
 	// Processing.
+	const int remap_r = p_options["process/channel_remap/red"];
+	const int remap_g = p_options["process/channel_remap/green"];
+	const int remap_b = p_options["process/channel_remap/blue"];
+	const int remap_a = p_options["process/channel_remap/alpha"];
 	const bool fix_alpha_border = p_options["process/fix_alpha_border"];
 	const bool premult_alpha = p_options["process/premult_alpha"];
 	const bool normal_map_invert_y = p_options["process/normal_map_invert_y"];
@@ -628,6 +729,17 @@ Error ResourceImporterTexture::import(ResourceUID::ID p_source_id, const String
 			}
 		}
 
+		{
+			ChannelRemap remaps[4] = {
+				(ChannelRemap)remap_r,
+				(ChannelRemap)remap_g,
+				(ChannelRemap)remap_b,
+				(ChannelRemap)remap_a,
+			};
+
+			_remap_channels(target_image, remaps);
+		}
+
 		// Fix alpha border.
 		if (fix_alpha_border) {
 			target_image->fix_alpha_edges();

+ 15 - 0
editor/import/resource_importer_texture.h

@@ -49,6 +49,20 @@ public:
 		COMPRESS_BASIS_UNIVERSAL
 	};
 
+	enum ChannelRemap {
+		REMAP_R,
+		REMAP_G,
+		REMAP_B,
+		REMAP_A,
+		REMAP_INV_R,
+		REMAP_INV_G,
+		REMAP_INV_B,
+		REMAP_INV_A,
+		REMAP_UNUSED,
+		REMAP_0,
+		REMAP_1,
+	};
+
 protected:
 	enum {
 		MAKE_3D_FLAG = 1,
@@ -76,6 +90,7 @@ protected:
 	void _save_editor_meta(const Dictionary &p_metadata, const String &p_to_path);
 	Dictionary _load_editor_meta(const String &p_to_path) const;
 
+	static inline void _remap_channels(Ref<Image> &r_image, ChannelRemap p_options[4]);
 	static inline void _clamp_hdr_exposure(Ref<Image> &r_image);
 	static inline void _invert_y_channel(Ref<Image> &r_image);