decompiler: add texture merging feature (#3083)

This commit is contained in:
Tyler Wilding 2023-10-12 17:02:36 -06:00 committed by GitHub
parent 598ba1aaa3
commit 60eaac8051
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 47 additions and 0 deletions

View file

@ -99,6 +99,36 @@ void TextureDB::add_index_texture(u32 tpage,
}
}
void TextureDB::merge_textures(const fs::path& base_path) {
for (auto& tex : textures) {
fs::path full_path = base_path / tpage_names.at(tex.second.page) / (tex.second.name + ".png");
if (fs::exists(full_path)) {
lg::info("Merging {}", full_path.string().c_str());
int w, h;
auto merge_data = stbi_load(full_path.string().c_str(), &w, &h, 0, 4); // rgba channels
if (!merge_data) {
lg::warn("failed to load PNG file: {}", full_path.string().c_str());
continue;
} else if (w != tex.second.w || h != tex.second.h) {
lg::warn("merge texture does not match the same dimensions: {}, {} != {} || {} != {}",
full_path.string().c_str(), w, tex.second.w, h, tex.second.h);
stbi_image_free(merge_data);
continue;
}
// Merge any non-transparent pixels into the existing texture
for (int i = 0; i < w * h * 4; i += 4) {
const auto merge_pixel_a = merge_data[i + 3];
if (merge_pixel_a != 0) {
u32 merge_pixel;
memcpy(&merge_pixel, &merge_data[i], sizeof(u32));
tex.second.rgba_bytes.at(i / 4) = merge_pixel;
}
}
stbi_image_free(merge_data);
}
}
}
void TextureDB::replace_textures(const fs::path& path) {
fs::path base_path(path);
for (auto& tex : textures) {

View file

@ -55,6 +55,7 @@ struct TextureDB {
const std::string& tpage_name,
const std::vector<std::string>& level_names);
void merge_textures(const fs::path& base_path);
void replace_textures(const fs::path& path);
std::string generate_texture_dest_adjustment_table() const;

View file

@ -172,6 +172,15 @@ void decompile(const fs::path& iso_data_path, const std::string& data_subfolder)
file_util::create_dir_if_needed(textures_out);
file_util::write_text_file(textures_out / "tpage-dir.txt",
db.process_tpages(tex_db, textures_out, config));
// texture merges
// TODO - put all this stuff in somewhere common
auto texture_merge_path = file_util::get_jak_project_dir() / "game" / "assets" /
game_version_names[config.game_version] / "texture_merges";
if (fs::exists(texture_merge_path)) {
tex_db.merge_textures(texture_merge_path);
}
// texture replacements
auto replacements_path = file_util::get_jak_project_dir() / "texture_replacements";
if (fs::exists(replacements_path)) {

View file

@ -298,6 +298,13 @@ int main(int argc, char** argv) {
mem_log("After textures: {} MB", get_peak_rss() / (1024 * 1024));
// Merge textures before replacing them, in other words, replacements take priority
auto texture_merge_path = file_util::get_jak_project_dir() / "game" / "assets" /
game_version_names[config.game_version] / "texture_merges";
if (fs::exists(texture_merge_path)) {
tex_db.merge_textures(texture_merge_path);
}
auto replacements_path = file_util::get_jak_project_dir() / "texture_replacements";
if (fs::exists(replacements_path)) {
tex_db.replace_textures(replacements_path);