Skip to content

Commit 635d9f5

Browse files
committed
BasisU: Use KTX2 format and add import options to configure encoder
1 parent 67c96c8 commit 635d9f5

14 files changed

+232
-62
lines changed

core/io/image.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ void (*Image::_image_decompress_astc)(Image *) = nullptr;
130130
Vector<uint8_t> (*Image::webp_lossy_packer)(const Ref<Image> &, float) = nullptr;
131131
Vector<uint8_t> (*Image::webp_lossless_packer)(const Ref<Image> &) = nullptr;
132132
Vector<uint8_t> (*Image::png_packer)(const Ref<Image> &) = nullptr;
133-
Vector<uint8_t> (*Image::basis_universal_packer)(const Ref<Image> &, Image::UsedChannels) = nullptr;
133+
Vector<uint8_t> (*Image::basis_universal_packer)(const Ref<Image> &p_image, Image::UsedChannels p_channels, const BasisUniversalPackerParams &p_basisu_params) = nullptr;
134134

135135
Ref<Image> (*Image::webp_unpacker)(const Vector<uint8_t> &) = nullptr;
136136
Ref<Image> (*Image::png_unpacker)(const Vector<uint8_t> &) = nullptr;

core/io/image.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,15 @@ class Image : public Resource {
182182
ALPHA_BLEND
183183
};
184184

185+
struct BasisUniversalPackerParams {
186+
int uastc_level = 0;
187+
bool rdo_enabled = false;
188+
float rdo_quality_loss = 3;
189+
int rdo_dict_size = 1024;
190+
bool zstd_supercompression = true;
191+
int zstd_supercompression_level = 6;
192+
};
193+
185194
// External saver function pointers.
186195

