From c263bc21145c11de14acbfdd90bdedb9f83c00db Mon Sep 17 00:00:00 2001 From: Hat Kid <6624576+Hat-Kid@users.noreply.github.com> Date: Sat, 23 Nov 2024 14:32:55 +0100 Subject: [PATCH] custom models: envmap support (#3777) Custom models and model replacements now support environment mapping. Also fixed some cases in Jak 3 where tfrags had missing textures (defaulting to texture 0 from tpage 0, which in Jak 3 is the default eye texture) and replaced them with more suitable alternatives. Fixes #3776 https://github.com/user-attachments/assets/7c11b0de-b254-40cb-9719-11238dfb3d43 ![image](https://github.com/user-attachments/assets/4cc60b55-4965-4cb8-b29d-096560e7b3aa) ![image](https://github.com/user-attachments/assets/cb46d0d1-57d7-482c-b235-15d0e633f62c) --- common/util/gltf_util.cpp | 73 +++++++ common/util/gltf_util.h | 12 ++ decompiler/config/jak3/ntsc_v1/hacks.jsonc | 4 - decompiler/level_extractor/extract_tfrag.cpp | 14 ++ .../level_extractor/merc_replacement.cpp | 108 ++++++++-- .../opengl_renderer/foreground/Merc2.cpp | 13 +- goal_src/jak1/kernel/gkernel.gc | 5 + goalc/build_actor/common/MercExtract.cpp | 97 +++++++-- goalc/build_actor/jak1/build_actor.cpp | 194 ++++++------------ goalc/build_actor/jak1/build_actor.h | 1 + .../build_level/common/gltf_mesh_extract.cpp | 75 ------- 11 files changed, 350 insertions(+), 246 deletions(-) diff --git a/common/util/gltf_util.cpp b/common/util/gltf_util.cpp index 1d3115089f0..8c6c8895f3f 100644 --- a/common/util/gltf_util.cpp +++ b/common/util/gltf_util.cpp @@ -1,5 +1,7 @@ #include "gltf_util.h" +#include "image_resize.h" + #include "common/log/log.h" namespace gltf_util { @@ -424,6 +426,64 @@ int texture_pool_add_texture(TexturePool* pool, const tinygltf::Image& tex, int return idx; } +int texture_pool_add_envmap_control_texture(TexturePool* pool, + const tinygltf::Model& model, + int rgb_image_id, + int mr_image_id, + bool wrap_w, + bool wrap_h) { + const auto& existing = pool->envmap_textures_by_gltf_id.find({rgb_image_id, mr_image_id}); + if (existing != pool->envmap_textures_by_gltf_id.end()) { + lg::info("Reusing envmap textures"); + return existing->second; + } + const auto& rgb_tex = model.images.at(rgb_image_id); + const auto& mr_tex = model.images.at(mr_image_id); + lg::info("new envmap texture {} {}", rgb_tex.name, mr_tex.name); + ASSERT(rgb_tex.bits == 8); + ASSERT(rgb_tex.component == 4); + ASSERT(rgb_tex.pixel_type == TINYGLTF_TEXTURE_TYPE_UNSIGNED_BYTE); + + ASSERT(mr_tex.bits == 8); + ASSERT(mr_tex.pixel_type == TINYGLTF_TEXTURE_TYPE_UNSIGNED_BYTE); + ASSERT(mr_tex.component == 4); + + std::vector resized_mr_tex; + const u8* mr_src; + if (rgb_tex.width == mr_tex.width && rgb_tex.height == mr_tex.height) { + mr_src = mr_tex.image.data(); + } else { + resized_mr_tex.resize(rgb_tex.width * rgb_tex.height * 4); + resize_rgba_image(resized_mr_tex.data(), rgb_tex.width, rgb_tex.height, mr_tex.image.data(), + mr_tex.width, mr_tex.height, wrap_w, wrap_h); + mr_src = resized_mr_tex.data(); + } + + size_t idx = pool->textures_by_idx.size(); + pool->envmap_textures_by_gltf_id[{rgb_image_id, mr_image_id}] = idx; + auto& tt = pool->textures_by_idx.emplace_back(); + tt.w = rgb_tex.width; + tt.h = rgb_tex.height; + tt.debug_name = rgb_tex.name; + tt.debug_tpage_name = "custom-level"; + tt.load_to_pool = false; + tt.combo_id = 0; // doesn't matter, not a pool tex + tt.data.resize(tt.w * tt.h); + ASSERT(rgb_tex.image.size() >= tt.data.size()); + memcpy(tt.data.data(), rgb_tex.image.data(), tt.data.size() * 4); + + // adjust alpha from metallic channel + for (size_t i = 0; i < tt.data.size(); i++) { + u32 rgb = tt.data[i]; + u32 metal = mr_src[4 * i + 2] / 4; + rgb &= 0xff'ff'ff; + rgb |= (metal << 24); + tt.data[i] = rgb; + } + + return idx; +} + math::Matrix4f affine_translation(const math::Vector3f& translation) { math::Matrix4f result = math::Matrix4f::identity(); result(0, 3) = translation[0]; @@ -607,6 +667,19 @@ void setup_draw_mode_from_sampler(const tinygltf::Sampler& sampler, DrawMode* mo } } +EnvmapSettings envmap_settings_from_gltf(const tinygltf::Material& mat) { + EnvmapSettings settings; + + ASSERT(mat.extensions.contains("KHR_materials_specular")); + const auto& specular_extension = mat.extensions.at("KHR_materials_specular"); + ASSERT(specular_extension.Has("specularColorTexture")); + + auto& texture = specular_extension.Get("specularColorTexture"); + ASSERT(texture.Has("index")); + settings.texture_idx = texture.Get("index").Get(); + return settings; +} + std::optional find_single_skin(const tinygltf::Model& model, const std::vector& all_nodes) { std::optional skin_index; diff --git a/common/util/gltf_util.h b/common/util/gltf_util.h index 436508f3b38..d52f4780a22 100644 --- a/common/util/gltf_util.h +++ b/common/util/gltf_util.h @@ -65,6 +65,12 @@ struct TexturePool { }; int texture_pool_add_texture(TexturePool* pool, const tinygltf::Image& tex, int alpha_shift = 1); +int texture_pool_add_envmap_control_texture(TexturePool* pool, + const tinygltf::Model& model, + int rgb_image_id, + int mr_image_id, + bool wrap_w, + bool wrap_h); int texture_pool_debug_checker(TexturePool* pool); struct NodeWithTransform { @@ -114,6 +120,12 @@ std::vector flatten_nodes_from_all_scenes(const tinygltf::Mod void setup_alpha_from_material(const tinygltf::Material& material, DrawMode* mode); void setup_draw_mode_from_sampler(const tinygltf::Sampler& sampler, DrawMode* mode); +struct EnvmapSettings { + int texture_idx = -1; +}; + +EnvmapSettings envmap_settings_from_gltf(const tinygltf::Material& mat); + /*! * Find the index of the skin for this model. Returns nullopt if there is no skin, the index of the * skin if there is a single skin used, or fatal error if there are multiple skins. diff --git a/decompiler/config/jak3/ntsc_v1/hacks.jsonc b/decompiler/config/jak3/ntsc_v1/hacks.jsonc index 9707fcb79c3..de1f4f55401 100644 --- a/decompiler/config/jak3/ntsc_v1/hacks.jsonc +++ b/decompiler/config/jak3/ntsc_v1/hacks.jsonc @@ -735,10 +735,6 @@ // there are some missing textures. I don't know what the game actually does here. // the format for entries is [level, tpage, index] "missing_textures": [ - ["lfac", 0, 0], - ["ltow", 0, 0], - ["lcit", 0, 0], - ["pow", 0, 0], ["wasintro", 0, 0], ["lfacctyb", 0, 0], ["intpfall", 0, 0], diff --git a/decompiler/level_extractor/extract_tfrag.cpp b/decompiler/level_extractor/extract_tfrag.cpp index 0949db9fcc2..4002bf57a3c 100644 --- a/decompiler/level_extractor/extract_tfrag.cpp +++ b/decompiler/level_extractor/extract_tfrag.cpp @@ -2032,6 +2032,20 @@ s32 find_or_add_texture_to_level(u32 combo_tex_id, if (ok_to_miss) { // we're missing a texture, just use the first one. tex_it = tdb.textures.begin(); + // some tfrags in jak 3 are missing textures, so we use some suitable + // replacements instead of the default eye texture + static std::map per_level_tex_hacks = { + {"wasintro", "des-rock-01"}, + {"intpfall", "common-black"}, + {"powergd", "common-black"}, + }; + auto it = std::find_if(tdb.textures.begin(), tdb.textures.end(), + [&](const std::pair val) { + return val.second.name == per_level_tex_hacks[level_name]; + }); + if (it != tdb.textures.end()) { + tex_it = it; + } } else { ASSERT_MSG( false, diff --git a/decompiler/level_extractor/merc_replacement.cpp b/decompiler/level_extractor/merc_replacement.cpp index ee8129d9ec2..b8f3ccb5d45 100644 --- a/decompiler/level_extractor/merc_replacement.cpp +++ b/decompiler/level_extractor/merc_replacement.cpp @@ -3,6 +3,11 @@ using namespace gltf_util; namespace decompiler { + +bool material_has_envmap(const tinygltf::Material& mat) { + return mat.extensions.contains("KHR_materials_specular"); +} + void extract(const std::string& name, MercExtractData& out, const tinygltf::Model& model, @@ -16,6 +21,7 @@ void extract(const std::string& name, std::map draw_by_material; int mesh_count = 0; int prim_count = 0; + bool has_envmaps = false; for (const auto& n : all_nodes) { const auto& node = model.nodes[n.node_idx]; @@ -72,42 +78,108 @@ void extract(const std::string& name, } tfrag3::MercEffect e; + tfrag3::MercEffect envmap_eff; out.new_model.name = name; - out.new_model.max_bones = 120; + out.new_model.max_bones = 100; // idk out.new_model.max_draws = 200; - for (const auto& [mat_idx, d_] : draw_by_material) { - e.all_draws.push_back(d_); - auto& draw = e.all_draws.back(); - draw.mode = make_default_draw_mode(); + + auto process_normal_draw = [&](tfrag3::MercEffect& eff, int mat_idx, const tfrag3::MercDraw& d_) { + const auto& mat = model.materials[mat_idx]; + eff.all_draws.push_back(d_); + auto& draw = eff.all_draws.back(); + draw.mode = gltf_util::make_default_draw_mode(); if (mat_idx == -1) { - lg::warn("Draw had a material index of -1, using bogus texture."); + lg::warn("Draw had a material index of -1, using default texture."); draw.tree_tex_id = 0; - continue; + return; } - const auto& mat = model.materials[mat_idx]; int tex_idx = mat.pbrMetallicRoughness.baseColorTexture.index; if (tex_idx == -1) { - lg::warn("Material {} has no texture, using bogus texture.", mat.name); + lg::warn("Material {} has no texture, using default texture.", mat.name); draw.tree_tex_id = 0; - continue; + return; } const auto& tex = model.textures[tex_idx]; ASSERT(tex.sampler >= 0); ASSERT(tex.source >= 0); - setup_alpha_from_material(mat, &draw.mode); - setup_draw_mode_from_sampler(model.samplers.at(tex.sampler), &draw.mode); + gltf_util::setup_draw_mode_from_sampler(model.samplers.at(tex.sampler), &draw.mode); + gltf_util::setup_alpha_from_material(mat, &draw.mode); const auto& img = model.images[tex.source]; draw.tree_tex_id = tex_offset + texture_pool_add_texture(&out.tex_pool, img); + }; + + auto process_envmap_draw = [&](tfrag3::MercEffect& eff, int mat_idx, const tfrag3::MercDraw& d_) { + const auto& mat = model.materials[mat_idx]; + eff.all_draws.push_back(d_); + auto& draw = eff.all_draws.back(); + draw.mode = gltf_util::make_default_draw_mode(); + + if (mat_idx == -1) { + lg::warn("Envmap draw had a material index of -1, using default texture."); + draw.tree_tex_id = texture_pool_debug_checker(&out.tex_pool); + return; + } + int base_tex_idx = mat.pbrMetallicRoughness.baseColorTexture.index; + if (base_tex_idx == -1) { + lg::warn("Envmap material {} has no texture, using default texture.", mat.name); + draw.tree_tex_id = texture_pool_debug_checker(&out.tex_pool); + return; + } + + int roughness_tex_idx = mat.pbrMetallicRoughness.metallicRoughnessTexture.index; + ASSERT(roughness_tex_idx >= 0); + const auto& base_tex = model.textures[base_tex_idx]; + ASSERT(base_tex.sampler >= 0); + ASSERT(base_tex.source >= 0); + gltf_util::setup_draw_mode_from_sampler(model.samplers.at(base_tex.sampler), &draw.mode); + gltf_util::setup_alpha_from_material(mat, &draw.mode); + const auto& roughness_tex = model.textures.at(roughness_tex_idx); + ASSERT(roughness_tex.sampler >= 0); + ASSERT(roughness_tex.source >= 0); + + draw.tree_tex_id = + tex_offset + gltf_util::texture_pool_add_envmap_control_texture( + &out.tex_pool, model, base_tex.source, roughness_tex.source, + !draw.mode.get_clamp_s_enable(), !draw.mode.get_clamp_t_enable()); + + // now, setup envmap draw: + auto envmap_settings = gltf_util::envmap_settings_from_gltf(mat); + const auto& envmap_tex = model.textures[envmap_settings.texture_idx]; + ASSERT(envmap_tex.sampler >= 0); + ASSERT(envmap_tex.source >= 0); + auto env_mode = gltf_util::make_default_draw_mode(); + gltf_util::setup_draw_mode_from_sampler(model.samplers.at(envmap_tex.sampler), &env_mode); + eff.envmap_texture = tex_offset + gltf_util::texture_pool_add_texture( + &out.tex_pool, model.images[envmap_tex.source]); + env_mode.set_alpha_blend(DrawMode::AlphaBlend::SRC_0_DST_DST); + env_mode.enable_ab(); + eff.envmap_mode = env_mode; + }; + + for (const auto& [mat_idx, d_] : draw_by_material) { + const auto& mat = model.materials[mat_idx]; + if (!material_has_envmap(mat)) { + process_normal_draw(e, mat_idx, d_); + } else { + has_envmaps = true; + envmap_eff.has_envmap = true; + process_envmap_draw(envmap_eff, mat_idx, d_); + } + } + + lg::info("total of {} unique materials ({} normal, {} envmap)", + e.all_draws.size() + envmap_eff.all_draws.size(), e.all_draws.size(), + envmap_eff.all_draws.size()); + // in case a model only has envmap draws, we don't push the normal merc effect + if (!e.all_draws.empty()) { + out.new_model.effects.push_back(e); + } + if (has_envmaps) { + out.new_model.effects.push_back(envmap_eff); } - lg::info("total of {} unique materials", e.all_draws.size()); - e.has_mod_draw = false; - out.new_model.effects.push_back(e); - out.new_model.effects.push_back(e); - out.new_model.effects.push_back(e); - out.new_model.effects.push_back(e); lg::info("Merged {} meshes and {} prims into {} vertices", mesh_count, prim_count, out.new_vertices.size()); diff --git a/game/graphics/opengl_renderer/foreground/Merc2.cpp b/game/graphics/opengl_renderer/foreground/Merc2.cpp index 24322fc7488..e738448d3b2 100644 --- a/game/graphics/opengl_renderer/foreground/Merc2.cpp +++ b/game/graphics/opengl_renderer/foreground/Merc2.cpp @@ -542,10 +542,9 @@ void Merc2::handle_pc_model(const DmaTransfer& setup, bool is_custom_model = model->effects.at(0).all_draws.at(0).no_strip; u64 current_ignore_alpha_bits = flags->ignore_alpha_mask; // shader settings u64 current_effect_enable_bits = flags->enable_mask; // mask for game to disable an effect - bool model_uses_mod = - flags->bitflags & 1 && !is_custom_model; // if we should update vertices from game. + bool model_uses_mod = flags->bitflags & 1; // if we should update vertices from game. bool model_disables_fog = flags->bitflags & 2; - bool model_uses_pc_blerc = flags->bitflags & 4 && !is_custom_model; + bool model_uses_pc_blerc = flags->bitflags & 4; bool model_disables_envmap = flags->bitflags & 8; bool model_no_texture = flags->bitflags & 16; input_data += 32; @@ -569,9 +568,9 @@ void Merc2::handle_pc_model(const DmaTransfer& setup, // will hold opengl buffers for the updated vertices ModBuffers mod_opengl_buffers[kMaxEffect]; - if (model_uses_pc_blerc) { + if (model_uses_pc_blerc && !is_custom_model) { model_mod_blerc_draws(num_effects, model, lev, mod_opengl_buffers, blerc_weights, stats); - } else if (model_uses_mod) { // only if we've enabled, this path is slow. + } else if (model_uses_mod && !is_custom_model) { // only if we've enabled, this path is slow. model_mod_draws(num_effects, model, lev, input_data, setup, mod_opengl_buffers, stats); } @@ -651,7 +650,8 @@ void Merc2::handle_pc_model(const DmaTransfer& setup, auto& effect = model->effects[ei]; bool should_envmap = effect.has_envmap && !model_disables_envmap; - bool should_mod = (model_uses_pc_blerc || model_uses_mod) && effect.has_mod_draw; + bool should_mod = + !is_custom_model && ((model_uses_pc_blerc || model_uses_mod) && effect.has_mod_draw); if (should_mod) { // draw as two parts, fixed and mod @@ -1079,6 +1079,7 @@ Merc2::Draw* Merc2::try_alloc_envmap_draw(const tfrag3::MercDraw& mdraw, draw->first_bone = args.first_bone; draw->light_idx = args.lights; draw->num_triangles = mdraw.num_triangles; + draw->no_strip = mdraw.no_strip; for (int i = 0; i < 4; i++) { draw->fade[i] = args.fade[i]; } diff --git a/goal_src/jak1/kernel/gkernel.gc b/goal_src/jak1/kernel/gkernel.gc index e19f3ec7450..73a056e45a4 100644 --- a/goal_src/jak1/kernel/gkernel.gc +++ b/goal_src/jak1/kernel/gkernel.gc @@ -271,6 +271,11 @@ (define *pause-lock* #f) ;; set to #t when paused and doing a single frame advance with R2. +;; og:preserve-this added +(defmethod print ((this process-tree)) + (format #t "#<~A ~S @ #x~X>" (-> this type) (-> this name) this) + this) + (defmethod new process-tree ((allocation symbol) (type-to-make type) (name basic)) "Create a process-tree node" ;; allocate diff --git a/goalc/build_actor/common/MercExtract.cpp b/goalc/build_actor/common/MercExtract.cpp index 1257c334cc3..a04132223d5 100644 --- a/goalc/build_actor/common/MercExtract.cpp +++ b/goalc/build_actor/common/MercExtract.cpp @@ -1,9 +1,14 @@ #include "MercExtract.h" #include "common/log/log.h" +#include "common/util/gltf_util.h" #include "goalc/build_level/common/gltf_mesh_extract.h" +bool material_has_envmap(const tinygltf::Material& mat) { + return mat.extensions.contains("KHR_materials_specular"); +} + void extract(const std::string& name, MercExtractData& out, const tinygltf::Model& model, @@ -16,6 +21,7 @@ void extract(const std::string& name, std::map draw_by_material; int mesh_count = 0; int prim_count = 0; + bool has_envmaps = false; for (const auto& n : all_nodes) { const auto& node = model.nodes[n.node_idx]; @@ -84,25 +90,27 @@ void extract(const std::string& name, } tfrag3::MercEffect e; + tfrag3::MercEffect envmap_eff; out.new_model.name = name; - out.new_model.max_bones = 120; // idk + out.new_model.max_bones = 100; // idk out.new_model.max_draws = 200; - for (const auto& [mat_idx, d_] : draw_by_material) { - e.all_draws.push_back(d_); - auto& draw = e.all_draws.back(); + + auto process_normal_draw = [&](tfrag3::MercEffect& eff, int mat_idx, const tfrag3::MercDraw& d_) { + const auto& mat = model.materials[mat_idx]; + eff.all_draws.push_back(d_); + auto& draw = eff.all_draws.back(); draw.mode = gltf_util::make_default_draw_mode(); if (mat_idx == -1) { lg::warn("Draw had a material index of -1, using default texture."); draw.tree_tex_id = 0; - continue; + return; } - const auto& mat = model.materials[mat_idx]; int tex_idx = mat.pbrMetallicRoughness.baseColorTexture.index; if (tex_idx == -1) { lg::warn("Material {} has no texture, using default texture.", mat.name); draw.tree_tex_id = 0; - continue; + return; } const auto& tex = model.textures[tex_idx]; @@ -113,12 +121,77 @@ void extract(const std::string& name, const auto& img = model.images[tex.source]; draw.tree_tex_id = tex_offset + texture_pool_add_texture(&out.tex_pool, img); + }; + + auto process_envmap_draw = [&](tfrag3::MercEffect& eff, int mat_idx, const tfrag3::MercDraw& d_) { + const auto& mat = model.materials[mat_idx]; + eff.all_draws.push_back(d_); + auto& draw = eff.all_draws.back(); + draw.mode = gltf_util::make_default_draw_mode(); + + if (mat_idx == -1) { + lg::warn("Envmap draw had a material index of -1, using default texture."); + draw.tree_tex_id = texture_pool_debug_checker(&out.tex_pool); + return; + } + int base_tex_idx = mat.pbrMetallicRoughness.baseColorTexture.index; + if (base_tex_idx == -1) { + lg::warn("Envmap material {} has no texture, using default texture.", mat.name); + draw.tree_tex_id = texture_pool_debug_checker(&out.tex_pool); + return; + } + + int roughness_tex_idx = mat.pbrMetallicRoughness.metallicRoughnessTexture.index; + ASSERT(roughness_tex_idx >= 0); + const auto& base_tex = model.textures[base_tex_idx]; + ASSERT(base_tex.sampler >= 0); + ASSERT(base_tex.source >= 0); + gltf_util::setup_draw_mode_from_sampler(model.samplers.at(base_tex.sampler), &draw.mode); + gltf_util::setup_alpha_from_material(mat, &draw.mode); + const auto& roughness_tex = model.textures.at(roughness_tex_idx); + ASSERT(roughness_tex.sampler >= 0); + ASSERT(roughness_tex.source >= 0); + + draw.tree_tex_id = + tex_offset + gltf_util::texture_pool_add_envmap_control_texture( + &out.tex_pool, model, base_tex.source, roughness_tex.source, + !draw.mode.get_clamp_s_enable(), !draw.mode.get_clamp_t_enable()); + + // now, setup envmap draw: + auto envmap_settings = gltf_util::envmap_settings_from_gltf(mat); + const auto& envmap_tex = model.textures[envmap_settings.texture_idx]; + ASSERT(envmap_tex.sampler >= 0); + ASSERT(envmap_tex.source >= 0); + auto env_mode = gltf_util::make_default_draw_mode(); + gltf_util::setup_draw_mode_from_sampler(model.samplers.at(envmap_tex.sampler), &env_mode); + eff.envmap_texture = tex_offset + gltf_util::texture_pool_add_texture( + &out.tex_pool, model.images[envmap_tex.source]); + env_mode.set_alpha_blend(DrawMode::AlphaBlend::SRC_0_DST_DST); + env_mode.enable_ab(); + eff.envmap_mode = env_mode; + }; + + for (const auto& [mat_idx, d_] : draw_by_material) { + const auto& mat = model.materials[mat_idx]; + if (!material_has_envmap(mat)) { + process_normal_draw(e, mat_idx, d_); + } else { + has_envmaps = true; + envmap_eff.has_envmap = true; + process_envmap_draw(envmap_eff, mat_idx, d_); + } + } + + lg::info("total of {} unique materials ({} normal, {} envmap)", + e.all_draws.size() + envmap_eff.all_draws.size(), e.all_draws.size(), + envmap_eff.all_draws.size()); + // in case a model only has envmap draws, we don't push the normal merc effect + if (!e.all_draws.empty()) { + out.new_model.effects.push_back(e); + } + if (has_envmaps) { + out.new_model.effects.push_back(envmap_eff); } - lg::info("total of {} unique materials", e.all_draws.size()); - out.new_model.effects.push_back(e); - out.new_model.effects.push_back(e); - out.new_model.effects.push_back(e); - out.new_model.effects.push_back(e); lg::info("Merged {} meshes and {} prims into {} vertices", mesh_count, prim_count, out.new_vertices.size()); diff --git a/goalc/build_actor/jak1/build_actor.cpp b/goalc/build_actor/jak1/build_actor.cpp index 603f06505f9..d7180af5c42 100644 --- a/goalc/build_actor/jak1/build_actor.cpp +++ b/goalc/build_actor/jak1/build_actor.cpp @@ -376,107 +376,25 @@ size_t ArtJointAnim::generate(DataObjectGenerator& gen) const { static size_t gen_dummy_frag_geo(DataObjectGenerator& gen) { size_t result = gen.current_offset_bytes(); - // frag geo stolen from money-lod0 + // frag geo stolen from money-lod2 static std::vector words = { - 0xa4320c04, 0x8000026, 0x302a0000, 0x604, 0xa910, 0xac16, 0x100af1c, - 0xb23d, 0x100b585, 0x100b870, 0xbb76, 0xbe52, 0x80808080, 0x80808080, + 0x51180504, 0x1000013, 0x1b150000, 0x604, 0x5225, 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, - 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, - 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, - 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, - 0x80808080, 0x0, 0x0, 0x89b78086, 0xf1a910a, 0x3a4b7000, 0x5f818086, - 0xf1a1094, 0x29347014, 0x49648186, 0x91313, 0x4e5d8024, 0x354b8186, 0xf1a6416, - 0x3a497024, 0x40538186, 0x91919, 0x647b8034, 0x24348186, 0xf1a371c, 0x647f7034, - 0x495d8186, 0x91f1f, 0x7a9c8044, 0x35498086, 0xf1a2231, 0x8eb57044, 0x5f7b8186, - 0x92525, 0x83ad8054, 0x5f7f8186, 0xf1a2828, 0x9fcc7054, 0x759c8186, 0x92b2b, - 0x7aa38064, 0x1c257f86, 0x273b2e2e, 0x94b86040, 0xe198186, 0x2737d034, 0x71936038, - 0xe188186, 0x273bcd3a, 0x57676030, 0x1c2a8186, 0x2737613d, 0x34456028, 0xe1b8086, - 0x485d40c7, 0x2e3c5028, 0x293c8186, 0x485d5b43, 0x131a5020, 0x26398186, 0x6e804646, - 0xf164020, 0x4b688186, 0x6e805549, 0x34018, 0x4c688186, 0x979f4c4c, 0x5073018, - 0x72978086, 0x979f4fc1, 0x5073010, 0x73988086, 0x6e807352, 0x34010, 0x4c698186, - 0x485d6d58, 0x5085018, 0x2f488086, 0x273b5e67, 0x21256020, 0x526d8186, 0x2737a66a, - 0x13196018, 0x72988186, 0x485da070, 0x5085010, 0x98c78086, 0x6e80767f, 0xf164008, - 0x95c48186, 0x979fc479, 0x13193008, 0xb0e68186, 0x979f7c7c, 0x2e3b3000, 0xb4ea8186, - 0x6e808282, 0x2b394000, 0x95c48186, 0x485d9d85, 0x131b5008, 0xb0e68186, 0x485d8888, - 0x2e3c5000, 0x8fbb8186, 0x2737978b, 0x212a6008, 0xa2db8186, 0x273b8e8e, 0x34486000, - 0x6c998086, 0x273b9aa3, 0x13186010, 0x87f86, 0x485dcaca, 0x51685030, 0x75a37f86, - 0x90707, 0x4e648000, 0x5f858186, 0x90d0d, 0x45538014, 0x0, 0x0, - 0xcb01005f, 0xcb00fffa, 0xcb010064, 0x5101e01, 0x0, 0x0, 0x306, - 0x60030000, 0x120, 0x0, 0x1cf02c14, 0x2008044, 0x0, 0x0, - 0x34, 0x81010000, 0x0, 0x0, 0x8, 0x6d100000, 0x44, - 0x80, 0x42, 0x30000, 0x86321604, 0x400001c, 0x2422440e, 0x4, - 0x1004f28, 0x1008b4c, 0xb225, 0xca4c, 0x1000128, 0x1000422, 0x1000a2e, - 0x10064ca, 0x6a34, 0x1006d2e, 0x70ca, 0x1007340, 0x7946, 0x7f4c, - 0x100884c, 0x8e4f, 0x9479, 0x9a7c, 0x80808080, 0x80808080, 0x80808080, - 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, - 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, - 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, - 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x0, 0x0, 0x131a8086, - 0x215d0d9d, 0x87c45040, 0x38186, 0x4780a313, 0x65984038, 0x38186, 0x47806116, - 0x3d684030, 0x5078186, 0x709fa919, 0x3e693030, 0x13198186, 0x709f5b1c, 0x1b3c3028, - 0x21208186, 0x96bbaf1f, 0x21452028, 0x34428186, 0x96bf5522, 0xe242020, 0x3a408086, - 0xb6da252e, 0x27411024, 0x647f8186, 0xb6da4628, 0x16261014, 0x647a8186, 0xcbf1402b, - 0x32450014, 0x4e528086, 0xcbf1313a, 0x3b5b0024, 0x29268086, 0xb6da34b5, 0x51811034, - 0x45458186, 0xcbf13737, 0x51860034, 0x64808186, 0xd3ff3d3d, 0x51800040, 0x7aa58186, - 0xcbf14343, 0x3b520000, 0x8ebf8186, 0xb6dac749, 0x27401000, 0x71948186, 0x96bf854c, - 0x132010, 0x57668186, 0x96bb8252, 0x122018, 0x2e3b8186, 0x709f7c58, 0x1a3020, - 0xf168186, 0x4780765e, 0x18394028, 0x94bb8086, 0x96bb91c4, 0xe202008, 0xa7dc8086, - 0x96bf97c1, 0x21422000, 0xf167f86, 0x4780a0a0, 0x8ac74040, 0x5078186, 0x709fbea6, - 0x64983038, 0x13138186, 0x96bfb8ac, 0x446c2030, 0x13128186, 0x96bbbbbb, 0x5e9a2038, - 0x34458186, 0x370707, 0x94d66048, 0x5088186, 0x215d6710, 0x64975038, 0xcb010064, - 0xcb00ffd3, 0xcb010051, 0x5021000, 0x4088003, 0x10306060, 0x3, 0x0, - 0x8d301104, 0x300001f, 0x2624430a, 0x4, 0x910a, 0x100a928, 0xc42b, - 0x1006aa0, 0x70a6, 0x73bb, 0x9a07, 0xa00d, 0x100a3a0, 0x100a6bb, - 0xac34, 0xb237, 0xb83d, 0x80808080, 0x80808080, 0x80808080, 0x80808080, - 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, - 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, - 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, - 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x8ccc8186, - 0xf1a4c07, 0x16817074, 0x7bb58186, 0xf1a550a, 0x40b77064, 0x94d68186, 0x2737460d, - 0x46bb6068, 0x81b88186, 0x273b8e10, 0x59db6060, 0x87c48186, 0x485d4013, 0x67e65060, - 0x64978186, 0x485d8816, 0x75f85058, 0x65988186, 0x6e803a19, 0x7afd4058, 0x3d688186, - 0x6e80821c, 0x7afd4050, 0x3e698186, 0x979f341f, 0x75f93050, 0x1b3c8186, 0x979f7c22, - 0x67e73048, 0x21458086, 0xbdbb252e, 0x59e02048, 0xe248086, 0xbdbf2876, 0x46be2040, - 0x27418186, 0xdddaaf2b, 0x40c01044, 0x446c8186, 0xbdbfc731, 0x67ed2050, 0x64988186, - 0x979f3737, 0x75f93058, 0x8ac78186, 0x6e803d3d, 0x6bea4060, 0xa2e58186, 0x485d4343, - 0x4cc45068, 0xa2e88186, 0x273b4949, 0x23996070, 0x679c7f86, 0x95252, 0x2ca38064, - 0x517f8086, 0xf1a5894, 0x51cc7054, 0x5e938186, 0x27378b5b, 0x67e76058, 0x44678086, - 0x273b5e97, 0x67e86050, 0x3e688186, 0x485d8561, 0x75f85050, 0x1b3c8186, 0x485d9d64, - 0x67e55048, 0x18398186, 0x6e807f67, 0x6bea4048, 0x1a8186, 0x979f796d, 0x4cc53040, - 0x3b5b8086, 0xf2f1b5be, 0x2cae0044, 0x51868186, 0xf2f1bbbb, 0x35bb0054, 0x51818186, - 0xdddac1c1, 0x51da1054, 0x67a37f86, 0x90101, 0x648080, 0x70ad7f86, 0x94f04, - 0x16858074, 0x0, 0x0, 0x0, 0xcb010051, 0xcb00fffa, 0xcb010016, - 0x5021000, 0xc008003, 0x81860080, 0x0, 0x0, 0x92351604, 0x300001f, - 0x2826450f, 0x4, 0xac31, 0x100af5e, 0x100c449, 0xa01, 0x1000d07, - 0x6143, 0x100643d, 0x10079c1, 0x8537, 0x883d, 0x1008b07, 0x1008e49, - 0x100b243, 0xb549, 0x100b837, 0xbe31, 0xc1c1, 0xc7bb, 0x80808080, - 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, - 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, - 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, - 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, - 0x80808080, 0x80808080, 0x0, 0x0, 0x0, 0x808186, 0x707, - 0x39800040, 0x2ab78186, 0x141a1010, 0xf4b7080, 0x51e78186, 0x2c379113, 0x2c6d6078, - 0x43db8186, 0x2c3b1616, 0x9486080, 0x5ff88186, 0x4d5d9719, 0x26695078, 0x51e68186, - 0x4d5d1c1c, 0x33c5080, 0x64fd8186, 0x73809d1f, 0x25684078, 0x55ea8186, 0x73802222, - 0x394080, 0x5ff98186, 0x9c9fa325, 0x26683078, 0x51e68186, 0x9c9f2828, 0x33b3080, - 0x51ee8186, 0xc2bba92b, 0x2c662078, 0x43dc8186, 0xc2bf2e2e, 0x9422080, 0x3bda8186, - 0xe2da4631, 0x397f1074, 0x2abf8186, 0xe2da3434, 0xf401080, 0x1fbb8086, 0xf7f13740, - 0x397a0074, 0x16a58186, 0xf7f13a3a, 0x23520080, 0x808186, 0xffffcd3d, 0x39800040, - 0x16ae8186, 0xf7f1ca43, 0x4fa50064, 0x2ac08186, 0xe2da7649, 0x63bf1064, 0x51ed8186, - 0xc2bfa64c, 0x46942070, 0x43e08186, 0xc2bb734f, 0x69bb2068, 0x5ff98186, 0x9c9fa052, - 0x4c973070, 0x51e78186, 0x9c9f6d55, 0x6fc43068, 0x64fd8186, 0x73809a58, 0x4d984070, - 0x55ea8186, 0x7380675b, 0x72c74068, 0x5ff88186, 0x4d5d945e, 0x4c985070, 0x36c58186, - 0x9c9f826a, 0x8ae63060, 0x30be8186, 0xc2bf7c70, 0x7cdc2060, 0xd9a8086, 0xc2bb7fbb, - 0x8aee2058, 0x16a37f86, 0x5090101, 0x23640000, 0x1fad7f86, 0x5090404, 0x39850074, - 0x0, 0x0, 0x0, 0xcb010000, 0xcb00ffff, 0xcb010039, 0x5021000, - 0x20001b, 0x6c00c102, 0x2, 0x0, 0x210f0904, 0x6, 0xb090b05, - 0x4, 0x101, 0x707, 0x1307, 0x1c04, 0x1f07, 0x80808080, - 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x80808080, 0x0, 0x538186, - 0x90d0d, 0x1f7b0034, 0x95d7f86, 0x91010, 0x359c0044, 0x1f7b8186, 0x91616, - 0x3ead0054, 0x359c8186, 0x91919, 0x35a30064, 0x1f857f86, 0x90404, 0x530014, - 0x9648186, 0x90a0a, 0x95d0024, 0x0, 0x0, 0xcb01001f, 0xcb00fffa, - 0xcb01001f, 0x1021000, 0x223, 0x0, 0x0, 0x0}; + 0x80808080, 0x80808080, 0x80808080, 0xb4e48086, 0x757d3a0a, 0x1e324000, 0x1e328186, + 0x757d3410, 0x1c4020, 0x432e8186, 0x251313, 0x71a28044, 0x1c8186, 0x757d2e16, + 0x96ce4040, 0x719b8186, 0x151919, 0x71c08064, 0x96ce8186, 0x757d281c, 0xb4e44060, + 0x71d28186, 0x251f1f, 0x435e8080, 0xb4e48186, 0x757d4322, 0x1e324080, 0x71cc7f86, + 0xffdb4025, 0x71ad0064, 0x435c8186, 0xffea582b, 0x71bc0044, 0x43348186, 0xffdb5b31, + 0x43530024, 0x71a48086, 0xffea3755, 0x43440000, 0x71a47f86, 0xffea3d3d, 0x43440080, + 0x432e7f86, 0x254646, 0x71a20044, 0x43657f86, 0x154949, 0x43400024, 0x719b8186, + 0x154c4c, 0x71c00064, 0x71d28186, 0x254f4f, 0x435e0000, 0x71d27f86, 0x250707, + 0x435e8000, 0x43658186, 0x150d0d, 0x43408024, 0x0, 0x0, 0x0, + 0xcb01005a, 0xcb00fffa, 0xcb01005a, 0x2101e01, 0x0, 0x0, 0x306, + 0x4030000, 0x120, 0x0, 0x1cf02c14, 0x66c801d, 0x0, 0x0, + 0x34, 0x0, 0x0, 0x0, 0x8, 0x0, 0x44, + 0x80, 0x42, 0x0, + }; for (auto& word : words) { gen.add_word(word); } @@ -485,12 +403,8 @@ static size_t gen_dummy_frag_geo(DataObjectGenerator& gen) { size_t gen_dummy_frag_ctrl(DataObjectGenerator& gen) { size_t result = gen.current_offset_bytes(); - gen.add_word(0x1067232); - gen.add_word(0x54320603); - gen.add_word(0x5d300002); - gen.add_word(0x5d350002); - gen.add_word(0x120f0002); - gen.add_word(0x2); + gen.add_word(0x1063918); + gen.add_word(0x603); gen.add_word(0x0); gen.add_word(0x0); return result; @@ -501,11 +415,11 @@ size_t gen_dummy_frag_ctrl_for_uploads(DataObjectGenerator& gen, int n) { std::vector packed_frag_ctrls; - // this is still a bit of a hack - the dummy_frag_ctrl above has 8 fragments, so we need to + // this is still a bit of a hack - the dummy_frag_ctrl above has 4 fragments, so we need to // provide fragment controls for each. The PC merc renderer will de-duplicate bone uploads over // all effects and fragments, so we just need to have a single fragment that asks for all bones, // and everything will work out. - for (int k = 0; k < 8; k++) { + for (int k = 0; k < 4; k++) { packed_frag_ctrls.push_back(0); packed_frag_ctrls.push_back(0); packed_frag_ctrls.push_back(0); @@ -544,6 +458,32 @@ size_t gen_dummy_extra_info(DataObjectGenerator& gen) { return result; } +void generate_merc_effects(DataObjectGenerator& gen, int effect_count, int joints) { + struct EffectLocs { + size_t frag_geo; + size_t frag_ctrl; + size_t extra_info; + }; + std::vector locs; + for (int i = 0; i < effect_count; i++) { + EffectLocs loc{}; + loc.frag_geo = gen.add_word(0); // 112-140 (effect) + loc.frag_ctrl = gen.add_word(0); // 116 (frag-ctrl) + gen.add_word(0x0); // 120 (blend-data) + gen.add_word(0x0); // 124 (blend-ctrl) + gen.add_word(0x10000); // 128 + gen.add_word(0x140000); // 132 + gen.add_word(0x100001d); // 136 + loc.extra_info = gen.add_word(0); // 140 (extra-info) + locs.push_back(loc); + } + for (auto& loc : locs) { + gen.link_word_to_byte(loc.extra_info, gen_dummy_extra_info(gen)); + gen.link_word_to_byte(loc.frag_ctrl, gen_dummy_frag_ctrl_for_uploads(gen, joints + 3)); + gen.link_word_to_byte(loc.frag_geo, gen_dummy_frag_geo(gen)); + } +} + size_t generate_dummy_merc_ctrl(DataObjectGenerator& gen, const ArtGroup& ag) { gen.align_to_basic(); gen.add_type_tag("merc-ctrl"); @@ -557,37 +497,28 @@ size_t generate_dummy_merc_ctrl(DataObjectGenerator& gen, const ArtGroup& ag) { gen.add_word(joints); // 20 (num-joints) gen.add_word(0x0); // 24 (pad) gen.add_word(0x0); // 28 (pad) - gen.add_word(0x4188ee86); // 32-112 (xyz-scale) + gen.add_word(0x4181b897); // 32-112 (xyz-scale) gen.add_word(0xc780ff80); // 36 (st-magic) gen.add_word(0x40798000); // 40 (st-out-a) gen.add_word(0x40eb4000); // 44 (st-out-b) gen.add_word(0x4780ff80); // 48 (st-vif-add) gen.add_word(0x50000); // 52 ((st-int-off << 16) + st-int-scale) - gen.add_word(0x1); // 56 (effect-count) + gen.add_word(ag.merc_effect_count); // 56 (effect-count) gen.add_word(0x0); // 60 (blend-target-count) - gen.add_word(0xe00005); // 64 ((fragment-count << 16) + tri-count) - gen.add_word(0x860101); // 68 - gen.add_word(0x86011b); // 72 - gen.add_word(0x0); // 76 - gen.add_word(0x0); // 80 - gen.add_word(0x120101); // 84 - gen.add_word(0x83002c); // 88 - gen.add_word(0x3e780184); // 92 - gen.add_word(0x0); // 96 - gen.add_word(0x0); // 100 - gen.add_word(0x0); // 104 - gen.add_word(0x0); // 108 - auto frag_geo_slot = gen.add_word(0); // 112-140 (effect) - auto frag_ctrl_slot = gen.add_word(0); // 116 (frag-ctrl) - gen.add_word(0x0); // 120 (blend-data) - gen.add_word(0x0); // 124 (blend-ctrl) - gen.add_word(0x50000); // 128 - gen.add_word(0xe00000); // 132 - gen.add_word(0x100011b); // 136 - auto extra_info_slot = gen.add_word(0); // 140 (extra-info) - gen.link_word_to_byte(extra_info_slot, gen_dummy_extra_info(gen)); - gen.link_word_to_byte(frag_ctrl_slot, gen_dummy_frag_ctrl_for_uploads(gen, joints + 3)); - gen.link_word_to_byte(frag_geo_slot, gen_dummy_frag_geo(gen)); + gen.add_word((0x14 * ag.merc_effect_count << 16) + + ag.merc_effect_count); // 64 ((fragment-count << 16) + tri-count) + gen.add_word(0x130101); // 68 + gen.add_word(0x13001d); // 72 + gen.add_word(0x0); // 76 + gen.add_word(0x0); // 80 + gen.add_word(0x10101); // 84 + gen.add_word(0x130000); // 88 + gen.add_word(0x3f319ca9); // 92 + gen.add_word(0x0); // 96 + gen.add_word(0x0); // 100 + gen.add_word(0x0); // 104 + gen.add_word(0x0); // 108 + generate_merc_effects(gen, ag.merc_effect_count, joints); return result; } @@ -811,6 +742,7 @@ bool run_build_actor(const std::string& mdl_name, std::vector joints; MercExtractData extract_data; extract("test", extract_data, model, all_nodes, 0, 0, 0); + ag.merc_effect_count = extract_data.new_model.effects.size(); // MercSwapData out; // merc_convert(out, extract_data); // Set up joints: diff --git a/goalc/build_actor/jak1/build_actor.h b/goalc/build_actor/jak1/build_actor.h index 3150d5fb995..ccb347cecc5 100644 --- a/goalc/build_actor/jak1/build_actor.h +++ b/goalc/build_actor/jak1/build_actor.h @@ -207,6 +207,7 @@ struct ArtGroup : Art { FileInfo info; std::vector> elts; std::map joint_map; + int merc_effect_count; explicit ArtGroup(const std::string& file_name) { info.file_type = "art-group"; diff --git a/goalc/build_level/common/gltf_mesh_extract.cpp b/goalc/build_level/common/gltf_mesh_extract.cpp index 3e4d0efa787..3d84f74fda2 100644 --- a/goalc/build_level/common/gltf_mesh_extract.cpp +++ b/goalc/build_level/common/gltf_mesh_extract.cpp @@ -87,23 +87,6 @@ bool prim_needs_tie(const tinygltf::Model& model, const tinygltf::Primitive& pri return false; } -struct EnvmapSettings { - int texture_idx = -1; -}; - -EnvmapSettings envmap_settings_from_gltf(const tinygltf::Material& mat) { - EnvmapSettings settings; - - ASSERT(mat.extensions.contains("KHR_materials_specular")); - const auto& specular_extension = mat.extensions.at("KHR_materials_specular"); - ASSERT(specular_extension.Has("specularColorTexture")); - - auto& texture = specular_extension.Get("specularColorTexture"); - ASSERT(texture.Has("index")); - settings.texture_idx = texture.Get("index").Get(); - return settings; -} - void extract(const Input& in, TfragOutput& out, const tinygltf::Model& model, @@ -260,64 +243,6 @@ void add_to_packed_verts(std::vector* out, } } -int texture_pool_add_envmap_control_texture(TexturePool* pool, - const tinygltf::Model& model, - int rgb_image_id, - int mr_image_id, - bool wrap_w, - bool wrap_h) { - const auto& existing = pool->envmap_textures_by_gltf_id.find({rgb_image_id, mr_image_id}); - if (existing != pool->envmap_textures_by_gltf_id.end()) { - lg::info("Reusing envmap textures"); - return existing->second; - } - const auto& rgb_tex = model.images.at(rgb_image_id); - const auto& mr_tex = model.images.at(mr_image_id); - lg::info("new envmap texture {} {}", rgb_tex.name, mr_tex.name); - ASSERT(rgb_tex.bits == 8); - ASSERT(rgb_tex.component == 4); - ASSERT(rgb_tex.pixel_type == TINYGLTF_TEXTURE_TYPE_UNSIGNED_BYTE); - - ASSERT(mr_tex.bits == 8); - ASSERT(mr_tex.pixel_type == TINYGLTF_TEXTURE_TYPE_UNSIGNED_BYTE); - ASSERT(mr_tex.component == 4); - - std::vector resized_mr_tex; - const u8* mr_src; - if (rgb_tex.width == mr_tex.width && rgb_tex.height == mr_tex.height) { - mr_src = mr_tex.image.data(); - } else { - resized_mr_tex.resize(rgb_tex.width * rgb_tex.height * 4); - resize_rgba_image(resized_mr_tex.data(), rgb_tex.width, rgb_tex.height, mr_tex.image.data(), - mr_tex.width, mr_tex.height, wrap_w, wrap_h); - mr_src = resized_mr_tex.data(); - } - - size_t idx = pool->textures_by_idx.size(); - pool->envmap_textures_by_gltf_id[{rgb_image_id, mr_image_id}] = idx; - auto& tt = pool->textures_by_idx.emplace_back(); - tt.w = rgb_tex.width; - tt.h = rgb_tex.height; - tt.debug_name = rgb_tex.name; - tt.debug_tpage_name = "custom-level"; - tt.load_to_pool = false; - tt.combo_id = 0; // doesn't matter, not a pool tex - tt.data.resize(tt.w * tt.h); - ASSERT(rgb_tex.image.size() >= tt.data.size()); - memcpy(tt.data.data(), rgb_tex.image.data(), tt.data.size() * 4); - - // adjust alpha from metallic channel - for (size_t i = 0; i < tt.data.size(); i++) { - u32 rgb = tt.data[i]; - u32 metal = mr_src[4 * i + 2] / 4; - rgb &= 0xff'ff'ff; - rgb |= (metal << 24); - tt.data[i] = rgb; - } - - return idx; -} - void extract(const Input& in, TieOutput& out, const tinygltf::Model& model,