diff --git a/lib/RT64-HLE b/lib/RT64-HLE index 05a835c..c0d8952 160000 --- a/lib/RT64-HLE +++ b/lib/RT64-HLE @@ -1 +1 @@ -Subproject commit 05a835cc92886042de1ba44d3be4f352560ec5c7 +Subproject commit c0d895269efe314ac1403b6fba87f7aeba93b03f diff --git a/patches/culling.c b/patches/culling.c index 4084123..f647778 100644 --- a/patches/culling.c +++ b/patches/culling.c @@ -88,3 +88,89 @@ void Player_DrawGameplay(PlayState* play, Player* this, s32 lod, Gfx* cullDList, CLOSE_DISPS(play->state.gfxCtx); } + +// Replace point light glow effect with RT64 point Z test so it works in widescreen + +void Lights_GlowCheck(PlayState* play) { + LightNode* light = play->lightCtx.listHead; + + while (light != NULL) { + LightPoint* params = &light->info->params.point; + + if (light->info->type == LIGHT_POINT_GLOW) { + Vec3f worldPos; + Vec3f projectedPos; + f32 invW; + + worldPos.x = params->x; + worldPos.y = params->y; + worldPos.z = params->z; + Actor_GetProjectedPos(play, &worldPos, &projectedPos, &invW); + + params->drawGlow = 0; + + // @recomp Enable glow as long as the projected Z position is valid to enable widescreen support. + // The depth check will be handled via the vertex Z test extended gbi command. + if ((projectedPos.z > 1)) { + params->drawGlow = 1; + } + } + + light = light->next; + } +} + +extern Gfx gameplay_keep_DL_029CB0[]; +extern Gfx gameplay_keep_DL_029CF0[]; + +Vtx light_test_vert = VTX(0, 0, 0, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF); + +void Lights_DrawGlow(PlayState* play) { + Gfx* dl; + LightPoint* params; + LightNode* light = play->lightCtx.listHead; + + if (light != NULL) { + OPEN_DISPS(play->state.gfxCtx); + + dl = Gfx_SetupDL65_NoCD(POLY_XLU_DISP); + + gDPSetDither(dl++, G_CD_NOISE); + + gDPSetCombineLERP(dl++, 0, 0, 0, PRIMITIVE, TEXEL0, 0, PRIMITIVE, 0, 0, 0, 0, PRIMITIVE, TEXEL0, 0, PRIMITIVE, + 0); + + gSPDisplayList(dl++, gameplay_keep_DL_029CB0); + + do { + if (light->info->type == LIGHT_POINT_GLOW) { + params = &light->info->params.point; + if (params->drawGlow) { + f32 scale = SQ((f32)params->radius) * 2e-6f; + + gDPSetPrimColor(dl++, 0, 0, params->color[0], params->color[1], params->color[2], 50); + + Matrix_Translate(params->x, params->y, params->z, MTXMODE_NEW); + Matrix_Scale(scale, scale, scale, MTXMODE_APPLY); + + gSPMatrix(dl++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); // <--- Made these use the right DL pointer + + // @recomp Use the vertex Z test to prevent drawing the glow if the depth check fails. + // This replaces the normal Z buffer read in a way that supports widescreen and isn't 1 frame out of date. + gSPVertex(dl++, &light_test_vert, 1, 0); + gEXVertexZTest(dl++, 0); + + gSPDisplayList(dl++, gameplay_keep_DL_029CF0); + + gEXEndVertexZTest(dl++); + } + } + + light = light->next; + } while (light != NULL); + + POLY_XLU_DISP = dl; + + CLOSE_DISPS(play->state.gfxCtx); + } +} diff --git a/src/game/input.cpp b/src/game/input.cpp index 565a39b..0d14e2f 100644 --- a/src/game/input.cpp +++ b/src/game/input.cpp @@ -98,6 +98,7 @@ const recomp::DefaultN64Mappings recomp::default_n64_mappings = { }, .r = { {.device_type = (uint32_t)DeviceType::ControllerDigital, .input_id = SDL_CONTROLLER_BUTTON_RIGHTSHOULDER}, + {.device_type = (uint32_t)DeviceType::ControllerAnalog, .input_id = SDL_CONTROLLER_AXIS_TRIGGERRIGHT + 1}, {.device_type = (uint32_t)DeviceType::Keyboard, .input_id = SDL_SCANCODE_R} }, .z = {