[jak2] fix flickering and depth writes (#2406)

Fixes some mistakes with merc draw modes. The glass in the palace level
no longer writes to the depth buffer (it's "water"):

![image](https://user-images.githubusercontent.com/48171810/227727825-d6726621-88a8-45a8-9cf3-8d6e9edc3d54.png)

Also fixes the one-frame flickers when level draw orders change. We
might be able to make this more efficient in the future, but this will
at least fix the frame with nothing drawn.
This commit is contained in:
water111 2023-03-25 14:00:54 -04:00 committed by GitHub
parent ebdb0ecadd
commit 0a511da2ce
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 1693 additions and 1522 deletions

View file

@ -87,8 +87,13 @@ std::string TextureDB::generate_texture_dest_adjustment_table() const {
for (const auto& [tpage, texture_ids_in_page] : textures_by_page) {
// organize by tbp offset
std::map<u32, std::vector<u32>> textures_by_tbp_offset;
std::set<u32> all_used_tbp_offsets;
u32 max_tbp_offset = 0;
for (auto tid : texture_ids_in_page) {
textures_by_tbp_offset[textures.at(tid).dest].push_back(tid);
u32 tbp = textures.at(tid).dest;
textures_by_tbp_offset[tbp].push_back(tid);
all_used_tbp_offsets.insert(tbp);
max_tbp_offset = std::max(max_tbp_offset, tbp);
}
// find tbp's with overlaps:
@ -104,9 +109,25 @@ std::string TextureDB::generate_texture_dest_adjustment_table() const {
result += fmt::format("{{{},{{\n", tpage);
for (const auto& [tbp, tex_ids] : textures_by_tbp_offset) {
if (tex_ids.size() > 1) {
int offset = 0;
for (auto id : tex_ids) {
result += fmt::format("{{{}, {}}},", id & 0xffff, offset++);
int offset = 1;
for (size_t id_id = 1; id_id < tex_ids.size(); id_id++) {
auto id = tex_ids[id_id];
bool ok = false;
int tries = 50;
// make sure we don't overlap again.
while (!ok && tries > 0) {
tries--;
if (!all_used_tbp_offsets.count(tbp + offset)) {
ok = true;
break;
}
offset++;
}
ASSERT(ok);
all_used_tbp_offsets.insert(tbp + offset);
result += fmt::format("{{{}, {}}},", id & 0xffff, offset);
offset++;
}
}

View file

@ -227,7 +227,8 @@ void update_mode_from_alpha1(GsAlpha reg, DrawMode& mode) {
*/
DrawMode process_draw_mode(const MercShader& info,
bool enable_alpha_test,
bool enable_alpha_blend) {
bool enable_alpha_blend,
bool depth_write) {
DrawMode mode;
/*
* (new 'static 'gs-test
@ -244,7 +245,7 @@ DrawMode process_draw_mode(const MercShader& info,
mode.set_alpha_fail(GsTest::AlphaFail::KEEP);
mode.set_alpha_test(DrawMode::AlphaTest::GEQUAL);
mode.enable_zt();
mode.enable_depth_write();
mode.set_depth_write_enable(depth_write);
mode.set_depth_test(GsTest::ZTest::GEQUAL);
// check these
@ -768,7 +769,7 @@ ConvertedMercEffect convert_merc_effect(const MercEffect& input_effect,
}
if (input_effect.extra_info.shader) {
result.has_envmap = true;
result.envmap_mode = process_draw_mode(*input_effect.extra_info.shader, false, false);
result.envmap_mode = process_draw_mode(*input_effect.extra_info.shader, false, false, false);
result.envmap_mode.set_ab(true);
u32 new_tex = remap_texture(input_effect.extra_info.shader->original_tex, map);
ASSERT(result.envmap_mode.get_tcc_enable());
@ -823,8 +824,17 @@ ConvertedMercEffect convert_merc_effect(const MercEffect& input_effect,
}
bool use_alpha_blend = false;
bool depth_write = true;
if (version == GameVersion::Jak2) {
use_alpha_blend = input_effect.texture_index == 4; // water
constexpr int kWaterTexture = 4;
constexpr int kAlphaTexture = 3;
if (input_effect.texture_index == kAlphaTexture) {
use_alpha_blend = true;
}
if (input_effect.texture_index == kWaterTexture) {
depth_write = false;
use_alpha_blend = true;
}
}
// full reset of state per effect.
@ -901,7 +911,7 @@ ConvertedMercEffect convert_merc_effect(const MercEffect& input_effect,
const auto& shader = frag.shaders.at(i);
// update merc state from shader (will hold over to next fragment, if needed)
merc_state.merc_draw_mode.mode =
process_draw_mode(shader, result.has_envmap, use_alpha_blend);
process_draw_mode(shader, result.has_envmap, use_alpha_blend, depth_write);
if (!merc_state.merc_draw_mode.mode.get_tcc_enable()) {
ASSERT(false);
}

File diff suppressed because it is too large Load diff

View file

@ -166,13 +166,24 @@ bool Shrub::setup_for_level(const std::string& level, SharedRenderState* render_
// make sure we have the level data.
Timer tfrag3_setup_timer;
auto lev_data = render_state->loader->get_tfrag3_level(level);
if (!lev_data || (m_has_level && lev_data->load_id != m_load_id)) {
if (!lev_data) {
// not loaded
m_has_level = false;
m_textures = nullptr;
m_level_name = "";
discard_tree_cache();
return false;
}
if (m_has_level && lev_data->load_id != m_load_id) {
m_has_level = false;
m_textures = nullptr;
m_level_name = "";
discard_tree_cache();
return setup_for_level(level, render_state);
}
m_textures = &lev_data->textures;
m_load_id = lev_data->load_id;

View file

@ -144,13 +144,24 @@ bool Tfrag3::setup_for_level(const std::vector<tfrag3::TFragmentTreeKind>& tree_
// make sure we have the level data.
Timer tfrag3_setup_timer;
auto lev_data = render_state->loader->get_tfrag3_level(level);
if (!lev_data || (m_has_level && lev_data->load_id != m_load_id)) {
if (!lev_data) {
// not loaded
m_has_level = false;
m_textures = nullptr;
m_level_name = "";
discard_tree_cache();
return false;
}
if (m_has_level && lev_data->load_id != m_load_id) {
m_has_level = false;
m_textures = nullptr;
m_level_name = "";
discard_tree_cache();
return setup_for_level(tree_kinds, level, render_state);
}
m_load_id = lev_data->load_id;
if (m_level_name != level) {

View file

@ -215,8 +215,8 @@ bool Tie3::try_loading_level(const std::string& level, SharedRenderState* render
Timer tfrag3_setup_timer;
auto lev_data = render_state->loader->get_tfrag3_level(level);
if (!lev_data || (m_has_level && lev_data->load_id != m_load_id)) {
// loader failed, or we have an old copy of a level. either way, we have nothing to draw.
if (!lev_data) {
// not loaded
m_has_level = false;
m_textures = nullptr;
m_level_name = "";
@ -224,6 +224,14 @@ bool Tie3::try_loading_level(const std::string& level, SharedRenderState* render
return false;
}
if (m_has_level && lev_data->load_id != m_load_id) {
m_has_level = false;
m_textures = nullptr;
m_level_name = "";
discard_tree_cache();
return try_loading_level(level, render_state);
}
// loading was successful. Link textures/load ID.
m_textures = &lev_data->textures;
m_load_id = lev_data->load_id;

View file

@ -1072,7 +1072,6 @@ void Merc2::do_draws(const Draw* draw_array,
bool normal_vtx_buffer_bound = true;
for (u32 di = 0; di < num_draws; di++) {
auto& draw = draw_array[di];
auto mode = draw.mode;
if (draw.flags & MOD_VTX) {
glBindVertexArray(draw.mod_vtx_buffer.vao);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, lev->merc_indices);
@ -1113,7 +1112,7 @@ void Merc2::do_draws(const Draw* draw_array,
set_uniform(uniforms.light_ambient, m_lights_buffer[draw.light_idx].ambient);
last_light = draw.light_idx;
}
setup_opengl_from_draw_mode(mode, GL_TEXTURE0, use_mipmaps_for_filtering);
setup_opengl_from_draw_mode(draw.mode, GL_TEXTURE0, use_mipmaps_for_filtering);
glUniform1i(uniforms.decal, draw.mode.get_decal());