From 42a4e787b664e169ef42b65f11cf8a5e968c724c Mon Sep 17 00:00:00 2001 From: "Jasper St. Pierre" Date: Sun, 12 Apr 2026 22:26:19 -0700 Subject: [PATCH] bloom cleanup start start working on a better bloom --- src/m_Do/m_Do_graphic.cpp | 213 +++++++++++++++++++++++++++++++++++--- 1 file changed, 196 insertions(+), 17 deletions(-) diff --git a/src/m_Do/m_Do_graphic.cpp b/src/m_Do/m_Do_graphic.cpp index f9d5750d71..dc6f80b63f 100644 --- a/src/m_Do/m_Do_graphic.cpp +++ b/src/m_Do/m_Do_graphic.cpp @@ -1232,12 +1232,12 @@ void mDoGph_drawFilterQuad(s8 param_0, s8 param_1) { void mDoGph_gInf_c::bloom_c::create() { if (m_buffer == NULL) { #ifdef TARGET_PC - u32 size = 0x20; // No need to allocate memory for texture + m_buffer = (void*)1; #else u32 size = GXGetTexBufferSize(FB_WIDTH / 2, FB_HEIGHT / 2, GX_TF_RGBA8, GX_FALSE, 0); -#endif m_buffer = mDoExt_getArchiveHeap()->alloc(size, -32); JUT_ASSERT(1621, m_buffer != NULL); +#endif mEnable = false; mMode = 0; @@ -1249,20 +1249,202 @@ void mDoGph_gInf_c::bloom_c::create() { } void mDoGph_gInf_c::bloom_c::remove() { +#if !TARGET_PC if (m_buffer != NULL) { mDoExt_getArchiveHeap()->free(m_buffer); m_buffer = NULL; } +#endif mMonoColor.a = 0; } -void mDoGph_gInf_c::bloom_c::draw() { + #if TARGET_PC +static void CopyToTexObj(GXTexObj* pDst, uintptr_t texID, int dstWidth, int dstHeight, GXTexFmt dstFmt = GX_TF_RGBA8) { + GXSetTexCopyDst(dstWidth, dstHeight, dstFmt, FALSE); + GXCopyTex((void*)texID, false); + GXInitTexObj(pDst, (void*)texID, dstWidth, dstHeight, dstFmt, GX_CLAMP, GX_CLAMP, GX_FALSE); + GXInitTexObjLOD(pDst, GX_LINEAR, GX_LINEAR, 0.0f, 0.0f, 0.0f, GX_FALSE, GX_FALSE, GX_ANISO_1); +} + +void mDoGph_gInf_c::bloom_c::draw() { ZoneScoped; if (!dusk::getSettings().game.enableBloom) { return; } -#endif + + bool enabled = mEnable; + if (mMonoColor.a == 0 && !enabled) + return; + + f32 width = mDoGph_gInf_c::getWidth(); + f32 height = mDoGph_gInf_c::getHeight(); + GXSetViewport(0.0f, 0.0f, width, height, 0.0f, 1.0f); + GXSetScissor(0, 0, width, height); + + GXLoadTexObj(getFrameBufferTexObj(), GX_TEXMAP0); + GXSetNumChans(0); + GXSetNumTexGens(1); + GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, 0x3c); + GXSetTevSwapModeTable(GX_TEV_SWAP1, GX_CH_RED, GX_CH_RED, GX_CH_RED, GX_CH_GREEN); + GXSetTevSwapModeTable(GX_TEV_SWAP3, GX_CH_BLUE, GX_CH_BLUE, GX_CH_BLUE, GX_CH_ALPHA); + GXSetZCompLoc(1); + GXSetZMode(0, GX_ALWAYS, 0); + GXSetAlphaCompare(GX_ALWAYS, 0, GX_AOP_OR, GX_ALWAYS, 0); + GXSetFog(GX_FOG_NONE, 0.0f, 0.0f, 0.0f, 0.0f, g_clearColor); + GXSetFogRangeAdj(0, 0, 0); + GXSetCullMode(GX_CULL_NONE); + GXSetDither(1); + Mtx44 ortho; + C_MTXOrtho(ortho, 0.0f, height, 0.0f, width, 0.0f, 10.0f); + GXLoadPosMtxImm(cMtx_getIdentity(), 0); + GXSetProjection(ortho, GX_ORTHOGRAPHIC); + GXSetCurrentMtx(0); + GXClearVtxDesc(); + GXSetVtxDesc(GX_VA_POS, GX_DIRECT); + GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_S8, 0); + + auto filterQuad = [&](int div) { + f32 x = width / div, y = height / div; + GXBegin(GX_QUADS, GX_VTXFMT0, 4); + GXPosition3f32(0, 0, -5); + GXTexCoord2s8(0, 0); + GXPosition3f32(x, 0, -5); + GXTexCoord2s8(1, 0); + GXPosition3f32(x, y, -5); + GXTexCoord2s8(1, 1); + GXPosition3f32(0, y, -5); + GXTexCoord2s8(0, 1); + GXEnd(); + }; + + if (mMonoColor.a != 0) { + GXSetNumTevStages(1); + GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL); + GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_TEXC, GX_CC_C2, GX_CC_ZERO); + GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_A2); + GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + GXSetTevSwapMode(GX_TEVSTAGE0, GX_TEV_SWAP1, GX_TEV_SWAP1); + GXSetTevColor(GX_TEVREG2, mMonoColor); + GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_OR); + filterQuad(1); + } + + if (enabled) { + enum PassID { Pass0, Pass1, Pass2 }; + + GXCreateFrameBuffer(width, height); + + GXSetNumTevStages(3); + GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL); + GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_TEXC, GX_CC_TEXA, GX_CC_HALF, GX_CC_ZERO); + GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO); + GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + GXSetTevSwapMode(GX_TEVSTAGE0, GX_TEV_SWAP1, GX_TEV_SWAP1); + GXSetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL); + GXSetTevColorIn(GX_TEVSTAGE1, GX_CC_TEXC, GX_CC_CPREV, GX_CC_HALF, GX_CC_C0); + GXSetTevColorOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + GXSetTevAlphaIn(GX_TEVSTAGE1, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO); + GXSetTevAlphaOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + GXSetTevSwapMode(GX_TEVSTAGE1, GX_TEV_SWAP3, GX_TEV_SWAP3); + GXSetTevOrder(GX_TEVSTAGE2, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL); + GXSetTevColorIn(GX_TEVSTAGE2, GX_CC_ZERO, GX_CC_TEXC, GX_CC_CPREV, GX_CC_ZERO); + GXSetTevColorOp(GX_TEVSTAGE2, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + GXSetTevAlphaIn(GX_TEVSTAGE2, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO); + GXSetTevAlphaOp(GX_TEVSTAGE2, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + GXSetBlendMode(GX_BM_NONE, GX_BL_ZERO, GX_BL_ZERO, GX_LO_OR); + GXColorS10 tevColor0 = {(s16)-mPoint, (s16)-mPoint, (s16)-mPoint, 0x40}; + GXSetTevColorS10(GX_TEVREG0, tevColor0); + GXColor tevColor1 = {mBlureRatio, mBlureRatio, mBlureRatio, mBlureRatio}; + GXSetTevColor(GX_TEVREG1, tevColor1); + GXPixModeSync(); + filterQuad(2); + + GXSetTevSwapModeTable(GX_TEV_SWAP1, GX_CH_RED, GX_CH_RED, GX_CH_RED, GX_CH_ALPHA); + GXSetTevSwapMode(GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0); + GXSetTevSwapMode(GX_TEVSTAGE1, GX_TEV_SWAP0, GX_TEV_SWAP0); + + // Downsample and filter from 1/2 EFB into 1/4. + TGXTexObj tmpTex[3]; + GXSetTexCopySrc(0, 0, width / 2, height / 2); + CopyToTexObj(&tmpTex[0], Pass0, width / 4, height / 4); + GXLoadTexObj(&tmpTex[0], GX_TEXMAP0); + + GXSetNumTexGens(8); + u32 texMtxID = GX_TEXMTX0; + int angle = 0; + GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY); + for (int texCoord = (int)GX_TEXCOORD1; texCoord < (int)GX_MAX_TEXCOORD; texCoord++) { + GXSetTexCoordGen((GXTexCoordID)texCoord, GX_TG_MTX2x4, GX_TG_TEX0, texMtxID); + + f32 dVar15 = mBlureSize * ((448.0f / getHeight()) / 6400.0f); + + mDoMtx_stack_c::transS((dVar15 * cM_scos(angle)) * getInvScale(), + dVar15 * cM_ssin(angle), 0.0f); + GXLoadTexMtxImm(mDoMtx_stack_c::get(), texMtxID, GX_MTX2x4); + + texMtxID += 3; + angle += 0x2492; + } + + GXSetNumTevStages(8); + GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL); + GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_TEXC, GX_CC_A1, GX_CC_ZERO); + GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO); + GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + for (int tevStage = (int)GX_TEVSTAGE1; tevStage < 8; tevStage++) { + GXSetTevOrder((GXTevStageID)tevStage, (GXTexCoordID)tevStage, GX_TEXMAP0, + GX_COLOR_NULL); + GXSetTevColorIn((GXTevStageID)tevStage, GX_CC_ZERO, GX_CC_TEXC, GX_CC_A1, GX_CC_CPREV); + GXSetTevColorOp((GXTevStageID)tevStage, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, + GX_TEVPREV); + GXSetTevAlphaIn((GXTevStageID)tevStage, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_A0); + GXSetTevAlphaOp((GXTevStageID)tevStage, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, + GX_TEVPREV); + } + GXPixModeSync(); + + // Blur filter from tmp_tex1 1/4 to EFB 1/4. + filterQuad(4); + + GXSetTexCopySrc(0, 0, width / 4, height / 4); + CopyToTexObj(&tmpTex[1], Pass1, width / 8, height / 8); + GXLoadTexObj(&tmpTex[1], GX_TEXMAP0); + + // Upsample 1/8 buffer back up to 1/4 buffer. + GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_OR); + GXPixModeSync(); + GXInvalidateTexAll(); + filterQuad(4); + + // Now that we've upsampled and filtered our final bloom, copy 1/4 buffer. + GXSetTexCopySrc(0, 0, width / 4, height / 4); + CopyToTexObj(&tmpTex[2], Pass2, width / 4, height / 4); + GXLoadTexObj(&tmpTex[2], GX_TEXMAP0); + + GXRestoreFrameBuffer(); + + // Now blend our bloom into the real FB. + GXSetTevColor(GX_TEVREG0, mBlendColor); + GXSetNumTevStages(1); + GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL); + GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_TEXC, GX_CC_C0, GX_CC_ZERO); + GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_A0); + GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); + GXSetBlendMode(GX_BM_BLEND, mMode == 1 ? GX_BL_INVDSTCLR : GX_BL_ONE, GX_BL_SRCALPHA, GX_LO_OR); + GXPixModeSync(); + GXInvalidateTexAll(); + filterQuad(1); + } +} +#else +void mDoGph_gInf_c::bloom_c::draw() { bool enabled = mEnable && m_buffer != NULL; if (mMonoColor.a != 0 || enabled) { #if TARGET_PC @@ -1376,24 +1558,20 @@ void mDoGph_gInf_c::bloom_c::draw() { GXLoadTexObj(&tmp_tex1, GX_TEXMAP0); GXSetNumTexGens(8); - u32 iVar11 = 0x1e; - int sVar10 = 0; - GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, 0x3c); + u32 texMtxID = GX_TEXMTX0; + int angle = 0; + GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY); for (int texCoord = (int)GX_TEXCOORD1; texCoord < (int)GX_MAX_TEXCOORD; texCoord++) { - GXSetTexCoordGen((GXTexCoordID)texCoord, GX_TG_MTX2x4, GX_TG_TEX0, iVar11); + GXSetTexCoordGen((GXTexCoordID)texCoord, GX_TG_MTX2x4, GX_TG_TEX0, texMtxID); - #if TARGET_PC - f32 dVar15 = mBlureSize * ((448.0f / getHeight()) / 6400.0f); - #else f32 dVar15 = mBlureSize * (1.0f / 6400.0f); - #endif - mDoMtx_stack_c::transS((dVar15 * cM_scos(sVar10)) * getInvScale(), - dVar15 * cM_ssin(sVar10), 0.0f); - GXLoadTexMtxImm(mDoMtx_stack_c::get(), iVar11, GX_MTX2x4); + mDoMtx_stack_c::transS((dVar15 * cM_scos(angle)) * getInvScale(), + dVar15 * cM_ssin(angle), 0.0f); + GXLoadTexMtxImm(mDoMtx_stack_c::get(), texMtxID, GX_MTX2x4); - iVar11 += 3; - sVar10 += 0x2492; + texMtxID += 3; + angle += 0x2492; } GXSetNumTevStages(8); GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL); @@ -1495,6 +1673,7 @@ void mDoGph_gInf_c::bloom_c::draw() { } } } +#endif static void retry_captue_frame(view_class* param_0, view_port_class* param_1, int param_2) { UNUSED(param_0);