mirror of
https://github.com/jkdansereau/goldeneye-pc-port.git
synced 2026-10-23 15:52:42 +02:00
feat(D211-D213): PC QoL image options — FOV slider, anisotropic filtering, on-screen FPS
Three port-only knobs, each defaulting to byte-identical behaviour: - Video.FovScale (D211): multiplicative half-angle scale on every perspective projection matrix as it is loaded (gfx_apply_fov_scale, gfx_pc.cpp). Columns 0+1 scaled together so H/V FOV widen uniformly and aspect is preserved; ortho (HUD/menu) matrices untouched. Composes with the game's per-frame aim-zoom rewrites for free. Percent of vertical FOV, 50-150, default 100 => guarded early-return (zero FP ops, golden dumps byte-identical). WIDESCREEN-FOV-PLAN Phase 4, landed standalone. - Video.Anisotropy (D212): expose fast3d's already-implemented GL anisotropy hook as config (1-16). New gfx_set_anisotropy_level() extern-C wrapper clamps to the GL max. Default 4 = the value fast3d already hardcoded => no delta. - Video.DisplayFPS (D213): PD-parity top-right FPS readout, sampled once per emitted frame (optionsoverlay.c fpsTick). Config-only; default 0 => emit still returns NULL with the panel closed. F10 overlay gains 'Anisotropic' and 'FOV scale %' rows (DisplayFPS is file-only - the panel is at its 13-row layout limit, matching PD). Build clean (ntsc-final); bunker1 framediff worst_cell 12.219 vs 12.221 baseline = render noise, no-op confirmed. Interactive eyeballs owed (see docs/HANDOFF.md M-83). findings.md: D211-D213 rows + index regen. WIDESCREEN-FOV-PLAN Phase 4 and QOL-INVENTORY rows marked done.
This commit is contained in:
1 parent
8742b93f29
commit
7bcfbf313c
8 files changed
+159
-10
No files matched your search
@@ -916,6 +916,50 @@ bool g_fix_mip_textures = true;
|
||||
* off. Video.WrapFix = 1. */
|
||||
bool g_wrap_fix = false;
|
||||
|
||||
/* D211 port-only FOV slider. Multiplies the half-angle of every *perspective*
|
||||
* projection matrix as it is loaded, so it composes with the game's per-frame
|
||||
* aim-zoom rewrites for free (see docs/dev/WIDESCREEN-FOV-PLAN.md "FOV
|
||||
* adjustment design"). 1.0 = byte-identical to the original (guarded skip);
|
||||
* Video.FovScale is a percent, 100 = 1.0. */
|
||||
static float g_fov_scale = 1.0f;
|
||||
|
||||
extern "C" void gfx_set_fov_scale(float s) {
|
||||
if (!(s > 0.4f) || !(s < 2.01f)) {
|
||||
s = 1.0f;
|
||||
}
|
||||
g_fov_scale = s;
|
||||
}
|
||||
|
||||
/* Widen/narrow a freshly-loaded projection matrix in place. No-op unless the
|
||||
* matrix is a perspective projection (row-vector guPerspective layout: only
|
||||
* P[2][3] == -1, P[3][3] == 0 — an ortho matrix has P[3][3] == 1 and is left
|
||||
* alone so HUD/menu 2D is untouched). Scaling columns 0 and 1 by the same
|
||||
* factor scales the effective cotangent, i.e. widens H and V FOV uniformly —
|
||||
* aspect ratio is preserved, no stretch. */
|
||||
static void gfx_apply_fov_scale(float m[4][4]) {
|
||||
if (g_fov_scale == 1.0f) {
|
||||
return;
|
||||
}
|
||||
if (!(fabsf(m[3][3]) < 0.01f) || !(fabsf(m[2][3] + 1.0f) < 0.05f)) {
|
||||
return; /* not a perspective projection */
|
||||
}
|
||||
const float cot = m[1][1];
|
||||
if (!(cot > 1e-4f)) {
|
||||
return;
|
||||
}
|
||||
const float half = atanf(1.0f / cot);
|
||||
float nhalf = half * g_fov_scale;
|
||||
const float LIMIT = 1.48f; /* ~85 deg half-angle; keep cot well away from 0 */
|
||||
if (nhalf > LIMIT) {
|
||||
nhalf = LIMIT;
|
||||
}
|
||||
const float f = tanf(half) / tanf(nhalf);
|
||||
for (int k = 0; k < 4; k++) {
|
||||
m[k][0] *= f;
|
||||
m[k][1] *= f;
|
||||
}
|
||||
}
|
||||
|
||||
/* D183 source-pitch de-stride (see import_texture). Default on;
|
||||
* GE_TEXPITCH=0 restores the old flat read for A/B. */
|
||||
static bool gfx_tex_pitch_fix(void) {
|
||||
@@ -1212,6 +1256,11 @@ static void gfx_sp_matrix(uint8_t parameters, const int32_t* addr) {
|
||||
if (parameters & G_MTX_PROJECTION) {
|
||||
if (parameters & G_MTX_LOAD) {
|
||||
memcpy(rsp.P_matrix, matrix, sizeof(matrix));
|
||||
/* D211: apply the FOV slider on the load path only. GE always
|
||||
* (re)loads its view projection with G_MTX_LOAD (src/fr.c:725), so
|
||||
* a relative G_MTX_MUL onto an already-scaled matrix never
|
||||
* happens and cannot compound. */
|
||||
gfx_apply_fov_scale(rsp.P_matrix);
|
||||
} else {
|
||||
gfx_matrix_mul(rsp.P_matrix, matrix, rsp.P_matrix);
|
||||
}
|
||||
@@ -3227,6 +3276,20 @@ extern "C" void gfx_set_mipmap_filter(enum MipmapFilteringMode mode) {
|
||||
}
|
||||
|
||||
extern "C" void gfx_set_fix_mip_textures(int on) { g_fix_mip_textures = !!on; }
|
||||
|
||||
/* D212: expose the (already-implemented) rendering-API anisotropy hook to the
|
||||
* port layer. Clamp to [1, GL max] so a stale ini value can't feed an invalid
|
||||
* GL_TEXTURE_MAX_ANISOTROPY. 1 = isotropic (driver default). */
|
||||
extern "C" void gfx_set_anisotropy_level(int level) {
|
||||
reset_texture_state();
|
||||
int max = gfx_rapi->get_max_anisotropy_level ? gfx_rapi->get_max_anisotropy_level() : 1;
|
||||
if (max < 1) max = 1;
|
||||
if (level < 1) level = 1;
|
||||
if (level > max) level = max;
|
||||
if (gfx_rapi->set_anisotropy_level) {
|
||||
gfx_rapi->set_anisotropy_level(level);
|
||||
}
|
||||
}
|
||||
extern "C" void gfx_set_wrap_fix(int on) {
|
||||
const char* e = getenv("GE_WRAPFIX"); /* RC3 test override */
|
||||
g_wrap_fix = e ? (atoi(e) != 0) : !!on;
|
||||
|
||||
Reference in new issue
Block a user