jak2 fixes

This commit is contained in:
water111
2025-06-19 10:34:56 -04:00
parent cee354474c
commit 72d87f2867
5 changed files with 103 additions and 19 deletions
@@ -249,11 +249,10 @@ std::vector<ShadowData> extract_jak2_shadow_data(const LinkedObjectFile& file,
// lg::info("{} {} fragments", name, num_fragments);
auto frags_ref =
TypedRef(get_field_ref(tr, "frags", dts), dts.ts.lookup_type("shadow-frag-ref"));
auto header_ref = TypedRef(deref_label(get_field_ref(frags_ref, "header", dts)),
dts.ts.lookup_type("shadow-frag-header"));
u32 size_qwc = read_plain_data_field<s32>(frags_ref, "qwc", dts);
for (u32 i = 0; i < num_fragments; i++) {
auto header_ref = TypedRef(deref_label(get_field_ref(frags_ref, "header", dts)),
dts.ts.lookup_type("shadow-frag-header"));
u32 size_qwc = read_plain_data_field<s32>(frags_ref, "qwc", dts);
shadow_datas.push_back(
extract_shadow_data(file, dts, header_ref, name, size_qwc, num_joints));
frags_ref.ref.byte_offset += 8;
@@ -232,16 +232,58 @@ void Shadow3::draw_model(SharedRenderState* render_state,
void Shadow3::finish(SharedRenderState* render_state, ScopedProfilerNode& prof) {
// finally, draw shadow.
if (!m_hacks) {
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
// glStencilFunc(GL_GREATER, 0, 0);
glStencilFunc(GL_NOTEQUAL, 0, 0xFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glDepthFunc(GL_ALWAYS);
if (render_state->version == GameVersion::Jak1) {
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
glStencilFunc(GL_NOTEQUAL, 0, 0xFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glDepthFunc(GL_ALWAYS);
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
glBlendFuncSeparate(GL_DST_COLOR, GL_ZERO, GL_ONE, GL_ZERO);
m_full_screen_draw.draw(m_color, render_state, prof);
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
glBlendFuncSeparate(GL_DST_COLOR, GL_ZERO, GL_ONE, GL_ZERO);
m_full_screen_draw.draw(m_color, render_state, prof);
} else {
glStencilFunc(GL_NOTEQUAL, 0, 0xFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glDepthFunc(GL_ALWAYS);
glEnable(GL_BLEND);
glBlendFuncSeparate(GL_ONE, GL_ONE, GL_ONE, GL_ZERO);
bool have_darken = false;
bool have_lighten = false;
bool lighten_channel[3] = {false, false, false};
bool darken_channel[3] = {false, false, false};
for (int i = 0; i < 3; i++) {
if (m_color[i] > 128) {
have_lighten = true;
lighten_channel[i] = true;
} else if (m_color[i] < 128) {
have_darken = true;
darken_channel[i] = true;
}
}
if (have_darken) {
glColorMask(darken_channel[0], darken_channel[1], darken_channel[2], false);
glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
m_full_screen_draw.draw(
math::Vector4f((m_color[3] - m_color[0]) / 256.f, (m_color[3] - m_color[1]) / 256.f,
(m_color[3] - m_color[2]) / 256.f, 0) *
0.5f,
render_state, prof);
}
if (have_lighten) {
glColorMask(lighten_channel[0], lighten_channel[1], lighten_channel[2], false);
glBlendEquation(GL_FUNC_ADD);
m_full_screen_draw.draw(
math::Vector4f((m_color[0] - m_color[3]) / 256.f, (m_color[1] - m_color[3]) / 256.f,
(m_color[2] - m_color[3]) / 256.f, 0) *
0.5f,
render_state, prof);
}
}
}
// restore
@@ -293,6 +335,7 @@ void Shadow3::flush_requests(SharedRenderState* render_state, ScopedProfilerNode
void Shadow3::first_time_setup(SharedRenderState* render_state) {
glClearStencil(0);
glClear(GL_STENCIL_BUFFER_BIT);
render_state->stencil_dirty = true;
render_state->shaders[ShaderId::SHADOW3].activate();
glUniformMatrix4fv(m_uniforms.camera_rot, 1, GL_FALSE, &render_state->camera_rot[0].x());
@@ -314,6 +357,7 @@ void Shadow3::render_jak1(DmaFollower& dma,
m_did_first_time_setup = false;
while (dma.current_tag_offset() != render_state->next_bucket) {
auto data = dma.read_and_advance();
if (data.vifcode0().kind == VifCode::Kind::PC_PORT) {
u32 next = data.data_offset;
while (next) {
@@ -328,7 +372,7 @@ void Shadow3::render_jak1(DmaFollower& dma,
auto model = render_state->loader->get_shadow_model(name);
if (!model) {
printf(" SKIP: no model data\n");
// printf(" SKIP: no model data\n");
continue;
}
@@ -375,7 +419,9 @@ void Shadow3::render_jak1(DmaFollower& dma,
request.bones = g_ee_main_mem + game_request.mtx;
request.scissor_top = game_request.settings.flags & kUpperClip;
request.color = game_request.color;
request.dist_to_locus = game_request.settings.dist_to_locus;
m_color = request.color;
// m_color = {0.2, 0.8, 0.2, 1.};
// copy bones to buffer
constexpr int in_stride = 8 * 4 * sizeof(float);
@@ -415,9 +461,22 @@ void Shadow3::render_jak1(DmaFollower& dma,
chain->head = &request;
// detect if the origin is below the clipping plane and if so, move it up.
const float dot = request.bottom_plane.xyz().dot(request.origin);
if (dot + request.bottom_plane.w() > 0) {
request.bottom_plane.w() = -dot;
// the logic for this changed in jak2, to support shadows with negative dist_from_locus
if (render_state->version == GameVersion::Jak1) {
const float dot = request.bottom_plane.xyz().dot(request.origin);
if (dot + request.bottom_plane.w() > 0) {
request.bottom_plane.w() = -dot;
}
} else {
const float bot_offset = request.origin.dot(request.bottom_plane.xyz());
const float top_offset = request.origin.dot(request.top_plane.xyz());
if ((request.bottom_plane.w() < bot_offset) && (top_offset < request.top_plane.w())) {
if (request.dist_to_locus > 0) {
request.bottom_plane.w() = -bot_offset;
} else {
request.top_plane.w() = -top_offset;
}
}
}
const auto& cam_rot = render_state->camera_rot;
@@ -40,6 +40,7 @@ class Shadow3 {
math::Vector<float, 3> origin;
math::Vector4f top_plane, bottom_plane;
math::Vector3f light_dir;
float dist_to_locus;
math::Vector4f color;
ShadowRequest* next = nullptr;
const u8* bones = nullptr;
@@ -629,7 +629,6 @@
;; if we're the first in the list, store in the run
(when (zero? (-> run first))
(format 0 "Setting first to #x~X~%" pse)
(set! (-> run first) (the pointer pse)))
;; patch next pointer of previous
@@ -652,8 +652,34 @@
(dotimes (i 2)
(when (nonzero? (-> *pc-shadow-globals* bucket i first))
;; patch the color of each request.
(let ((iter (the pc-shadow-request (-> *pc-shadow-globals* bucket i first)))
(color (new-stack-vector0))
)
(cond
((= i 0)
(vector-float*! color (-> *time-of-day-context* current-shadow-color) 128.0)
)
(else
(let ((c (-> *pc-shadow-globals* bucket i shadow-color)))
(set! (-> color x) (the float (-> c r)))
(set! (-> color y) (the float (-> c g)))
(set! (-> color z) (the float (-> c b)))
)
)
)
(set! (-> color w) (the float (-> *pc-shadow-globals* bucket i shadow-color a)))
(while (nonzero? iter)
;(vector-copy! (-> iter color) color)
(set! (-> iter color quad) (-> color quad))
(set! iter (-> iter next))
)
)
(with-dma-buffer-add-bucket ((dma-buf (-> (current-frame) global-buf)) (if (zero? i) (bucket-id shadow) (bucket-id shadow2)))
(format 0 "dma bucket ~d from ~X~%" i (-> *pc-shadow-globals* bucket i first))
(dma-buffer-add-ref-vif2
dma-buf
6