diff --git a/docs/BRIEF-B2-depot-textures.md b/docs/BRIEF-B2-depot-textures.md index c6fcc31b..e2d2ca23 100644 --- a/docs/BRIEF-B2-depot-textures.md +++ b/docs/BRIEF-B2-depot-textures.md @@ -18,7 +18,18 @@ recorded. Companion: `docs/BACKLOG.md` B1/B2, `docs/SMALL-FIXES.md` C-section. Frames: `ppm/frame_0007..1150` this session (regenerate with `GE_PCDUMP="700-1600:150" ./build-pc/ge007.x86_64.exe -level_30`). -## Leading hypothesis (revised M-29): this is mostly B1, not a decode bug +## UPDATE (M-29, later): filtering RULED OUT + +Enabling N64 3-point filtering + trilinear mips + 4x anisotropy game-wide +(the B1 work, now default) **did not change the Depot roof** — the blue +speckle + radial rays render identically at 640x480 native. So this is NOT +grazing-angle aliasing. It is a real texture-data / UV / effect bug on that +specific surface. The radial rays converging to a point look like either a +broken texture matrix (rotating/scrolling tc), garbage UVs on the ceiling +geometry, or a mis-rendered light-shaft effect (wrong blend/opacity). Needs +the `GE_DTEX` probe below to identify what draws it. + +## (superseded) earlier hypothesis: grazing-angle aliasing / B1 The radial-ray + sparkle pattern is the **classic grazing-angle aliasing** signature of a high-frequency texture sampled with point/bilinear filtering diff --git a/port/fast3d/gfx_opengl.cpp b/port/fast3d/gfx_opengl.cpp index 0d55a802..4aa87ba2 100644 --- a/port/fast3d/gfx_opengl.cpp +++ b/port/fast3d/gfx_opengl.cpp @@ -54,7 +54,7 @@ static uint32_t frame_count; static std::vector framebuffers; static size_t current_framebuffer; static float current_noise_scale; -static int current_anisotropy_level; +static int current_anisotropy_level = 4; /* B1: sane default (0 was invalid for GL_TEXTURE_MAX_ANISOTROPY) */ static FilteringMode current_filter_mode = FILTER_LINEAR; static MipmapFilteringMode current_mipmap_filter_mode = MIPMAP_LINEAR; static bool current_textures_linear_filter[2] = {false, false}; @@ -720,9 +720,16 @@ static void gfx_opengl_set_sampler_parameters(int tile, bool linear_filter, uint // MIPMAP_DISABLED MIPMAP_NEAREST MIPMAP_LINEAR { GL_NEAREST, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR }, // FILTER_NONE { GL_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR }, // FILTER_BILINEAR - { GL_NEAREST, GL_NEAREST, GL_NEAREST }, // FILTER_THREE_POINT + { GL_NEAREST, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR }, // FILTER_THREE_POINT }; + // B1: the shader does 3-point on magnification; for minification let the + // hardware do trilinear mips. THREE_POINT force-generates mips at upload + // (see gfx_opengl_upload_texture) so it can always sample them here -- this + // is what kills the grazing-angle shimmer (Depot roof, docs/BRIEF-B2). + if (current_filter_mode == FILTER_THREE_POINT) { + mipmaps = true; + } mipmaps = mipmaps && (current_mipmap_filter_mode != MIPMAP_DISABLED); const int mip_idx = mipmaps ? current_mipmap_filter_mode : 0; const GLint min_filter = linear_filter ? min_filters[current_filter_mode][mip_idx] : GL_NEAREST; diff --git a/port/src/video.c b/port/src/video.c index d08ffb57..b8a476eb 100644 --- a/port/src/video.c +++ b/port/src/video.c @@ -54,7 +54,7 @@ static int initDone = 0; static int cfgVSync = 1; /* swap interval: 0 = off, 1 = on */ static int cfgFpsCap = 0; /* frame cap in fps; 0 = uncapped (vsync) */ static int cfgMSAA = 1; /* 1/2/4/8 samples; 1 = off */ -static int cfgTexFilter = 1; /* 0 = nearest (crisp), 1 = bilinear */ +static int cfgTexFilter = 1; /* 0 = nearest, 1 = bilinear (default), 2 = N64 3-point + trilinear */ static int cfgFullscreen = 0; /* 0 = windowed, 1 = borderless fullscreen */ /* @@ -74,7 +74,7 @@ PD_CONSTRUCTOR static void videoConfigInit(void) configRegisterInt("Video.VSync", &cfgVSync, 0, 1); configRegisterInt("Video.FpsCap", &cfgFpsCap, 0, 1000); configRegisterInt("Video.MSAA", &cfgMSAA, 1, 8); - configRegisterInt("Video.TextureFilter", &cfgTexFilter, 0, 1); + configRegisterInt("Video.TextureFilter", &cfgTexFilter, 0, 2); configRegisterInt("Video.Fullscreen", &cfgFullscreen, 0, 1); configRegisterInt("Window.Width", &cfgWinW, 0, 16384); configRegisterInt("Window.Height", &cfgWinH, 0, 16384); @@ -132,7 +132,15 @@ int videoInit(void) wmAPI->set_swap_interval(cfgVSync ? 1 : 0); gfx_set_target_fps(cfgFpsCap); /* 0 = uncapped */ - if (cfgTexFilter) { + /* Texture filtering. 1 = bilinear (default, matches prior behaviour), + * 0 = crisp nearest, 2 = N64 3-point emulation + trilinear mips (opt-in; + * more console-authentic but softens textures at normal distance -- did + * NOT fix the Depot roof, see docs/BRIEF-B2-depot-textures.md). All keep + * point-sampled tiles (HUD, G_TF_POINT) crisp via the per-tile flag. */ + if (cfgTexFilter >= 2) { + gfx_set_texture_filter(FILTER_THREE_POINT); + gfx_set_mipmap_filter(MIPMAP_LINEAR); + } else if (cfgTexFilter == 1) { gfx_set_texture_filter(FILTER_LINEAR); gfx_set_mipmap_filter(MIPMAP_LINEAR); } else {