Skip to content

Commit

Permalink
[jak3] Support texture anim in TIE (#3734)
Browse files Browse the repository at this point in the history
Support animated textures in TIE. Apparently this is also used in jak 2
for robotank and we never noticed??


https://github.com/user-attachments/assets/bfa45a1a-4a96-4b25-817a-4327afcc7c98

Co-authored-by: water111 <[email protected]>
  • Loading branch information
water111 and water111 authored Oct 26, 2024
1 parent 510b231 commit 5bc61c5
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 24 deletions.
4 changes: 2 additions & 2 deletions common/custom_data/Tfrag3Data.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ namespace tfrag3 {
// - if changing any large things (vertices, vis, bvh, colors, textures) update get_memory_usage
// - if adding a new category to the memory usage, update extract_level to print it.

constexpr int TFRAG3_VERSION = 42;
constexpr int TFRAG3_VERSION = 43;

enum MemoryUsageCategory {
TEXTURE,
Expand Down Expand Up @@ -241,7 +241,7 @@ struct ShrubDraw {

struct InstancedStripDraw {
DrawMode mode; // the OpenGL draw settings.
u32 tree_tex_id = 0; // the texture that should be bound for the draw
s32 tree_tex_id = 0; // the texture that should be bound for the draw

// the list of vertices in the draw. This includes the restart code of UINT32_MAX that OpenGL
// will use to start a new strip.
Expand Down
26 changes: 16 additions & 10 deletions decompiler/level_extractor/extract_tie.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2339,7 +2339,7 @@ TieCategoryInfo get_jak1_tie_category(u32 flags) {
return result;
}

u32 get_or_add_texture(u32 combo_tex, tfrag3::Level& lev, const TextureDB& tdb) {
s32 get_or_add_texture(u32 combo_tex, tfrag3::Level& lev, const TextureDB& tdb) {
if (combo_tex == 0) {
// untextured
combo_tex = (((u32)TextureDB::kPlaceholderWhiteTexturePage) << 16) |
Expand All @@ -2348,15 +2348,15 @@ u32 get_or_add_texture(u32 combo_tex, tfrag3::Level& lev, const TextureDB& tdb)

// try looking it up in the existing textures that we have in the C++ renderer data.
// (this is shared with tfrag)
u32 idx_in_lev_data = UINT32_MAX;
s32 idx_in_lev_data = INT32_MAX;
for (u32 i = 0; i < lev.textures.size(); i++) {
if (lev.textures[i].combo_id == combo_tex) {
idx_in_lev_data = i;
break;
}
}

if (idx_in_lev_data == UINT32_MAX) {
if (idx_in_lev_data == INT32_MAX) {
// didn't find it, have to add a new one texture.
auto tex_it = tdb.textures.find(combo_tex);
if (tex_it == tdb.textures.end()) {
Expand All @@ -2378,14 +2378,20 @@ u32 get_or_add_texture(u32 combo_tex, tfrag3::Level& lev, const TextureDB& tdb)
new_tex.debug_tpage_name = tdb.tpage_names.at(tex_it->second.page);
new_tex.data = tex_it->second.rgba_bytes;
}
const auto& level_tex = lev.textures.at(idx_in_lev_data);
const auto& it = tdb.animated_tex_output_to_anim_slot.find(level_tex.debug_name);
if (it != tdb.animated_tex_output_to_anim_slot.end()) {
// lg::warn("TIE animated texture: {}", level_tex.debug_name);
return -int(it->second) - 1;
}
return idx_in_lev_data;
}

void handle_wind_draw_for_strip(
tfrag3::TieTree& tree,
std::unordered_map<u32, std::vector<u32>>& wind_draws_by_tex,
std::unordered_map<s32, std::vector<u32>>& wind_draws_by_tex,
const std::vector<std::vector<std::pair<int, int>>>& packed_vert_indices,
u32 idx_in_lev_data,
s32 idx_in_lev_data,
DrawMode mode,
const TieStrip& strip,
const TieInstanceInfo& inst,
Expand Down Expand Up @@ -2452,7 +2458,7 @@ void handle_wind_draw_for_strip(
}

void handle_draw_for_strip(tfrag3::TieTree& tree,
std::unordered_map<u32, std::vector<u32>>& static_draws_by_tex,
std::unordered_map<s32, std::vector<u32>>& static_draws_by_tex,
std::vector<tfrag3::StripDraw>& category_draws,
const std::vector<std::vector<std::pair<int, int>>>& packed_vert_indices,
DrawMode mode,
Expand Down Expand Up @@ -2542,8 +2548,8 @@ void add_vertices_and_static_draw(tfrag3::TieTree& tree,
GameVersion version) {
// our current approach for static draws is just to flatten to giant mesh, except for wind stuff.
// this map sorts these two types of draws by texture.
std::unordered_map<u32, std::vector<u32>> static_draws_by_tex;
std::unordered_map<u32, std::vector<u32>> wind_draws_by_tex;
std::unordered_map<s32, std::vector<u32>> static_draws_by_tex;
std::unordered_map<s32, std::vector<u32>> wind_draws_by_tex;

std::array<std::vector<tfrag3::StripDraw>, tfrag3::kNumTieCategories> draws_by_category;

Expand Down Expand Up @@ -2632,7 +2638,7 @@ void add_vertices_and_static_draw(tfrag3::TieTree& tree,
for (size_t strip_idx = 0; strip_idx < frag.strips.size(); strip_idx++) {
auto& strip = frag.strips[strip_idx];

u32 idx_in_lev_data = get_or_add_texture(strip.adgif.combo_tex, lev, tdb);
s32 idx_in_lev_data = get_or_add_texture(strip.adgif.combo_tex, lev, tdb);
// determine the draw mode
DrawMode mode = process_draw_mode(strip.adgif, frag.prog_info.misc_x == 0,
frag.has_magic_tex0_bit, version, info.category);
Expand All @@ -2649,7 +2655,7 @@ void add_vertices_and_static_draw(tfrag3::TieTree& tree,
draws_by_category.at((int)info.category), packed_vert_indices,
mode, idx_in_lev_data, strip, inst, ifrag, proto_idx, frag_idx,
strip_idx, matrix_idx);
u32 envmap_tex_idx =
s32 envmap_tex_idx =
get_or_add_texture(proto.envmap_adgif.value().combo_tex, lev, tdb);

// second pass envmap draw mode, in envmap bucket, envmap-specific draw list
Expand Down
6 changes: 4 additions & 2 deletions game/graphics/opengl_renderer/OpenGLRenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,8 @@ void OpenGLRenderer::init_bucket_renderers_jak3() {
std::vector{tfrag3::TFragmentTreeKind::NORMAL}, false, i, anim_slot_array());
Tie3* tie = init_bucket_renderer<Tie3>(
fmt::format("tie-l{}-tfrag", i), BucketCategory::TIE,
GET_BUCKET_ID_FOR_LIST(BucketId::TIE_L0_TFRAG, BucketId::TIE_L1_TFRAG, i), i);
GET_BUCKET_ID_FOR_LIST(BucketId::TIE_L0_TFRAG, BucketId::TIE_L1_TFRAG, i), i,
anim_slot_array());
init_bucket_renderer<Tie3AnotherCategory>(
fmt::format("etie-l{}-tfrag", i), BucketCategory::TIE,
GET_BUCKET_ID_FOR_LIST(BucketId::ETIE_L0_TFRAG, BucketId::ETIE_L1_TFRAG, i), tie,
Expand Down Expand Up @@ -431,7 +432,8 @@ void OpenGLRenderer::init_bucket_renderers_jak2() {
std::vector{tfrag3::TFragmentTreeKind::NORMAL}, false, i, anim_slot_array());
Tie3* tie = init_bucket_renderer<Tie3>(
fmt::format("tie-l{}-tfrag", i), BucketCategory::TIE,
GET_BUCKET_ID_FOR_LIST(BucketId::TIE_L0_TFRAG, BucketId::TIE_L1_TFRAG, i), i);
GET_BUCKET_ID_FOR_LIST(BucketId::TIE_L0_TFRAG, BucketId::TIE_L1_TFRAG, i), i,
anim_slot_array());
init_bucket_renderer<Tie3AnotherCategory>(
fmt::format("etie-l{}-tfrag", i), BucketCategory::TIE,
GET_BUCKET_ID_FOR_LIST(BucketId::ETIE_L0_TFRAG, BucketId::ETIE_L1_TFRAG, i), tie,
Expand Down
38 changes: 29 additions & 9 deletions game/graphics/opengl_renderer/background/Tie3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,15 @@

#include "third-party/imgui/imgui.h"

Tie3::Tie3(const std::string& name, int my_id, int level_id, tfrag3::TieCategory category)
: BucketRenderer(name, my_id), m_level_id(level_id), m_default_category(category) {
Tie3::Tie3(const std::string& name,
int my_id,
int level_id,
const std::vector<GLuint>* anim_slot_array,
tfrag3::TieCategory category)
: BucketRenderer(name, my_id),
m_level_id(level_id),
m_default_category(category),
m_anim_slot_array(anim_slot_array) {
// regardless of how many we use some fixed max
// we won't actually interp or upload to gpu the unused ones, but we need a fixed maximum so
// indexing works properly.
Expand Down Expand Up @@ -573,8 +580,12 @@ void Tie3::draw_matching_draws_for_tree(int idx,
}
}

if ((int)draw.tree_tex_id != last_texture) {
glBindTexture(GL_TEXTURE_2D, m_textures->at(draw.tree_tex_id));
if (draw.tree_tex_id != last_texture) {
if (draw.tree_tex_id >= 0) {
glBindTexture(GL_TEXTURE_2D, m_textures->at(draw.tree_tex_id));
} else {
glBindTexture(GL_TEXTURE_2D, m_anim_slot_array->at(-(draw.tree_tex_id + 1)));
}
last_texture = draw.tree_tex_id;
}

Expand Down Expand Up @@ -665,8 +676,13 @@ void Tie3::envmap_second_pass_draw(const Tree& tree,
}
}

if ((int)draw.tree_tex_id != last_texture) {
glBindTexture(GL_TEXTURE_2D, m_textures->at(draw.tree_tex_id));
if (draw.tree_tex_id != last_texture) {
if (draw.tree_tex_id >= 0) {
glBindTexture(GL_TEXTURE_2D, m_textures->at(draw.tree_tex_id));
} else {
glBindTexture(GL_TEXTURE_2D, m_anim_slot_array->at(-(draw.tree_tex_id + 1)));
}

last_texture = draw.tree_tex_id;
}

Expand Down Expand Up @@ -922,8 +938,12 @@ void Tie3::render_tree_wind(int idx,
for (size_t draw_idx = 0; draw_idx < tree.wind_draws->size(); draw_idx++) {
const auto& draw = tree.wind_draws->operator[](draw_idx);

if ((int)draw.tree_tex_id != last_texture) {
glBindTexture(GL_TEXTURE_2D, m_textures->at(draw.tree_tex_id));
if (draw.tree_tex_id != last_texture) {
if (draw.tree_tex_id >= 0) {
glBindTexture(GL_TEXTURE_2D, m_textures->at(draw.tree_tex_id));
} else {
glBindTexture(GL_TEXTURE_2D, m_anim_slot_array->at(-(draw.tree_tex_id + 1)));
}
last_texture = draw.tree_tex_id;
}
auto double_draw = setup_tfrag_shader(render_state, draw.mode, ShaderId::TFRAG3);
Expand Down Expand Up @@ -993,7 +1013,7 @@ void Tie3AnotherCategory::render(DmaFollower& dma,
}

Tie3WithEnvmapJak1::Tie3WithEnvmapJak1(const std::string& name, int my_id, int level_id)
: Tie3(name, my_id, level_id, tfrag3::TieCategory::NORMAL) {}
: Tie3(name, my_id, level_id, nullptr, tfrag3::TieCategory::NORMAL) {}

void Tie3WithEnvmapJak1::render(DmaFollower& dma,
SharedRenderState* render_state,
Expand Down
3 changes: 2 additions & 1 deletion game/graphics/opengl_renderer/background/Tie3.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class Tie3 : public BucketRenderer {
Tie3(const std::string& name,
int my_id,
int level_id,
const std::vector<GLuint>* anim_slot_array,
tfrag3::TieCategory category = tfrag3::TieCategory::NORMAL);
void render(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof) override;
void draw_debug_window() override;
Expand Down Expand Up @@ -169,7 +170,7 @@ class Tie3 : public BucketRenderer {
} m_uniforms;

EtieUniforms m_etie_uniforms, m_etie_base_uniforms;

const std::vector<GLuint>* m_anim_slot_array;
static_assert(sizeof(WindWork) == 84 * 16);
};

Expand Down

0 comments on commit 5bc61c5

Please sign in to comment.