2
0
mirror of https://github.com/Laupetin/OpenAssetTools.git synced 2026-07-03 22:30:07 +00:00

fix: t6 modman textures (#849)

* feat: dynamically decompress bc5 textures for modman

* chore: restructure image format class

* chore: keep dds file conversions

* chore: convert all kinds of webgl unsupported formats

* chore: add decompressors for remaining formats

* chore: always set full alpha if available on bc4 and bc5 decompression
This commit is contained in:
Jan
2026-06-22 07:02:35 +02:00
committed by GitHub
parent 087ce0c208
commit 255c424aac
28 changed files with 2373 additions and 237 deletions
+50 -4
View File
@@ -2,10 +2,11 @@
#include "Context/ModManContext.h"
#include "Game/CommonAsset.h"
#include "Image/Compression/ImageDecompressor.h"
#include "Image/DdsWriter.h"
#include "Image/ImageToCommonConverter.h"
#include "Image/TextureConverter.h"
#include "Pool/XAssetInfo.h"
#include "SearchPath/SearchPaths.h"
#include "Utils/Logging/Log.h"
#include "Utils/StringUtils.h"
@@ -44,6 +45,26 @@ namespace
return false;
}
std::optional<ImageFormatId> NeedsConversionToWebGlSupportedFormat(const ImageFormatId imageFormatId)
{
static std::unordered_map<ImageFormatId, ImageFormatId> unsupportedFormatMap{
{ImageFormatId::BC4, ImageFormatId::B8_G8_R8 },
{ImageFormatId::BC5, ImageFormatId::B8_G8_R8 },
{ImageFormatId::B8_G8_R8_X8, ImageFormatId::B8_G8_R8 },
{ImageFormatId::R8_G8_B8, ImageFormatId::B8_G8_R8 },
{ImageFormatId::R8_G8_B8_A8, ImageFormatId::B8_G8_R8_A8},
{ImageFormatId::A8, ImageFormatId::B8_G8_R8 },
{ImageFormatId::R8, ImageFormatId::B8_G8_R8 },
{ImageFormatId::R8_A8, ImageFormatId::B8_G8_R8 },
};
const auto entry = unsupportedFormatMap.find(imageFormatId);
if (entry != unsupportedFormatMap.end())
return entry->second;
return std::nullopt;
}
void ImageDds(const webwindowed::dynamic_asset_request& request, webwindowed::dynamic_asset_response& response)
{
const auto imageName = request.get_query("name");
@@ -68,8 +89,8 @@ namespace
assert(zone);
const auto gameName = GameId_Names[std::to_underlying(zone->m_game_id)];
const auto converter = ToCommonConverter::GetForGame(zone->m_game_id);
if (!converter)
const auto toCommonConverter = ToCommonConverter::GetForGame(zone->m_game_id);
if (!toCommonConverter)
{
con::error("No image converter for game {}", gameName);
response.send_response(500);
@@ -79,7 +100,7 @@ namespace
std::unique_ptr<Texture> texture;
{
const auto searchPaths = ModManContext::Get().m_fast_file.GetSearchPaths();
texture = converter->Convert(*image, searchPaths.Data());
texture = toCommonConverter->Convert(*image, searchPaths.Data());
if (!texture)
{
con::warn("Failed to convert image {} of zone {}", *imageName, *zoneName);
@@ -88,6 +109,31 @@ namespace
}
}
const auto* originalTextureFormat = texture->GetFormat();
const auto originalTextureFormatId = originalTextureFormat->GetId();
const auto targetFormatId = NeedsConversionToWebGlSupportedFormat(originalTextureFormatId);
if (targetFormatId)
{
const auto* targetFormat = ImageFormat::GetImageFormatById(*targetFormatId);
if (originalTextureFormat->GetType() == ImageFormatType::BLOCK_COMPRESSED)
{
auto* textureDecompressor = ImageDecompressor::GetDecompressorForFormat(originalTextureFormatId);
assert(textureDecompressor);
if (textureDecompressor)
texture = textureDecompressor->Decompress(*texture, targetFormat);
}
else
{
TextureConverter converter(texture.get(), targetFormat);
auto newTexture = converter.Convert();
assert(newTexture);
if (newTexture)
texture = std::move(newTexture);
}
}
std::ostringstream ss;
DdsWriter output;
output.DumpImage(ss, texture.get());