From 2c20a0487ed7fb7e7dbb12fb9c4c12b6478b63df Mon Sep 17 00:00:00 2001 From: fgsfds Date: Sat, 2 Dec 2023 19:18:47 +0100 Subject: [PATCH] port: better menu blur TODO: make it render the blurred texture to the fb once instead of rendering it blurred every frame --- port/fast3d/gfx_cc.cpp | 1 + port/fast3d/gfx_cc.h | 2 ++ port/fast3d/gfx_opengl.cpp | 25 ++++++++++++++++++++++++- port/fast3d/gfx_pc.cpp | 4 ++++ src/game/menu.c | 21 +++++---------------- src/game/menugfx.c | 10 ++++++++++ src/include/gbiex.h | 4 ++++ 7 files changed, 50 insertions(+), 17 deletions(-) diff --git a/port/fast3d/gfx_cc.cpp b/port/fast3d/gfx_cc.cpp index 9f0f0170f..066612843 100644 --- a/port/fast3d/gfx_cc.cpp +++ b/port/fast3d/gfx_cc.cpp @@ -17,6 +17,7 @@ void gfx_cc_get_features(uint64_t shader_id0, uint32_t shader_id1, struct CCFeat cc_features->opt_alpha_threshold = (shader_id1 & SHADER_OPT_ALPHA_THRESHOLD) != 0; cc_features->opt_invisible = (shader_id1 & SHADER_OPT_INVISIBLE) != 0; cc_features->opt_grayscale = (shader_id1 & SHADER_OPT_GRAYSCALE) != 0; + cc_features->opt_blur = (shader_id1 & SHADER_OPT_BLUR) != 0; cc_features->clamp[0][0] = (shader_id1 & SHADER_OPT_TEXEL0_CLAMP_S); cc_features->clamp[0][1] = (shader_id1 & SHADER_OPT_TEXEL0_CLAMP_T); diff --git a/port/fast3d/gfx_cc.h b/port/fast3d/gfx_cc.h index 95eba812f..cfd00c9f6 100644 --- a/port/fast3d/gfx_cc.h +++ b/port/fast3d/gfx_cc.h @@ -53,6 +53,7 @@ enum { #define SHADER_OPT_TEXEL1_MASK (1 << 13) #define SHADER_OPT_TEXEL0_BLEND (1 << 14) #define SHADER_OPT_TEXEL1_BLEND (1 << 15) +#define SHADER_OPT_BLUR (1 << 16) struct ColorCombinerKey { uint64_t combine_mode; @@ -75,6 +76,7 @@ struct CCFeatures { bool opt_alpha_threshold; bool opt_invisible; bool opt_grayscale; + bool opt_blur; bool used_textures[2]; bool used_masks[2]; bool used_blend[2]; diff --git a/port/fast3d/gfx_opengl.cpp b/port/fast3d/gfx_opengl.cpp index 313155bbb..d446f111f 100644 --- a/port/fast3d/gfx_opengl.cpp +++ b/port/fast3d/gfx_opengl.cpp @@ -394,7 +394,30 @@ static struct ShaderProgram* gfx_opengl_create_and_load_new_shader(uint64_t shad append_line(fs_buf, &fs_len, " return fract(sin(random) * 143758.5453);"); append_line(fs_buf, &fs_len, "}"); - if (current_filter_mode == FILTER_THREE_POINT) { + if (cc_features.opt_blur) { + // blur filter, used for menu backgrounds + append_line(fs_buf, &fs_len, R"( + const vec4 blurOffsets = vec4(-1.5, -0.5, +0.5, +1.5); + const mat4 blurWeights = mat4( + 0.009947, 0.009641, 0.008778, 0.007509, + 0.009641, 0.009345, 0.008508, 0.007278, + 0.008778, 0.008508, 0.007747, 0.006626, + 0.007509, 0.007278, 0.006626, 0.005668 + ); + lowp vec4 hookTexture2D(in sampler2D tex, in vec2 texCoord, in vec2 texSize) { + lowp vec4 color = vec4(0.0); + lowp float wacc = 0.0; + for (int y = 0; y < 4; ++y) { + for (int x = 0; x < 4; ++x) { + vec2 ofs = vec2(blurOffsets[x], blurOffsets[y]) / texSize; + wacc += blurWeights[x][y]; + color += texture2D(tex, texCoord + ofs) * blurWeights[x][y]; + } + } + return vec4(color.rgb / wacc, 1.0); + })" + ); + } else if (current_filter_mode == FILTER_THREE_POINT) { #if __APPLE__ append_line(fs_buf, &fs_len, "#define TEX_OFFSET(off) texture(tex, texCoord - (off)/texSize)"); #else diff --git a/port/fast3d/gfx_pc.cpp b/port/fast3d/gfx_pc.cpp index ab060118a..5b2dcc0e3 100644 --- a/port/fast3d/gfx_pc.cpp +++ b/port/fast3d/gfx_pc.cpp @@ -1288,6 +1288,7 @@ static void gfx_sp_tri1(uint8_t vtx1_idx, uint8_t vtx2_idx, uint8_t vtx3_idx, bo (rdp.other_mode_l & (3 << 24)) == (G_BL_0 << 24) && (rdp.other_mode_l & (3 << 20)) == (G_BL_CLR_MEM << 20); bool use_grayscale = rdp.grayscale; bool use_modulate = use_alpha && (rsp.extra_geometry_mode & G_MODULATE_EXT) != 0; + bool use_blur = (rdp.other_mode_h & (3U << G_MDSFT_TEXTFILT)) == G_TF_BLUR_EXT; if (texture_edge) { use_alpha = true; @@ -1317,6 +1318,9 @@ static void gfx_sp_tri1(uint8_t vtx1_idx, uint8_t vtx2_idx, uint8_t vtx3_idx, bo if (use_grayscale) { cc_options |= (uint64_t)SHADER_OPT_GRAYSCALE; } + if (use_blur) { + cc_options |= (uint64_t)SHADER_OPT_BLUR; + } // If we are not using alpha, clear the alpha components of the combiner as they have no effect if (!use_alpha) { diff --git a/src/game/menu.c b/src/game/menu.c index 628f987b0..b63ad6315 100644 --- a/src/game/menu.c +++ b/src/game/menu.c @@ -50,6 +50,9 @@ #include "types.h" #ifndef PLATFORM_N64 #include "video.h" +#define BLUR_OFS 10 +#else +#define BLUR_OFS 30 #endif #if VERSION >= VERSION_PAL_FINAL @@ -5084,23 +5087,9 @@ Gfx *menuRenderBackgroundLayer1(Gfx *gdl, u8 bg, f32 frac) // Render the blurred background texture with full alpha gdl = menugfxRenderBgBlur(gdl, 0xffffff00 | alpha, 0, 0); -#ifdef PLATFORM_N64 // Render it twice more with half alpha and offset - gdl = menugfxRenderBgBlur(gdl, 0xffffff00 | alpha >> 1, -30, -30); - gdl = menugfxRenderBgBlur(gdl, 0xffffff00 | alpha >> 1, 30, 30); -#else - // HACK: we don't actually blur anything on the CPU, so - // render it offset to all cardinal and ordinal directions to achieve crappy box blur - const s32 card[2] = { -30, 30 }; - const s32 ord[2] = { -21, 21 }; // 30 / sqrt(2) - const u32 rgba = 0xffffff00 | alpha >> 3; - for (s32 i = 0; i < 2; ++i) { - gdl = menugfxRenderBgBlur(gdl, rgba, 0, card[i]); - gdl = menugfxRenderBgBlur(gdl, rgba, card[i], 0); - gdl = menugfxRenderBgBlur(gdl, rgba, ord[0], ord[i]); - gdl = menugfxRenderBgBlur(gdl, rgba, ord[i], ord[0]); - } -#endif + gdl = menugfxRenderBgBlur(gdl, 0xffffff00 | alpha >> 1, -BLUR_OFS, -BLUR_OFS); + gdl = menugfxRenderBgBlur(gdl, 0xffffff00 | alpha >> 1, BLUR_OFS, BLUR_OFS); } break; case MENUBG_BLACK: diff --git a/src/game/menugfx.c b/src/game/menugfx.c index 833f9a670..273e2c6f1 100644 --- a/src/game/menugfx.c +++ b/src/game/menugfx.c @@ -164,7 +164,13 @@ Gfx *menugfxRenderBgBlur(Gfx *gdl, u32 colour, s16 arg2, s16 arg3) gDPSetAlphaCompare(gdl++, G_AC_NONE); gDPSetCombineMode(gdl++, G_CC_MODULATEI, G_CC_MODULATEI); gSPClearGeometryMode(gdl++, G_CULL_BOTH); + +#ifdef PLATFORM_N64 gDPSetTextureFilter(gdl++, G_TF_BILERP); +#else + // enable blur filter for the texture + gDPSetTextureFilter(gdl++, G_TF_BLUR_EXT); +#endif gDPSetRenderMode(gdl++, G_RM_XLU_SURF, G_RM_XLU_SURF2); @@ -240,6 +246,10 @@ Gfx *menugfxRenderBgBlur(Gfx *gdl, u32 colour, s16 arg2, s16 arg3) gSPTri2(gdl++, 0, 1, 2, 2, 3, 0); +#ifndef PLATFORM_N64 + gDPSetTextureFilter(gdl++, G_TF_BILERP); +#endif + return gdl; } diff --git a/src/include/gbiex.h b/src/include/gbiex.h index ac01e736f..904de2fd0 100644 --- a/src/include/gbiex.h +++ b/src/include/gbiex.h @@ -207,6 +207,10 @@ #define G_NO_CLIPPING_EXT 0x00000100 #define G_MODULATE_EXT 0x00000200 // this should really go into OTHERMODE_H, but for some reason I can't get it to work +/* Extra texture filtering mode */ + +#define G_TF_BLUR_EXT (1 << G_MDSFT_TEXTFILT) + /* Extended command macros */ #define gDPSetFramebufferTargetEXT(pkt, f, s, w, i) \