From 52d59b2df73a1b23c24994b7bd94c11ce1f695f2 Mon Sep 17 00:00:00 2001 From: Brian Lach <32017152+lachbr@users.noreply.github.com> Date: Tue, 14 Feb 2023 11:02:35 +0100 Subject: [PATCH] add sRGB support to egg-palettize, sluminance to egg --- panda/src/egg/eggTexture.cxx | 10 +++ panda/src/egg/eggTexture.h | 3 +- panda/src/egg2pg/eggLoader.cxx | 10 +++ panda/src/egg2pg/eggSaver.cxx | 6 ++ pandatool/src/egg-palettize/eggPalettize.cxx | 6 ++ pandatool/src/palettizer/palettizer.cxx | 3 +- pandatool/src/palettizer/textureImage.cxx | 2 + .../src/palettizer/textureProperties.cxx | 84 ++++++++++++++++++- pandatool/src/palettizer/textureProperties.h | 1 + pandatool/src/palettizer/textureRequest.cxx | 1 + pandatool/src/palettizer/textureRequest.h | 1 + pandatool/src/palettizer/txaLine.cxx | 10 +++ pandatool/src/palettizer/txaLine.h | 3 +- 13 files changed, 133 insertions(+), 7 deletions(-) diff --git a/panda/src/egg/eggTexture.cxx b/panda/src/egg/eggTexture.cxx index 27bc23d392..6c78d57b3d 100644 --- a/panda/src/egg/eggTexture.cxx +++ b/panda/src/egg/eggTexture.cxx @@ -504,6 +504,7 @@ has_alpha_channel(int num_components) const { case F_green: case F_blue: case F_luminance: + case F_sluminance: case F_rgb: case F_rgb12: case F_rgb8: @@ -520,6 +521,7 @@ has_alpha_channel(int num_components) const { case F_luminance_alpha: case F_luminance_alphamask: + case F_sluminance_alpha: case F_rgba: case F_rgbm: case F_rgba12: @@ -732,6 +734,10 @@ string_format(const string &string) { return F_luminance_alpha; } else if (cmp_nocase_uh(string, "luminance_alphamask") == 0) { return F_luminance_alphamask; + } else if (cmp_nocase_uh(string, "sluminance") == 0) { + return F_sluminance; + } else if (cmp_nocase_uh(string, "sluminance_alpha") == 0) { + return F_sluminance_alpha; } else { return F_unspecified; } @@ -1179,6 +1185,10 @@ ostream &operator << (ostream &out, EggTexture::Format format) { return out << "luminance_alpha"; case EggTexture::F_luminance_alphamask: return out << "luminance_alphamask"; + case EggTexture::F_sluminance: + return out << "sluminance"; + case EggTexture::F_sluminance_alpha: + return out << "sluminance_alpha"; } nassertr(false, out); diff --git a/panda/src/egg/eggTexture.h b/panda/src/egg/eggTexture.h index 11dabbceda..e67cc2cdb3 100644 --- a/panda/src/egg/eggTexture.h +++ b/panda/src/egg/eggTexture.h @@ -63,7 +63,8 @@ PUBLISHED: F_luminance_alpha, F_luminance_alphamask, // Only for compatibility with .bam, use is discouraged! - F_srgb, F_srgb_alpha + F_srgb, F_srgb_alpha, + F_sluminance, F_sluminance_alpha }; enum CompressionMode { CM_default, CM_off, CM_on, diff --git a/panda/src/egg2pg/eggLoader.cxx b/panda/src/egg2pg/eggLoader.cxx index efee35c04c..7c780d9cd1 100644 --- a/panda/src/egg2pg/eggLoader.cxx +++ b/panda/src/egg2pg/eggLoader.cxx @@ -887,12 +887,14 @@ load_texture(TextureDef &def, EggTexture *egg_tex) { case EggTexture::F_blue: case EggTexture::F_alpha: case EggTexture::F_luminance: + case EggTexture::F_sluminance: wanted_channels = 1; wanted_alpha = false; break; case EggTexture::F_luminance_alpha: case EggTexture::F_luminance_alphamask: + case EggTexture::F_sluminance_alpha: wanted_channels = 2; wanted_alpha = true; break; @@ -1225,6 +1227,7 @@ check_texture_attributes(Texture *tex, SamplerState sampler, const EggTexture *e case EggTexture::F_blue: case EggTexture::F_alpha: case EggTexture::F_luminance: + case EggTexture::F_sluminance: break; default: egg2pg_cat.warning() @@ -1238,6 +1241,7 @@ check_texture_attributes(Texture *tex, SamplerState sampler, const EggTexture *e case EggTexture::F_unspecified: case EggTexture::F_luminance_alpha: case EggTexture::F_luminance_alphamask: + case EggTexture::F_sluminance: break; default: egg2pg_cat.error() @@ -1389,6 +1393,12 @@ convert_format(EggTexture::Format format, EggTexture::EnvType env) { case EggTexture::F_srgb_alpha: return Texture::F_srgb_alpha; + + case EggTexture::F_sluminance: + return Texture::F_sluminance; + + case EggTexture::F_sluminance_alpha: + return Texture::F_sluminance_alpha; } egg2pg_cat.warning() diff --git a/panda/src/egg2pg/eggSaver.cxx b/panda/src/egg2pg/eggSaver.cxx index db431a8eb2..c44aedd12a 100644 --- a/panda/src/egg2pg/eggSaver.cxx +++ b/panda/src/egg2pg/eggSaver.cxx @@ -1462,6 +1462,12 @@ get_egg_texture(Texture *tex) { case Texture::F_srgb_alpha: temp.set_format(EggTexture::F_srgb_alpha); break; + case Texture::F_sluminance: + temp.set_format(EggTexture::F_sluminance); + break; + case Texture::F_sluminance_alpha: + temp.set_format(EggTexture::F_sluminance_alpha); + break; default: break; } diff --git a/pandatool/src/egg-palettize/eggPalettize.cxx b/pandatool/src/egg-palettize/eggPalettize.cxx index afa7fa00b7..385dd78932 100644 --- a/pandatool/src/egg-palettize/eggPalettize.cxx +++ b/pandatool/src/egg-palettize/eggPalettize.cxx @@ -321,6 +321,12 @@ describe_input_file() { "match the number of channels. As above, any valid egg texture " "format may be used, e.g. force-rgba12, force-rgb5, etc.\n\n"); + show_text(" srgb", 10, + "This specifies that this texture is in sRGB space and the format " + "should be changed to reflect that. The texture format will be " + "changed to the appropriate sRGB equivalent based on the number " + "of image channels.\n\n"); + show_text(" keep-format", 10, "This specifies that the image format requested by an egg file " "should be exactly preserved, without attempting to optimize " diff --git a/pandatool/src/palettizer/palettizer.cxx b/pandatool/src/palettizer/palettizer.cxx index 157c267730..2b9df0f1e1 100644 --- a/pandatool/src/palettizer/palettizer.cxx +++ b/pandatool/src/palettizer/palettizer.cxx @@ -39,7 +39,7 @@ Palettizer *pal = nullptr; // update egg-palettize to write out additional information to its pi file, // without having it increment the bam version number for all bam and boo // files anywhere in the world. -int Palettizer::_pi_version = 20; +int Palettizer::_pi_version = 21; /* * Updated to version 8 on 32003 to remove extensions from texture key names. * Updated to version 9 on 41303 to add a few properties in various places. @@ -54,6 +54,7 @@ int Palettizer::_pi_version = 20; * TextureProperties::_quality_level. Updated to version 19 on 71609 to add * PaletteGroup::_override_margin Updated to version 20 on 72709 to add * TexturePlacement::_swapTextures + * Updated to version 21 on 110120 to add sRGB support. */ int Palettizer::_min_pi_version = 8; diff --git a/pandatool/src/palettizer/textureImage.cxx b/pandatool/src/palettizer/textureImage.cxx index 612aa5b3c6..bbc47002d2 100644 --- a/pandatool/src/palettizer/textureImage.cxx +++ b/pandatool/src/palettizer/textureImage.cxx @@ -360,6 +360,8 @@ post_txa_file() { _properties._anisotropic_degree = _request._anisotropic_degree; + _properties._srgb = _request._srgb; + if (_properties._color_type == nullptr) { _properties._color_type = _request._properties._color_type; _properties._alpha_type = _request._properties._alpha_type; diff --git a/pandatool/src/palettizer/textureProperties.cxx b/pandatool/src/palettizer/textureProperties.cxx index 1268405ce8..ced4dad771 100644 --- a/pandatool/src/palettizer/textureProperties.cxx +++ b/pandatool/src/palettizer/textureProperties.cxx @@ -42,6 +42,7 @@ TextureProperties() { _anisotropic_degree = 0; _color_type = nullptr; _alpha_type = nullptr; + _srgb = false; } /** @@ -59,6 +60,7 @@ TextureProperties(const TextureProperties ©) : _anisotropic_degree(copy._anisotropic_degree), _color_type(copy._color_type), _alpha_type(copy._alpha_type), + _srgb(copy._srgb), _got_num_channels(copy._got_num_channels), _num_channels(copy._num_channels), _effective_num_channels(copy._effective_num_channels) @@ -83,6 +85,7 @@ operator = (const TextureProperties ©) { _num_channels = copy._num_channels; _effective_num_channels = copy._effective_num_channels; _format = copy._format; + _srgb = copy._srgb; } /** @@ -168,6 +171,8 @@ uses_alpha() const { case EggTexture::F_alpha: case EggTexture::F_luminance_alpha: case EggTexture::F_luminance_alphamask: + case EggTexture::F_srgb_alpha: + case EggTexture::F_sluminance_alpha: return true; default: @@ -210,6 +215,9 @@ update_properties(const TextureProperties &other) { _num_channels = other._num_channels; _effective_num_channels = _num_channels; } + + _srgb = other._srgb; + if (_force_format) { // If we've forced our own format, it doesn't change. } else if (other._force_format) { @@ -260,6 +268,7 @@ fully_define() { case EggTexture::F_luminance_alpha: case EggTexture::F_luminance_alphamask: + case EggTexture::F_sluminance_alpha: _num_channels = 2; break; @@ -268,6 +277,7 @@ fully_define() { case EggTexture::F_blue: case EggTexture::F_alpha: case EggTexture::F_luminance: + case EggTexture::F_sluminance: _num_channels = 1; break; } @@ -294,6 +304,8 @@ fully_define() { case EggTexture::F_luminance_alphamask: case EggTexture::F_srgb: case EggTexture::F_srgb_alpha: + case EggTexture::F_sluminance: + case EggTexture::F_sluminance_alpha: break; case EggTexture::F_rgba12: @@ -323,6 +335,7 @@ fully_define() { case EggTexture::F_blue: case EggTexture::F_alpha: case EggTexture::F_luminance: + case EggTexture::F_sluminance: break; // These formats suggest an alpha channel; they are quietly replaced @@ -332,8 +345,16 @@ fully_define() { _format = EggTexture::F_luminance; break; + case EggTexture::F_sluminance_alpha: + _format = EggTexture::F_sluminance; + break; + default: - _format = EggTexture::F_luminance; + if (_srgb) { + _format = EggTexture::F_sluminance; + } else { + _format = EggTexture::F_luminance; + } } break; @@ -341,6 +362,7 @@ fully_define() { switch (_format) { case EggTexture::F_luminance_alpha: case EggTexture::F_luminance_alphamask: + case EggTexture::F_sluminance_alpha: break; // These formats implicitly reduce the number of channels to 1. @@ -349,10 +371,15 @@ fully_define() { case EggTexture::F_blue: case EggTexture::F_alpha: case EggTexture::F_luminance: + case EggTexture::F_sluminance: break; default: - _format = EggTexture::F_luminance_alpha; + if (_srgb) { + _format = EggTexture::F_sluminance_alpha; + } else { + _format = EggTexture::F_luminance_alpha; + } } break; @@ -363,6 +390,7 @@ fully_define() { case EggTexture::F_rgb8: case EggTexture::F_rgb5: case EggTexture::F_rgb332: + case EggTexture::F_srgb: break; // These formats suggest an alpha channel; they are quietly replaced @@ -382,10 +410,15 @@ fully_define() { case EggTexture::F_blue: case EggTexture::F_alpha: case EggTexture::F_luminance: + case EggTexture::F_sluminance: break; default: - _format = EggTexture::F_rgb; + if (_srgb) { + _format = EggTexture::F_srgb; + } else { + _format = EggTexture::F_rgb; + } } break; @@ -397,6 +430,7 @@ fully_define() { case EggTexture::F_rgba8: case EggTexture::F_rgba4: case EggTexture::F_rgba5: + case EggTexture::F_srgb_alpha: break; // These formats implicitly reduce the number of channels to 3. @@ -405,12 +439,14 @@ fully_define() { case EggTexture::F_rgb8: case EggTexture::F_rgb5: case EggTexture::F_rgb332: + case EggTexture::F_srgb: _effective_num_channels = 3; break; // These formats implicitly reduce the number of channels to 2. case EggTexture::F_luminance_alpha: case EggTexture::F_luminance_alphamask: + case EggTexture::F_sluminance_alpha: _effective_num_channels = 2; break; @@ -420,15 +456,40 @@ fully_define() { case EggTexture::F_blue: case EggTexture::F_alpha: case EggTexture::F_luminance: + case EggTexture::F_sluminance: _effective_num_channels = 1; break; default: - _format = EggTexture::F_rgba; + if (_srgb) { + _format = EggTexture::F_srgb_alpha; + } else { + _format = EggTexture::F_rgba; + } } } } + // Respect the _srgb flag. If this is set, it means the texture is in sRGB + // space and the format should be changed to reflect that. + if (_srgb) { + switch (_num_channels) { + case 1: + _format = EggTexture::F_sluminance; + break; + case 2: + _format = EggTexture::F_sluminance_alpha; + break; + case 3: + _format = EggTexture::F_srgb; + break; + case 4: + default: + _format = EggTexture::F_srgb_alpha; + break; + } + } + switch (_minfilter) { case EggTexture::FT_unspecified: _minfilter = EggTexture::FT_linear; @@ -504,6 +565,9 @@ operator < (const TextureProperties &other) const { if (_anisotropic_degree != other._anisotropic_degree) { return _anisotropic_degree < other._anisotropic_degree; } + if (_srgb != other._srgb) { + return _srgb < other._srgb; + } if (_color_type != other._color_type) { return _color_type < other._color_type; } @@ -525,6 +589,7 @@ operator == (const TextureProperties &other) const { _magfilter == other._magfilter && _quality_level == other._quality_level && _anisotropic_degree == other._anisotropic_degree && + _srgb == other._srgb && _color_type == other._color_type && (_color_type == nullptr || _alpha_type == other._alpha_type)); @@ -606,6 +671,12 @@ get_format_string(EggTexture::Format format) { case EggTexture::F_srgb_alpha: return "sa"; + + case EggTexture::F_sluminance: + return "sl"; + + case EggTexture::F_sluminance_alpha: + return "st"; } return "x"; @@ -779,6 +850,7 @@ write_datagram(BamWriter *writer, Datagram &datagram) { datagram.add_int32((int)_magfilter); datagram.add_int32((int)_quality_level); datagram.add_int32(_anisotropic_degree); + datagram.add_bool(_srgb); writer->write_pointer(datagram, _color_type); writer->write_pointer(datagram, _alpha_type); } @@ -852,6 +924,10 @@ fillin(DatagramIterator &scan, BamReader *manager) { } _anisotropic_degree = scan.get_int32(); + if (Palettizer::_read_pi_version >= 21) { + _srgb = scan.get_bool(); + } + manager->read_pointer(scan); // _color_type manager->read_pointer(scan); // _alpha_type } diff --git a/pandatool/src/palettizer/textureProperties.h b/pandatool/src/palettizer/textureProperties.h index 5186f29308..6d27e06216 100644 --- a/pandatool/src/palettizer/textureProperties.h +++ b/pandatool/src/palettizer/textureProperties.h @@ -62,6 +62,7 @@ public: int _anisotropic_degree; PNMFileType *_color_type; PNMFileType *_alpha_type; + bool _srgb; private: static std::string get_format_string(EggTexture::Format format); diff --git a/pandatool/src/palettizer/textureRequest.cxx b/pandatool/src/palettizer/textureRequest.cxx index 15756c0075..775c5bb575 100644 --- a/pandatool/src/palettizer/textureRequest.cxx +++ b/pandatool/src/palettizer/textureRequest.cxx @@ -21,6 +21,7 @@ TextureRequest:: TextureRequest() { _got_size = false; _got_num_channels = false; + _srgb = false; _x_size = 0; _y_size = 0; _num_channels = 0; diff --git a/pandatool/src/palettizer/textureRequest.h b/pandatool/src/palettizer/textureRequest.h index ab9e0b1e19..54162283de 100644 --- a/pandatool/src/palettizer/textureRequest.h +++ b/pandatool/src/palettizer/textureRequest.h @@ -41,6 +41,7 @@ public: bool _force_format; bool _generic_format; bool _keep_format; + bool _srgb; EggTexture::FilterType _minfilter; EggTexture::FilterType _magfilter; int _anisotropic_degree; diff --git a/pandatool/src/palettizer/txaLine.cxx b/pandatool/src/palettizer/txaLine.cxx index 41f9349c51..d704fdb045 100644 --- a/pandatool/src/palettizer/txaLine.cxx +++ b/pandatool/src/palettizer/txaLine.cxx @@ -179,6 +179,9 @@ parse(const string &line) { } else if (word == "cont") { _keywords.push_back(KW_cont); + } else if (word == "srgb") { + _keywords.push_back(KW_srgb); + } else if (word == "margin") { ++wi; if (wi == words.end()) { @@ -502,6 +505,9 @@ match_texture(TextureImage *texture) const { case KW_cont: got_cont = true; break; + + case KW_srgb: + request._srgb = true; } } @@ -586,6 +592,10 @@ output(std::ostream &out) const { case KW_anisotropic: out << " aniso " << _aniso_degree; break; + + case KW_srgb: + out << " srgb"; + break; } } diff --git a/pandatool/src/palettizer/txaLine.h b/pandatool/src/palettizer/txaLine.h index b0fe5e2c06..8a93c45a9a 100644 --- a/pandatool/src/palettizer/txaLine.h +++ b/pandatool/src/palettizer/txaLine.h @@ -81,7 +81,8 @@ private: KW_linear, KW_mipmap, KW_cont, - KW_anisotropic + KW_anisotropic, + KW_srgb, }; typedef pvector Keywords;