187196
static SavePNGFunc save_png_func;
@@ -231,7 +240,7 @@ class Image : public Resource {
231240
static Vector<uint8_t> (*webp_lossy_packer)(const Ref<Image> &p_image, float p_quality);
232241
static Vector<uint8_t> (*webp_lossless_packer)(const Ref<Image> &p_image);
233242
static Vector<uint8_t> (*png_packer)(const Ref<Image> &p_image);
234-
static Vector<uint8_t> (*basis_universal_packer)(const Ref<Image> &p_image, UsedChannels p_channels);
243+
static Vector<uint8_t> (*basis_universal_packer)(const Ref<Image> &p_image, Image::UsedChannels p_channels, const BasisUniversalPackerParams &p_basisu_params);
235244

236245
static Ref<Image> (*webp_unpacker)(const Vector<uint8_t> &p_buffer);
237246
static Ref<Image> (*png_unpacker)(const Vector<uint8_t> &p_buffer);

doc/classes/PortableCompressedTexture2D.xml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,19 @@
4343
Return whether the flag is overridden for all textures of this type.
4444
</description>
4545
</method>
46+
<method name="set_basisu_compressor_params">
47+
<return type="void" />
48+
<param index="0" name="uastc_level" type="int" />
49+
<param index="1" name="rdo_enabled" type="bool" />
50+
<param index="2" name="rdo_quality_loss" type="float" />
51+
<param index="3" name="rdo_dict_size" type="int" />
52+
<param index="4" name="zstd_supercompression" type="bool" />
53+
<param index="5" name="zstd_supercompression_level" type="int" />
54+
<description>
55+
Sets the compressor parameters for Basis Universal compression. See also the settings in [ResourceImporterTexture].
56+
[b]Note:[/b] This must be set before [method create_from_image] to take effect.
57+
</description>
58+
</method>
4659
<method name="set_keep_all_compressed_buffers" qualifiers="static">
4760
<return type="void" />
4861
<param index="0" name="keep" type="bool" />
@@ -55,6 +68,7 @@
5568
<member name="keep_compressed_buffer" type="bool" setter="set_keep_compressed_buffer" getter="is_keeping_compressed_buffer" default="false">
5669
When running on the editor, this class will keep the source compressed data in memory. Otherwise, the source compressed data is lost after loading and the resource can't be re saved.
5770
This flag allows to keep the compressed data in memory if you intend it to persist after loading.
71+
[b]Note:[/b] This must be set before [method create_from_image] to take effect.
5872
</member>
5973
<member name="resource_local_to_scene" type="bool" setter="set_local_to_scene" getter="is_local_to_scene" overrides="Resource" default="false" />
6074
<member name="size_override" type="Vector2" setter="set_size_override" getter="get_size_override" default="Vector2(0, 0)">

doc/classes/ResourceImporterLayeredTexture.xml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,26 @@
1010
<link title="Importing images">$DOCS_URL/tutorials/assets_pipeline/importing_images.html</link>
1111
</tutorials>
1212
<members>
13+
<member name="basis_universal/rdo_dict_size" type="int" setter="" getter="" default="1024">
14+
The dictionary size for RDO, ranging from [code]64[/code] to [code]65536[/code]. Higher values reduce the file size further, but significantly make encoding times longer.
15+
</member>
16+
<member name="basis_universal/rdo_enabled" type="bool" setter="" getter="" default="false">
17+
If [code]true[/code], enables Rate-Distortion Optimization (RDO) to reduce file size.
18+
[b]Note:[/b] Enabling RDO significantly significantly makes encoding times longer, especially when [member basis_universal/rdo_dict_size] is high.
19+
</member>
20+
<member name="basis_universal/rdo_quality_loss" type="float" setter="" getter="" default="3.0">
21+
The RDO quality loss, as a value ranging from [code]0.001[/code] to [code]50.0[/code]. Higher values result in smaller file sizes but lower quality. It is recommended to choose values from [code]0.25[/code] to [code]10.0[/code].
22+
</member>
23+
<member name="basis_universal/uastc_level" type="int" setter="" getter="" default="0">
24+
Sets the UASTC encoding level, ranging from [code]0[/code] to [code]4[/code]. Higher values result in better quality but slower encoding speed.
25+
</member>
26+
<member name="basis_universal/zstd_supercompression" type="bool" setter="" getter="" default="true">
27+
If [code]true[/code], enables Zstandard supercompression to reduce file size.
28+
[b]Note:[/b] Basis Universal textures need to be compressed to gain the benefit of smaller file sizes, otherwise they are as large as VRAM-compressed textures.
29+
</member>
30+
<member name="basis_universal/zstd_supercompression_level" type="int" setter="" getter="" default="6">
31+
Specify the Zstandard compression level, ranging from [code]1[/code] to [code]22[/code].
32+
</member>
1333
<member name="compress/channel_pack" type="int" setter="" getter="" default="0">
1434
Controls how color channels should be used in the imported texture.
1535
[b]sRGB Friendly:[/b], prevents the RG color format from being used, as it does not support sRGB color.

doc/classes/ResourceImporterTexture.xml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,26 @@
1010
<link title="Importing images">$DOCS_URL/tutorials/assets_pipeline/importing_images.html</link>
1111
</tutorials>
1212
<members>
13+
<member name="basis_universal/rdo_dict_size" type="int" setter="" getter="" default="1024">
14+
The dictionary size for RDO, ranging from [code]64[/code] to [code]65536[/code]. Higher values reduce the file size further, but significantly make encoding times longer.
15+
</member>
16+
<member name="basis_universal/rdo_enabled" type="bool" setter="" getter="" default="false">
17+
If [code]true[/code], enables Rate-Distortion Optimization (RDO) to reduce file size.
18+
[b]Note:[/b] Enabling RDO significantly significantly makes encoding times longer, especially when [member basis_universal/rdo_dict_size] is high.
19+
</member>
20+
<member name="basis_universal/rdo_quality_loss" type="float" setter="" getter="" default="3.0">
21+
The RDO quality loss, as a value ranging from [code]0.001[/code] to [code]50.0[/code]. Higher values result in smaller file sizes but lower quality. It is recommended to choose values from [code]0.25[/code] to [code]10.0[/code].
22+
</member>
23+
<member name="basis_universal/uastc_level" type="int" setter="" getter="" default="0">
24+
Sets the UASTC encoding level, ranging from [code]0[/code] to [code]4[/code]. Higher values result in better quality but slower encoding speed.
25+
</member>
26+
<member name="basis_universal/zstd_supercompression" type="bool" setter="" getter="" default="true">
27+
If [code]true[/code], enables Zstandard supercompression to reduce file size.
28+
[b]Note:[/b] Basis Universal textures need to be compressed to gain the benefit of smaller file sizes, otherwise they are as large as VRAM-compressed textures.
29+
</member>
30+
<member name="basis_universal/zstd_supercompression_level" type="int" setter="" getter="" default="6">
31+
Specify the Zstandard compression level, ranging from [code]1[/code] to [code]22[/code].
32+
</member>
1333
<member name="compress/channel_pack" type="int" setter="" getter="" default="0">
1434
Controls how color channels should be used in the imported texture.
1535
[b]sRGB Friendly:[/b] Prevents the RG color format from being used, as it does not support sRGB color.

editor/import/resource_importer_layered_texture.cpp

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,11 @@ bool ResourceImporterLayeredTexture::get_option_visibility(const String &p_path,
125125
if ((p_option == "compress/high_quality" || p_option == "compress/hdr_compression") && p_options.has("compress/mode")) {
126126
return int(p_options["compress/mode"]) == COMPRESS_VRAM_COMPRESSED;
127127
}
128+
129+
if ((int)(p_options["compress/mode"]) != COMPRESS_BASIS_UNIVERSAL && p_option.begins_with("basis_universal/")) {
130+
return false;
131+
}
132+
128133
return true;
129134
}
130135

@@ -156,9 +161,17 @@ void ResourceImporterLayeredTexture::get_import_options(const String &p_path, Li
156161
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "slices/amount", PROPERTY_HINT_RANGE, "1,1024,1,or_greater"), 1));
157162
}
158163
}
164+
165+
Image::BasisUniversalPackerParams basisu_params;
166+
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "basis_universal/uastc_level", PROPERTY_HINT_ENUM, "Fastest,Faster,Medium,Slower,Slowest"), basisu_params.uastc_level));
167+
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "basis_universal/rdo_enabled"), basisu_params.rdo_enabled));
168+
r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "basis_universal/rdo_quality_loss", PROPERTY_HINT_RANGE, "0.001,50,0.001"), basisu_params.rdo_quality_loss));
169+
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "basis_universal/rdo_dict_size", PROPERTY_HINT_RANGE, "64,65536,1"), basisu_params.rdo_dict_size));
170+
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "basis_universal/zstd_supercompression"), basisu_params.zstd_supercompression));
171+
r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "basis_universal/zstd_supercompression_level", PROPERTY_HINT_RANGE, "1,22,1"), basisu_params.zstd_supercompression_level));
159172
}
160173

