From a25b50c501c0df47a5a54f8aa7f01563b1cb1eaa Mon Sep 17 00:00:00 2001 From: Doyle Thai Date: Fri, 19 May 2017 20:45:18 +1000 Subject: [PATCH] Fix color modulation alpha bug Phasing color modulation over time would make bitmaps become transparent and show layers underneath even if alpha was set to 1. This was caused by the precomputed 1/255 calculation #defined in DTRRender which was missing the precision required so floating point errors began to accumulate causing erroneous colours. --- src/DTRenderer.cpp | 18 +++++++++++++----- src/DTRendererDebug.cpp | 21 ++++----------------- src/DTRendererDebug.h | 2 +- src/DTRendererPlatform.h | 1 + src/DTRendererRender.cpp | 5 +++-- src/DTRendererRender.h | 2 +- src/Win32DTRenderer.cpp | 21 +++++++++++++-------- 7 files changed, 36 insertions(+), 34 deletions(-) diff --git a/src/DTRenderer.cpp b/src/DTRenderer.cpp index c0d8011..60d30c2 100644 --- a/src/DTRenderer.cpp +++ b/src/DTRenderer.cpp @@ -1036,9 +1036,16 @@ extern "C" void DTR_Update(PlatformRenderBuffer *const renderBuffer, PlatformMemory *const memory) { DTRState *state = (DTRState *)memory->context; + if (input->executableReloaded) + { + DTR_DEBUG_PROFILE_END(); + DTR_DEBUG_PROFILE_START(); + } + + DTR_DEBUG_TIMED_FUNCTION(); if (!memory->isInit) { - DTR_DEBUG_PROFILE_START(); + DTR_DEBUG_TIMED_BLOCK("DTR_Update Memory Initialisation"); // NOTE(doyle): Do premultiply ourselves stbi_set_unpremultiply_on_load(true); stbi_set_flip_vertically_on_load(true); @@ -1061,7 +1068,6 @@ extern "C" void DTR_Update(PlatformRenderBuffer *const renderBuffer, int x = 5; DqnMemBuffer_EndTempRegion(tmp); } - DTR_DEBUG_TIMED_FUNCTION(); DTRRender_Clear(renderBuffer, DqnV3_3f(0, 0, 0)); @@ -1087,10 +1093,12 @@ extern "C" void DTR_Update(PlatformRenderBuffer *const renderBuffer, LOCAL_PERSIST f32 rotation = 0; rotation += input->deltaForFrame * 0.25f; +#if 1 DTRRenderTransform defaultTransform = DTRRender_DefaultTransform(); defaultTransform.rotation = rotation + 45; - DTRRender_Rectangle(renderBuffer, DqnV2_1f(300.0f), DqnV2_1f(300 + 20.0f), DqnV4_4f(0, 1.0f, 1.0f, 1.0f), + DTRRender_Rectangle(renderBuffer, DqnV2_1f(300.0f), DqnV2_1f(300 + 100.0f), DqnV4_4f(0, 1.0f, 1.0f, 1.0f), defaultTransform); +#endif // Rotating triangle { @@ -1104,7 +1112,7 @@ extern "C" void DTR_Update(PlatformRenderBuffer *const renderBuffer, DTRRender_Text(renderBuffer, state->font, fontP, "hello world!", DqnV4_4f(0, 0, 0, 1)); DTRRenderTransform transform = DTRRender_DefaultTransform(); - transform.rotation = rotation * 2.0f; + transform.rotation = 0; transform.scale = DqnV2_1f(2.0f); LOCAL_PERSIST DqnV2 bitmapP = DqnV2_2f(300, 250); @@ -1112,7 +1120,7 @@ extern "C" void DTR_Update(PlatformRenderBuffer *const renderBuffer, f32 cAngle = (f32)input->timeNowInS; DqnV4 color = DqnV4_4f(0.5f + 0.5f * sinf(cAngle), 0.5f + 0.5f * sinf(2.9f * cAngle), - 0.5f + 0.5f * cosf(9.9f * cAngle), 1.0f); + 0.5f + 0.5f * cosf(10.0f * cAngle), 1.0f); DTRRender_Bitmap(renderBuffer, &state->bitmap, bitmapP, transform, color); #else diff --git a/src/DTRendererDebug.cpp b/src/DTRendererDebug.cpp index 9632401..0477341 100644 --- a/src/DTRendererDebug.cpp +++ b/src/DTRendererDebug.cpp @@ -83,23 +83,8 @@ void DTRDebug_Update(DTRState *const state, debug->totalSetPixels += debug->setPixelsPerFrame; debug->totalSetPixels = DQN_MAX(0, debug->totalSetPixels); - // totalSetPixels - { - char str[128] = {}; - Dqn_sprintf(str, "%s: %'lld", "TotalSetPixels", debug->totalSetPixels); - DTRRender_Text(debug->renderBuffer, *debug->font, debug->displayP, str, - debug->displayColor); - debug->displayP.y += globalDebug.displayYOffset; - } - - // setPixelsPerFrame - { - char str[128] = {}; - Dqn_sprintf(str, "%s: %'lld", "SetPixelsPerFrame", debug->setPixelsPerFrame); - DTRRender_Text(debug->renderBuffer, *debug->font, debug->displayP, str, - debug->displayColor); - debug->displayP.y += globalDebug.displayYOffset; - } + DTRDebug_PushText("TotalSetPixels: %'lld", debug->totalSetPixels); + DTRDebug_PushText("SetPixelsPerFrame: %'lld", debug->setPixelsPerFrame); // memory { @@ -107,6 +92,8 @@ void DTRDebug_Update(DTRState *const state, PushMemBufferText("TransBuffer", &memory->transientBuffer); } + DTRDebug_PushText("SSE2Support: %s", (input->canUseSSE2) ? "true" : "false"); + debug->setPixelsPerFrame = 0; debug->displayP = DqnV2_2i(0, debug->renderBuffer->height + globalDebug.displayYOffset); diff --git a/src/DTRendererDebug.h b/src/DTRendererDebug.h index 0c3105d..92a06d7 100644 --- a/src/DTRendererDebug.h +++ b/src/DTRendererDebug.h @@ -4,7 +4,7 @@ #include "dqn.h" #define DTR_DEBUG 1 #ifdef DTR_DEBUG - #define DTR_DEBUG_RENDER 0 + #define DTR_DEBUG_RENDER 1 #define DTR_DEBUG_PROFILING 1 #ifdef DTR_DEBUG_PROFILING diff --git a/src/DTRendererPlatform.h b/src/DTRendererPlatform.h index a66f93a..734d826 100644 --- a/src/DTRendererPlatform.h +++ b/src/DTRendererPlatform.h @@ -72,6 +72,7 @@ typedef struct PlatformInput f32 deltaForFrame; f64 timeNowInS; bool executableReloaded; + bool canUseSSE2; PlatformAPI api; union { diff --git a/src/DTRendererRender.cpp b/src/DTRendererRender.cpp index d8332e7..d76ecae 100644 --- a/src/DTRendererRender.cpp +++ b/src/DTRendererRender.cpp @@ -160,9 +160,10 @@ FILE_SCOPE inline void SetPixel(PlatformRenderBuffer *const renderBuffer, const destB = 255; } - u32 pixel = ((u32)(destR) << 16 | + u32 pixel = // ((u32)(destA) << 24 | + (u32)(destR) << 16 | (u32)(destG) << 8 | - (u32)(destB) << 0); + (u32)(destB) << 0; bitmapPtr[x + (y * pitchInU32)] = pixel; globalDebug.setPixelsPerFrame++; diff --git a/src/DTRendererRender.h b/src/DTRendererRender.h index 6b6b01e..307cb21 100644 --- a/src/DTRendererRender.h +++ b/src/DTRendererRender.h @@ -3,7 +3,7 @@ #include "dqn.h" -#define DTRRENDER_INV_255 0.00392156862f; +#define DTRRENDER_INV_255 1.0f/255.0f typedef struct PlatformRenderBuffer PlatformRenderBuffer; typedef struct DTRBitmap DTRBitmap; diff --git a/src/Win32DTRenderer.cpp b/src/Win32DTRenderer.cpp index 203860f..47c3cb9 100644 --- a/src/Win32DTRenderer.cpp +++ b/src/Win32DTRenderer.cpp @@ -500,22 +500,29 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, } //////////////////////////////////////////////////////////////////////////// - // Update Loop + // Platform Data Pre-amble //////////////////////////////////////////////////////////////////////////// DQN_ASSERT(DqnMemBuffer_Init(&globalPlatformMemory.permanentBuffer, DQN_MEGABYTE(1), true, 4) && DqnMemBuffer_Init(&globalPlatformMemory.transientBuffer, DQN_MEGABYTE(1), true, 4)); - const f32 TARGET_FRAMES_PER_S = 60.0f; - f32 targetSecondsPerFrame = 1 / TARGET_FRAMES_PER_S; - f64 frameTimeInS = 0.0f; - globalRunning = true; - PlatformAPI platformAPI = {}; platformAPI.FileOpen = Platform_FileOpen; platformAPI.FileRead = Platform_FileRead; platformAPI.FileClose = Platform_FileClose; platformAPI.Print = Platform_Print; + PlatformInput platformInput = {}; + platformInput.canUseSSE2 = IsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE); + platformInput.api = platformAPI; + + //////////////////////////////////////////////////////////////////////////// + // Update Loop + //////////////////////////////////////////////////////////////////////////// + const f32 TARGET_FRAMES_PER_S = 60.0f; + f32 targetSecondsPerFrame = 1 / TARGET_FRAMES_PER_S; + f64 frameTimeInS = 0.0f; + globalRunning = true; + while (globalRunning) { //////////////////////////////////////////////////////////////////////// @@ -523,7 +530,6 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, //////////////////////////////////////////////////////////////////////// f64 startFrameTimeInS = DqnTime_NowInS(); - PlatformInput platformInput = {}; FILETIME lastWriteTime = Win32GetLastWriteTime(dllPath); if (CompareFileTime(&lastWriteTime, &dllCode.lastWriteTime) != 0) { @@ -535,7 +541,6 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, { platformInput.timeNowInS = DqnTime_NowInS(); platformInput.deltaForFrame = (f32)frameTimeInS; - platformInput.api = platformAPI; Win32ProcessMessages(mainWindow, &platformInput); PlatformRenderBuffer platformBuffer = {};