mirror of
https://github.com/open-goal/jak-project
synced 2026-07-07 22:22:21 -04:00
[jak2] WIP minimap (#2280)
Work in progress minimap. Known issues: - "path finding" doesn't appear to work - it gets stuck forever in many cases - some nasty patches around timer-based code - jak arrow blending issues - would be nice to make it higher resolution if the search is forced to terminate due to iteration/time limits, the icon is not in the right place 
This commit is contained in:
@@ -1059,7 +1059,9 @@ goos::Object decompile_structure(const TypeSpec& type,
|
||||
enum ByteStatus : u8 { ZERO_UNREAD, HAS_DATA_UNREAD, ZERO_READ, HAS_DATA_READ };
|
||||
std::vector<int> field_status_per_byte;
|
||||
for (int i = 0; i < byte_count; i++) {
|
||||
auto& w = obj_words.at(i / 4);
|
||||
// auto& w = obj_words.at(i / 4);
|
||||
int b = (offset_location + i);
|
||||
auto& w = words.at(label.target_segment).at(b / 4);
|
||||
switch (w.kind()) {
|
||||
case LinkedWord::TYPE_PTR:
|
||||
case LinkedWord::PTR:
|
||||
@@ -1068,7 +1070,7 @@ goos::Object decompile_structure(const TypeSpec& type,
|
||||
field_status_per_byte.push_back(HAS_DATA_UNREAD);
|
||||
break;
|
||||
case LinkedWord::PLAIN_DATA: {
|
||||
field_status_per_byte.push_back(w.get_byte(i % 4) ? HAS_DATA_UNREAD : ZERO_UNREAD);
|
||||
field_status_per_byte.push_back(w.get_byte(b % 4) ? HAS_DATA_UNREAD : ZERO_UNREAD);
|
||||
} break;
|
||||
default:
|
||||
throw std::runtime_error("Unsupported word in static data");
|
||||
@@ -1209,7 +1211,11 @@ goos::Object decompile_structure(const TypeSpec& type,
|
||||
}
|
||||
std::vector<u8> bytes_out;
|
||||
for (int byte_idx = field_start; byte_idx < field_end; byte_idx++) {
|
||||
bytes_out.push_back(obj_words.at(byte_idx / 4).get_byte(byte_idx % 4));
|
||||
int byte_idx_in_seg = byte_idx + label.offset - type_info->get_offset();
|
||||
bytes_out.push_back(words.at(label.target_segment)
|
||||
.at(byte_idx_in_seg / 4)
|
||||
.get_byte(byte_idx_in_seg % 4));
|
||||
// bytes_out.push_back(obj_words.at(byte_idx / 4).get_byte(byte_idx % 4));
|
||||
}
|
||||
|
||||
// use more specific types for gif tags.
|
||||
|
||||
@@ -158,6 +158,7 @@ set(RUNTIME_SOURCE
|
||||
graphics/opengl_renderer/opengl_utils.cpp
|
||||
graphics/opengl_renderer/OpenGLRenderer.cpp
|
||||
graphics/opengl_renderer/Profiler.cpp
|
||||
graphics/opengl_renderer/ProgressRenderer.cpp
|
||||
graphics/opengl_renderer/Shader.cpp
|
||||
graphics/opengl_renderer/Shadow_PS2.cpp
|
||||
graphics/opengl_renderer/ShadowRenderer.cpp
|
||||
|
||||
@@ -54,6 +54,15 @@ DirectRenderer::DirectRenderer(const std::string& name, int my_id, int batch_siz
|
||||
sizeof(Vertex), //
|
||||
(void*)offsetof(Vertex, tex_unit) // offset in array (why is this a pointer...)
|
||||
);
|
||||
|
||||
glEnableVertexAttribArray(4);
|
||||
glVertexAttribIPointer(
|
||||
4, // location 4 in the shader
|
||||
1, // 3 floats per vert
|
||||
GL_UNSIGNED_BYTE, // floats
|
||||
sizeof(Vertex), //
|
||||
(void*)offsetof(Vertex, use_uv) // offset in array (why is this a pointer...)
|
||||
);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
@@ -69,6 +78,7 @@ DirectRenderer::~DirectRenderer() {
|
||||
void DirectRenderer::render(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
pre_render();
|
||||
// if we're rendering from a bucket, we should start off we a totally reset state:
|
||||
reset_state();
|
||||
setup_common_state(render_state);
|
||||
@@ -91,6 +101,8 @@ void DirectRenderer::render(DmaFollower& dma,
|
||||
if (m_enabled) {
|
||||
flush_pending(render_state, prof);
|
||||
}
|
||||
post_render();
|
||||
glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||
}
|
||||
|
||||
void DirectRenderer::reset_state() {
|
||||
@@ -135,6 +147,7 @@ void DirectRenderer::draw_debug_window() {
|
||||
ImGui::Text(" tex1: %d", m_stats.flush_from_tex_1);
|
||||
ImGui::Text(" zbuf: %d", m_stats.flush_from_zbuf);
|
||||
ImGui::Text(" test: %d", m_stats.flush_from_test);
|
||||
ImGui::Text(" ta0: %d", m_stats.flush_from_ta0);
|
||||
ImGui::Text(" alph: %d", m_stats.flush_from_alpha);
|
||||
ImGui::Text(" clmp: %d", m_stats.flush_from_clamp);
|
||||
ImGui::Text(" prim: %d", m_stats.flush_from_prim);
|
||||
@@ -251,6 +264,7 @@ void DirectRenderer::update_gl_prim(SharedRenderState* render_state) {
|
||||
case GsTest::AlphaTest::ALWAYS:
|
||||
break;
|
||||
case GsTest::AlphaTest::GEQUAL:
|
||||
case GsTest::AlphaTest::GREATER: // todo
|
||||
alpha_reject = m_test_state.aref / 128.f;
|
||||
break;
|
||||
case GsTest::AlphaTest::NEVER:
|
||||
@@ -274,6 +288,12 @@ void DirectRenderer::update_gl_prim(SharedRenderState* render_state) {
|
||||
"fog_color"),
|
||||
render_state->fog_color[0] / 255.f, render_state->fog_color[1] / 255.f,
|
||||
render_state->fog_color[2] / 255.f, render_state->fog_intensity / 255);
|
||||
glUniform1i(glGetUniformLocation(render_state->shaders[ShaderId::DIRECT_BASIC_TEXTURED].id(),
|
||||
"offscreen_mode"),
|
||||
m_offscreen_mode);
|
||||
glUniform1f(
|
||||
glGetUniformLocation(render_state->shaders[ShaderId::DIRECT_BASIC_TEXTURED].id(), "ta0"),
|
||||
state.ta0 / 255.f);
|
||||
|
||||
} else {
|
||||
render_state->shaders[ShaderId::DIRECT_BASIC].activate();
|
||||
@@ -359,6 +379,7 @@ void DirectRenderer::update_gl_blend() {
|
||||
// glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
|
||||
} else if (state.a == GsAlpha::BlendMode::SOURCE &&
|
||||
state.b == GsAlpha::BlendMode::ZERO_OR_FIXED &&
|
||||
state.c == GsAlpha::BlendMode::SOURCE && state.d == GsAlpha::BlendMode::DEST) {
|
||||
@@ -442,6 +463,12 @@ void DirectRenderer::update_gl_test() {
|
||||
} else {
|
||||
glDepthMask(GL_FALSE);
|
||||
}
|
||||
|
||||
if (state.write_rgb) {
|
||||
glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||
} else {
|
||||
glColorMaski(0, GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
void DirectRenderer::setup_common_state(SharedRenderState* /*render_state*/) {
|
||||
@@ -658,7 +685,7 @@ void DirectRenderer::handle_ad(const u8* data,
|
||||
handle_tex1_1(value);
|
||||
break;
|
||||
case GsRegisterAddress::TEXA:
|
||||
handle_texa(value);
|
||||
handle_texa(value, render_state, prof);
|
||||
break;
|
||||
case GsRegisterAddress::TEXCLUT:
|
||||
// TODO
|
||||
@@ -679,6 +706,7 @@ void DirectRenderer::handle_ad(const u8* data,
|
||||
case GsRegisterAddress::TEXFLUSH:
|
||||
break;
|
||||
case GsRegisterAddress::FRAME_1:
|
||||
handle_frame(value, render_state, prof);
|
||||
break;
|
||||
case GsRegisterAddress::RGBAQ:
|
||||
// shadow scissor does this?
|
||||
@@ -690,11 +718,28 @@ void DirectRenderer::handle_ad(const u8* data,
|
||||
memcpy(&m_prim_building.Q, data + 4, 4);
|
||||
}
|
||||
break;
|
||||
case GsRegisterAddress::SCISSOR_1:
|
||||
// fmt::print("ignoring scissor\n");
|
||||
break;
|
||||
case GsRegisterAddress::XYOFFSET_1:
|
||||
ASSERT(render_state->version == GameVersion::Jak2); // hardcoded jak 2 scissor vals in handle
|
||||
handle_xyoffset(value);
|
||||
break;
|
||||
default:
|
||||
ASSERT_MSG(false, fmt::format("Address {} is not supported", register_address_name(addr)));
|
||||
}
|
||||
}
|
||||
|
||||
void DirectRenderer::handle_frame(u64, SharedRenderState*, ScopedProfilerNode&) {}
|
||||
|
||||
void DirectRenderer::handle_xyoffset(u64 val) {
|
||||
GsXYOffset xyo(val);
|
||||
// :ofx #x7000 :ofy #x7300
|
||||
float scale = -65536;
|
||||
m_prim_buffer.x_off = scale * ((s32)xyo.ofx() - 0x7000) / float(UINT32_MAX);
|
||||
m_prim_buffer.y_off = scale * ((s32)xyo.ofy() - 0x7300) / float(UINT32_MAX);
|
||||
}
|
||||
|
||||
void DirectRenderer::handle_tex1_1(u64 val) {
|
||||
GsTex1 reg(val);
|
||||
// for now, we aren't going to handle mipmapping. I don't think it's used with direct.
|
||||
@@ -750,17 +795,6 @@ void DirectRenderer::handle_tex0_1(u64 val) {
|
||||
// csm: assume they got it right
|
||||
}
|
||||
|
||||
void DirectRenderer::handle_texa(u64 val) {
|
||||
GsTexa reg(val);
|
||||
|
||||
// rgba16 isn't used so this doesn't matter?
|
||||
// but they use sane defaults anyway
|
||||
ASSERT(reg.ta0() == 0);
|
||||
ASSERT(reg.ta1() == 0x80); // note: check rgba16_to_rgba32 if this changes.
|
||||
|
||||
ASSERT(reg.aem() == false);
|
||||
}
|
||||
|
||||
void DirectRenderer::handle_st_packed(const u8* data) {
|
||||
memcpy(&m_prim_building.st_reg.x(), data + 0, 4);
|
||||
memcpy(&m_prim_building.st_reg.y(), data + 4, 4);
|
||||
@@ -773,7 +807,7 @@ void DirectRenderer::handle_uv_packed(const u8* data) {
|
||||
memcpy(&v, data + 4, 4);
|
||||
m_prim_building.st_reg.x() = u;
|
||||
m_prim_building.st_reg.y() = v;
|
||||
m_prim_building.Q = 16.f;
|
||||
m_prim_building.Q = 1;
|
||||
}
|
||||
|
||||
void DirectRenderer::handle_rgbaq_packed(const u8* data) {
|
||||
@@ -852,7 +886,26 @@ void DirectRenderer::handle_test1(u64 val,
|
||||
m_prim_gl_state_needs_gl_update = true;
|
||||
}
|
||||
}
|
||||
void DirectRenderer::handle_texa(u64 val,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
GsTexa reg(val);
|
||||
|
||||
// rgba16 isn't used so this doesn't matter?
|
||||
// but they use sane defaults anyway
|
||||
// ASSERT(reg.ta0() == 0); TODO
|
||||
if (m_prim_gl_state.ta0 != reg.ta0()) {
|
||||
m_stats.flush_from_ta0++;
|
||||
flush_pending(render_state, prof);
|
||||
m_prim_gl_state.ta0 = reg.ta0();
|
||||
m_test_state_needs_gl_update = true;
|
||||
m_prim_gl_state_needs_gl_update = true;
|
||||
m_blend_state_needs_gl_update = true;
|
||||
}
|
||||
ASSERT(reg.ta1() == 0x80); // note: check rgba16_to_rgba32 if this changes.
|
||||
|
||||
ASSERT(reg.aem() == false);
|
||||
}
|
||||
void DirectRenderer::handle_alpha1(u64 val,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
@@ -965,6 +1018,7 @@ void DirectRenderer::handle_xyzf2_common(u32 x,
|
||||
bool tcc = m_buffered_tex_state[tex_unit].tcc;
|
||||
bool decal = m_buffered_tex_state[tex_unit].decal;
|
||||
bool fge = m_prim_gl_state.fogging_enable;
|
||||
bool use_uv = m_prim_gl_state.use_uv;
|
||||
|
||||
switch (m_prim_building.kind) {
|
||||
case GsPrim::Kind::SPRITE: {
|
||||
@@ -990,12 +1044,12 @@ void DirectRenderer::handle_xyzf2_common(u32 x,
|
||||
auto& corner3_rgba = corner2_rgba;
|
||||
auto& corner4_rgba = corner2_rgba;
|
||||
|
||||
m_prim_buffer.push(corner1_rgba, corner1_vert, corner1_stq, 0, tcc, decal, fge);
|
||||
m_prim_buffer.push(corner3_rgba, corner3_vert, corner3_stq, 0, tcc, decal, fge);
|
||||
m_prim_buffer.push(corner2_rgba, corner2_vert, corner2_stq, 0, tcc, decal, fge);
|
||||
m_prim_buffer.push(corner2_rgba, corner2_vert, corner2_stq, 0, tcc, decal, fge);
|
||||
m_prim_buffer.push(corner4_rgba, corner4_vert, corner4_stq, 0, tcc, decal, fge);
|
||||
m_prim_buffer.push(corner1_rgba, corner1_vert, corner1_stq, 0, tcc, decal, fge);
|
||||
m_prim_buffer.push(corner1_rgba, corner1_vert, corner1_stq, 0, tcc, decal, fge, use_uv);
|
||||
m_prim_buffer.push(corner3_rgba, corner3_vert, corner3_stq, 0, tcc, decal, fge, use_uv);
|
||||
m_prim_buffer.push(corner2_rgba, corner2_vert, corner2_stq, 0, tcc, decal, fge, use_uv);
|
||||
m_prim_buffer.push(corner2_rgba, corner2_vert, corner2_stq, 0, tcc, decal, fge, use_uv);
|
||||
m_prim_buffer.push(corner4_rgba, corner4_vert, corner4_stq, 0, tcc, decal, fge, use_uv);
|
||||
m_prim_buffer.push(corner1_rgba, corner1_vert, corner1_stq, 0, tcc, decal, fge, use_uv);
|
||||
m_prim_building.building_idx = 0;
|
||||
}
|
||||
} break;
|
||||
@@ -1011,7 +1065,7 @@ void DirectRenderer::handle_xyzf2_common(u32 x,
|
||||
if (advance) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
m_prim_buffer.push(m_prim_building.building_rgba[i], m_prim_building.building_vert[i],
|
||||
m_prim_building.building_stq[i], tex_unit, tcc, decal, fge);
|
||||
m_prim_building.building_stq[i], tex_unit, tcc, decal, fge, use_uv);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1023,7 +1077,7 @@ void DirectRenderer::handle_xyzf2_common(u32 x,
|
||||
m_prim_building.building_idx = 0;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
m_prim_buffer.push(m_prim_building.building_rgba[i], m_prim_building.building_vert[i],
|
||||
m_prim_building.building_stq[i], tex_unit, tcc, decal, fge);
|
||||
m_prim_building.building_stq[i], tex_unit, tcc, decal, fge, use_uv);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1039,7 +1093,7 @@ void DirectRenderer::handle_xyzf2_common(u32 x,
|
||||
}
|
||||
for (int i = 0; i < 3; i++) {
|
||||
m_prim_buffer.push(m_prim_building.building_rgba[i], m_prim_building.building_vert[i],
|
||||
m_prim_building.building_stq[i], tex_unit, tcc, decal, fge);
|
||||
m_prim_building.building_stq[i], tex_unit, tcc, decal, fge, use_uv);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
@@ -1064,13 +1118,13 @@ void DirectRenderer::handle_xyzf2_common(u32 x,
|
||||
math::Vector<u32, 4> di{d.x(), d.y(), d.z(), 0};
|
||||
|
||||
// ACB:
|
||||
m_prim_buffer.push(m_prim_building.building_rgba[0], ai, {}, 0, false, false, false);
|
||||
m_prim_buffer.push(m_prim_building.building_rgba[0], ci, {}, 0, false, false, false);
|
||||
m_prim_buffer.push(m_prim_building.building_rgba[1], bi, {}, 0, false, false, false);
|
||||
m_prim_buffer.push(m_prim_building.building_rgba[0], ai, {}, 0, false, false, false, false);
|
||||
m_prim_buffer.push(m_prim_building.building_rgba[0], ci, {}, 0, false, false, false, false);
|
||||
m_prim_buffer.push(m_prim_building.building_rgba[1], bi, {}, 0, false, false, false, false);
|
||||
// b c d
|
||||
m_prim_buffer.push(m_prim_building.building_rgba[1], bi, {}, 0, false, false, false);
|
||||
m_prim_buffer.push(m_prim_building.building_rgba[0], ci, {}, 0, false, false, false);
|
||||
m_prim_buffer.push(m_prim_building.building_rgba[1], di, {}, 0, false, false, false);
|
||||
m_prim_buffer.push(m_prim_building.building_rgba[1], bi, {}, 0, false, false, false, false);
|
||||
m_prim_buffer.push(m_prim_building.building_rgba[0], ci, {}, 0, false, false, false, false);
|
||||
m_prim_buffer.push(m_prim_building.building_rgba[1], di, {}, 0, false, false, false, false);
|
||||
//
|
||||
|
||||
m_prim_building.building_idx = 0;
|
||||
@@ -1142,11 +1196,14 @@ void DirectRenderer::PrimitiveBuffer::push(const math::Vector<u8, 4>& rgba,
|
||||
int unit,
|
||||
bool tcc,
|
||||
bool decal,
|
||||
bool fog_enable) {
|
||||
bool fog_enable,
|
||||
bool use_uv) {
|
||||
auto& v = vertices[vert_count];
|
||||
v.rgba = rgba;
|
||||
v.xyzf[0] = (float)vert[0] / (float)UINT32_MAX;
|
||||
v.xyzf[0] += x_off;
|
||||
v.xyzf[1] = (float)vert[1] / (float)UINT32_MAX;
|
||||
v.xyzf[1] += y_off;
|
||||
v.xyzf[2] = (float)vert[2] / (float)0xffffff;
|
||||
v.xyzf[3] = (float)vert[3];
|
||||
v.stq = st;
|
||||
@@ -1154,5 +1211,6 @@ void DirectRenderer::PrimitiveBuffer::push(const math::Vector<u8, 4>& rgba,
|
||||
v.tcc = tcc;
|
||||
v.decal = decal;
|
||||
v.fog_enable = fog_enable;
|
||||
v.use_uv = use_uv;
|
||||
vert_count++;
|
||||
}
|
||||
|
||||
@@ -23,7 +23,8 @@ class DirectRenderer : public BucketRenderer {
|
||||
DirectRenderer(const std::string& name, int my_id, int batch_size);
|
||||
~DirectRenderer();
|
||||
void render(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof) override;
|
||||
|
||||
virtual void pre_render() {}
|
||||
virtual void post_render() {}
|
||||
/*!
|
||||
* Render directly from _VIF_ data.
|
||||
* You can optionally provide two vif tags that come in front of data.
|
||||
@@ -66,22 +67,9 @@ class DirectRenderer : public BucketRenderer {
|
||||
}
|
||||
|
||||
void set_mipmap(bool en) { m_debug_state.disable_mipmap = !en; }
|
||||
|
||||
private:
|
||||
void handle_ad(const u8* data, SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
void handle_zbuf1(u64 val, SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
void handle_test1(u64 val, SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
void handle_alpha1(u64 val, SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
void handle_pabe(u64 val);
|
||||
void handle_clamp1(u64 val);
|
||||
void handle_prim(u64 val, SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
void handle_prim_packed(const u8* data,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof);
|
||||
void handle_rgbaq(u64 val);
|
||||
void handle_xyzf2(u64 val, SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
void handle_ad(const u8* data, SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
void handle_st_packed(const u8* data);
|
||||
void handle_uv_packed(const u8* data);
|
||||
void handle_rgbaq_packed(const u8* data);
|
||||
void handle_xyzf2_packed(const u8* data,
|
||||
SharedRenderState* render_state,
|
||||
@@ -89,11 +77,25 @@ class DirectRenderer : public BucketRenderer {
|
||||
void handle_xyz2_packed(const u8* data,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof);
|
||||
void handle_prim_packed(const u8* data,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof);
|
||||
void handle_tex0_1_packed(const u8* data);
|
||||
void handle_uv_packed(const u8* data);
|
||||
void handle_rgbaq(u64 val);
|
||||
void handle_xyzf2(u64 val, SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
|
||||
protected:
|
||||
virtual void handle_frame(u64 val, SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
void handle_zbuf1(u64 val, SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
void handle_test1(u64 val, SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
void handle_alpha1(u64 val, SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
void handle_pabe(u64 val);
|
||||
void handle_clamp1(u64 val);
|
||||
void handle_tex0_1(u64 val);
|
||||
void handle_tex1_1(u64 val);
|
||||
void handle_texa(u64 val);
|
||||
|
||||
void handle_texa(u64 val, SharedRenderState* render_state, ScopedProfilerNode& prof);
|
||||
void handle_xyoffset(u64 val);
|
||||
void handle_xyzf2_common(u32 x,
|
||||
u32 y,
|
||||
u32 z,
|
||||
@@ -106,6 +108,7 @@ class DirectRenderer : public BucketRenderer {
|
||||
void update_gl_blend();
|
||||
void update_gl_test();
|
||||
void update_gl_texture(SharedRenderState* render_state, int unit);
|
||||
bool m_offscreen_mode = false;
|
||||
|
||||
struct TestState {
|
||||
void from_register(GsTest reg);
|
||||
@@ -120,7 +123,7 @@ class DirectRenderer : public BucketRenderer {
|
||||
bool datm = false;
|
||||
bool zte = true;
|
||||
GsTest::ZTest ztst = GsTest::ZTest::GEQUAL;
|
||||
|
||||
bool write_rgb = true;
|
||||
bool depth_writes = true;
|
||||
|
||||
} m_test_state;
|
||||
@@ -151,6 +154,7 @@ class DirectRenderer : public BucketRenderer {
|
||||
bool use_uv = false; // todo: might not require a gl state change
|
||||
bool ctxt = false; // do they ever use ctxt2?
|
||||
bool fix = false; // what does this even do?
|
||||
u32 ta0 = 0;
|
||||
} m_prim_gl_state;
|
||||
|
||||
static constexpr int TEXTURE_STATE_COUNT = 1;
|
||||
@@ -161,7 +165,6 @@ class DirectRenderer : public BucketRenderer {
|
||||
bool using_mt4hh = false;
|
||||
bool tcc = false;
|
||||
bool decal = false;
|
||||
|
||||
bool enable_tex_filt = true;
|
||||
|
||||
struct ClampState {
|
||||
@@ -206,7 +209,6 @@ class DirectRenderer : public BucketRenderer {
|
||||
int tri_strip_startup = 0;
|
||||
|
||||
float Q = 1.0;
|
||||
|
||||
} m_prim_building;
|
||||
|
||||
struct Vertex {
|
||||
@@ -217,7 +219,8 @@ class DirectRenderer : public BucketRenderer {
|
||||
u8 tcc;
|
||||
u8 decal;
|
||||
u8 fog_enable;
|
||||
math::Vector<u8, 28> pad;
|
||||
u8 use_uv;
|
||||
math::Vector<u8, 27> pad;
|
||||
};
|
||||
static_assert(sizeof(Vertex) == 64);
|
||||
static_assert(offsetof(Vertex, tex_unit) == 32);
|
||||
@@ -227,7 +230,8 @@ class DirectRenderer : public BucketRenderer {
|
||||
std::vector<Vertex> vertices;
|
||||
int vert_count = 0;
|
||||
int max_verts = 0;
|
||||
|
||||
float x_off = 0;
|
||||
float y_off = 0;
|
||||
// leave 6 free on the end so we always have room to flush one last primitive.
|
||||
bool is_full() { return max_verts < (vert_count + 18); }
|
||||
void push(const math::Vector<u8, 4>& rgba,
|
||||
@@ -236,7 +240,8 @@ class DirectRenderer : public BucketRenderer {
|
||||
int unit,
|
||||
bool tcc,
|
||||
bool decal,
|
||||
bool fog_enable);
|
||||
bool fog_enable,
|
||||
bool use_uv);
|
||||
} m_prim_buffer;
|
||||
|
||||
struct {
|
||||
@@ -264,6 +269,7 @@ class DirectRenderer : public BucketRenderer {
|
||||
int flush_from_tex_1 = 0;
|
||||
int flush_from_zbuf = 0;
|
||||
int flush_from_test = 0;
|
||||
int flush_from_ta0 = 0;
|
||||
int flush_from_alpha = 0;
|
||||
int flush_from_clamp = 0;
|
||||
int flush_from_prim = 0;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "game/graphics/opengl_renderer/DirectRenderer.h"
|
||||
#include "game/graphics/opengl_renderer/EyeRenderer.h"
|
||||
#include "game/graphics/opengl_renderer/LightningRenderer.h"
|
||||
#include "game/graphics/opengl_renderer/ProgressRenderer.h"
|
||||
#include "game/graphics/opengl_renderer/ShadowRenderer.h"
|
||||
#include "game/graphics/opengl_renderer/SkyRenderer.h"
|
||||
#include "game/graphics/opengl_renderer/TextureUploadHandler.h"
|
||||
@@ -310,8 +311,8 @@ void OpenGLRenderer::init_bucket_renderers_jak2() {
|
||||
init_bucket_renderer<TextureUploadHandler>("tex-all-map", BucketCategory::TEX,
|
||||
BucketId::TEX_ALL_MAP);
|
||||
// 320
|
||||
init_bucket_renderer<DirectRenderer>("progress", BucketCategory::OTHER, BucketId::PROGRESS,
|
||||
0x8000);
|
||||
init_bucket_renderer<ProgressRenderer>("progress", BucketCategory::OTHER, BucketId::PROGRESS,
|
||||
0x8000);
|
||||
init_bucket_renderer<DirectRenderer>("screen-filter", BucketCategory::OTHER,
|
||||
BucketId::SCREEN_FILTER, 256);
|
||||
init_bucket_renderer<DirectRenderer>("bucket-322", BucketCategory::OTHER, BucketId::BUCKET_322,
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
#include "ProgressRenderer.h"
|
||||
|
||||
ProgressRenderer::ProgressRenderer(const std::string& name, int my_id, int batch_size)
|
||||
: DirectRenderer(name, my_id, batch_size),
|
||||
m_minimap_fb(kMinimapWidth, kMinimapHeight, GL_UNSIGNED_INT_8_8_8_8_REV) {}
|
||||
|
||||
void ProgressRenderer::pre_render() {
|
||||
m_current_fbp = kScreenFbp;
|
||||
}
|
||||
|
||||
void ProgressRenderer::post_render() {
|
||||
m_fb_ctxt.reset();
|
||||
m_offscreen_mode = false;
|
||||
}
|
||||
|
||||
void ProgressRenderer::init_textures(TexturePool& texture_pool, GameVersion) {
|
||||
TextureInput in;
|
||||
in.gpu_texture = m_minimap_fb.texture();
|
||||
in.w = kMinimapWidth;
|
||||
in.h = kMinimapHeight;
|
||||
in.debug_page_name = "PC-MAP";
|
||||
in.debug_name = "map";
|
||||
in.id = texture_pool.allocate_pc_port_texture();
|
||||
m_minimap_gpu_tex = texture_pool.give_texture_and_load_to_vram(in, kMinimapVramAddr);
|
||||
}
|
||||
|
||||
void ProgressRenderer::handle_frame(u64 val,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
GsFrame f(val);
|
||||
u32 fbp = f.fbp();
|
||||
bool flushed = false;
|
||||
if (fbp != m_current_fbp) {
|
||||
flush_pending(render_state, prof);
|
||||
flushed = true;
|
||||
m_prim_gl_state_needs_gl_update = true;
|
||||
m_current_fbp = fbp;
|
||||
switch (f.fbp()) {
|
||||
case kScreenFbp: // 408
|
||||
m_fb_ctxt.reset();
|
||||
m_offscreen_mode = false;
|
||||
break;
|
||||
case kMinimapFbp: // 126
|
||||
m_fb_ctxt.emplace(m_minimap_fb);
|
||||
m_offscreen_mode = true;
|
||||
break;
|
||||
default:
|
||||
fmt::print("Unknown fbp in ProgressRenderer: {}\n", f.fbp());
|
||||
ASSERT(false);
|
||||
}
|
||||
}
|
||||
|
||||
bool write_rgb = f.fbmsk() != 0xffffff;
|
||||
if (write_rgb != m_test_state.write_rgb) {
|
||||
if (!flushed) {
|
||||
m_stats.flush_from_test++;
|
||||
flush_pending(render_state, prof);
|
||||
}
|
||||
|
||||
m_test_state.write_rgb = write_rgb;
|
||||
m_test_state_needs_gl_update = true;
|
||||
m_prim_gl_state_needs_gl_update = true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include "game/graphics/opengl_renderer/BucketRenderer.h"
|
||||
#include "game/graphics/opengl_renderer/DirectRenderer.h"
|
||||
#include "game/graphics/opengl_renderer/opengl_utils.h"
|
||||
|
||||
/*!
|
||||
* Renderer for the "Progress Bucket" of Jak 2.
|
||||
*/
|
||||
class ProgressRenderer : public DirectRenderer {
|
||||
public:
|
||||
static constexpr int kMinimapVramAddr = 4032;
|
||||
static constexpr int kMinimapWidth = 128;
|
||||
static constexpr int kMinimapHeight = 128;
|
||||
static constexpr int kScreenFbp = 408;
|
||||
static constexpr int kMinimapFbp = 126;
|
||||
ProgressRenderer(const std::string& name, int my_id, int batch_size);
|
||||
void init_textures(TexturePool& texture_pool, GameVersion) override;
|
||||
void handle_frame(u64 val, SharedRenderState* render_state, ScopedProfilerNode& prof) override;
|
||||
void pre_render() override;
|
||||
void post_render() override;
|
||||
|
||||
private:
|
||||
GpuTexture* m_minimap_gpu_tex = nullptr;
|
||||
FramebufferTexturePair m_minimap_fb;
|
||||
std::optional<FramebufferTexturePairContext> m_fb_ctxt;
|
||||
u32 m_current_fbp = kScreenFbp;
|
||||
};
|
||||
@@ -4,10 +4,12 @@ out vec4 color;
|
||||
|
||||
in vec4 fragment_color;
|
||||
in vec3 tex_coord;
|
||||
in flat uint use_uv;
|
||||
uniform float alpha_reject;
|
||||
uniform float color_mult;
|
||||
uniform float alpha_mult;
|
||||
uniform float alpha_sub;
|
||||
uniform float ta0;
|
||||
|
||||
uniform vec4 fog_color;
|
||||
|
||||
@@ -41,10 +43,37 @@ vec4 sample_tex(vec2 coord, uint unit) {
|
||||
}
|
||||
}
|
||||
|
||||
vec4 sample_tex_px(vec2 coordf, uint unit) {
|
||||
ivec2 coord;
|
||||
coord.x = int(coordf.x / 16);
|
||||
coord.y = int(coordf.y / 16);
|
||||
switch (unit) {
|
||||
case 0: return texelFetch(tex_T0, coord, 0);
|
||||
case 1: return texelFetch(tex_T1, coord, 0);
|
||||
case 2: return texelFetch(tex_T2, coord, 0);
|
||||
case 3: return texelFetch(tex_T3, coord, 0);
|
||||
case 4: return texelFetch(tex_T4, coord, 0);
|
||||
case 5: return texelFetch(tex_T5, coord, 0);
|
||||
case 6: return texelFetch(tex_T6, coord, 0);
|
||||
case 7: return texelFetch(tex_T7, coord, 0);
|
||||
case 8: return texelFetch(tex_T8, coord, 0);
|
||||
case 9: return texelFetch(tex_T9, coord, 0);
|
||||
default : return vec4(1.0, 0, 1.0, 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec4 T0 = sample_tex(tex_coord.xy / tex_coord.z, tex_info.x);
|
||||
vec4 T0;
|
||||
if (use_uv == 1) {
|
||||
T0 = sample_tex_px(tex_coord.xy, tex_info.x);
|
||||
} else {
|
||||
T0 = sample_tex(tex_coord.xy / tex_coord.z, tex_info.x);
|
||||
}
|
||||
// y is tcc
|
||||
// z is decal
|
||||
if (T0.w == 0) {
|
||||
T0.w = ta0;
|
||||
}
|
||||
|
||||
if (tex_info.y == 0) {
|
||||
if (tex_info.z == 0) {
|
||||
|
||||
@@ -10,14 +10,23 @@ out float fog;
|
||||
|
||||
// putting all texture info stuff here so it's easier to copy-paste
|
||||
layout (location = 3) in uvec4 tex_info_in;
|
||||
layout (location = 4) in uint use_uv_in;
|
||||
out flat uvec4 tex_info;
|
||||
out flat uint use_uv;
|
||||
uniform int offscreen_mode;
|
||||
|
||||
void main() {
|
||||
gl_Position = vec4((position_in.x - 0.5) * 16., -(position_in.y - 0.5) * 32 * HEIGHT_SCALE, position_in.z * 2 - 1., 1.0);
|
||||
// scissoring area adjust
|
||||
gl_Position.y *= SCISSOR_ADJUST;
|
||||
if (offscreen_mode == 1) {
|
||||
gl_Position = vec4((position_in.x - 0.453125) * 64., (position_in.y - 0.5 + (2.25 / 64)) * 64, position_in.z * 2 - 1., 1.0);
|
||||
} else {
|
||||
gl_Position = vec4((position_in.x - 0.5) * 16., -(position_in.y - 0.5) * 32 * HEIGHT_SCALE, position_in.z * 2 - 1., 1.0);
|
||||
// scissoring area adjust
|
||||
gl_Position.y *= SCISSOR_ADJUST;
|
||||
}
|
||||
|
||||
fragment_color = vec4(rgba_in.x, rgba_in.y, rgba_in.z, rgba_in.w * 2.);
|
||||
tex_coord = tex_coord_in;
|
||||
tex_info = tex_info_in;
|
||||
fog = 255 - position_in.w;
|
||||
use_uv = use_uv_in;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
;; DECOMP BEGINS
|
||||
|
||||
(defglobalconstant SKIP_MINIMAP_DRAW #t)
|
||||
(defglobalconstant SKIP_MINIMAP_DRAW #f)
|
||||
|
||||
;; WARN: Failed store: (s.w! (+ v1-35 8) 0) at op 135
|
||||
;; WARN: Failed store: (s.w! (+ v1-35 12) 0) at op 136
|
||||
|
||||
@@ -990,6 +990,8 @@
|
||||
)
|
||||
)
|
||||
)
|
||||
;; added in PC port: they timed stuff, we just allow it to run a fixed number of iterations.
|
||||
(+! v1-1 100)
|
||||
(.mfc0 v1-1 Count)
|
||||
)
|
||||
)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -751,7 +751,11 @@
|
||||
(let ((v0-0 (the-as int (-> obj mode))))
|
||||
0
|
||||
(.mfc0 v1-1 Count)
|
||||
(while (and (= v0-0 1) (< (the-as uint v1-1) (the-as uint arg0)))
|
||||
(while (and (= v0-0 1)
|
||||
;; changed in PC port: they used to abort early if searching takes too long
|
||||
;; it is fast enough on PC that we don't care.
|
||||
;; (< (the-as uint v1-1) (the-as uint arg0)) HACK
|
||||
)
|
||||
(set! v0-0 (do-some-work obj))
|
||||
(.mfc0 v1-1 Count)
|
||||
)
|
||||
|
||||
+331
-335
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user