161-
void ResourceImporterLayeredTexture::_save_tex(Vector<Ref<Image>> p_images, const String &p_to_path, int p_compress_mode, float p_lossy, Image::CompressMode p_vram_compression, Image::CompressSource p_csource, Image::UsedChannels used_channels, bool p_mipmaps, bool p_force_po2) {
174+
void ResourceImporterLayeredTexture::_save_tex(Vector<Ref<Image>> p_images, const String &p_to_path, int p_compress_mode, float p_lossy, const Image::BasisUniversalPackerParams &p_basisu_params, Image::CompressMode p_vram_compression, Image::CompressSource p_csource, Image::UsedChannels used_channels, bool p_mipmaps, bool p_force_po2) {
162175
Vector<Ref<Image>> mipmap_images; //for 3D
163176

164177
if (mode == MODE_3D) {
@@ -278,11 +291,11 @@ void ResourceImporterLayeredTexture::_save_tex(Vector<Ref<Image>> p_images, cons
278291
}
279292

280293
for (int i = 0; i < p_images.size(); i++) {
281-
ResourceImporterTexture::save_to_ctex_format(f, p_images[i], ResourceImporterTexture::CompressMode(p_compress_mode), used_channels, p_vram_compression, p_lossy);
294+
ResourceImporterTexture::save_to_ctex_format(f, p_images[i], ResourceImporterTexture::CompressMode(p_compress_mode), used_channels, p_vram_compression, p_lossy, p_basisu_params);
282295
}
283296

284297
for (int i = 0; i < mipmap_images.size(); i++) {
285-
ResourceImporterTexture::save_to_ctex_format(f, mipmap_images[i], ResourceImporterTexture::CompressMode(p_compress_mode), used_channels, p_vram_compression, p_lossy);
298+
ResourceImporterTexture::save_to_ctex_format(f, mipmap_images[i], ResourceImporterTexture::CompressMode(p_compress_mode), used_channels, p_vram_compression, p_lossy, p_basisu_params);
286299
}
287300
}
288301

@@ -375,6 +388,16 @@ Error ResourceImporterLayeredTexture::import(ResourceUID::ID p_source_id, const
375388
slices.push_back(slice);
376389
}
377390
}
391+
392+
const Image::BasisUniversalPackerParams basisu_params = {
393+
p_options["basis_universal/uastc_level"],
394+
p_options["basis_universal/rdo_enabled"],
395+
p_options["basis_universal/rdo_quality_loss"],
396+
p_options["basis_universal/rdo_dict_size"],
397+
p_options["basis_universal/zstd_supercompression"],
398+
p_options["basis_universal/zstd_supercompression_level"],
399+
};
400+
378401
Array formats_imported;
379402
Ref<LayeredTextureImport> texture_import;
380403
texture_import.instantiate();
@@ -392,6 +415,8 @@ Error ResourceImporterLayeredTexture::import(ResourceUID::ID p_source_id, const
392415
texture_import->used_channels = used_channels;
393416
texture_import->high_quality = high_quality;
394417

418+
texture_import->basisu_params = basisu_params;
419+
395420
_check_compress_ctex(p_source_file, texture_import);
396421
if (r_metadata) {
397422
Dictionary meta;
@@ -486,7 +511,8 @@ void ResourceImporterLayeredTexture::_check_compress_ctex(const String &p_source
486511
ERR_FAIL_NULL(r_texture_import->csource);
487512
if (r_texture_import->compress_mode != COMPRESS_VRAM_COMPRESSED) {
488513
// Import normally.
489-
_save_tex(*r_texture_import->slices, r_texture_import->save_path + "." + extension, r_texture_import->compress_mode, r_texture_import->lossy, Image::COMPRESS_S3TC /* IGNORED */, *r_texture_import->csource, r_texture_import->used_channels, r_texture_import->mipmaps, false);
514+
_save_tex(*r_texture_import->slices, r_texture_import->save_path + "." + extension, r_texture_import->compress_mode, r_texture_import->lossy, r_texture_import->basisu_params,
515+
Image::COMPRESS_S3TC /* IGNORED */, *r_texture_import->csource, r_texture_import->used_channels, r_texture_import->mipmaps, false);
490516
return;
491517
}
492518
// Must import in all formats, in order of priority (so platform chooses the best supported one. IE, etc2 over etc).
@@ -541,7 +567,8 @@ void ResourceImporterLayeredTexture::_check_compress_ctex(const String &p_source
541567
}
542568

543569
if (use_uncompressed) {
544-
_save_tex(*r_texture_import->slices, r_texture_import->save_path + "." + extension, COMPRESS_VRAM_UNCOMPRESSED, r_texture_import->lossy, Image::COMPRESS_S3TC /* IGNORED */, *r_texture_import->csource, r_texture_import->used_channels, r_texture_import->mipmaps, false);
570+
_save_tex(*r_texture_import->slices, r_texture_import->save_path + "." + extension, COMPRESS_VRAM_UNCOMPRESSED, r_texture_import->lossy, r_texture_import->basisu_params,
571+
Image::COMPRESS_S3TC /* IGNORED */, *r_texture_import->csource, r_texture_import->used_channels, r_texture_import->mipmaps, false);
545572
} else {
546573
if (can_s3tc_bptc) {
547574
Image::CompressMode image_compress_mode;
@@ -553,7 +580,7 @@ void ResourceImporterLayeredTexture::_check_compress_ctex(const String &p_source
553580
image_compress_mode = Image::COMPRESS_S3TC;
554581
image_compress_format = "s3tc";
555582
}
556-
_save_tex(*r_texture_import->slices, r_texture_import->save_path + "." + image_compress_format + "." + extension, r_texture_import->compress_mode, r_texture_import->lossy, image_compress_mode, *r_texture_import->csource, r_texture_import->used_channels, r_texture_import->mipmaps, true);
583+
_save_tex(*r_texture_import->slices, r_texture_import->save_path + "." + image_compress_format + "." + extension, r_texture_import->compress_mode, r_texture_import->lossy, r_texture_import->basisu_params, image_compress_mode, *r_texture_import->csource, r_texture_import->used_channels, r_texture_import->mipmaps, true);
557584
r_texture_import->platform_variants->push_back(image_compress_format);
558585
}
559586

@@ -567,7 +594,7 @@ void ResourceImporterLayeredTexture::_check_compress_ctex(const String &p_source
567594
image_compress_mode = Image::COMPRESS_ETC2;
568595
image_compress_format = "etc2";
569596
}
570-
_save_tex(*r_texture_import->slices, r_texture_import->save_path + "." + image_compress_format + "." + extension, r_texture_import->compress_mode, r_texture_import->lossy, image_compress_mode, *r_texture_import->csource, r_texture_import->used_channels, r_texture_import->mipmaps, true);
597+
_save_tex(*r_texture_import->slices, r_texture_import->save_path + "." + image_compress_format + "." + extension, r_texture_import->compress_mode, r_texture_import->lossy, r_texture_import->basisu_params, image_compress_mode, *r_texture_import->csource, r_texture_import->used_channels, r_texture_import->mipmaps, true);
571598
r_texture_import->platform_variants->push_back(image_compress_format);
572599
}
573600
}

editor/import/resource_importer_layered_texture.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ class LayeredTextureImport : public RefCounted {
4949
Vector<Ref<Image>> *slices = nullptr;
5050
int compress_mode = 0;
5151
float lossy = 1.0;
52+
53+
Image::BasisUniversalPackerParams basisu_params;
54+
5255
int hdr_compression = 0;
5356
bool mipmaps = true;
5457
bool high_quality = false;
@@ -108,7 +111,7 @@ class ResourceImporterLayeredTexture : public ResourceImporter {
108111
virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override;
109112
virtual bool get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const override;
110113

111-
void _save_tex(Vector<Ref<Image>> p_images, const String &p_to_path, int p_compress_mode, float p_lossy, Image::CompressMode p_vram_compression, Image::CompressSource p_csource, Image::UsedChannels used_channels, bool p_mipmaps, bool p_force_po2);
114+
void _save_tex(Vector<Ref<Image>> p_images, const String &p_to_path, int p_compress_mode, float p_lossy, const Image::BasisUniversalPackerParams &p_basisu_params, Image::CompressMode p_vram_compression, Image::CompressSource p_csource, Image::UsedChannels used_channels, bool p_mipmaps, bool p_force_po2);
112115

113116
virtual Error import(ResourceUID::ID p_source_id, const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override;
114117

0 commit comments

Comments
 (0)