From a31d8dd81b16d7df1e064105458e1dc37abafdd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emre=20Ak=C4=B1?= Date: Sat, 4 Nov 2023 03:57:09 +0300 Subject: [PATCH] fix(r_draw): implement double-buffering and optimize frame flushing * add "true" double-buffering and set a pristine framebuffer on each flush call, instead of diligently painting the entire `` black --- src/engine/r_draw.ts | 24 +++++++++--------------- src/game/g_run.ts | 7 +------ src/typedef.d.ts | 8 ++------ 3 files changed, 12 insertions(+), 27 deletions(-) diff --git a/src/engine/r_draw.ts b/src/engine/r_draw.ts index ba4b9d3..88c0ca1 100644 --- a/src/engine/r_draw.ts +++ b/src/engine/r_draw.ts @@ -26,32 +26,28 @@ const R_FlushBuffer = R_Screen.R_FlushBuffer; const R_InitBuffer = R_Screen.R_InitBuffer; - let frameBuffer: ImageData; + /* double-buffering */ + let frameBuffer: ImageData, cleanFrameBuffer: Uint8ClampedArray; let zBuffer: Float32Array, cleanZBuffer: Float32Array; function R_InitFrameBuffer (): void { + const frameBufferSize = N_PIXELS << 2; + cleanFrameBuffer = new Uint8ClampedArray(frameBufferSize); + for (let i = 3; i < frameBufferSize; i += 4) cleanFrameBuffer[i] = 255; frameBuffer = R_InitBuffer(SCREEN_W, SCREEN_H); } - function R_ResetFrameBuffer (): void - { - R_FillRect(0, 0, SCREEN_W, SCREEN_H, 0, 0, 0, 255); - } - - function R_FlushFrame (): void - { - R_FlushBuffer(frameBuffer); - } - function R_InitZBuffer (): void { cleanZBuffer = new Float32Array(N_PIXELS); zBuffer = new Float32Array(N_PIXELS); } - function R_ResetZBuffer (): void + function R_FlushFrame (): void { + R_FlushBuffer(frameBuffer); + frameBuffer.data.set(cleanFrameBuffer); zBuffer.set(cleanZBuffer); } @@ -1024,10 +1020,8 @@ { return { R_InitFrameBuffer, - R_ResetFrameBuffer, - R_FlushFrame, R_InitZBuffer, - R_ResetZBuffer, + R_FlushFrame, R_FillRect, R_DrawLine, R_DrawLine_DDA, diff --git a/src/game/g_run.ts b/src/game/g_run.ts index ea8565d..6103ccc 100644 --- a/src/game/g_run.ts +++ b/src/game/g_run.ts @@ -31,9 +31,7 @@ const R_DebugStats = R_Camera.R_DebugStats; const R_Draw = __import__R_Draw(); - const R_ResetFrameBuffer = R_Draw.R_ResetFrameBuffer; const R_FlushFrame = R_Draw.R_FlushFrame; - const R_ResetZBuffer = R_Draw.R_ResetZBuffer; const R_Drawers = __import__R_Drawers(); const R_TitleDrawer = R_Drawers.R_TitleDrawer; @@ -53,9 +51,6 @@ function G_UpdateScreen (deltaT: number): void { - // clear the frame buffer so that the frame can start fresh - R_ResetFrameBuffer(); - R_ResetZBuffer(); R_ChangeRenderMode(); R_RenderGeometries(nTrisOnScreen); R_FlushFrame(); @@ -100,7 +95,7 @@ { if (!setupResolution) return; // exit with error // first, clear the frame buffer for any further drawing to take place - R_ResetFrameBuffer(); + R_FlushFrame(); // then, clear the loading animation that is currently running AN_CancelAnimation(setupResolution.loadingId); /* finally, start the animation for the title screen */ diff --git a/src/typedef.d.ts b/src/typedef.d.ts index 0d87566..2a2eb71 100644 --- a/src/typedef.d.ts +++ b/src/typedef.d.ts @@ -432,10 +432,8 @@ declare function __import__R_Camera (): __Mod__R_Camera; // engine/r_draw.ts // ----------------------------------------------------------------------------- type R_InitFrameBuffer = () => void; -type R_ResetFrameBuffer = () => void; -type R_FlushFrame = () => void; type R_InitZBuffer = () => void; -type R_ResetZBuffer = () => void; +type R_FlushFrame = () => void; type R_FillRect = ( x: number, y: number, @@ -535,10 +533,8 @@ type R_Print = ( type __Mod__R_Draw = { R_InitFrameBuffer: R_InitFrameBuffer, - R_ResetFrameBuffer: R_ResetFrameBuffer, - R_FlushFrame: R_FlushFrame, R_InitZBuffer: R_InitZBuffer, - R_ResetZBuffer: R_ResetZBuffer, + R_FlushFrame: R_FlushFrame, R_FillRect: R_FillRect, R_DrawLine: R_DrawLine, R_DrawLine_DDA: R_DrawLine_DDA,