diff --git a/libraries/gpu/src/gpu/Texture_ktx.cpp b/libraries/gpu/src/gpu/Texture_ktx.cpp index d2f93c0036..d5710bf84b 100644 --- a/libraries/gpu/src/gpu/Texture_ktx.cpp +++ b/libraries/gpu/src/gpu/Texture_ktx.cpp @@ -99,6 +99,61 @@ struct GPUKTXPayload { }; const std::string GPUKTXPayload::KEY { "hifi.gpu" }; + +struct IrradianceKTXPayload { + using Version = uint8; + + static const std::string KEY; + static const Version CURRENT_VERSION{ 0 }; + static const size_t PADDING{ 3 }; + static const size_t SIZE{ sizeof(Version) + sizeof(SphericalHarmonics) + PADDING }; + static_assert(IrradianceKTXPayload::SIZE == 148, "Packing size may differ between platforms"); + static_assert(IrradianceKTXPayload::SIZE % 4 == 0, "IrradianceKTXPayload is not 4 bytes aligned"); + + SphericalHarmonics _irradianceSH; + + Byte* serialize(Byte* data) const { + *(Version*)data = CURRENT_VERSION; + data += sizeof(Version); + + memcpy(data, &_irradianceSH, sizeof(SphericalHarmonics)); + data += sizeof(SphericalHarmonics); + + return data + PADDING; + } + + bool unserialize(const Byte* data, size_t size) { + if (size != SIZE) { + return false; + } + + Version version = *(const Version*)data; + if (version != CURRENT_VERSION) { + return false; + } + data += sizeof(Version); + + memcpy(&_irradianceSH, data, sizeof(SphericalHarmonics)); + data += sizeof(SphericalHarmonics); + + return true; + } + + static bool isIrradianceKTX(const ktx::KeyValue& val) { + return (val._key.compare(KEY) == 0); + } + + static bool findInKeyValues(const ktx::KeyValues& keyValues, IrradianceKTXPayload& payload) { + auto found = std::find_if(keyValues.begin(), keyValues.end(), isIrradianceKTX); + if (found != keyValues.end()) { + auto value = found->_value; + return payload.unserialize(value.data(), value.size()); + } + return false; + } +}; +const std::string IrradianceKTXPayload::KEY{ "hifi.irradianceSH" }; + KtxStorage::KtxStorage(const std::string& filename) : _filename(filename) { { // We are doing a lot of work here just to get descriptor data @@ -304,16 +359,27 @@ ktx::KTXUniquePointer Texture::serialize(const Texture& texture) { } } - GPUKTXPayload keyval; - keyval._samplerDesc = texture.getSampler().getDesc(); - keyval._usage = texture.getUsage(); - keyval._usageType = texture.getUsageType(); + GPUKTXPayload gpuKeyval; + gpuKeyval._samplerDesc = texture.getSampler().getDesc(); + gpuKeyval._usage = texture.getUsage(); + gpuKeyval._usageType = texture.getUsageType(); + Byte keyvalPayload[GPUKTXPayload::SIZE]; - keyval.serialize(keyvalPayload); + gpuKeyval.serialize(keyvalPayload); ktx::KeyValues keyValues; keyValues.emplace_back(GPUKTXPayload::KEY, (uint32)GPUKTXPayload::SIZE, (ktx::Byte*) &keyvalPayload); + if (texture.getIrradiance()) { + IrradianceKTXPayload irradianceKeyval; + irradianceKeyval._irradianceSH = *texture.getIrradiance(); + + Byte irradianceKeyvalPayload[IrradianceKTXPayload::SIZE]; + irradianceKeyval.serialize(irradianceKeyvalPayload); + + keyValues.emplace_back(IrradianceKTXPayload::KEY, (uint32)IrradianceKTXPayload::SIZE, (ktx::Byte*) &irradianceKeyvalPayload); + } + auto hash = texture.sourceHash(); if (!hash.empty()) { // the sourceHash is an std::string in hex @@ -409,6 +475,12 @@ TexturePointer Texture::unserialize(const std::string& ktxfile, const ktx::KTXDe // Assing the mips availables texture->setStoredMipFormat(mipFormat); texture->setKtxBacking(ktxfile); + + IrradianceKTXPayload irradianceKtxKeyValue; + if (IrradianceKTXPayload::findInKeyValues(descriptor.keyValues, irradianceKtxKeyValue)) { + texture->overrideIrradiance(std::make_shared(irradianceKtxKeyValue._irradianceSH)); + } + return texture; }