diff --git a/decompiler/config/jak1_ntsc_black_label/type_casts.jsonc b/decompiler/config/jak1_ntsc_black_label/type_casts.jsonc index 20fc420f4..e21bac788 100644 --- a/decompiler/config/jak1_ntsc_black_label/type_casts.jsonc +++ b/decompiler/config/jak1_ntsc_black_label/type_casts.jsonc @@ -4010,7 +4010,16 @@ [249, "a0", "(pointer gs-reg64)"], [251, "a0", "(pointer gs-alpha)"], [253, "a0", "(pointer gs-reg64)"], - [[270, 273], "v1", "dma-packet"] + [[270, 273], "v1", "dma-packet"], + [[312, 316], "a0", "dma-packet"], + [[322, 325], "a0", "gs-gif-tag"], + [330, "a0", "(pointer gs-zbuf)"], + [332, "a0", "(pointer gs-reg)"], + [334, "a0", "(pointer gs-test)"], + [336, "a0", "(pointer gs-reg64)"], + [338, "a0", "(pointer gs-alpha)"], + [340, "a0", "(pointer gs-reg64)"], + [[357, 360], "v1", "dma-packet"] ], "(event target-racing-start)": [ diff --git a/game/graphics/opengl_renderer/ocean/CommonOceanRenderer.cpp b/game/graphics/opengl_renderer/ocean/CommonOceanRenderer.cpp index 3f3f841c0..9643d27ce 100644 --- a/game/graphics/opengl_renderer/ocean/CommonOceanRenderer.cpp +++ b/game/graphics/opengl_renderer/ocean/CommonOceanRenderer.cpp @@ -266,7 +266,7 @@ void CommonOceanRenderer::handle_near_adgif(const u8* data, u32 offset, u32 coun } } -void CommonOceanRenderer::flush(SharedRenderState* render_state, ScopedProfilerNode& prof) { +void CommonOceanRenderer::flush_near(SharedRenderState* render_state, ScopedProfilerNode& prof) { glBindVertexArray(m_ogl.vao); glBindBuffer(GL_ARRAY_BUFFER, m_ogl.vertex_buffer); glEnable(GL_PRIMITIVE_RESTART); @@ -334,4 +334,191 @@ void CommonOceanRenderer::flush(SharedRenderState* render_state, ScopedProfilerN prof.add_draw_call(); prof.add_tri(m_next_free_index[bucket]); } +} + +void CommonOceanRenderer::kick_from_mid(const u8* data) { + bool eop = false; + + u32 offset = 0; + while (!eop) { + GifTag tag(data + offset); + offset += 16; + + // unpack registers. + // faster to do it once outside of the nloop loop. + GifTag::RegisterDescriptor reg_desc[16]; + u32 nreg = tag.nreg(); + for (u32 i = 0; i < nreg; i++) { + reg_desc[i] = tag.reg(i); + } + + auto format = tag.flg(); + if (format == GifTag::Format::PACKED) { + if (tag.nreg() == 1) { + ASSERT(!tag.pre()); + ASSERT(tag.nloop() == 5); + handle_mid_adgif(data, offset); + offset += 5 * 16; + } else { + ASSERT(tag.nreg() == 3); + ASSERT(tag.pre()); + m_current_bucket = GsPrim(tag.prim()).abe() ? 1 : 0; + + int count = tag.nloop(); + if (GsPrim(tag.prim()).kind() == GsPrim::Kind::TRI_STRIP) { + handle_near_vertex_gif_data_strip(data, offset, tag.nloop()); + } else { + handle_near_vertex_gif_data_fan(data, offset, tag.nloop()); + } + offset += 3 * 16 * count; + // todo handle. + } + } else { + ASSERT(false); // format not packed or reglist. + } + + eop = tag.eop(); + } +} + +void CommonOceanRenderer::handle_mid_adgif(const u8* data, u32 offset) { + u32 most_recent_tbp = 0; + + for (u32 i = 0; i < 5; i++) { + u64 value; + GsRegisterAddress addr; + memcpy(&value, data + offset + 16 * i, sizeof(u64)); + memcpy(&addr, data + offset + 16 * i + 8, sizeof(GsRegisterAddress)); + switch (addr) { + case GsRegisterAddress::MIPTBP1_1: + case GsRegisterAddress::MIPTBP2_1: + // ignore this, it's just mipmapping settings + break; + case GsRegisterAddress::TEX1_1: { + GsTex1 reg(value); + ASSERT(reg.mmag()); + } break; + case GsRegisterAddress::CLAMP_1: { + bool s = value & 0b001; + bool t = value & 0b100; + ASSERT(s == t); + } break; + case GsRegisterAddress::TEX0_1: { + GsTex0 reg(value); + ASSERT(reg.tfx() == GsTex0::TextureFunction::MODULATE); + most_recent_tbp = reg.tbp0(); + } break; + case GsRegisterAddress::ALPHA_1: { + } break; + + default: + fmt::print("reg: {}\n", register_address_name(addr)); + break; + } + } + + if (most_recent_tbp != 8160) { + m_envmap_tex = most_recent_tbp; + } + + if (m_vertices.size() - 128 < m_next_free_vertex) { + ASSERT(false); // add more vertices. + } +} + +void CommonOceanRenderer::init_for_mid() { + m_next_free_vertex = 0; + for (auto& x : m_next_free_index) { + x = 0; + } +} + +void reverse_indices(u32* indices, u32 count) { + if (count) { + for (u32 a = 0, b = count - 1; a < b; a++, b--) { + std::swap(indices[a], indices[b]); + } + } +} + +void CommonOceanRenderer::flush_mid(SharedRenderState* render_state, ScopedProfilerNode& prof) { + glBindVertexArray(m_ogl.vao); + glBindBuffer(GL_ARRAY_BUFFER, m_ogl.vertex_buffer); + glEnable(GL_PRIMITIVE_RESTART); + glPrimitiveRestartIndex(UINT32_MAX); + glBufferData(GL_ARRAY_BUFFER, m_next_free_vertex * sizeof(Vertex), m_vertices.data(), + GL_STREAM_DRAW); + render_state->shaders[ShaderId::OCEAN_COMMON].activate(); + glUniform4f(glGetUniformLocation(render_state->shaders[ShaderId::OCEAN_COMMON].id(), "fog_color"), + render_state->fog_color[0], render_state->fog_color[1], render_state->fog_color[2], + render_state->fog_intensity); + + glDepthMask(GL_TRUE); + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_ALWAYS); + glDisable(GL_BLEND); + + // note: + // there are some places where the game draws the same section of ocean twice, in this order: + // - low poly mesh with ocean texture + // - low poly mesh with envmap texture + // - high poly mesh with ocean texture (overwrites previous draw) + // - high poly mesh with envmap texture (overwrites previous draw) + + // we draw all ocean textures together and all envmap textures togther. luckily, there's a trick + // we can use to get the same result. + // first, we'll draw all ocean textures. The high poly mesh is drawn second, so it wins. + // then, we'll draw all envmaps, but with two changes: + // - first, we draw it in reverse, so the high poly versions are drawn first + // - second, we'll modify the shader to set alpha = 0 of the destination. when the low poly + // version is drawn on top, it won't draw at all because of the blending mode + // (s_factor = DST_ALPHA, d_factor = 1) + + // draw it in reverse + reverse_indices(m_indices[1].data(), m_next_free_index[1]); + + for (int bucket = 0; bucket < 2; bucket++) { + switch (bucket) { + case 0: { + auto tex = render_state->texture_pool->lookup(8160); + if (!tex) { + tex = render_state->texture_pool->get_placeholder_texture(); + } + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, *tex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glUniform1i( + glGetUniformLocation(render_state->shaders[ShaderId::OCEAN_COMMON].id(), "tex_T0"), 0); + glUniform1i( + glGetUniformLocation(render_state->shaders[ShaderId::OCEAN_COMMON].id(), "bucket"), 3); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } + + break; + case 1: + glEnable(GL_BLEND); + auto tex = render_state->texture_pool->lookup(m_envmap_tex); + if (!tex) { + tex = render_state->texture_pool->get_placeholder_texture(); + } + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, *tex); + + glBlendFuncSeparate(GL_DST_ALPHA, GL_ONE, GL_ONE, GL_ZERO); + glBlendEquation(GL_FUNC_ADD); + glUniform1i( + glGetUniformLocation(render_state->shaders[ShaderId::OCEAN_COMMON].id(), "bucket"), 4); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + break; + } + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ogl.index_buffer[bucket]); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_next_free_index[bucket] * sizeof(u32), + m_indices[bucket].data(), GL_STREAM_DRAW); + glDrawElements(GL_TRIANGLE_STRIP, m_next_free_index[bucket], GL_UNSIGNED_INT, nullptr); + prof.add_draw_call(); + prof.add_tri(m_next_free_index[bucket]); + } } \ No newline at end of file diff --git a/game/graphics/opengl_renderer/ocean/CommonOceanRenderer.h b/game/graphics/opengl_renderer/ocean/CommonOceanRenderer.h index 12eadf8a8..fbe0546a8 100644 --- a/game/graphics/opengl_renderer/ocean/CommonOceanRenderer.h +++ b/game/graphics/opengl_renderer/ocean/CommonOceanRenderer.h @@ -8,7 +8,11 @@ class CommonOceanRenderer { void init_for_near(); void kick_from_near(const u8* data); - void flush(SharedRenderState* render_state, ScopedProfilerNode& prof); + void flush_near(SharedRenderState* render_state, ScopedProfilerNode& prof); + + void init_for_mid(); + void kick_from_mid(const u8* data); + void flush_mid(SharedRenderState* render_state, ScopedProfilerNode& prof); private: void handle_near_vertex_gif_data_fan(const u8* data, u32 offset, u32 loop); @@ -16,6 +20,8 @@ class CommonOceanRenderer { void handle_near_adgif(const u8* data, u32 offset, u32 count); + void handle_mid_adgif(const u8* data, u32 offset); + enum VertexBucket { RGB_TEXTURE = 0, ALPHA = 1, diff --git a/game/graphics/opengl_renderer/ocean/OceanMid.cpp b/game/graphics/opengl_renderer/ocean/OceanMid.cpp index 0d6d675b5..9be7a481f 100644 --- a/game/graphics/opengl_renderer/ocean/OceanMid.cpp +++ b/game/graphics/opengl_renderer/ocean/OceanMid.cpp @@ -12,10 +12,8 @@ OceanMid::OceanMid() { vu.vf25 = Vf(1, 1, 1, 1); } -void OceanMid::run(DmaFollower& dma, - SharedRenderState* render_state, - ScopedProfilerNode& prof, - DirectRenderer& direct) { +void OceanMid::run(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof) { + m_common_ocean_renderer.init_for_mid(); // first is setting base and offset { auto base_offset_tag = dma.read_and_advance(); @@ -97,26 +95,24 @@ void OceanMid::run(DmaFollower& dma, memcpy(m_vu_data + addr + addr_off, temp, 16); } ASSERT(8 * v1.num == data.size_bytes); - // TODO } else if (v0.kind == VifCode::Kind::STCYCL && v0.immediate == 0x404 && v1.kind == VifCode::Kind::MSCALF) { switch (v1.immediate) { case 46: - run_call46_vu2c(render_state, prof, direct); + run_call46_vu2c(); break; case 73: - run_call73_vu2c(render_state, prof, direct); + run_call73_vu2c(); break; case 107: - run_call107_vu2c(render_state, prof, direct); + run_call107_vu2c(); break; case 275: - run_call275_vu2c(render_state, prof, direct); + run_call275_vu2c(); break; default: fmt::print("unknown call1: {}\n", v1.immediate); } - // TODO } else if (v0.kind == VifCode::Kind::MSCALF && v1.kind == VifCode::Kind::FLUSHA) { switch (v0.immediate) { case 41: @@ -129,17 +125,18 @@ void OceanMid::run(DmaFollower& dma, fmt::print("unknown call2: {}\n", v0.immediate); ASSERT(false); } - - // TODO - } - - else { + } else { fmt::print("{} {}\n", data.vifcode0().print(), data.vifcode1().print()); ASSERT(false); } } + m_common_ocean_renderer.flush_mid(render_state, prof); } void OceanMid::run_call0() { run_call0_vu2c(); } + +void OceanMid::xgkick(u16 addr) { + m_common_ocean_renderer.kick_from_mid((const u8*)&m_vu_data[addr]); +} \ No newline at end of file diff --git a/game/graphics/opengl_renderer/ocean/OceanMid.h b/game/graphics/opengl_renderer/ocean/OceanMid.h index d94a37e2f..8f9fac96d 100644 --- a/game/graphics/opengl_renderer/ocean/OceanMid.h +++ b/game/graphics/opengl_renderer/ocean/OceanMid.h @@ -3,48 +3,31 @@ #include "game/graphics/opengl_renderer/BucketRenderer.h" #include "game/graphics/opengl_renderer/DirectRenderer.h" #include "game/common/vu.h" +#include "game/graphics/opengl_renderer/ocean/CommonOceanRenderer.h" class OceanMid { public: OceanMid(); - void run(DmaFollower& dma, - SharedRenderState* render_state, - ScopedProfilerNode& prof, - DirectRenderer& direct); + void run(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof); private: void run_call0(); void run_call0_vu2c(); void run_call41_vu2c(); void run_call43_vu2c(); - void run_call46_vu2c(SharedRenderState* render_state, - ScopedProfilerNode& prof, - DirectRenderer& direct); - - void run_call73_vu2c(SharedRenderState* render_state, - ScopedProfilerNode& prof, - DirectRenderer& direct); - void run_call107_vu2c(SharedRenderState* render_state, - ScopedProfilerNode& prof, - DirectRenderer& direct); - void run_call275_vu2c(SharedRenderState* render_state, - ScopedProfilerNode& prof, - DirectRenderer& direct); - void xgkick(u16 addr, - SharedRenderState* render_state, - ScopedProfilerNode& prof, - DirectRenderer& direct); + void run_call46_vu2c(); + void run_call73_vu2c(); + void run_call107_vu2c(); + void run_call275_vu2c(); + void xgkick(u16 addr); void run_L26_vu2c(); void run_L32_vu2c(); - void run_L38_vu2c(SharedRenderState* render_state, - ScopedProfilerNode& prof, - DirectRenderer& direct); - void run_L43_vu2c(SharedRenderState* render_state, - ScopedProfilerNode& prof, - DirectRenderer& direct); + void run_L38_vu2c(); + void run_L43_vu2c(); void run_L45_vu2c(); + CommonOceanRenderer m_common_ocean_renderer; bool m_buffer_toggle = false; static constexpr int VU1_INPUT_BUFFER_BASE = 0; static constexpr int VU1_INPUT_BUFFER_OFFSET = 0x76; diff --git a/game/graphics/opengl_renderer/ocean/OceanMidAndFar.cpp b/game/graphics/opengl_renderer/ocean/OceanMidAndFar.cpp index 8c0c1af02..4df6660a3 100644 --- a/game/graphics/opengl_renderer/ocean/OceanMidAndFar.cpp +++ b/game/graphics/opengl_renderer/ocean/OceanMidAndFar.cpp @@ -97,7 +97,7 @@ void OceanMidAndFar::handle_ocean_mid(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof) { if (dma.current_tag_vifcode0().kind == VifCode::Kind::BASE) { - m_mid_renderer.run(dma, render_state, prof, m_direct); + m_mid_renderer.run(dma, render_state, prof); } else { // not drawing return; diff --git a/game/graphics/opengl_renderer/ocean/OceanMid_PS2.cpp b/game/graphics/opengl_renderer/ocean/OceanMid_PS2.cpp index 4751e2d17..0bfb3da32 100644 --- a/game/graphics/opengl_renderer/ocean/OceanMid_PS2.cpp +++ b/game/graphics/opengl_renderer/ocean/OceanMid_PS2.cpp @@ -54,13 +54,6 @@ static inline REALLY_INLINE float erleng(const Vf& in) { } } // namespace -void OceanMid::xgkick(u16 addr, - SharedRenderState* render_state, - ScopedProfilerNode& prof, - DirectRenderer& direct) { - direct.render_gif((const u8*)&m_vu_data[addr], UINT32_MAX, render_state, prof); -} - void OceanMid::run_call0_vu2c() { bool bc; // lq.xyzw vf01, 733(vi00) | nop 0 @@ -209,9 +202,7 @@ void OceanMid::run_call43_vu2c() { return; } -void OceanMid::run_call46_vu2c(SharedRenderState* render_state, - ScopedProfilerNode& prof, - DirectRenderer& direct) { +void OceanMid::run_call46_vu2c() { bool bc; // xtop vi02 | nop 46 vu.vi02 = xtop(); @@ -272,7 +263,7 @@ L10: // iaddiu vi01, vi00, 0x318 | nop 66 vu.vi01 = 0x318; /* 792 */ // xgkick vi09 | nop 67 - xgkick(vu.vi09, render_state, prof, direct); + xgkick(vu.vi09); // isub vi09, vi01, vi09 | nop 68 vu.vi09 = vu.vi01 - vu.vi09; L11: @@ -292,9 +283,7 @@ L11: return; } -void OceanMid::run_call73_vu2c(SharedRenderState* render_state, - ScopedProfilerNode& prof, - DirectRenderer& direct) { +void OceanMid::run_call73_vu2c() { bool bc; // xtop vi02 | nop 73 vu.vi02 = xtop(); @@ -363,7 +352,7 @@ L14: // iaddiu vi01, vi00, 0x318 | nop 97 vu.vi01 = 0x318; /* 792 */ // xgkick vi09 | nop 98 - xgkick(vu.vi09, render_state, prof, direct); // draws envmapped ocean + xgkick(vu.vi09); // draws envmapped ocean // BRANCH! // ibeq vi00, vi14, L15 | nop 99 bc = (vu.vi14 == 0); @@ -379,7 +368,7 @@ L14: // nop | nop 102 // if (bc) { goto L38; } - run_L38_vu2c(render_state, prof, direct); + run_L38_vu2c(); L15: // BRANCH! @@ -398,9 +387,7 @@ L15: return; } -void OceanMid::run_call107_vu2c(SharedRenderState* render_state, - ScopedProfilerNode& prof, - DirectRenderer& direct) { +void OceanMid::run_call107_vu2c() { bool bc; // xtop vi02 | nop 107 vu.vi02 = xtop(); @@ -657,7 +644,7 @@ L18: // iaddiu vi06, vi06, 0x4000 | nop 214 vu.vi06 = vu.vi06 + 0x4000; /* 16384 */ // if (bc) { goto L43; } - run_L43_vu2c(render_state, prof, direct); + run_L43_vu2c(); L19: // BRANCH! @@ -794,7 +781,7 @@ L20: // iaddiu vi06, vi06, 0x4000 | nop 270 vu.vi06 = vu.vi06 + 0x4000; /* 16384 */ // if (bc) { goto L43; } - run_L43_vu2c(render_state, prof, direct); + run_L43_vu2c(); L21: // BRANCH! @@ -813,9 +800,7 @@ L21: return; } -void OceanMid::run_call275_vu2c(SharedRenderState* render_state, - ScopedProfilerNode& prof, - DirectRenderer& direct) { +void OceanMid::run_call275_vu2c() { bool bc; // fmt::print("call 275\n"); // xtop vi02 | nop 275 @@ -1005,7 +990,7 @@ L23: // if (bc) { // goto L43; // } - run_L43_vu2c(render_state, prof, direct); + run_L43_vu2c(); // ior vi03, vi00, vi00 | nop 350 vu.vi03 = 0; @@ -1101,7 +1086,7 @@ L24: // if (bc) { // goto L43; // } - run_L43_vu2c(render_state, prof, direct); + run_L43_vu2c(); L25: // nop | nop :e 389 @@ -1848,9 +1833,7 @@ L37: // nop | nop 613 } -void OceanMid::run_L38_vu2c(SharedRenderState* render_state, - ScopedProfilerNode& prof, - DirectRenderer& direct) { +void OceanMid::run_L38_vu2c() { bool bc; // lq.xyzw vf31, 734(vi00) | nop 614 @@ -2089,7 +2072,7 @@ L41: // iaddiu vi06, vi06, 0x4000 | nop 705 vu.vi06 = vu.vi06 + 0x4000; /* 16384 */ // if (bc) { goto L43; } - run_L43_vu2c(render_state, prof, direct); + run_L43_vu2c(); // iaddi vi08, vi10, 0x7 | nop 706 vu.vi08 = vu.vi10 + 7; @@ -2175,7 +2158,7 @@ L41: // iaddiu vi06, vi06, 0x4000 | nop 744 vu.vi06 = vu.vi06 + 0x4000; /* 16384 */ // if (bc) { goto L43; } - run_L43_vu2c(render_state, prof, direct); + run_L43_vu2c(); L42: // BRANCH! @@ -2190,9 +2173,7 @@ L42: // jr vi15 | nop 747 // nop | nop 748 } -void OceanMid::run_L43_vu2c(SharedRenderState* render_state, - ScopedProfilerNode& prof, - DirectRenderer& direct) { +void OceanMid::run_L43_vu2c() { bool bc; // sq.xyzw vf07, -1(vi08) | nop 749 sq_buffer(Mask::xyzw, vu.vf07, vu.vi08 + -1); @@ -2285,7 +2266,7 @@ L44: // iaddiu vi01, vi00, 0x4d3 | nop 789 vu.vi01 = 0x4d3; /* 1235 */ // xgkick vi10 | nop 790 - xgkick(vu.vi10, render_state, prof, direct); + xgkick(vu.vi10); // jr vi13 | nop 791 // ASSERT(false); // isub vi10, vi01, vi10 | nop 792 diff --git a/game/graphics/opengl_renderer/ocean/OceanNear.cpp b/game/graphics/opengl_renderer/ocean/OceanNear.cpp index 9a51b7d02..554f5901c 100644 --- a/game/graphics/opengl_renderer/ocean/OceanNear.cpp +++ b/game/graphics/opengl_renderer/ocean/OceanNear.cpp @@ -2,16 +2,13 @@ #include "third-party/imgui/imgui.h" OceanNear::OceanNear(const std::string& name, BucketId my_id) - : BucketRenderer(name, my_id), m_texture_renderer(false), m_direct(name, my_id, 0x4000) { + : BucketRenderer(name, my_id), m_texture_renderer(false) { for (auto& a : m_vu_data) { a.fill(0); } } -void OceanNear::draw_debug_window() { - ImGui::Checkbox("New", &m_use_new); - m_direct.draw_debug_window(); -} +void OceanNear::draw_debug_window() {} void OceanNear::init_textures(TexturePool& pool) { m_texture_renderer.init_textures(pool); @@ -65,19 +62,11 @@ void OceanNear::render(DmaFollower& dma, // direct setup { - if (m_use_new) { - m_common_ocean_renderer.init_for_near(); - } else { - m_direct.reset_state(); - } + m_common_ocean_renderer.init_for_near(); auto setup = dma.read_and_advance(); ASSERT(setup.vifcode0().kind == VifCode::Kind::NOP); ASSERT(setup.vifcode1().kind == VifCode::Kind::DIRECT); ASSERT(setup.size_bytes == 32); - if (m_use_new) { - } else { - m_direct.render_gif(setup.data, 32, render_state, prof); - } } // oofset and base @@ -110,7 +99,7 @@ void OceanNear::render(DmaFollower& dma, run_call0_vu2c(); break; case 39: - run_call39_vu2c(render_state, prof); + run_call39_vu2c(); break; default: fmt::print("unknown ocean near call: {}\n", v0.immediate); @@ -123,17 +112,9 @@ void OceanNear::render(DmaFollower& dma, dma.read_and_advance(); } - if (m_use_new) { - m_common_ocean_renderer.flush(render_state, prof); - } else { - m_direct.flush_pending(render_state, prof); - } + m_common_ocean_renderer.flush_near(render_state, prof); } -void OceanNear::xgkick(u16 addr, SharedRenderState* render_state, ScopedProfilerNode& prof) { - if (m_use_new) { - m_common_ocean_renderer.kick_from_near((const u8*)&m_vu_data[addr]); - } else { - m_direct.render_gif((const u8*)&m_vu_data[addr], UINT32_MAX, render_state, prof); - } +void OceanNear::xgkick(u16 addr) { + m_common_ocean_renderer.kick_from_near((const u8*)&m_vu_data[addr]); } \ No newline at end of file diff --git a/game/graphics/opengl_renderer/ocean/OceanNear.h b/game/graphics/opengl_renderer/ocean/OceanNear.h index c2fc4948e..81f9516a7 100644 --- a/game/graphics/opengl_renderer/ocean/OceanNear.h +++ b/game/graphics/opengl_renderer/ocean/OceanNear.h @@ -14,25 +14,22 @@ class OceanNear : public BucketRenderer { private: void run_call0_vu2c(); - void run_call39_vu2c(SharedRenderState* render_state, ScopedProfilerNode& prof); + void run_call39_vu2c(); void run_L15_vu2c(); void run_L21_vu2c(); void run_L23_vu2c(); - void run_L25_vu2c(SharedRenderState* render_state, ScopedProfilerNode& prof); + void run_L25_vu2c(); void run_L30_vu2c(); void run_L32_vu2c(); OceanTexture m_texture_renderer; - DirectRenderer m_direct; CommonOceanRenderer m_common_ocean_renderer; bool m_buffer_toggle = false; static constexpr int VU1_INPUT_BUFFER_BASE = 0; static constexpr int VU1_INPUT_BUFFER_OFFSET = 0x10; - bool m_use_new = true; - - void xgkick(u16 addr, SharedRenderState* render_state, ScopedProfilerNode& prof); + void xgkick(u16 addr); u16 xtop() { m_buffer_toggle = !m_buffer_toggle; diff --git a/game/graphics/opengl_renderer/ocean/OceanNear_PS2.cpp b/game/graphics/opengl_renderer/ocean/OceanNear_PS2.cpp index 569876209..3904740c2 100644 --- a/game/graphics/opengl_renderer/ocean/OceanNear_PS2.cpp +++ b/game/graphics/opengl_renderer/ocean/OceanNear_PS2.cpp @@ -110,7 +110,7 @@ L4: // nop | nop 38 } -void OceanNear::run_call39_vu2c(SharedRenderState* render_state, ScopedProfilerNode& prof) { +void OceanNear::run_call39_vu2c() { bool bc; // xtop vi02 | nop 39 vu.vi02 = xtop(); @@ -363,11 +363,11 @@ L9: // sq.xyzw vf07, 6(vi09) | nop 138 sq_buffer(Mask::xyzw, vu.vf07, vu.vi09 + 6); // xgkick vi09 | nop 139 - xgkick(vu.vi09, render_state, prof); + xgkick(vu.vi09); // lq.xyzw vf07, 980(vi00) | nop 140 lq_buffer(Mask::xyzw, vu.vf07, 980); // xgkick vi08 | nop 141 - xgkick(vu.vi08, render_state, prof); + xgkick(vu.vi08); // sq.xyzw vf07, 6(vi09) | nop 142 sq_buffer(Mask::xyzw, vu.vf07, vu.vi09 + 6); // iaddi vi08, vi09, 0x6 | nop 143 @@ -375,13 +375,13 @@ L9: // nop | nop 144 // xgkick vi08 | nop 145 - xgkick(vu.vi08, render_state, prof); + xgkick(vu.vi08); // iaddiu vi08, vi00, 0x3d5 | nop 146 vu.vi08 = 0x3d5; /* 981 */ // nop | nop 147 // xgkick vi08 | nop 148 - xgkick(vu.vi08, render_state, prof); + xgkick(vu.vi08); // BRANCH! // bal vi15, L21 | nop 149 // ASSERT(false); @@ -405,7 +405,7 @@ L9: // nop | nop 154 // if (bc) { goto L25; } - run_L25_vu2c(render_state, prof); + run_L25_vu2c(); L10: // BRANCH! @@ -421,7 +421,7 @@ L10: // iaddiu vi01, vi00, 0x4b2 | nop 158 vu.vi01 = 0x4b2; /* 1202 */ // xgkick vi08 | nop 159 - xgkick(vu.vi08, render_state, prof); + xgkick(vu.vi08); // isub vi09, vi01, vi09 | nop 160 vu.vi09 = vu.vi01 - vu.vi09; L11: @@ -479,11 +479,11 @@ L12: // sq.xyzw vf07, 6(vi09) | nop 179 sq_buffer(Mask::xyzw, vu.vf07, vu.vi09 + 6); // xgkick vi09 | nop 180 - xgkick(vu.vi09, render_state, prof); + xgkick(vu.vi09); // lq.xyzw vf07, 980(vi00) | nop 181 lq_buffer(Mask::xyzw, vu.vf07, 980); // xgkick vi08 | nop 182 - xgkick(vu.vi08, render_state, prof); + xgkick(vu.vi08); // sq.xyzw vf07, 6(vi09) | nop 183 sq_buffer(Mask::xyzw, vu.vf07, vu.vi09 + 6); // iaddi vi08, vi09, 0x6 | nop 184 @@ -491,13 +491,13 @@ L12: // nop | nop 185 // xgkick vi08 | nop 186 - xgkick(vu.vi08, render_state, prof); + xgkick(vu.vi08); // iaddiu vi08, vi00, 0x3d5 | nop 187 vu.vi08 = 0x3d5; /* 981 */ // nop | nop 188 // xgkick vi08 | nop 189 - xgkick(vu.vi08, render_state, prof); + xgkick(vu.vi08); // BRANCH! // bal vi15, L21 | nop 190 // ASSERT(false); @@ -521,7 +521,7 @@ L12: // nop | nop 195 // if (bc) { goto L25; } - run_L25_vu2c(render_state, prof); + run_L25_vu2c(); L13: // BRANCH! @@ -539,7 +539,7 @@ L13: // nop | nop 200 // xgkick vi08 | nop 201 - xgkick(vu.vi08, render_state, prof); + xgkick(vu.vi08); // isub vi09, vi01, vi09 | nop 202 vu.vi09 = vu.vi01 - vu.vi09; L14: @@ -1362,7 +1362,7 @@ L24: // nop | nop 468 } -void OceanNear::run_L25_vu2c(SharedRenderState* render_state, ScopedProfilerNode& prof) { +void OceanNear::run_L25_vu2c() { bool bc; // lq.xyzw vf31, 952(vi00) | nop 469 lq_buffer(Mask::xyzw, vu.vf31, 952); @@ -1529,11 +1529,11 @@ L28: // iaddiu vi08, vi00, 0x3d1 | nop 535 vu.vi08 = 0x3d1; /* 977 */ // xgkick vi10 | nop 536 - xgkick(vu.vi10, render_state, prof); + xgkick(vu.vi10); // lq.xyzw vf07, 960(vi00) | nop 537 lq_buffer(Mask::xyzw, vu.vf07, 960); // xgkick vi08 | nop 538 - xgkick(vu.vi08, render_state, prof); + xgkick(vu.vi08); // iaddi vi08, vi10, 0x6 | nop 539 vu.vi08 = vu.vi10 + 6; // sq.xyzw vf07, 6(vi10) | nop 540 @@ -1541,13 +1541,13 @@ L28: // isw.x vi06, 6(vi10) | nop 541 isw_buffer(Mask::x, vu.vi06, vu.vi10 + 6); // xgkick vi08 | nop 542 - xgkick(vu.vi08, render_state, prof); + xgkick(vu.vi08); // iaddiu vi08, vi00, 0x3d5 | nop 543 vu.vi08 = 0x3d5; /* 981 */ // nop | nop 544 // xgkick vi08 | nop 545 - xgkick(vu.vi08, render_state, prof); + xgkick(vu.vi08); // iaddiu vi08, vi10, 0x2a | nop 546 vu.vi08 = vu.vi10 + 0x2a; /* 42 */ // iaddiu vi03, vi10, 0x2a | nop 547 @@ -1577,7 +1577,7 @@ L28: // iaddiu vi01, vi00, 0x69c | nop 555 vu.vi01 = 0x69c; /* 1692 */ // xgkick vi08 | nop 556 - xgkick(vu.vi08, render_state, prof); + xgkick(vu.vi08); // isub vi10, vi01, vi10 | nop 557 vu.vi10 = vu.vi01 - vu.vi10; L29: diff --git a/game/graphics/opengl_renderer/shaders/ocean_common.frag b/game/graphics/opengl_renderer/shaders/ocean_common.frag index 219aa8a76..e920be3b9 100644 --- a/game/graphics/opengl_renderer/shaders/ocean_common.frag +++ b/game/graphics/opengl_renderer/shaders/ocean_common.frag @@ -26,6 +26,13 @@ void main() { color.xyzw *= 2; } else if (bucket == 2) { color = fragment_color * T0; + } else if (bucket == 3) { + color = fragment_color * T0; + color.xyzw *= 2; + color.xyz = mix(color.xyz, fog_color.xyz / 255., clamp(fog_color.w * (1 - fog), 0, 1)); + } else if (bucket == 4) { + color = fragment_color * T0; + color.w = 0; } } diff --git a/goal_src/engine/draw/drawable.gc b/goal_src/engine/draw/drawable.gc index 0a4ecf9b9..49ccfb78a 100644 --- a/goal_src/engine/draw/drawable.gc +++ b/goal_src/engine/draw/drawable.gc @@ -907,6 +907,8 @@ (define *generic-effect-mode* 0) (defun real-main-draw-hook () + "The main drawing function. This dispatches all renderers and is called directly from the display-loop + in main.gc." (when *slow-frame-rate* (dotimes (v1-2 40000000) ;; was 50000 (nop!) @@ -918,106 +920,109 @@ ) ) "Function to be executed to set up for engine dma" - + ;; update render enables from the debug menu (set! *vu1-enable-user* *vu1-enable-user-menu*) (set! *texture-enable-user* *texture-enable-user-menu*) - + ;; reset and display dma memory stats. (when *debug-segment* - (when (or *stats-memory* *stats-memory-short*) - (dotimes (gp-0 (-> *level* length)) - (let ((s5-0 (-> *level* level gp-0))) - (if (= (-> s5-0 status) 'active) - (print-mem-usage (compute-memory-usage s5-0 #f) s5-0 *stdcon*) - ) + (when (or *stats-memory* *stats-memory-short*) + (dotimes (gp-0 (-> *level* length)) + (let ((s5-0 (-> *level* level gp-0))) + (if (= (-> s5-0 status) 'active) + (print-mem-usage (compute-memory-usage s5-0 #f) s5-0 *stdcon*) + ) + ) + ) ) - ) + (reset! *dma-mem-usage*) ) - (reset! *dma-mem-usage*) - ) - + ;; todo shrub matrix - ;; todo generic init + + ;; initialize dma buckets that are generic sinks. + ;; other renderers may output to these, so do them first. (generic-init-buffers) - + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; texture uploads ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - - ;; tfrag - ;; note: PC port uses preconverted tfrag textures. - ; (#unless PC_PORT - (when (logtest? *texture-enable-user* 1) - (dotimes (gp-1 (-> *level* length)) - (let ((a1-2 (-> *level* level gp-1))) - (if (= (-> a1-2 status) 'active) - (add-tex-to-dma! *texture-pool* a1-2 0) - ) - ) - ) - ) - ; ) - - ;; pris - + + ;; next we use the texture system to build DMA commands to load texture. + ;; internally, add-tex-to-dma! has special logic to avoid loading textures + ;; that won't be used. (though it's pretty basic, it doesn't actually track per-texture usage) + + ;; level tfrag's upload if the level is running. + (when (logtest? *texture-enable-user* 1) + (dotimes (gp-1 (-> *level* length)) + (let ((a1-2 (-> *level* level gp-1))) + (if (= (-> a1-2 status) 'active) + (add-tex-to-dma! *texture-pool* a1-2 0) + ) + ) + ) + ) + ;; level pris's upload if the level is running. (when (logtest? *texture-enable-user* 2) - (dotimes (gp-2 (-> *level* length)) - (let ((a1-3 (-> *level* level gp-2))) - (if (= (-> a1-3 status) 'active) - (add-tex-to-dma! *texture-pool* a1-3 1) + (dotimes (gp-2 (-> *level* length)) + (let ((a1-3 (-> *level* level gp-2))) + (if (= (-> a1-3 status) 'active) + (add-tex-to-dma! *texture-pool* a1-3 1) + ) + ) ) - ) ) - ) - - ;; shrub - + + ;; level shrubs upload if the level is loading. (when (logtest? *texture-enable-user* 4) - (dotimes (gp-3 (-> *level* length)) - (let ((a1-4 (-> *level* level gp-3))) - (if (= (-> a1-4 status) 'active) - (add-tex-to-dma! *texture-pool* a1-4 2) + (dotimes (gp-3 (-> *level* length)) + (let ((a1-4 (-> *level* level gp-3))) + (if (= (-> a1-4 status) 'active) + (add-tex-to-dma! *texture-pool* a1-4 2) + ) + ) ) - ) ) - ) - + ;; alpha and common. (when (logtest? *texture-enable-user* 8) - (let ((uploaded-common #f)) - (dotimes (gp-4 (-> *level* length)) - (let ((a1-5 (-> *level* level gp-4))) - (when (= (-> a1-5 status) 'active) - (add-tex-to-dma! *texture-pool* a1-5 3) - (when (not uploaded-common) - (upload-one-common! *texture-pool* (-> *level* level0)) - (set! uploaded-common #t) + (let ((uploaded-common #f)) + (dotimes (gp-4 (-> *level* length)) + (let ((a1-5 (-> *level* level gp-4))) + (when (= (-> a1-5 status) 'active) + (add-tex-to-dma! *texture-pool* a1-5 3) + (when (not uploaded-common) + (upload-one-common! *texture-pool* (-> *level* level0)) + (set! uploaded-common #t) + ) + ) + ) + ) + (when (not uploaded-common) + (upload-one-common! *texture-pool* (-> *level* level0)) + #t ) - ) ) - ) - (when (not uploaded-common) - (upload-one-common! *texture-pool* (-> *level* level0)) - #t - ) ) - ) - + ;; water. (when (logtest? *texture-enable-user* 16) - (dotimes (gp-5 (-> *level* length)) - (let ((a1-8 (-> *level* level gp-5))) - (if (= (-> a1-8 status) 'active) - (add-tex-to-dma! *texture-pool* a1-8 4) + (dotimes (gp-5 (-> *level* length)) + (let ((a1-8 (-> *level* level gp-5))) + (if (= (-> a1-8 status) 'active) + (add-tex-to-dma! *texture-pool* a1-8 4) + ) + ) ) - ) ) - ) - + + ;;;;;;;;;;;;; ;; sky - ;; todo - disabled sky - (when (zero? (logand *vu1-enable-user* 8)) + ;;;;;;;;;;;;; + + (when (zero? (logand *vu1-enable-user* (vu1-renderer-mask sky))) + ;; the sky is disabled. Just draw a solid gradient on the whole screen. (with-dma-buffer-add-bucket ((dma-buf (-> (current-frame) global-buf)) (bucket-id sky-draw)) (dma-buffer-add-gs-set dma-buf (zbuf-1 (new 'static 'gs-zbuf :zbp #x1c0 :psm (gs-psm ct24))) @@ -1033,28 +1038,63 @@ ) ) ) - (when (logtest? *vu1-enable-user* 8) + (when (logtest? *vu1-enable-user* (vu1-renderer-mask sky)) + ;; check if we want the sky, and if we actually have textures ready. + ;; we generate sky textures on the previous frame and they sit in vram (8160) until the next frame. + ;; on the first frame after we request sky, we draw the textures, but they aren't ready until the next frame. (cond ((and (-> *time-of-day-context* sky) *sky-drawn*) (render-sky-tng *time-of-day-context*) ) (else ;; todo + (with-dma-buffer-add-bucket ((dma-buf (-> (current-frame) global-buf)) (bucket-id sky-draw)) + (dma-buffer-add-gs-set dma-buf + (zbuf-1 (new 'static 'gs-zbuf :zbp #x1c0 :psm (gs-psm ct24))) + (test-1 (new 'static 'gs-test :ate #x1 :atst (gs-atest always) :zte #x1 :ztst (gs-ztest always))) + (alpha-1 (new 'static 'gs-alpha :b #x1 :d #x1)) + ) + (screen-gradient + dma-buf + (-> *time-of-day-context* erase-color) + (-> *time-of-day-context* erase-color) + (-> *time-of-day-context* erase-color) + (-> *time-of-day-context* erase-color) + ) + ) ) ) ) - - ;; tod update + + + ;; update mood lighting, draw sky textures. (update-time-of-day *time-of-day-context*) - ;; closest - (update-ocean) - (draw-ocean) + + ;; reset the closest object and desired texture masks for all levels. + (dotimes (v1-150 (-> *level* length)) + (let ((a0-59 (-> *level* level v1-150))) + (when (= (-> a0-59 status) 'active) + (dotimes (a1-38 9) + (set! (-> a0-59 closest-object a1-38) 4095996000.0) + (set! (-> a0-59 texture-mask a1-38) (the-as uint 0)) + ) + ) + ) + ) + (add-ee-profile-frame 'draw :r #x40 :b #x40 :a #x80) + + ;;;;;;; OCEAN + (update-ocean) ;; ocean map update + (draw-ocean) ;; far, mid, near, transition, and texture. + (add-ee-profile-frame 'draw :b #xff :a #x80) + + ;; reset MERC (set! (-> *merc-global-array* count) (the-as uint 0)) (set! *merc-globals* (the-as merc-globals (-> *merc-global-array* globals))) (set! (-> *shadow-queue* cur-run) (the-as uint 0)) - (init-background) - ;; exec bg + ;; draw the background! + (init-background) (execute-connections *background-draw-engine* (-> *display* frames (-> *display* on-screen) frame)) ;; finish bg (most of the work is here) @@ -1063,7 +1103,7 @@ (read! (-> *perf-stats* data 3)) (update-wait-stats (-> *perf-stats* data 3) (-> *background-work* wait-to-vu0) (the-as uint 0) (the-as uint 0)) - ;; + ;; perf stats are printed and restarted here, for some reason. (end-perf-stat-collection) (when (not (paused?)) (when *stats-poly* @@ -1081,6 +1121,8 @@ ) ) (start-perf-stat-collection) + + ;; draw the foreground engines. (foreground-engine-execute (-> *level* level-default foreground-draw-engine 0) (-> *display* frames (-> *display* on-screen) frame) @@ -1093,30 +1135,36 @@ 2 1 ) + + ;; handle extra processing for foreground (let ((gp-9 (-> *display* frames (-> *display* on-screen) frame global-buf))) - (bones-mtx-calc-execute) - (generic-merc-execute-all gp-9) + (bones-mtx-calc-execute) ;; skinning matrix calculation + (generic-merc-execute-all gp-9) ;; mercneric conversion. ;;(shadow-execute-all gp-9 *shadow-queue*) + (update-eyes) ) - ;; fg engine - ;; bones - ;; gmerc - ;; shadow - (update-eyes) + + ;; sprite draw (when (logtest? (vu1-renderer-mask sprite) *vu1-enable-user*) (swap-fake-shadow-buffers) (sprite-draw *display*) ) - ;; lots more in this function. + ;; debug drawing (when *debug-segment* (debug-draw-actors *level* *display-actor-marks*) (collide-shape-draw-debug-marks) ) (render-boundaries) + + ;; for some reason we clear the touching list here... (send-events-for-touching-shapes *touching-list*) (free-all-prim-nodes *touching-list*) + (add-ee-profile-frame 'draw :r #x40 :b #x40 :a #x80) + ;; spawn actors, compact heaps, etc. (actors-update *level*) + (add-ee-profile-frame 'draw :r #x80 :a #x80) + (when (not (paused?)) (if *stats-collide* (print-collide-stats) diff --git a/goal_src/engine/gfx/ocean/ocean-mid.gc b/goal_src/engine/gfx/ocean/ocean-mid.gc index ef26f87ea..296d4eb98 100644 --- a/goal_src/engine/gfx/ocean/ocean-mid.gc +++ b/goal_src/engine/gfx/ocean/ocean-mid.gc @@ -1232,9 +1232,6 @@ ) ) - ; (dotimes (i 36) - ; (format 0 "tidx: ~d ~X~%" i (-> *ocean-work* mid-camera-masks i)) - ; ) ;; for now, skip seams. ;; when it's both on and cam is low