[jak2] Fix dark jak anim and low res skull gems

This commit is contained in:
water
2023-07-24 18:37:23 -04:00
parent 50230e05fa
commit f387ad3c1a
4 changed files with 50 additions and 19 deletions
@@ -707,6 +707,11 @@ void OpenGLRenderer::render(DmaFollower dma, const RenderOptions& settings) {
{
auto prof = m_profiler.root()->make_scoped_child("buckets");
dispatch_buckets(dma, prof, settings.gpu_sync);
if (m_texture_animator) {
// if animation requests weren't made, assume the level is unloaded and the textures should
// reset.
m_texture_animator->clear_stale_textures(m_render_state.frame_idx);
}
}
// apply effects done with PCRTC registers
@@ -223,17 +223,18 @@ void opengl_upload_texture(GLint dest, const void* data, int w, int h) {
* texture using the index data in dest.
*/
ClutBlender::ClutBlender(const std::string& dest,
const std::vector<std::string>& sources,
const std::array<std::string, 2>& sources,
const std::optional<std::string>& level_name,
const tfrag3::Level* level,
OpenGLTexturePool* tpool) {
// find the destination texture
m_dest = itex_by_name(level, dest, level_name);
// find the clut source textures
for (const auto& sname : sources) {
m_cluts.push_back(&itex_by_name(level, sname, level_name)->color_table);
m_current_weights.push_back(0);
for (int i = 0; i < 2; i++) {
m_cluts[i] = &itex_by_name(level, sources[i], level_name)->color_table;
m_current_weights[i] = 0;
}
// opengl texture that we'll write to
m_texture = tpool->allocate(m_dest->w, m_dest->h);
m_temp_rgba.resize(m_dest->w * m_dest->h);
@@ -510,8 +511,9 @@ void TextureAnimator::add_to_clut_blender_group(int idx,
const std::optional<std::string>& dgo) {
auto& grp = m_clut_blender_groups.at(idx);
for (auto& prefix : textures) {
grp.blenders.emplace_back(prefix, std::vector<std::string>{prefix + suffix0, prefix + suffix1},
dgo, m_common_level, &m_opengl_texture_pool);
grp.blenders.emplace_back(prefix,
std::array<std::string, 2>{prefix + suffix0, prefix + suffix1}, dgo,
m_common_level, &m_opengl_texture_pool);
grp.outputs.push_back(output_slot_by_idx(GameVersion::Jak2, prefix));
m_private_output_slots.at(grp.outputs.back()) = grp.blenders.back().texture();
}
@@ -584,7 +586,8 @@ struct TextureAnimPcTransform {
*/
void TextureAnimator::handle_texture_anim_data(DmaFollower& dma,
const u8* ee_mem,
TexturePool* texture_pool) {
TexturePool* texture_pool,
u64 frame_idx) {
dprintf("animator\n");
m_current_shader = {};
glBindVertexArray(m_vao);
@@ -645,23 +648,23 @@ void TextureAnimator::handle_texture_anim_data(DmaFollower& dma,
} break;
case DARKJAK: {
auto p = scoped_prof("darkjak");
run_clut_blender_group(tf, m_darkjak_clut_blender_idx);
run_clut_blender_group(tf, m_darkjak_clut_blender_idx, frame_idx);
} break;
case PRISON_JAK: {
auto p = scoped_prof("prisonjak");
run_clut_blender_group(tf, m_jakb_prison_clut_blender_idx);
run_clut_blender_group(tf, m_jakb_prison_clut_blender_idx, frame_idx);
} break;
case ORACLE_JAK: {
auto p = scoped_prof("oraclejak");
run_clut_blender_group(tf, m_jakb_oracle_clut_blender_idx);
run_clut_blender_group(tf, m_jakb_oracle_clut_blender_idx, frame_idx);
} break;
case NEST_JAK: {
auto p = scoped_prof("nestjak");
run_clut_blender_group(tf, m_jakb_nest_clut_blender_idx);
run_clut_blender_group(tf, m_jakb_nest_clut_blender_idx, frame_idx);
} break;
case KOR_TRANSFORM: {
auto p = scoped_prof("kor");
run_clut_blender_group(tf, m_kor_transform_clut_blender_idx);
run_clut_blender_group(tf, m_kor_transform_clut_blender_idx, frame_idx);
} break;
case SKULL_GEM: {
auto p = scoped_prof("skull-gem");
@@ -990,17 +993,31 @@ void TextureAnimator::handle_copy_clut_alpha(const DmaTransfer& tf) {
glColorMask(true, true, true, true);
}
void TextureAnimator::run_clut_blender_group(DmaTransfer& tf, int idx) {
void TextureAnimator::run_clut_blender_group(DmaTransfer& tf, int idx, u64 frame_idx) {
float f;
ASSERT(tf.size_bytes == 16);
memcpy(&f, tf.data, sizeof(float));
float weights[2] = {1.f - f, f};
auto& blender = m_clut_blender_groups.at(idx);
blender.last_updated_frame = frame_idx;
for (size_t i = 0; i < blender.blenders.size(); i++) {
m_private_output_slots[blender.outputs[i]] = blender.blenders[i].run(weights);
}
}
void TextureAnimator::clear_stale_textures(u64 frame_idx) {
for (auto& group : m_clut_blender_groups) {
if (frame_idx > group.last_updated_frame) {
for (auto& blender : group.blenders) {
if (!blender.at_default()) {
float weights[2] = {1, 0};
blender.run(weights);
}
}
}
}
}
/*!
* Create an entry for a 16x16 clut texture upload. Leaves it on the CPU.
* They upload cluts as PSM32, so there's no funny addressing stuff, other than
@@ -1948,6 +1965,8 @@ void TextureAnimator::setup_texture_anims() {
skull_gem.move_to_pool = true;
skull_gem.tex_name = "skull-gem-dest";
skull_gem.color = math::Vector4<u8>{0, 0, 0, 0x80};
// overriden in texture-finish.gc
skull_gem.override_size = math::Vector2<int>(32, 32);
auto& skull_gem_0 = skull_gem.layers.emplace_back();
skull_gem_0.end_time = 300.;
@@ -65,17 +65,18 @@ struct OpenGLTexturePool {
class ClutBlender {
public:
ClutBlender(const std::string& dest,
const std::vector<std::string>& sources,
const std::array<std::string, 2>& sources,
const std::optional<std::string>& level_name,
const tfrag3::Level* level,
OpenGLTexturePool* tpool);
GLuint run(const float* weights);
GLuint texture() const { return m_texture; }
bool at_default() const { return m_current_weights[0] == 1.f && m_current_weights[1] == 0.f; }
private:
const tfrag3::IndexTexture* m_dest;
std::vector<const std::array<math::Vector4<u8>, 256>*> m_cluts;
std::vector<float> m_current_weights;
std::array<const std::array<math::Vector4<u8>, 256>*, 2> m_cluts;
std::array<float, 2> m_current_weights;
GLuint m_texture;
std::array<math::Vector4<u8>, 256> m_temp_clut;
std::vector<u32> m_temp_rgba;
@@ -199,10 +200,14 @@ class TextureAnimator {
public:
TextureAnimator(ShaderLibrary& shaders, const tfrag3::Level* common_level);
~TextureAnimator();
void handle_texture_anim_data(DmaFollower& dma, const u8* ee_mem, TexturePool* texture_pool);
void handle_texture_anim_data(DmaFollower& dma,
const u8* ee_mem,
TexturePool* texture_pool,
u64 frame_idx);
GLuint get_by_slot(int idx);
void draw_debug_window();
const std::vector<GLuint>* slots() { return &m_public_output_slots; }
void clear_stale_textures(u64 frame_idx);
private:
void copy_private_to_public();
@@ -314,6 +319,7 @@ class TextureAnimator {
struct ClutBlenderGroup {
std::vector<ClutBlender> blenders;
std::vector<int> outputs;
u64 last_updated_frame = 0;
};
std::vector<ClutBlenderGroup> m_clut_blender_groups;
@@ -332,7 +338,7 @@ class TextureAnimator {
const std::string& suffix0,
const std::string& suffix1,
const std::optional<std::string>& dgo);
void run_clut_blender_group(DmaTransfer& tf, int idx);
void run_clut_blender_group(DmaTransfer& tf, int idx, u64 frame_idx);
Psm32ToPsm8Scrambler m_psm32_to_psm8_8_8, m_psm32_to_psm8_16_16, m_psm32_to_psm8_32_32,
m_psm32_to_psm8_64_64;
@@ -30,7 +30,8 @@ void TextureUploadHandler::render(DmaFollower& dma,
dma.read_and_advance();
auto p = scoped_prof("texture-animator");
m_texture_animator->handle_texture_anim_data(dma, (const u8*)render_state->ee_main_memory,
render_state->texture_pool.get());
render_state->texture_pool.get(),
render_state->frame_idx);
}
// does it look like data to do eye rendering?
if (dma_tag.qwc == (128 / 16)) {