diff --git a/editor/import/resource_importer_texture.cpp b/editor/import/resource_importer_texture.cpp index d72c15bc2ac..4dd0173cbfb 100644 --- a/editor/import/resource_importer_texture.cpp +++ b/editor/import/resource_importer_texture.cpp @@ -46,7 +46,6 @@ void ResourceImporterTexture::_texture_reimport_roughness(const Refmutex); - StringName path = p_tex->get_path(); if (!singleton->make_flags.has(path)) { @@ -62,7 +61,6 @@ void ResourceImporterTexture::_texture_reimport_3d(const Refmutex); - StringName path = p_tex->get_path(); if (!singleton->make_flags.has(path)) { @@ -76,7 +74,6 @@ void ResourceImporterTexture::_texture_reimport_normal(const Refmutex); - StringName path = p_tex->get_path(); if (!singleton->make_flags.has(path)) { @@ -86,79 +83,87 @@ void ResourceImporterTexture::_texture_reimport_normal(const Refmake_flags[path].flags |= MAKE_NORMAL_FLAG; } +inline void ResourceImporterTexture::_print_callback_message(const String &p_message) { +#ifdef TOOLS_ENABLED + EditorToaster::get_singleton()->popup_str(p_message); +#endif + print_line(p_message); +} + void ResourceImporterTexture::update_imports() { if (EditorFileSystem::get_singleton()->is_scanning() || EditorFileSystem::get_singleton()->is_importing()) { - return; // do nothing for now + return; // Don't update when EditorFileSystem is doing something else. } MutexLock lock(mutex); Vector to_reimport; - { - if (make_flags.is_empty()) { - return; - } - for (const KeyValue &E : make_flags) { - Ref cf; - cf.instantiate(); - String src_path = String(E.key) + ".import"; - - Error err = cf->load(src_path); - ERR_CONTINUE(err != OK); - - bool changed = false; - - if (E.value.flags & MAKE_NORMAL_FLAG && int(cf->get_value("params", "compress/normal_map")) == 0) { - String message = vformat(TTR("%s: Texture detected as used as a normal map in 3D. Enabling red-green texture compression to reduce memory usage (blue channel is discarded)."), String(E.key)); -#ifdef TOOLS_ENABLED - EditorToaster::get_singleton()->popup_str(message); -#endif - print_line(message); - cf->set_value("params", "compress/normal_map", 1); - changed = true; - } - - if (E.value.flags & MAKE_ROUGHNESS_FLAG && int(cf->get_value("params", "roughness/mode")) == 0) { - String message = vformat(TTR("%s: Texture detected as used as a roughness map in 3D. Enabling roughness limiter based on the detected associated normal map at %s."), String(E.key), E.value.normal_path_for_roughness); -#ifdef TOOLS_ENABLED - EditorToaster::get_singleton()->popup_str(message); -#endif - print_line(message); - cf->set_value("params", "roughness/mode", E.value.channel_for_roughness + 2); - cf->set_value("params", "roughness/src_normal", E.value.normal_path_for_roughness); - changed = true; - } - - if (E.value.flags & MAKE_3D_FLAG && bool(cf->get_value("params", "detect_3d/compress_to"))) { - const int compress_to = cf->get_value("params", "detect_3d/compress_to"); - String compress_string; - cf->set_value("params", "detect_3d/compress_to", 0); - if (compress_to == 1) { - cf->set_value("params", "compress/mode", COMPRESS_VRAM_COMPRESSED); - compress_string = "VRAM Compressed (S3TC/ETC/BPTC)"; - } else if (compress_to == 2) { - cf->set_value("params", "compress/mode", COMPRESS_BASIS_UNIVERSAL); - compress_string = "Basis Universal"; - } - String message = vformat(TTR("%s: Texture detected as used in 3D. Enabling mipmap generation and setting the texture compression mode to %s."), String(E.key), compress_string); -#ifdef TOOLS_ENABLED - EditorToaster::get_singleton()->popup_str(message); -#endif - print_line(message); - cf->set_value("params", "mipmaps/generate", true); - changed = true; - } - - if (changed) { - cf->save(src_path); - to_reimport.push_back(E.key); - } - } - - make_flags.clear(); + if (make_flags.is_empty()) { + return; } - if (to_reimport.size()) { + for (const KeyValue &E : make_flags) { + Ref cf; + cf.instantiate(); + String src_path = String(E.key) + ".import"; + + Error err = cf->load(src_path); + ERR_CONTINUE(err != OK); + + bool changed = false; + + if (E.value.flags & MAKE_NORMAL_FLAG && int(cf->get_value("params", "compress/normal_map")) == 0) { + _print_callback_message( + vformat(TTR("%s: Texture detected as used as a normal map in 3D. Enabling red-green texture compression to reduce memory usage (blue channel is discarded)."), + String(E.key))); + + cf->set_value("params", "compress/normal_map", 1); + changed = true; + } + + if (E.value.flags & MAKE_ROUGHNESS_FLAG && int(cf->get_value("params", "roughness/mode")) == 0) { + _print_callback_message( + vformat(TTR("%s: Texture detected as used as a roughness map in 3D. Enabling roughness limiter based on the detected associated normal map at %s."), + String(E.key), E.value.normal_path_for_roughness)); + + cf->set_value("params", "roughness/mode", E.value.channel_for_roughness + 2); + cf->set_value("params", "roughness/src_normal", E.value.normal_path_for_roughness); + changed = true; + } + + if (E.value.flags & MAKE_3D_FLAG && bool(cf->get_value("params", "detect_3d/compress_to"))) { + const int compress_to = cf->get_value("params", "detect_3d/compress_to"); + + // 3D detected, disable the callback. + cf->set_value("params", "detect_3d/compress_to", 0); + + String compress_string; + if (compress_to == 1) { + cf->set_value("params", "compress/mode", COMPRESS_VRAM_COMPRESSED); + compress_string = "VRAM Compressed (S3TC/ETC/BPTC)"; + + } else if (compress_to == 2) { + cf->set_value("params", "compress/mode", COMPRESS_BASIS_UNIVERSAL); + compress_string = "Basis Universal"; + } + + _print_callback_message( + vformat(TTR("%s: Texture detected as used in 3D. Enabling mipmap generation and setting the texture compression mode to %s."), + String(E.key), compress_string)); + + cf->set_value("params", "mipmaps/generate", true); + changed = true; + } + + if (changed) { + cf->save(src_path); + to_reimport.push_back(E.key); + } + } + + make_flags.clear(); + + if (!to_reimport.is_empty()) { EditorFileSystem::get_singleton()->reimport_files(to_reimport); } } @@ -189,21 +194,25 @@ bool ResourceImporterTexture::get_option_visibility(const String &p_path, const if (compress_mode != COMPRESS_VRAM_COMPRESSED) { return false; } + } else if (p_option == "compress/lossy_quality") { int compress_mode = int(p_options["compress/mode"]); if (compress_mode != COMPRESS_LOSSY) { return false; } + } else if (p_option == "compress/hdr_mode") { int compress_mode = int(p_options["compress/mode"]); if (compress_mode < COMPRESS_VRAM_COMPRESSED) { return false; } + } else if (p_option == "compress/normal_map") { int compress_mode = int(p_options["compress/mode"]); if (compress_mode == COMPRESS_LOSSLESS) { return false; } + } else if (p_option == "mipmaps/limit") { return p_options["mipmaps/generate"]; } @@ -260,9 +269,9 @@ void ResourceImporterTexture::get_import_options(const String &p_path, List f, const Ref &p_image, CompressMode p_compress_mode, Image::UsedChannels p_channels, Image::CompressMode p_compress_format, float p_lossy_quality) { switch (p_compress_mode) { case COMPRESS_LOSSLESS: { - bool lossless_force_png = GLOBAL_GET("rendering/textures/lossless_compression/force_png") || - !Image::_webp_mem_loader_func; // WebP module disabled. - bool use_webp = !lossless_force_png && p_image->get_width() <= 16383 && p_image->get_height() <= 16383; // WebP has a size limit + bool lossless_force_png = GLOBAL_GET("rendering/textures/lossless_compression/force_png") || !Image::_webp_mem_loader_func; // WebP module disabled or png is forced. + bool use_webp = !lossless_force_png && p_image->get_width() <= 16383 && p_image->get_height() <= 16383; // WebP has a size limit. + f->store_32(use_webp ? CompressedTexture2D::DATA_FORMAT_WEBP : CompressedTexture2D::DATA_FORMAT_PNG); f->store_16(p_image->get_width()); f->store_16(p_image->get_height()); @@ -276,11 +285,11 @@ void ResourceImporterTexture::save_to_ctex_format(Ref f, const Refget_image_from_mipmap(i) : p_image); } - int data_len = data.size(); - f->store_32(data_len); - const uint8_t *r = data.ptr(); - f->store_buffer(r, data_len); + const uint64_t data_size = data.size(); + + f->store_32(data_size); + f->store_buffer(data.ptr(), data_size); } } break; @@ -293,16 +302,15 @@ void ResourceImporterTexture::save_to_ctex_format(Ref f, const Refget_mipmap_count() + 1; i++) { Vector data = Image::webp_lossy_packer(i ? p_image->get_image_from_mipmap(i) : p_image, p_lossy_quality); - int data_len = data.size(); - f->store_32(data_len); + const uint64_t data_size = data.size(); - const uint8_t *r = data.ptr(); - f->store_buffer(r, data_len); + f->store_32(data_size); + f->store_buffer(data.ptr(), data_size); } + } break; case COMPRESS_VRAM_COMPRESSED: { Ref image = p_image->duplicate(); - image->compress_from_channels(p_compress_format, p_channels); f->store_32(CompressedTexture2D::DATA_FORMAT_IMAGE); @@ -310,11 +318,8 @@ void ResourceImporterTexture::save_to_ctex_format(Ref f, const Refstore_16(image->get_height()); f->store_32(image->get_mipmap_count()); f->store_32(image->get_format()); + f->store_buffer(image->get_data()); - Vector data = image->get_data(); - int dl = data.size(); - const uint8_t *r = data.ptr(); - f->store_buffer(r, dl); } break; case COMPRESS_VRAM_UNCOMPRESSED: { f->store_32(CompressedTexture2D::DATA_FORMAT_IMAGE); @@ -322,12 +327,7 @@ void ResourceImporterTexture::save_to_ctex_format(Ref f, const Refstore_16(p_image->get_height()); f->store_32(p_image->get_mipmap_count()); f->store_32(p_image->get_format()); - - Vector data = p_image->get_data(); - int dl = data.size(); - const uint8_t *r = data.ptr(); - - f->store_buffer(r, dl); + f->store_buffer(p_image->get_data()); } break; case COMPRESS_BASIS_UNIVERSAL: { @@ -336,11 +336,12 @@ void ResourceImporterTexture::save_to_ctex_format(Ref f, const Refstore_16(p_image->get_height()); f->store_32(p_image->get_mipmap_count()); f->store_32(p_image->get_format()); + Vector data = Image::basis_universal_packer(p_image, p_channels); - int data_len = data.size(); - f->store_32(data_len); - const uint8_t *r = data.ptr(); - f->store_buffer(r, data_len); + const uint64_t data_size = data.size(); + + f->store_32(data_size); + f->store_buffer(data.ptr(), data_size); } break; } } @@ -348,14 +349,17 @@ void ResourceImporterTexture::save_to_ctex_format(Ref f, const Ref &p_image, const String &p_to_path, CompressMode p_compress_mode, float p_lossy_quality, Image::CompressMode p_vram_compression, bool p_mipmaps, bool p_streamable, bool p_detect_3d, bool p_detect_roughness, bool p_detect_normal, bool p_force_normal, bool p_srgb_friendly, bool p_force_po2_for_compressed, uint32_t p_limit_mipmap, const Ref &p_normal, Image::RoughnessChannel p_roughness_channel) { Ref f = FileAccess::open(p_to_path, FileAccess::WRITE); ERR_FAIL_COND(f.is_null()); + + // Godot Streamable Texture 2D. f->store_8('G'); f->store_8('S'); f->store_8('T'); - f->store_8('2'); //godot streamable texture 2D + f->store_8('2'); - //format version + // Current format version. f->store_32(CompressedTexture2D::FORMAT_VERSION); - //texture may be resized later, so original size must be saved first + + // Texture may be resized later, so original size must be saved first. f->store_32(p_image->get_width()); f->store_32(p_image->get_height()); @@ -364,7 +368,7 @@ void ResourceImporterTexture::_save_ctex(const Ref &p_image, const String flags |= CompressedTexture2D::FORMAT_BIT_STREAM; } if (p_mipmaps) { - flags |= CompressedTexture2D::FORMAT_BIT_HAS_MIPMAPS; //mipmaps bit + flags |= CompressedTexture2D::FORMAT_BIT_HAS_MIPMAPS; } if (p_detect_3d) { flags |= CompressedTexture2D::FORMAT_BIT_DETECT_3D; @@ -378,7 +382,8 @@ void ResourceImporterTexture::_save_ctex(const Ref &p_image, const String f->store_32(flags); f->store_32(p_limit_mipmap); - //reserved for future use + + // Reserved. f->store_32(0); f->store_32(0); f->store_32(0); @@ -389,30 +394,37 @@ void ResourceImporterTexture::_save_ctex(const Ref &p_image, const String Ref image = p_image->duplicate(); - if (p_force_po2_for_compressed && p_mipmaps && ((p_compress_mode == COMPRESS_BASIS_UNIVERSAL) || (p_compress_mode == COMPRESS_VRAM_COMPRESSED))) { - image->resize_to_po2(); - } + if (p_mipmaps) { + if (p_force_po2_for_compressed && (p_compress_mode == COMPRESS_BASIS_UNIVERSAL || p_compress_mode == COMPRESS_VRAM_COMPRESSED)) { + image->resize_to_po2(); + } - if (p_mipmaps && (!image->has_mipmaps() || p_force_normal)) { - image->generate_mipmaps(p_force_normal); - } + if (!image->has_mipmaps() || p_force_normal) { + image->generate_mipmaps(p_force_normal); + } - if (!p_mipmaps) { + } else { image->clear_mipmaps(); } + // Generate roughness mipmaps from normal texture. if (image->has_mipmaps() && p_normal.is_valid()) { image->generate_mipmap_roughness(p_roughness_channel, p_normal); } - Image::CompressSource csource = Image::COMPRESS_SOURCE_GENERIC; - if (p_force_normal) { - csource = Image::COMPRESS_SOURCE_NORMAL; - } else if (p_srgb_friendly) { - csource = Image::COMPRESS_SOURCE_SRGB; - } + // Optimization: Only check for color channels when compressing as BasisU or VRAM. + Image::UsedChannels used_channels = Image::USED_CHANNELS_RGBA; - Image::UsedChannels used_channels = image->detect_used_channels(csource); + if (p_compress_mode == COMPRESS_BASIS_UNIVERSAL || p_compress_mode == COMPRESS_VRAM_COMPRESSED) { + Image::CompressSource comp_source = Image::COMPRESS_SOURCE_GENERIC; + if (p_force_normal) { + comp_source = Image::COMPRESS_SOURCE_NORMAL; + } else if (p_srgb_friendly) { + comp_source = Image::COMPRESS_SOURCE_SRGB; + } + + used_channels = image->detect_used_channels(comp_source); + } save_to_ctex_format(f, image, p_compress_mode, used_channels, p_vram_compression, p_lossy_quality); } @@ -431,6 +443,50 @@ Dictionary ResourceImporterTexture::_load_editor_meta(const String &p_path) cons return f->get_var(); } +void ResourceImporterTexture::_invert_y_channel(Ref &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 + // sometimes needed when using a normal map exported from another program. + // See . + const int height = r_image->get_height(); + const int width = r_image->get_width(); + + for (int i = 0; i < width; i++) { + for (int j = 0; j < height; j++) { + const Color color = r_image->get_pixel(i, j); + r_image->set_pixel(i, j, Color(color.r, 1 - color.g, color.b, color.a)); + } + } +} + +void ResourceImporterTexture::_clamp_hdr_exposure(Ref &r_image) { + // Clamp HDR exposure following Filament's tonemapping formula. + // This can be used to reduce fireflies in environment maps or reduce the influence + // of the sun from an HDRI panorama on environment lighting (when a DirectionalLight3D is used instead). + const int height = r_image->get_height(); + const int width = r_image->get_width(); + + // These values are chosen arbitrarily and seem to produce good results with 4,096 samples. + const float linear = 4096.0; + const float compressed = 16384.0; + + for (int i = 0; i < width; i++) { + for (int j = 0; j < height; j++) { + const Color color = r_image->get_pixel(i, j); + const float luma = color.get_luminance(); + + Color clamped_color; + if (luma <= linear) { + clamped_color = color; + } else { + clamped_color = (color / luma) * ((linear * linear - compressed * luma) / (2 * linear - compressed - luma)); + } + + r_image->set_pixel(i, j, clamped_color); + } + } +} + Error ResourceImporterTexture::import(ResourceUID::ID p_source_id, const String &p_source_file, const String &p_save_path, const HashMap &p_options, List *r_platform_variants, List *r_gen_files, Variant *r_metadata) { // Parse import options. int32_t loader_flags = ImageFormatLoader::FLAG_NONE; @@ -455,10 +511,11 @@ Error ResourceImporterTexture::import(ResourceUID::ID p_source_id, const String 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"]; - // Support for texture streaming is not implemented yet. - const bool stream = false; + const bool hdr_as_srgb = p_options["process/hdr_as_srgb"]; + const bool hdr_clamp_exposure = p_options["process/hdr_clamp_exposure"]; int size_limit = p_options["process/size_limit"]; + bool using_fallback_size_limit = false; if (size_limit == 0) { using_fallback_size_limit = true; @@ -479,28 +536,27 @@ Error ResourceImporterTexture::import(ResourceUID::ID p_source_id, const String } } - const bool hdr_as_srgb = p_options["process/hdr_as_srgb"]; - if (hdr_as_srgb) { - loader_flags |= ImageFormatLoader::FLAG_FORCE_LINEAR; - } - const bool hdr_clamp_exposure = p_options["process/hdr_clamp_exposure"]; + // Support for texture streaming is not implemented yet. + const bool stream = false; - float scale = 1.0; // SVG-specific options. - if (p_options.has("svg/scale")) { - scale = p_options["svg/scale"]; - } + float scale = p_options.has("svg/scale") ? float(p_options["svg/scale"]) : 1.0f; // Editor-specific options. bool use_editor_scale = p_options.has("editor/scale_with_editor_scale") && p_options["editor/scale_with_editor_scale"]; bool convert_editor_colors = p_options.has("editor/convert_colors_with_editor_theme") && p_options["editor/convert_colors_with_editor_theme"]; + if (hdr_as_srgb) { + loader_flags |= ImageFormatLoader::FLAG_FORCE_LINEAR; + } + // Start importing images. - List> images_imported; + LocalVector> images_imported; // Load the normal image. Ref normal_image; Image::RoughnessChannel roughness_channel = Image::ROUGHNESS_CHANNEL_R; + if (mipmaps && roughness > 1 && FileAccess::exists(normal_map)) { normal_image.instantiate(); if (ImageLoader::load_image(normal_map, normal_image) == OK) { @@ -520,11 +576,9 @@ Error ResourceImporterTexture::import(ResourceUID::ID p_source_id, const String // Load the editor-only image. Ref editor_image; bool import_editor_image = use_editor_scale || convert_editor_colors; + if (import_editor_image) { - float editor_scale = scale; - if (use_editor_scale) { - editor_scale = scale * EDSCALE; - } + float editor_scale = use_editor_scale ? scale * EDSCALE : scale; int32_t editor_loader_flags = loader_flags; if (convert_editor_colors) { @@ -533,8 +587,9 @@ Error ResourceImporterTexture::import(ResourceUID::ID p_source_id, const String editor_image.instantiate(); err = ImageLoader::load_image(p_source_file, editor_image, nullptr, editor_loader_flags, editor_scale); + if (err != OK) { - WARN_PRINT("Failed to import an image resource for editor use from '" + p_source_file + "'"); + WARN_PRINT(vformat("Failed to import an image resource for editor use from '%s'.", p_source_file)); } else { images_imported.push_back(editor_image); } @@ -580,48 +635,12 @@ Error ResourceImporterTexture::import(ResourceUID::ID p_source_id, const String // Invert the green channel of the image to flip the normal map it contains. if (normal_map_invert_y) { - // 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 - // sometimes needed when using a normal map exported from another program. - // See . - const int height = target_image->get_height(); - const int width = target_image->get_width(); - - for (int i = 0; i < width; i++) { - for (int j = 0; j < height; j++) { - const Color color = target_image->get_pixel(i, j); - target_image->set_pixel(i, j, Color(color.r, 1 - color.g, color.b, color.a)); - } - } + _invert_y_channel(target_image); } // Clamp HDR exposure. if (hdr_clamp_exposure) { - // Clamp HDR exposure following Filament's tonemapping formula. - // This can be used to reduce fireflies in environment maps or reduce the influence - // of the sun from an HDRI panorama on environment lighting (when a DirectionalLight3D is used instead). - const int height = target_image->get_height(); - const int width = target_image->get_width(); - - // These values are chosen arbitrarily and seem to produce good results with 4,096 samples. - const float linear = 4096.0; - const float compressed = 16384.0; - - for (int i = 0; i < width; i++) { - for (int j = 0; j < height; j++) { - const Color color = target_image->get_pixel(i, j); - const float luma = color.get_luminance(); - - Color clamped_color; - if (luma <= linear) { - clamped_color = color; - } else { - clamped_color = (color / luma) * ((linear * linear - compressed * luma) / (2 * linear - compressed - luma)); - } - - target_image->set_pixel(i, j, clamped_color); - } - } + _clamp_hdr_exposure(target_image); } } @@ -634,14 +653,12 @@ Error ResourceImporterTexture::import(ResourceUID::ID p_source_id, const String Array formats_imported; if (compress_mode == COMPRESS_VRAM_COMPRESSED) { - // Must import in all formats, in order of priority (so platform choses the best supported one. IE, etc2 over etc). - // Android, GLES 2.x - + // Must import in desktop and mobile formats in order of priority, so platform chooses the best supported one (e.g. s3tc over etc2 on desktop). const bool is_hdr = (image->get_format() >= Image::FORMAT_RF && image->get_format() <= Image::FORMAT_RGBE9995); const bool can_s3tc_bptc = ResourceImporterTextureSettings::should_import_s3tc_bptc(); const bool can_etc2_astc = ResourceImporterTextureSettings::should_import_etc2_astc(); - // Add list of formats imported + // Add list of formats imported. if (can_s3tc_bptc) { formats_imported.push_back("s3tc_bptc"); } @@ -651,7 +668,7 @@ Error ResourceImporterTexture::import(ResourceUID::ID p_source_id, const String bool can_compress_hdr = hdr_compression > 0; bool has_alpha = image->detect_alpha() != Image::ALPHA_NONE; - bool use_uncompressed = false; + bool force_uncompressed = false; if (is_hdr) { if (has_alpha) { @@ -668,17 +685,16 @@ Error ResourceImporterTexture::import(ResourceUID::ID p_source_id, const String } } - if (!can_compress_hdr) { - // Fallback to RGBE99995. - if (image->get_format() != Image::FORMAT_RGBE9995) { - image->convert(Image::FORMAT_RGBE9995); - use_uncompressed = true; - } + // Fall back to RGBE99995. + if (!can_compress_hdr && image->get_format() != Image::FORMAT_RGBE9995) { + image->convert(Image::FORMAT_RGBE9995); + force_uncompressed = true; } } - if (use_uncompressed) { - _save_ctex(image, p_save_path + ".ctex", COMPRESS_VRAM_UNCOMPRESSED, lossy, Image::COMPRESS_S3TC /*this is ignored */, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, false, mipmap_limit, normal_image, roughness_channel); + if (force_uncompressed) { + _save_ctex(image, p_save_path + ".ctex", COMPRESS_VRAM_UNCOMPRESSED, lossy, Image::COMPRESS_S3TC /* This is ignored. */, + mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, false, mipmap_limit, normal_image, roughness_channel); } else { if (can_s3tc_bptc) { Image::CompressMode image_compress_mode; @@ -690,7 +706,9 @@ Error ResourceImporterTexture::import(ResourceUID::ID p_source_id, const String image_compress_mode = Image::COMPRESS_S3TC; image_compress_format = "s3tc"; } - _save_ctex(image, p_save_path + "." + image_compress_format + ".ctex", compress_mode, lossy, image_compress_mode, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, false, mipmap_limit, normal_image, roughness_channel); + + _save_ctex(image, p_save_path + "." + image_compress_format + ".ctex", compress_mode, lossy, image_compress_mode, mipmaps, stream, detect_3d, + detect_roughness, detect_normal, force_normal, srgb_friendly_pack, false, mipmap_limit, normal_image, roughness_channel); r_platform_variants->push_back(image_compress_format); } @@ -704,17 +722,21 @@ Error ResourceImporterTexture::import(ResourceUID::ID p_source_id, const String image_compress_mode = Image::COMPRESS_ETC2; image_compress_format = "etc2"; } - _save_ctex(image, p_save_path + "." + image_compress_format + ".ctex", compress_mode, lossy, image_compress_mode, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, false, mipmap_limit, normal_image, roughness_channel); + + _save_ctex(image, p_save_path + "." + image_compress_format + ".ctex", compress_mode, lossy, image_compress_mode, mipmaps, stream, detect_3d, + detect_roughness, detect_normal, force_normal, srgb_friendly_pack, false, mipmap_limit, normal_image, roughness_channel); r_platform_variants->push_back(image_compress_format); } } } else { // Import normally. - _save_ctex(image, p_save_path + ".ctex", compress_mode, lossy, Image::COMPRESS_S3TC /*this is ignored */, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, false, mipmap_limit, normal_image, roughness_channel); + _save_ctex(image, p_save_path + ".ctex", compress_mode, lossy, Image::COMPRESS_S3TC /* This is ignored. */, + mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, false, mipmap_limit, normal_image, roughness_channel); } if (editor_image.is_valid()) { - _save_ctex(editor_image, p_save_path + ".editor.ctex", compress_mode, lossy, Image::COMPRESS_S3TC /*this is ignored */, mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, false, mipmap_limit, normal_image, roughness_channel); + _save_ctex(editor_image, p_save_path + ".editor.ctex", compress_mode, lossy, Image::COMPRESS_S3TC /* This is ignored. */, + mipmaps, stream, detect_3d, detect_roughness, detect_normal, force_normal, srgb_friendly_pack, false, mipmap_limit, normal_image, roughness_channel); // Generate and save editor-specific metadata, which we cannot save to the .import file. Dictionary editor_meta; @@ -722,6 +744,7 @@ Error ResourceImporterTexture::import(ResourceUID::ID p_source_id, const String if (use_editor_scale) { editor_meta["editor_scale"] = EDSCALE; } + if (convert_editor_colors) { editor_meta["editor_dark_theme"] = EditorThemeManager::is_dark_theme(); } @@ -732,6 +755,7 @@ Error ResourceImporterTexture::import(ResourceUID::ID p_source_id, const String if (r_metadata) { Dictionary meta; meta["vram_texture"] = compress_mode == COMPRESS_VRAM_COMPRESSED; + if (formats_imported.size()) { meta["imported_formats"] = formats_imported; } @@ -751,16 +775,17 @@ const char *ResourceImporterTexture::compression_formats[] = { "etc2_astc", nullptr }; + String ResourceImporterTexture::get_import_settings_string() const { String s; int index = 0; while (compression_formats[index]) { - String setting_path = "rendering/textures/vram_compression/import_" + String(compression_formats[index]); - bool test = GLOBAL_GET(setting_path); - if (test) { + const String setting_path = "rendering/textures/vram_compression/import_" + String(compression_formats[index]); + if (bool(GLOBAL_GET(setting_path))) { s += String(compression_formats[index]); } + index++; } @@ -780,6 +805,7 @@ bool ResourceImporterTexture::are_import_settings_valid(const String &p_path, co if (editor_meta.has("editor_scale") && (float)editor_meta["editor_scale"] != EDSCALE) { return false; } + if (editor_meta.has("editor_dark_theme") && (bool)editor_meta["editor_dark_theme"] != EditorThemeManager::is_dark_theme()) { return false; } @@ -789,8 +815,7 @@ bool ResourceImporterTexture::are_import_settings_valid(const String &p_path, co return false; } - bool vram = p_meta["vram_texture"]; - if (!vram) { + if (!bool(p_meta["vram_texture"])) { return true; // Do not care about non-VRAM. } @@ -803,18 +828,16 @@ bool ResourceImporterTexture::are_import_settings_valid(const String &p_path, co int index = 0; bool valid = true; while (compression_formats[index]) { - String setting_path = "rendering/textures/vram_compression/import_" + String(compression_formats[index]); + const String setting_path = "rendering/textures/vram_compression/import_" + String(compression_formats[index]); if (ProjectSettings::get_singleton()->has_setting(setting_path)) { - bool test = GLOBAL_GET(setting_path); - if (test) { - if (!formats_imported.has(compression_formats[index])) { - valid = false; - break; - } + if (bool(GLOBAL_GET(setting_path)) && !formats_imported.has(compression_formats[index])) { + valid = false; + break; } } else { WARN_PRINT("Setting for imported format not found: " + setting_path); } + index++; } diff --git a/editor/import/resource_importer_texture.h b/editor/import/resource_importer_texture.h index 8aa044f3c85..7fd55d9e2bd 100644 --- a/editor/import/resource_importer_texture.h +++ b/editor/import/resource_importer_texture.h @@ -78,6 +78,10 @@ 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 _clamp_hdr_exposure(Ref &r_image); + static inline void _invert_y_channel(Ref &r_image); + static inline void _print_callback_message(const String &p_message); + public: static void save_to_ctex_format(Ref f, const Ref &p_image, CompressMode p_compress_mode, Image::UsedChannels p_channels, Image::CompressMode p_compress_format, float p_lossy_quality);