diff options
| author | Derek Hensley <hensley.derek58@gmail.com> | 2024-01-20 16:04:28 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-01-20 21:04:28 -0300 |
| commit | 9c10ee1d28a45e7373af455f59c5e66235be30ee (patch) | |
| tree | 39c583393035f81600ca0e023d5eb0dcfa9284d5 /src/code | |
| parent | 665353f3446db43d0efe0e9c6a9c80d16684da7a (diff) | |
Framebuffer filter docs (#1528)
* Framebuffer filter docs
* PR
* Format
* Leading 0s
Diffstat (limited to 'src/code')
| -rw-r--r-- | src/code/game.c | 67 | ||||
| -rw-r--r-- | src/code/z_demo.c | 16 | ||||
| -rw-r--r-- | src/code/z_play.c | 10 | ||||
| -rw-r--r-- | src/code/z_viscvg.c | 93 | ||||
| -rw-r--r-- | src/code/z_vismono.c | 52 | ||||
| -rw-r--r-- | src/code/z_viszbuf.c | 81 |
6 files changed, 205 insertions, 114 deletions
diff --git a/src/code/game.c b/src/code/game.c index 0179062f4..908a0c315 100644 --- a/src/code/game.c +++ b/src/code/game.c @@ -7,9 +7,7 @@ #include "z64rumble.h" #include "z64speed_meter.h" #include "z64vimode.h" -#include "z64viscvg.h" -#include "z64vismono.h" -#include "z64viszbuf.h" +#include "z64vis.h" #include "overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope.h" #include "debug.h" @@ -20,7 +18,7 @@ f32 gFramerateDivisorThird = 1.0f / 3.0f; SpeedMeter sGameSpeedMeter; VisCvg sGameVisCvg; -VisZbuf sGameVisZbuf; +VisZBuf sGameVisZBuf; VisMono sGameVisMono; ViMode sGameViMode; @@ -40,34 +38,37 @@ void GameState_SetFramerateDivisor(GameState* gameState, s32 divisor) { void GameState_SetFBFilter(Gfx** gfxP, void* zbuffer) { Gfx* gfx = *gfxP; - if ((R_FB_FILTER_TYPE > 0) && (R_FB_FILTER_TYPE < 5)) { - sGameVisCvg.type = R_FB_FILTER_TYPE; - sGameVisCvg.color.r = R_FB_FILTER_PRIM_COLOR(0); - sGameVisCvg.color.g = R_FB_FILTER_PRIM_COLOR(1); - sGameVisCvg.color.b = R_FB_FILTER_PRIM_COLOR(2); - sGameVisCvg.color.a = R_FB_FILTER_A; + if ((R_FB_FILTER_TYPE >= FB_FILTER_CVG_RGB) && (R_FB_FILTER_TYPE <= FB_FILTER_CVG_RGB_FOG)) { + // Visualize coverage + sGameVisCvg.vis.type = FB_FILTER_TO_CVG_TYPE(R_FB_FILTER_TYPE); + sGameVisCvg.vis.primColor.r = R_FB_FILTER_PRIM_COLOR(0); + sGameVisCvg.vis.primColor.g = R_FB_FILTER_PRIM_COLOR(1); + sGameVisCvg.vis.primColor.b = R_FB_FILTER_PRIM_COLOR(2); + sGameVisCvg.vis.primColor.a = R_FB_FILTER_A; VisCvg_Draw(&sGameVisCvg, &gfx); - } else if ((R_FB_FILTER_TYPE == 5) || (R_FB_FILTER_TYPE == 6)) { - sGameVisZbuf.useRgba = (R_FB_FILTER_TYPE == 6); - sGameVisZbuf.primColor.r = R_FB_FILTER_PRIM_COLOR(0); - sGameVisZbuf.primColor.g = R_FB_FILTER_PRIM_COLOR(1); - sGameVisZbuf.primColor.b = R_FB_FILTER_PRIM_COLOR(2); - sGameVisZbuf.primColor.a = R_FB_FILTER_A; - sGameVisZbuf.envColor.r = R_FB_FILTER_ENV_COLOR(0); - sGameVisZbuf.envColor.g = R_FB_FILTER_ENV_COLOR(1); - sGameVisZbuf.envColor.b = R_FB_FILTER_ENV_COLOR(2); - sGameVisZbuf.envColor.a = R_FB_FILTER_A; - VisZbuf_Draw(&sGameVisZbuf, &gfx, zbuffer); - } else if (R_FB_FILTER_TYPE == 7) { - sGameVisMono.unk_00 = 0; - sGameVisMono.primColor.r = R_FB_FILTER_PRIM_COLOR(0); - sGameVisMono.primColor.g = R_FB_FILTER_PRIM_COLOR(1); - sGameVisMono.primColor.b = R_FB_FILTER_PRIM_COLOR(2); - sGameVisMono.primColor.a = R_FB_FILTER_A; - sGameVisMono.envColor.r = R_FB_FILTER_ENV_COLOR(0); - sGameVisMono.envColor.g = R_FB_FILTER_ENV_COLOR(1); - sGameVisMono.envColor.b = R_FB_FILTER_ENV_COLOR(2); - sGameVisMono.envColor.a = R_FB_FILTER_A; + } else if ((R_FB_FILTER_TYPE == FB_FILTER_ZBUF_IA) || (R_FB_FILTER_TYPE == FB_FILTER_ZBUF_RGBA)) { + // Visualize z-buffer + sGameVisZBuf.vis.type = (R_FB_FILTER_TYPE == FB_FILTER_ZBUF_RGBA); + sGameVisZBuf.vis.primColor.r = R_FB_FILTER_PRIM_COLOR(0); + sGameVisZBuf.vis.primColor.g = R_FB_FILTER_PRIM_COLOR(1); + sGameVisZBuf.vis.primColor.b = R_FB_FILTER_PRIM_COLOR(2); + sGameVisZBuf.vis.primColor.a = R_FB_FILTER_A; + sGameVisZBuf.vis.envColor.r = R_FB_FILTER_ENV_COLOR(0); + sGameVisZBuf.vis.envColor.g = R_FB_FILTER_ENV_COLOR(1); + sGameVisZBuf.vis.envColor.b = R_FB_FILTER_ENV_COLOR(2); + sGameVisZBuf.vis.envColor.a = R_FB_FILTER_A; + VisZBuf_Draw(&sGameVisZBuf, &gfx, zbuffer); + } else if (R_FB_FILTER_TYPE == FB_FILTER_MONO) { + // Monochrome filter + sGameVisMono.vis.type = 0; + sGameVisMono.vis.primColor.r = R_FB_FILTER_PRIM_COLOR(0); + sGameVisMono.vis.primColor.g = R_FB_FILTER_PRIM_COLOR(1); + sGameVisMono.vis.primColor.b = R_FB_FILTER_PRIM_COLOR(2); + sGameVisMono.vis.primColor.a = R_FB_FILTER_A; + sGameVisMono.vis.envColor.r = R_FB_FILTER_ENV_COLOR(0); + sGameVisMono.vis.envColor.g = R_FB_FILTER_ENV_COLOR(1); + sGameVisMono.vis.envColor.b = R_FB_FILTER_ENV_COLOR(2); + sGameVisMono.vis.envColor.a = R_FB_FILTER_A; VisMono_Draw(&sGameVisMono, &gfx); } @@ -222,7 +223,7 @@ void GameState_Init(GameState* gameState, GameStateFunc init, GraphicsContext* g init(gameState); VisCvg_Init(&sGameVisCvg); - VisZbuf_Init(&sGameVisZbuf); + VisZBuf_Init(&sGameVisZBuf); VisMono_Init(&sGameVisMono); ViMode_Init(&sGameViMode); SpeedMeter_Init(&sGameSpeedMeter); @@ -243,7 +244,7 @@ void GameState_Destroy(GameState* gameState) { Rumble_Destroy(); SpeedMeter_Destroy(&sGameSpeedMeter); VisCvg_Destroy(&sGameVisCvg); - VisZbuf_Destroy(&sGameVisZbuf); + VisZBuf_Destroy(&sGameVisZBuf); VisMono_Destroy(&sGameVisMono); ViMode_Destroy(&sGameViMode); THA_Destroy(&gameState->tha); diff --git a/src/code/z_demo.c b/src/code/z_demo.c index 985b3c240..e9264ec84 100644 --- a/src/code/z_demo.c +++ b/src/code/z_demo.c @@ -219,17 +219,17 @@ void CutsceneCmd_Misc(PlayState* play, CutsceneContext* csCtx, CsCmdMisc* cmd) { break; case CS_MISC_VISMONO_BLACK_AND_WHITE: - gVisMonoColor.r = 255; - gVisMonoColor.g = 255; - gVisMonoColor.b = 255; - gVisMonoColor.a = 255 * lerp; + gPlayVisMonoColor.r = 255; + gPlayVisMonoColor.g = 255; + gPlayVisMonoColor.b = 255; + gPlayVisMonoColor.a = 255 * lerp; break; case CS_MISC_VISMONO_SEPIA: - gVisMonoColor.r = 255; - gVisMonoColor.g = 180; - gVisMonoColor.b = 100; - gVisMonoColor.a = 255 * lerp; + gPlayVisMonoColor.r = 255; + gPlayVisMonoColor.g = 180; + gPlayVisMonoColor.b = 100; + gPlayVisMonoColor.a = 255 * lerp; break; case CS_MISC_HIDE_ROOM: diff --git a/src/code/z_play.c b/src/code/z_play.c index 38a9ede2a..12357f59a 100644 --- a/src/code/z_play.c +++ b/src/code/z_play.c @@ -2,7 +2,7 @@ #include "regs.h" #include "functions.h" #include "z64malloc.h" -#include "z64vismono.h" +#include "z64vis.h" #include "z64visfbuf.h" // Variables are put before most headers as a hacky way to bypass bss reordering @@ -11,7 +11,7 @@ Input D_801F6C18; TransitionTile sTransitionTile; s32 gTransitionTileState; VisMono sPlayVisMono; -Color_RGBA8_u32 gVisMonoColor; +Color_RGBA8_u32 gPlayVisMonoColor; VisFbuf sPlayVisFbuf; VisFbuf* sPlayVisFbufInstance; BombersNotebook sBombersNotebook; @@ -1232,8 +1232,8 @@ void Play_DrawMain(PlayState* this) { TransitionFade_Draw(&this->unk_18E48, &sp218); - if (gVisMonoColor.a != 0) { - sPlayVisMono.primColor.rgba = gVisMonoColor.rgba; + if (gPlayVisMonoColor.a != 0) { + sPlayVisMono.vis.primColor.rgba = gPlayVisMonoColor.rgba; VisMono_Draw(&sPlayVisMono, &sp218); } @@ -2301,7 +2301,7 @@ void Play_Init(GameState* thisx) { TransitionFade_Start(&this->unk_18E48); VisMono_Init(&sPlayVisMono); - gVisMonoColor.a = 0; + gPlayVisMonoColor.a = 0; sPlayVisFbufInstance = &sPlayVisFbuf; VisFbuf_Init(sPlayVisFbufInstance); sPlayVisFbufInstance->lodProportion = 0.0f; diff --git a/src/code/z_viscvg.c b/src/code/z_viscvg.c index 1821805ee..739af628f 100644 --- a/src/code/z_viscvg.c +++ b/src/code/z_viscvg.c @@ -1,14 +1,43 @@ +/** + * @file z_viscvg.c + * + * This file implements full-screen frame buffer effects involving the visualization of Coverage in various ways. + * + * Coverage is roughly how much of a pixel is covered by a primitive; the final coverage for a frame is stored in the + * color image alpha component where it is used for antialiasing, see PreRender.c and §15 of the programming manual for + * details. + * + * To understand this file, it is helpful to remember that A_MEM is essentially synonymous with coverage, and that + * `GBL_c1/2(p, a, m, b)` usually represents the RDP blender calculation `(p * a + m * b)`. + * Note the division step that is often included in the blender calculation is omitted; the division is skipped if + * force blending (FORCE_BL) is set, which is the case for all render modes used in this file. + * + * Coverage is full when not on an edge, while on an edge it is usually lower. Since coverage is treated as an alpha + * value, edges of primitives where coverage is lower will show up darker than primitive interiors in all of the + * available modes. + * + * Coverage is abbreviated to "cvg"; "FB RGB" ("framebuffer red/green/blue") is the color the pixel originally had + * before the filter is applied. + */ +#include "z64vis.h" #include "global.h" -#include "z64viscvg.h" -Gfx D_801C5DD0[] = { +/** + * Draws only coverage: does not retain any of the original pixel RGB, primColor is used as background color. + */ +Gfx sCoverageOnlyDL[] = { gsDPSetOtherMode(G_AD_PATTERN | G_CD_MAGICSQ | G_CK_NONE | G_TC_CONV | G_TF_POINT | G_TT_NONE | G_TL_TILE | G_TD_CLAMP | G_TP_NONE | G_CYC_1CYCLE | G_PM_NPRIMITIVE, G_AC_NONE | G_ZS_PRIM | G_RM_VISCVG | G_RM_VISCVG2), gsSPBranchList(D_0E000000.fillRect), }; -Gfx D_801C5DE0[] = { +/** + * Draws fog + coverage * RGB of pixels + * + * @bug This easily overflows the blender because the fog value is added to the coverage value. + */ +Gfx sCoverageRGBFogDL[] = { gsDPSetOtherMode(G_AD_PATTERN | G_CD_MAGICSQ | G_CK_NONE | G_TC_CONV | G_TF_POINT | G_TT_NONE | G_TL_TILE | G_TD_CLAMP | G_TP_NONE | G_CYC_1CYCLE | G_PM_NPRIMITIVE, G_AC_NONE | G_ZS_PRIM | IM_RD | CVG_DST_CLAMP | ZMODE_OPA | FORCE_BL | @@ -17,7 +46,10 @@ Gfx D_801C5DE0[] = { gsSPBranchList(D_0E000000.fillRect), }; -Gfx D_801C5DF0[] = { +/** + * Draws coverage and RGB of pixels + */ +Gfx sCoverageRGBDL[] = { gsDPSetOtherMode(G_AD_PATTERN | G_CD_MAGICSQ | G_CK_NONE | G_TC_CONV | G_TF_POINT | G_TT_NONE | G_TL_TILE | G_TD_CLAMP | G_TP_NONE | G_CYC_1CYCLE | G_PM_NPRIMITIVE, G_AC_NONE | G_ZS_PRIM | IM_RD | CVG_DST_CLAMP | ZMODE_OPA | FORCE_BL | @@ -26,7 +58,14 @@ Gfx D_801C5DF0[] = { gsSPBranchList(D_0E000000.fillRect), }; -Gfx D_801C5E00[] = { +/** + * Two stage filtering: + * + * 1. Apply a uniform color filter by transparently blending primColor with original frame. The "cloud surface" + * RenderMode is used to preserve the coverage for the second stage. + * 2. Second half is the same as `sCoverageRGBDL`'s, i.e. (RGB from stage 1) * cvg + */ +Gfx sCoverageRGBUniformDL[] = { gsDPSetCombineMode(G_CC_PRIMITIVE, G_CC_PRIMITIVE), gsDPSetOtherMode(G_AD_NOTPATTERN | G_CD_DISABLE | G_CK_NONE | G_TC_CONV | G_TF_POINT | G_TT_NONE | G_TL_TILE | G_TD_CLAMP | G_TP_NONE | G_CYC_1CYCLE | G_PM_NPRIMITIVE, @@ -41,45 +80,45 @@ Gfx D_801C5E00[] = { }; void VisCvg_Init(VisCvg* this) { - this->type = 0; - this->setScissor = false; - this->color.r = 255; - this->color.g = 255; - this->color.b = 255; - this->color.a = 255; + this->vis.type = VIS_CVG_TYPE_NONE; + this->vis.scissorType = VIS_NO_SETSCISSOR; + this->vis.primColor.r = 255; + this->vis.primColor.g = 255; + this->vis.primColor.b = 255; + this->vis.primColor.a = 255; } void VisCvg_Destroy(VisCvg* this) { } -void VisCvg_Draw(VisCvg* this, Gfx** gfxp) { - Gfx* gfx = *gfxp; +void VisCvg_Draw(VisCvg* this, Gfx** gfxP) { + Gfx* gfx = *gfxP; gDPPipeSync(gfx++); gDPSetPrimDepth(gfx++, -1, -1); - if (this->setScissor == true) { + if (this->vis.scissorType == VIS_SETSCISSOR) { gSPDisplayList(gfx++, D_0E000000.setScissor); } - switch (this->type) { - case 1: - gSPDisplayList(gfx++, D_801C5DF0); + switch (this->vis.type) { + case VIS_CVG_TYPE_CVG_RGB: + gSPDisplayList(gfx++, sCoverageRGBDL); break; - case 2: - gDPSetColor(gfx++, G_SETPRIMCOLOR, this->color.rgba); - gSPDisplayList(gfx++, D_801C5E00); + case VIS_CVG_TYPE_CVG_RGB_UNIFORM: + gDPSetColor(gfx++, G_SETPRIMCOLOR, this->vis.primColor.rgba); + gSPDisplayList(gfx++, sCoverageRGBUniformDL); break; - case 3: - gDPSetColor(gfx++, G_SETBLENDCOLOR, this->color.rgba); - gSPDisplayList(gfx++, D_801C5DD0); + case VIS_CVG_TYPE_CVG_ONLY: + gDPSetColor(gfx++, G_SETBLENDCOLOR, this->vis.primColor.rgba); + gSPDisplayList(gfx++, sCoverageOnlyDL); break; - case 4: - gDPSetColor(gfx++, G_SETFOGCOLOR, this->color.rgba); - gSPDisplayList(gfx++, D_801C5DE0); + case VIS_CVG_TYPE_CVG_RGB_FOG: + gDPSetColor(gfx++, G_SETFOGCOLOR, this->vis.primColor.rgba); + gSPDisplayList(gfx++, sCoverageRGBFogDL); break; default: @@ -87,5 +126,5 @@ void VisCvg_Draw(VisCvg* this, Gfx** gfxp) { } gDPPipeSync(gfx++); - *gfxp = gfx; + *gfxP = gfx; } diff --git a/src/code/z_vismono.c b/src/code/z_vismono.c index d4c462fc4..5e4330786 100644 --- a/src/code/z_vismono.c +++ b/src/code/z_vismono.c @@ -1,16 +1,20 @@ -/* - * File: z_vismono.c - * Description: Color frame buffer effect to desaturate the colors. +/** + * @file z_vismono.c + * + * This file implements a full-screen framebuffer effect for desaturating the contents of the framebuffer image. + * + * Broadly, this effect is achieved by reinterpreting the contents of the RGBA16 color image as indices into an IA16 + * color palette that converts each color into the desaturated equivalent. More precise details can be found in inline + * comments. */ - +#include "z64vis.h" #include "global.h" -#include "z64vismono.h" #include "libc64/malloc.h" // Height of the fragments the color frame buffer (CFB) is split into. // It is the maximum amount of lines such that all rgba16 SCREEN_WIDTH-long lines fit into -// the half of tmem (0x800 bytes) dedicated to color-indexed data. -#define VISMONO_CFBFRAG_HEIGHT (0x800 / (SCREEN_WIDTH * G_IM_SIZ_16b_BYTES)) +// the half of TMEM dedicated to color-indexed data. +#define VISMONO_CFBFRAG_HEIGHT ((TMEM_SIZE / 2) / (SCREEN_WIDTH * G_IM_SIZ_16b_BYTES)) // Maximum size of the dlist written by `VisMono_DesaturateDList`. // `VisMono_DesaturateDList` consistently uses `VISMONO_DLSIZE - 2` double words, so this can be 2 less. @@ -26,16 +30,16 @@ void VisMono_Init(VisMono* this) { bzero(this, sizeof(VisMono)); - this->unk_00 = 0; - this->setScissor = false; - this->primColor.r = 255; - this->primColor.g = 255; - this->primColor.b = 255; - this->primColor.a = 255; - this->envColor.r = 0; - this->envColor.g = 0; - this->envColor.b = 0; - this->envColor.a = 0; + this->vis.type = 0; + this->vis.scissorType = VIS_NO_SETSCISSOR; + this->vis.primColor.r = 255; + this->vis.primColor.g = 255; + this->vis.primColor.b = 255; + this->vis.primColor.a = 255; + this->vis.envColor.r = 0; + this->vis.envColor.g = 0; + this->vis.envColor.b = 0; + this->vis.envColor.a = 0; } void VisMono_Destroy(VisMono* this) { @@ -95,6 +99,8 @@ Gfx* VisMono_DesaturateDList(Gfx* gfx) { // Set texel 1 to be a CI8 image with width `SCREEN_WIDTH * 2` and height `VISMONO_CFBFRAG_HEIGHT` // Its position in texture image space is shifted along +S by 1 + // Note the palette index for this tile has also been incremented from 0 to 1, however the palette index is + // ignored for CI8 texture sampling. gDPSetTile(gfx++, G_IM_FMT_CI, G_IM_SIZ_8b, SCREEN_WIDTH * 2 * G_IM_SIZ_8b_LINE_BYTES / 8, 0x0, 1, 1, G_TX_NOMIRROR | G_TX_CLAMP, 0, 0, G_TX_NOMIRROR | G_TX_CLAMP, 0, 0); gDPSetTileSize(gfx++, 1, 1 << 2, 0, (SCREEN_WIDTH * 2) << 2, (VISMONO_CFBFRAG_HEIGHT - 1) << 2); @@ -129,8 +135,8 @@ Gfx* VisMono_DesaturateDList(Gfx* gfx) { return gfx; } -void VisMono_Draw(VisMono* this, Gfx** gfxp) { - Gfx* gfx = *gfxp; +void VisMono_Draw(VisMono* this, Gfx** gfxP) { + Gfx* gfx = *gfxP; u16* tlut; Gfx* dList; Gfx* dListEnd; @@ -151,12 +157,12 @@ void VisMono_Draw(VisMono* this, Gfx** gfxp) { gDPPipeSync(gfx++); - if (this->setScissor == true) { + if (this->vis.scissorType == VIS_SETSCISSOR) { gSPDisplayList(gfx++, D_0E000000.setScissor); } - gDPSetColor(gfx++, G_SETPRIMCOLOR, this->primColor.rgba); - gDPSetColor(gfx++, G_SETENVCOLOR, this->envColor.rgba); + gDPSetColor(gfx++, G_SETPRIMCOLOR, this->vis.primColor.rgba); + gDPSetColor(gfx++, G_SETENVCOLOR, this->vis.envColor.rgba); gDPLoadTLUT_pal256(gfx++, tlut); @@ -164,7 +170,7 @@ void VisMono_Draw(VisMono* this, Gfx** gfxp) { gDPPipeSync(gfx++); - *gfxp = gfx; + *gfxP = gfx; } void VisMono_DrawOld(VisMono* this) { diff --git a/src/code/z_viszbuf.c b/src/code/z_viszbuf.c index 17c734cb0..86fb64474 100644 --- a/src/code/z_viszbuf.c +++ b/src/code/z_viszbuf.c @@ -1,55 +1,100 @@ +/** + * @file z_viszbuf.c + * + * This file implements a full-screen framebuffer effect for visualizing the z-buffer (AKA depth buffer), using either + * cycling RGBA or a single fading color. + * + * This is done by reading the z-buffer as if it were a color image, the format of which is specified by the selected + * vis type: + * - VIS_ZBUF_TYPE_IA : Produces a monotonic fade from primColor to envColor as depth increases. + * - VIS_ZBUF_TYPE_RGBA : Produces vibrant almost-periodic-looking bands. + * + * In both cases this occurs because of the format the depth information takes: it is 18-bit, and is a nonnegative + * floating-point number with + * bbb mmmmmmmmmmm dd|dd + * exponent mantissa dz value (only first 16 bits visible to CPU, the least significant 2 bits of dz are ignored) + * + * Reading z-buffer as IA16: + * bbbmmmmm mmmmmmdd + * iiiiiiii aaaaaaaa + * + * Since floating-point numbers of this format have the same ordering as their binary/hex representation, increasing + * the depth also increases the intensity in the IA16 representation and hence the interpolation parameter used to + * combine primColor and envColor. The alpha is ignored by the RenderMode. + * + * Reading z-buffer as RGBA16: + * bbbmm mmmmm mmmmd d + * rrrrr ggggg bbbbb a + * + * The red increases monotonically with the depth. The significant visible oscillation is the green component, because + * it rolls over every time the second-most-significant bit of the mantissa increments. The blue component oscillates + * too rapidly to be particularly visible (it rolls over when the 7th-most-significant bit increments). The alpha is + * again ignored by the RenderMode. + */ +#include "z64vis.h" #include "global.h" -#include "z64viszbuf.h" #include "sys_cfb.h" #include "libc/stdbool.h" +// Height of the fragments the z-buffer is split into. +// It is the maximum amount of lines such that all rgba16 SCREEN_WIDTH-long lines fit into TMEM. #define VISZBUF_ZBUFFRAG_HEIGHT (TMEM_SIZE / (gCfbWidth * G_IM_SIZ_16b_BYTES)) -void VisZbuf_Init(VisZbuf* this) { - this->useRgba = false; - this->setScissor = false; - this->primColor.r = 255; - this->primColor.g = 255; - this->primColor.b = 255; - this->primColor.a = 255; - this->envColor.r = 0; - this->envColor.g = 0; - this->envColor.b = 0; - this->envColor.a = 255; +/** + * Initialise to IA type with white and black as default colors. + */ +void VisZBuf_Init(VisZBuf* this) { + this->vis.type = VIS_ZBUF_TYPE_IA; + this->vis.scissorType = VIS_NO_SETSCISSOR; + this->vis.primColor.r = 255; + this->vis.primColor.g = 255; + this->vis.primColor.b = 255; + this->vis.primColor.a = 255; + this->vis.envColor.r = 0; + this->vis.envColor.g = 0; + this->vis.envColor.b = 0; + this->vis.envColor.a = 255; } -void VisZbuf_Destroy(VisZbuf* this) { +void VisZBuf_Destroy(VisZBuf* this) { } -void VisZbuf_Draw(VisZbuf* this, Gfx** gfxP, void* zbuffer) { +void VisZBuf_Draw(VisZBuf* this, Gfx** gfxP, void* zbuffer) { Gfx* gfx = *gfxP; s32 height = VISZBUF_ZBUFFRAG_HEIGHT; s32 y; - s32 fmt = !this->useRgba ? G_IM_FMT_IA : G_IM_FMT_RGBA; + s32 fmt = (this->vis.type == VIS_ZBUF_TYPE_IA) ? G_IM_FMT_IA : G_IM_FMT_RGBA; if (zbuffer == NULL) { return; } gDPPipeSync(gfx++); - if (this->setScissor == true) { + if (this->vis.scissorType == VIS_SETSCISSOR) { gSPDisplayList(gfx++, D_0E000000.setScissor); } + // No palette so can use all of TMEM. + // G_RM_OPA_SURF discards all information previously in the pixel, and the current alpha, leaving only the color + // from this filter. gDPSetOtherMode(gfx++, G_AD_DISABLE | G_CD_MAGICSQ | G_CK_NONE | G_TC_FILT | G_TF_POINT | G_TT_NONE | G_TL_TILE | G_TD_CLAMP | G_TP_NONE | G_CYC_1CYCLE | G_PM_NPRIMITIVE, G_AC_NONE | G_ZS_PRIM | G_RM_OPA_SURF | G_RM_OPA_SURF2); + + // LERP between primColor and envColor in 1-cycle mode using the z-buffer value. gDPSetCombineLERP(gfx++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT); - gDPSetColor(gfx++, G_SETPRIMCOLOR, this->primColor.rgba); - gDPSetColor(gfx++, G_SETENVCOLOR, this->envColor.rgba); + gDPSetColor(gfx++, G_SETPRIMCOLOR, this->vis.primColor.rgba); + gDPSetColor(gfx++, G_SETENVCOLOR, this->vis.envColor.rgba); for (y = 0; y < (gCfbHeight - height) + 1; y += height) { + // Load a few lines of the z-buffer, as many as can fit in TMEM at once. gDPLoadTextureTile(gfx++, zbuffer, fmt, G_IM_SIZ_16b, gCfbWidth, 0, 0, y, gCfbWidth - 1, (y + height) - 1, 0, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); + // Overwrite them with the calculated colors. gSPTextureRectangle(gfx++, 0, y << 2, gCfbWidth << 2, (y + height) << 2, G_TX_RENDERTILE, 0, y << 5, 1 << 10, 1 << 10); } |
