Organise functions to files
This commit is contained in:
parent
75f23b6d66
commit
13860e4089
@ -6,9 +6,9 @@ MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{911E67C6-3D85-4FCE-B560-20A9C3E3FF48}") = "Win32DRenderer", "bin\Win32DRenderer.exe", "{6A9F3AE0-4D5E-4F89-8572-B868AC43C38A}"
|
||||
ProjectSection(DebuggerProjectSystem) = preProject
|
||||
PortSupplier = 00000000-0000-0000-0000-000000000000
|
||||
Executable = C:\git\drenderer\bin\Win32DRenderer.exe
|
||||
Executable = C:\git\dtrenderer\bin\Win32DTRenderer.exe
|
||||
RemoteMachine = THAI-PC
|
||||
StartingDirectory = C:\git\drenderer\data
|
||||
StartingDirectory = C:\git\dtrenderer\data
|
||||
Environment = Default
|
||||
LaunchingEngine = 00000000-0000-0000-0000-000000000000
|
||||
UseLegacyDebugEngines = No
|
||||
@ -21,7 +21,7 @@ Global
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{6A9F3AE0-4D5E-4F89-8572-B868AC43C38A}.Release|x64.ActiveCfg = Release|x64
|
||||
{6A9F3AE0-4D5E-4F89-8572-B868AC43C38A}.Release|x64.ActiveCfg = Release
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
@ -1,7 +0,0 @@
|
||||
#ifndef DRENDERER_H
|
||||
#define DRENDERER_H
|
||||
|
||||
typedef void DR_UpdateFunction(struct PlatformRenderBuffer *const renderBuffer,
|
||||
struct PlatformInput *const input,
|
||||
struct PlatformMemory *const memory);
|
||||
#endif
|
222
src/DTRenderer.cpp
Normal file
222
src/DTRenderer.cpp
Normal file
@ -0,0 +1,222 @@
|
||||
#include "DTRenderer.h"
|
||||
#include "DTRendererDebug.h"
|
||||
#include "DTRendererPlatform.h"
|
||||
#include "DTRendererRender.h"
|
||||
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include "external/stb_image.h"
|
||||
|
||||
#define DQN_IMPLEMENTATION
|
||||
#include "dqn.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
FILE_SCOPE bool BitmapFontCreate(const PlatformAPI api,
|
||||
PlatformMemory *const memory,
|
||||
DTRFont *const font, const char *const path,
|
||||
const DqnV2i bitmapDim,
|
||||
const DqnV2i codepointRange,
|
||||
const f32 sizeInPt)
|
||||
{
|
||||
if (!memory || !font || !path) return false;
|
||||
|
||||
DTRFont loadedFont = {};
|
||||
loadedFont.bitmapDim = bitmapDim;
|
||||
loadedFont.codepointRange = codepointRange;
|
||||
loadedFont.sizeInPt = sizeInPt;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Load font data
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
PlatformFile file = {};
|
||||
if (!api.FileOpen(path, &file, PlatformFilePermissionFlag_Read))
|
||||
return false; // TODO(doyle): Logging
|
||||
|
||||
DqnTempBuffer tmpMemRegion = DqnMemBuffer_BeginTempRegion(&memory->transientBuffer);
|
||||
u8 *fontBuf = (u8 *)DqnMemBuffer_Allocate(&memory->transientBuffer, file.size);
|
||||
size_t bytesRead = api.FileRead(&file, fontBuf, file.size);
|
||||
api.FileClose(&file);
|
||||
if (bytesRead != file.size)
|
||||
{
|
||||
// TODO(doyle): Logging
|
||||
DqnMemBuffer_EndTempRegion(tmpMemRegion);
|
||||
return false;
|
||||
}
|
||||
|
||||
stbtt_fontinfo fontInfo = {};
|
||||
if (stbtt_InitFont(&fontInfo, fontBuf, 0) == 0)
|
||||
{
|
||||
DQN_ASSERT(DQN_INVALID_CODE_PATH);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (DTR_DEBUG) DQN_ASSERT(stbtt_GetNumberOfFonts(fontBuf) == 1);
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Pack font data to bitmap
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
loadedFont.bitmap = (u8 *)DqnMemBuffer_Allocate(
|
||||
&memory->permanentBuffer,
|
||||
(size_t)(loadedFont.bitmapDim.w * loadedFont.bitmapDim.h));
|
||||
|
||||
stbtt_pack_context fontPackContext = {};
|
||||
if (stbtt_PackBegin(&fontPackContext, loadedFont.bitmap, bitmapDim.w,
|
||||
bitmapDim.h, 0, 1, NULL) == 1)
|
||||
{
|
||||
// stbtt_PackSetOversampling(&fontPackContext, 2, 2);
|
||||
|
||||
i32 numCodepoints =
|
||||
(i32)((codepointRange.max + 1) - codepointRange.min);
|
||||
|
||||
loadedFont.atlas = (stbtt_packedchar *)DqnMemBuffer_Allocate(
|
||||
&memory->permanentBuffer, numCodepoints * sizeof(stbtt_packedchar));
|
||||
stbtt_PackFontRange(&fontPackContext, fontBuf, 0,
|
||||
STBTT_POINT_SIZE(sizeInPt), (i32)codepointRange.min,
|
||||
numCodepoints, loadedFont.atlas);
|
||||
stbtt_PackEnd(&fontPackContext);
|
||||
}
|
||||
else
|
||||
{
|
||||
DQN_ASSERT(DQN_INVALID_CODE_PATH);
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Premultiply Alpha of Bitmap
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
for (i32 y = 0; y < bitmapDim.h; y++)
|
||||
{
|
||||
for (i32 x = 0; x < bitmapDim.w; x++)
|
||||
{
|
||||
// NOTE: Bitmap from stb_truetype is 1BPP. So the actual color
|
||||
// value represents its' alpha value but also its' color.
|
||||
u32 index = x + (y * bitmapDim.w);
|
||||
f32 alpha = (f32)(loadedFont.bitmap[index]) / 255.0f;
|
||||
f32 color = alpha;
|
||||
f32 preMulAlphaColor = color * alpha;
|
||||
DQN_ASSERT(preMulAlphaColor >= 0.0f && preMulAlphaColor <= 255.0f);
|
||||
|
||||
loadedFont.bitmap[index] = (u8)(preMulAlphaColor * 255.0f);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DTR_DEBUG_RENDER_FONT_BITMAP
|
||||
stbi_write_bmp("test.bmp", bitmapDim.w, bitmapDim.h, 1, loadedFont.bitmap);
|
||||
#endif
|
||||
|
||||
*font = loadedFont;
|
||||
return true;
|
||||
}
|
||||
|
||||
FILE_SCOPE bool BitmapLoad(const PlatformAPI api, DTRBitmap *bitmap,
|
||||
const char *const path,
|
||||
DqnMemBuffer *const transientBuffer)
|
||||
{
|
||||
if (!bitmap) return false;
|
||||
|
||||
PlatformFile file = {};
|
||||
if (!api.FileOpen(path, &file, PlatformFilePermissionFlag_Read))
|
||||
return false;
|
||||
|
||||
DqnTempBuffer tempBuffer = DqnMemBuffer_BeginTempRegion(transientBuffer);
|
||||
{
|
||||
u8 *const rawData =
|
||||
(u8 *)DqnMemBuffer_Allocate(transientBuffer, file.size);
|
||||
size_t bytesRead = api.FileRead(&file, rawData, file.size);
|
||||
api.FileClose(&file);
|
||||
|
||||
if (bytesRead != file.size)
|
||||
{
|
||||
DqnMemBuffer_EndTempRegion(tempBuffer);
|
||||
return false;
|
||||
}
|
||||
|
||||
bitmap->memory =
|
||||
stbi_load_from_memory(rawData, (i32)file.size, &bitmap->dim.w,
|
||||
&bitmap->dim.h, &bitmap->bytesPerPixel, 4);
|
||||
}
|
||||
DqnMemBuffer_EndTempRegion(tempBuffer);
|
||||
if (!bitmap->memory) return false;
|
||||
|
||||
const i32 pitch = bitmap->dim.w * bitmap->bytesPerPixel;
|
||||
for (i32 y = 0; y < bitmap->dim.h; y++)
|
||||
{
|
||||
u8 *const srcRow = bitmap->memory + (y * pitch);
|
||||
for (i32 x = 0; x < bitmap->dim.w; x++)
|
||||
{
|
||||
u32 *pixelPtr = (u32 *)srcRow;
|
||||
u32 pixel = pixelPtr[x];
|
||||
|
||||
DqnV4 color = {};
|
||||
color.a = (f32)(pixel >> 24);
|
||||
color.b = (f32)((pixel >> 16) & 0xFF);
|
||||
color.g = (f32)((pixel >> 8) & 0xFF);
|
||||
color.r = (f32)((pixel >> 0) & 0xFF);
|
||||
color = DTRRender_PreMultiplyAlpha(color);
|
||||
|
||||
pixel = (((u32)color.a << 24) |
|
||||
((u32)color.b << 16) |
|
||||
((u32)color.g << 8) |
|
||||
((u32)color.r << 0));
|
||||
|
||||
pixelPtr[x] = pixel;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
extern "C" void DTR_Update(PlatformRenderBuffer *const renderBuffer,
|
||||
PlatformInput *const input,
|
||||
PlatformMemory *const memory)
|
||||
{
|
||||
DTRState *state = (DTRState *)memory->context;
|
||||
if (!memory->isInit)
|
||||
{
|
||||
stbi_set_flip_vertically_on_load(true);
|
||||
memory->isInit = true;
|
||||
memory->context =
|
||||
DqnMemBuffer_Allocate(&memory->permanentBuffer, sizeof(DTRState));
|
||||
DQN_ASSERT(memory->context);
|
||||
|
||||
state = (DTRState *)memory->context;
|
||||
BitmapFontCreate(input->api, memory, &state->font, "Roboto-bold.ttf",
|
||||
DqnV2i_2i(256, 256), DqnV2i_2i(' ', '~'), 16);
|
||||
BitmapLoad(input->api, &state->bitmap, "lune_logo.png",
|
||||
&memory->transientBuffer);
|
||||
}
|
||||
|
||||
DTRRender_Clear(renderBuffer, DqnV3_3f(0, 0, 0));
|
||||
DqnV4 colorRed = DqnV4_4i(180, 0, 0, 255);
|
||||
DqnV2i bufferMidP =
|
||||
DqnV2i_2f(renderBuffer->width * 0.5f, renderBuffer->height * 0.5f);
|
||||
i32 boundsOffset = 100;
|
||||
|
||||
DqnV2 t0[3] = {DqnV2_2i(10, 70), DqnV2_2i(50, 160), DqnV2_2i(70, 80)};
|
||||
DqnV2 t1[3] = {DqnV2_2i(180, 50), DqnV2_2i(150, 1), DqnV2_2i(70, 180)};
|
||||
DqnV2 t2[3] = {DqnV2_2i(180, 150), DqnV2_2i(120, 160), DqnV2_2i(130, 180)};
|
||||
LOCAL_PERSIST DqnV2 t3[3] = {
|
||||
DqnV2_2i(boundsOffset, boundsOffset),
|
||||
DqnV2_2i(bufferMidP.w, renderBuffer->height - boundsOffset),
|
||||
DqnV2_2i(renderBuffer->width - boundsOffset, boundsOffset)};
|
||||
|
||||
#if 1
|
||||
DTRRender_Triangle(renderBuffer, t0[0], t0[1], t0[2], colorRed);
|
||||
DTRRender_Triangle(renderBuffer, t1[0], t1[1], t1[2], colorRed);
|
||||
DTRRender_Triangle(renderBuffer, t2[0], t2[1], t2[2], colorRed);
|
||||
#endif
|
||||
|
||||
DqnV4 colorRedHalfA = DqnV4_4i(255, 0, 0, 64);
|
||||
LOCAL_PERSIST f32 rotation = 0;
|
||||
rotation += input->deltaForFrame * 0.25f;
|
||||
DTRRender_Triangle(renderBuffer, t3[0], t3[1], t3[2], colorRedHalfA,
|
||||
DqnV2_1f(1.0f), rotation, DqnV2_2f(0.33f, 0.33f));
|
||||
|
||||
DTRRender_Rectangle(renderBuffer, DqnV2_1f(300.0f), DqnV2_1f(300 + 20.0f),
|
||||
colorRed, DqnV2_1f(1.0f), 45 + rotation);
|
||||
|
||||
DqnV2 fontP = DqnV2_2i(200, 180);
|
||||
DTRRender_Text(renderBuffer, state->font, fontP, "hello world!");
|
||||
|
||||
DTRRender_Bitmap(renderBuffer, &state->bitmap, 300, 250);
|
||||
DTRDebug_Update(state, renderBuffer, input, memory);
|
||||
}
|
33
src/DTRenderer.h
Normal file
33
src/DTRenderer.h
Normal file
@ -0,0 +1,33 @@
|
||||
#ifndef DTRENDERER_H
|
||||
#define DTRENDERER_H
|
||||
|
||||
#include "dqn.h"
|
||||
#include "external/stb_truetype.h"
|
||||
|
||||
typedef void DTR_UpdateFunction(struct PlatformRenderBuffer *const renderBuffer,
|
||||
struct PlatformInput *const input,
|
||||
struct PlatformMemory *const memory);
|
||||
|
||||
typedef struct DTRFont
|
||||
{
|
||||
u8 *bitmap;
|
||||
DqnV2i bitmapDim;
|
||||
DqnV2i codepointRange;
|
||||
f32 sizeInPt;
|
||||
|
||||
stbtt_packedchar *atlas;
|
||||
} DTRFont;
|
||||
|
||||
typedef struct DTRBitmap
|
||||
{
|
||||
u8 *memory;
|
||||
DqnV2i dim;
|
||||
i32 bytesPerPixel;
|
||||
} DTRBitmap;
|
||||
|
||||
typedef struct DTRState
|
||||
{
|
||||
DTRFont font;
|
||||
DTRBitmap bitmap;
|
||||
} DTRState;
|
||||
#endif
|
114
src/DTRendererDebug.cpp
Normal file
114
src/DTRendererDebug.cpp
Normal file
@ -0,0 +1,114 @@
|
||||
#include "DTRendererDebug.h"
|
||||
#include "DTRenderer.h"
|
||||
#include "DTRendererPlatform.h"
|
||||
#include "DTRendererRender.h"
|
||||
|
||||
DTRDebug globalDebug;
|
||||
|
||||
void DTRDebug_PushText(const char *const formatStr, ...)
|
||||
{
|
||||
if (DTR_DEBUG)
|
||||
{
|
||||
DTRDebug *const debug = &globalDebug;
|
||||
if (!debug->renderBuffer) return;
|
||||
|
||||
char str[1024] = {};
|
||||
|
||||
va_list argList;
|
||||
va_start(argList, formatStr);
|
||||
{
|
||||
i32 numCopied = Dqn_vsprintf(str, formatStr, argList);
|
||||
DQN_ASSERT(numCopied < DQN_ARRAY_COUNT(str));
|
||||
}
|
||||
va_end(argList);
|
||||
|
||||
DTRRender_Text(debug->renderBuffer, *debug->font, debug->displayP, str);
|
||||
debug->displayP.y += globalDebug.displayYOffset;
|
||||
}
|
||||
}
|
||||
|
||||
FILE_SCOPE void PushMemBufferText(const char *const name,
|
||||
const DqnMemBuffer *const buffer)
|
||||
{
|
||||
if (DTR_DEBUG)
|
||||
{
|
||||
if (!buffer) return;
|
||||
|
||||
size_t totalUsed = 0;
|
||||
size_t totalSize = 0;
|
||||
size_t totalWasted = 0;
|
||||
i32 numBlocks = 0;
|
||||
|
||||
DqnMemBufferBlock *blockPtr = buffer->block;
|
||||
while (blockPtr)
|
||||
{
|
||||
totalUsed += blockPtr->used;
|
||||
totalSize += blockPtr->size;
|
||||
blockPtr = blockPtr->prevBlock;
|
||||
numBlocks++;
|
||||
}
|
||||
|
||||
size_t totalUsedKb = totalUsed / 1024;
|
||||
size_t totalSizeKb = totalSize / 1024;
|
||||
size_t totalWastedKb = totalWasted / 1024;
|
||||
|
||||
char str[128] = {};
|
||||
Dqn_sprintf(str, "%s: %d block(s): %_$lld/%_$lld", name, numBlocks,
|
||||
totalUsed, totalSize);
|
||||
|
||||
DTRRender_Text(globalDebug.renderBuffer, *globalDebug.font,
|
||||
globalDebug.displayP, str);
|
||||
globalDebug.displayP.y += globalDebug.displayYOffset;
|
||||
}
|
||||
}
|
||||
|
||||
void DTRDebug_Update(DTRState *const state,
|
||||
PlatformRenderBuffer *const renderBuffer,
|
||||
PlatformInput *const input, PlatformMemory *const memory)
|
||||
{
|
||||
if (DTR_DEBUG)
|
||||
{
|
||||
DTRDebug *const debug = &globalDebug;
|
||||
|
||||
debug->renderBuffer = renderBuffer;
|
||||
debug->font = &state->font;
|
||||
if (debug->font->bitmap && debug->renderBuffer)
|
||||
{
|
||||
debug->displayYOffset = -(i32)(state->font.sizeInPt + 0.5f);
|
||||
debug->displayP =
|
||||
DqnV2_2i(0, renderBuffer->height + globalDebug.displayYOffset);
|
||||
DQN_ASSERT(globalDebug.displayYOffset < 0);
|
||||
}
|
||||
|
||||
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->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->displayP.y += globalDebug.displayYOffset;
|
||||
}
|
||||
|
||||
// memory
|
||||
{
|
||||
PushMemBufferText("PermBuffer", &memory->permanentBuffer);
|
||||
PushMemBufferText("TransBuffer", &memory->transientBuffer);
|
||||
}
|
||||
|
||||
debug->setPixelsPerFrame = 0;
|
||||
debug->displayP =
|
||||
DqnV2_2i(0, debug->renderBuffer->height + globalDebug.displayYOffset);
|
||||
}
|
||||
}
|
||||
|
||||
|
32
src/DTRendererDebug.h
Normal file
32
src/DTRendererDebug.h
Normal file
@ -0,0 +1,32 @@
|
||||
#ifndef DTRENDERER_DEBUG_H
|
||||
#define DTRENDERER_DEBUG_H
|
||||
|
||||
#include "dqn.h"
|
||||
|
||||
#define DTR_DEBUG 1
|
||||
|
||||
typedef struct PlatformRenderBuffer PlatformRenderBuffer;
|
||||
typedef struct DTRFont DTRFont;
|
||||
typedef struct DTRState DTRState;
|
||||
typedef struct PlatformInput PlatformInput;
|
||||
typedef struct PlatformMemory PlatformMemory;
|
||||
|
||||
typedef struct DTRDebug
|
||||
{
|
||||
DTRFont *font;
|
||||
PlatformRenderBuffer *renderBuffer;
|
||||
|
||||
DqnV2 displayP;
|
||||
i32 displayYOffset;
|
||||
|
||||
u64 setPixelsPerFrame;
|
||||
u64 totalSetPixels;
|
||||
} DTRDebug;
|
||||
|
||||
extern DTRDebug globalDebug;
|
||||
|
||||
void DTRDebug_PushText(const char *const formatStr, ...);
|
||||
void DTRDebug_Update(DTRState *const state,
|
||||
PlatformRenderBuffer *const renderBuffer,
|
||||
PlatformInput *const input, PlatformMemory *const memory);
|
||||
#endif
|
@ -1,61 +1,18 @@
|
||||
#include "DRenderer.h"
|
||||
#include "DRendererPlatform.h"
|
||||
#include "DTRendererRender.h"
|
||||
#include "DTRendererPlatform.h"
|
||||
|
||||
#define STB_RECT_PACK_IMPLEMENTATION
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#define STB_TRUETYPE_IMPLEMENTATION
|
||||
#include "external/stb_rect_pack.h"
|
||||
#include "external/stb_image.h"
|
||||
#include "external/stb_truetype.h"
|
||||
|
||||
// #define DR_DEBUG_RENDER_FONT_BITMAP
|
||||
#ifdef DR_DEBUG_RENDER_FONT_BITMAP
|
||||
// #define DTR_DEBUG_RENDER_FONT_BITMAP
|
||||
#ifdef DTR_DEBUG_RENDER_FONT_BITMAP
|
||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
#include "external/stb_image_write.h"
|
||||
#endif
|
||||
|
||||
#define DQN_IMPLEMENTATION
|
||||
#include "dqn.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#define DR_DEBUG 1
|
||||
typedef struct DRFont
|
||||
{
|
||||
u8 *bitmap;
|
||||
DqnV2i bitmapDim;
|
||||
DqnV2i codepointRange;
|
||||
f32 sizeInPt;
|
||||
|
||||
stbtt_packedchar *atlas;
|
||||
} DRFont;
|
||||
|
||||
typedef struct DRBitmap
|
||||
{
|
||||
u8 *memory;
|
||||
DqnV2i dim;
|
||||
i32 bytesPerPixel;
|
||||
} DRBitmap;
|
||||
|
||||
typedef struct DRState
|
||||
{
|
||||
DRFont font;
|
||||
DRBitmap bitmap;
|
||||
} DRState;
|
||||
|
||||
typedef struct DRDebug
|
||||
{
|
||||
DRFont *font;
|
||||
PlatformRenderBuffer *renderBuffer;
|
||||
|
||||
DqnV2 displayP;
|
||||
i32 displayYOffset;
|
||||
|
||||
u64 setPixelsPerFrame;
|
||||
u64 totalSetPixels;
|
||||
} DRDebug;
|
||||
|
||||
FILE_SCOPE inline DqnV4 PreMultiplyAlpha(DqnV4 color)
|
||||
inline DqnV4 DTRRender_PreMultiplyAlpha(const DqnV4 color)
|
||||
{
|
||||
DqnV4 result;
|
||||
f32 normA = color.a / 255.0f;
|
||||
@ -67,8 +24,6 @@ FILE_SCOPE inline DqnV4 PreMultiplyAlpha(DqnV4 color)
|
||||
return result;
|
||||
}
|
||||
|
||||
FILE_SCOPE DRDebug globalDebug;
|
||||
|
||||
// IMPORTANT(doyle): Color is expected to be premultiplied already
|
||||
FILE_SCOPE inline void SetPixel(PlatformRenderBuffer *const renderBuffer,
|
||||
const i32 x, const i32 y, const DqnV4 color)
|
||||
@ -94,12 +49,10 @@ FILE_SCOPE inline void SetPixel(PlatformRenderBuffer *const renderBuffer,
|
||||
// NOTE(doyle): AlphaBlend equations is (alpha * new) + (1 - alpha) * src.
|
||||
// IMPORTANT(doyle): We pre-multiply so we can take out the (alpha * new)
|
||||
f32 invANorm = 1 - newANorm;
|
||||
// f32 destA = (((1 - srcA) * newA) + srcA) * 255.0f;
|
||||
f32 destR = newR + (invANorm * srcR);
|
||||
f32 destG = newG + (invANorm * srcG);
|
||||
f32 destB = newB + (invANorm * srcB);
|
||||
|
||||
// DQN_ASSERT(destA >= 0 && destA <= 255.0f);
|
||||
DQN_ASSERT(destR >= 0 && destR <= 255.0f);
|
||||
DQN_ASSERT(destG >= 0 && destG <= 255.0f);
|
||||
DQN_ASSERT(destB >= 0 && destB <= 255.0f);
|
||||
@ -112,15 +65,17 @@ FILE_SCOPE inline void SetPixel(PlatformRenderBuffer *const renderBuffer,
|
||||
globalDebug.setPixelsPerFrame++;
|
||||
}
|
||||
|
||||
FILE_SCOPE void DrawText(PlatformRenderBuffer *const renderBuffer,
|
||||
const DRFont font, DqnV2 pos, const char *const text,
|
||||
DqnV4 color = DqnV4_4f(255, 255, 255, 255), i32 len = -1)
|
||||
void DTRRender_Text(PlatformRenderBuffer *const renderBuffer,
|
||||
const DTRFont font, DqnV2 pos, const char *const text,
|
||||
DqnV4 color, i32 len)
|
||||
{
|
||||
if (!text) return;
|
||||
if (!font.bitmap || !font.atlas || !renderBuffer) return;
|
||||
|
||||
if (len == -1) len = Dqn_strlen(text);
|
||||
|
||||
i32 index = 0;
|
||||
color = PreMultiplyAlpha(color);
|
||||
color = DTRRender_PreMultiplyAlpha(color);
|
||||
while (index < len)
|
||||
{
|
||||
if (text[index] < font.codepointRange.min &&
|
||||
@ -187,33 +142,29 @@ FILE_SCOPE void DrawText(PlatformRenderBuffer *const renderBuffer,
|
||||
}
|
||||
}
|
||||
|
||||
FILE_SCOPE void DebugPushText(const char *const formatStr, ...)
|
||||
FILE_SCOPE void TransformPoints(const DqnV2 origin, DqnV2 *const pList,
|
||||
const i32 numP, const DqnV2 scale,
|
||||
const f32 rotation)
|
||||
{
|
||||
if (DR_DEBUG)
|
||||
if (!pList || numP == 0) return;
|
||||
|
||||
DqnV2 xAxis = (DqnV2_2f(cosf(rotation), sinf(rotation)));
|
||||
DqnV2 yAxis = DqnV2_2f(-xAxis.y, xAxis.x);
|
||||
xAxis *= scale.x;
|
||||
yAxis *= scale.y;
|
||||
|
||||
for (i32 i = 0; i < numP; i++)
|
||||
{
|
||||
DRDebug *const debug = &globalDebug;
|
||||
if (!debug->renderBuffer) return;
|
||||
|
||||
char str[1024] = {};
|
||||
|
||||
va_list argList;
|
||||
va_start(argList, formatStr);
|
||||
{
|
||||
i32 numCopied = Dqn_vsprintf(str, formatStr, argList);
|
||||
DQN_ASSERT(numCopied < DQN_ARRAY_COUNT(str));
|
||||
}
|
||||
va_end(argList);
|
||||
|
||||
DrawText(debug->renderBuffer, *debug->font, debug->displayP, str);
|
||||
debug->displayP.y += globalDebug.displayYOffset;
|
||||
DqnV2 p = pList[i];
|
||||
pList[i] = origin + (xAxis * p.x) + (yAxis * p.y);
|
||||
}
|
||||
}
|
||||
|
||||
FILE_SCOPE void DrawLine(PlatformRenderBuffer *const renderBuffer, DqnV2i a,
|
||||
void DTRRender_Line(PlatformRenderBuffer *const renderBuffer, DqnV2i a,
|
||||
DqnV2i b, DqnV4 color)
|
||||
{
|
||||
if (!renderBuffer) return;
|
||||
color = PreMultiplyAlpha(color);
|
||||
color = DTRRender_PreMultiplyAlpha(color);
|
||||
|
||||
bool yTallerThanX = false;
|
||||
if (DQN_ABS(a.x - b.x) < DQN_ABS(a.y - b.y))
|
||||
@ -269,44 +220,10 @@ FILE_SCOPE void DrawLine(PlatformRenderBuffer *const renderBuffer, DqnV2i a,
|
||||
}
|
||||
}
|
||||
|
||||
FILE_SCOPE void TransformPoints(const DqnV2 origin, DqnV2 *const pList,
|
||||
const i32 numP, const DqnV2 scale,
|
||||
const f32 rotation)
|
||||
void DTRRender_Rectangle(PlatformRenderBuffer *const renderBuffer, DqnV2 min,
|
||||
DqnV2 max, DqnV4 color, const DqnV2 scale,
|
||||
const f32 rotation, const DqnV2 anchor)
|
||||
{
|
||||
if (!pList || numP == 0) return;
|
||||
|
||||
DqnV2 xAxis = (DqnV2_2f(cosf(rotation), sinf(rotation)));
|
||||
DqnV2 yAxis = DqnV2_2f(-xAxis.y, xAxis.x);
|
||||
xAxis *= scale.x;
|
||||
yAxis *= scale.y;
|
||||
|
||||
for (i32 i = 0; i < numP; i++)
|
||||
{
|
||||
DqnV2 p = pList[i];
|
||||
pList[i] = origin + (xAxis * p.x) + (yAxis * p.y);
|
||||
}
|
||||
}
|
||||
|
||||
FILE_SCOPE void DrawRectangle(PlatformRenderBuffer *const renderBuffer,
|
||||
DqnV2 min, DqnV2 max, DqnV4 color,
|
||||
const DqnV2 scale = DqnV2_1f(1.0f),
|
||||
f32 rotation = 0,
|
||||
const DqnV2 anchor = DqnV2_1f(0.5f))
|
||||
{
|
||||
// TODO(doyle): Do edge test for quads
|
||||
#if 0
|
||||
if (rotation > 0)
|
||||
{
|
||||
DqnV2 p1 = min;
|
||||
DqnV2 p2 = DqnV2_2f(max.x, min.y);
|
||||
DqnV2 p3 = max;
|
||||
DqnV2 p4 = DqnV2_2f(min.x, max.y);
|
||||
DrawTriangle(renderBuffer, p1, p2, p3, color, scale, rotation, anchor);
|
||||
DrawTriangle(renderBuffer, p1, p3, p4, color, scale, rotation, anchor);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Transform vertexes
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
@ -332,7 +249,7 @@ FILE_SCOPE void DrawRectangle(PlatformRenderBuffer *const renderBuffer,
|
||||
max.y = DQN_MAX(max.y, checkP.y);
|
||||
}
|
||||
|
||||
color = PreMultiplyAlpha(color);
|
||||
color = DTRRender_PreMultiplyAlpha(color);
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Clip Drawing Space
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
@ -376,10 +293,10 @@ FILE_SCOPE void DrawRectangle(PlatformRenderBuffer *const renderBuffer,
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i32 y = 0; y < clippedSize.w; y++)
|
||||
for (i32 y = 0; y < clippedSize.h; y++)
|
||||
{
|
||||
i32 bufferY = (i32)clippedRect.min.y + y;
|
||||
for (i32 x = 0; x < clippedSize.h; x++)
|
||||
for (i32 x = 0; x < clippedSize.w; x++)
|
||||
{
|
||||
i32 bufferX = (i32)clippedRect.min.x + x;
|
||||
SetPixel(renderBuffer, bufferX, bufferY, color);
|
||||
@ -387,35 +304,39 @@ FILE_SCOPE void DrawRectangle(PlatformRenderBuffer *const renderBuffer,
|
||||
}
|
||||
}
|
||||
|
||||
if (DR_DEBUG)
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Debug
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
if (DTR_DEBUG)
|
||||
{
|
||||
// Draw Bounding box
|
||||
{
|
||||
DrawLine(renderBuffer, DqnV2i_2f(min.x, min.y), DqnV2i_2f(min.x, max.y), color);
|
||||
DrawLine(renderBuffer, DqnV2i_2f(min.x, max.y), DqnV2i_2f(max.x, max.y), color);
|
||||
DrawLine(renderBuffer, DqnV2i_2f(max.x, max.y), DqnV2i_2f(max.x, min.y), color);
|
||||
DrawLine(renderBuffer, DqnV2i_2f(max.x, min.y), DqnV2i_2f(min.x, min.y), color);
|
||||
DTRRender_Line(renderBuffer, DqnV2i_2f(min.x, min.y), DqnV2i_2f(min.x, max.y), color);
|
||||
DTRRender_Line(renderBuffer, DqnV2i_2f(min.x, max.y), DqnV2i_2f(max.x, max.y), color);
|
||||
DTRRender_Line(renderBuffer, DqnV2i_2f(max.x, max.y), DqnV2i_2f(max.x, min.y), color);
|
||||
DTRRender_Line(renderBuffer, DqnV2i_2f(max.x, min.y), DqnV2i_2f(min.x, min.y), color);
|
||||
}
|
||||
|
||||
// Draw rotating outline
|
||||
if (rotation > 0)
|
||||
{
|
||||
DqnV4 green = DqnV4_4f(0, 255, 0, 255);
|
||||
DrawLine(renderBuffer, DqnV2i_V2(pList[0]), DqnV2i_V2(pList[1]), green);
|
||||
DrawLine(renderBuffer, DqnV2i_V2(pList[1]), DqnV2i_V2(pList[2]), green);
|
||||
DrawLine(renderBuffer, DqnV2i_V2(pList[2]), DqnV2i_V2(pList[3]), green);
|
||||
DrawLine(renderBuffer, DqnV2i_V2(pList[3]), DqnV2i_V2(pList[0]), green);
|
||||
DTRRender_Line(renderBuffer, DqnV2i_V2(pList[0]), DqnV2i_V2(pList[1]), green);
|
||||
DTRRender_Line(renderBuffer, DqnV2i_V2(pList[1]), DqnV2i_V2(pList[2]), green);
|
||||
DTRRender_Line(renderBuffer, DqnV2i_V2(pList[2]), DqnV2i_V2(pList[3]), green);
|
||||
DTRRender_Line(renderBuffer, DqnV2i_V2(pList[3]), DqnV2i_V2(pList[0]), green);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
FILE_SCOPE void DrawTriangle(PlatformRenderBuffer *const renderBuffer, DqnV2 p1,
|
||||
DqnV2 p2, DqnV2 p3, DqnV4 color,
|
||||
DqnV2 scale = DqnV2_1f(1.0f), f32 rotation = 0,
|
||||
DqnV2 anchor = DqnV2_1f(0.33f))
|
||||
void DTRRender_Triangle(PlatformRenderBuffer *const renderBuffer, DqnV2 p1,
|
||||
DqnV2 p2, DqnV2 p3, DqnV4 color, const DqnV2 scale,
|
||||
const f32 rotation, const DqnV2 anchor)
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Transform vertexes
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
DqnV2 p1p2 = p2 - p1;
|
||||
DqnV2 p1p3 = p3 - p1;
|
||||
DqnV2 p1p2Anchored = p1p2 * anchor;
|
||||
@ -428,7 +349,11 @@ FILE_SCOPE void DrawTriangle(PlatformRenderBuffer *const renderBuffer, DqnV2 p1,
|
||||
p2 = pList[1];
|
||||
p3 = pList[2];
|
||||
|
||||
color = PreMultiplyAlpha(color);
|
||||
color = DTRRender_PreMultiplyAlpha(color);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Calculate Bounding Box
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
DqnV2i max = DqnV2i_2f(DQN_MAX(DQN_MAX(p1.x, p2.x), p3.x),
|
||||
DQN_MAX(DQN_MAX(p1.y, p2.y), p3.y));
|
||||
DqnV2i min = DqnV2i_2f(DQN_MIN(DQN_MIN(p1.x, p2.x), p3.x),
|
||||
@ -566,6 +491,9 @@ FILE_SCOPE void DrawTriangle(PlatformRenderBuffer *const renderBuffer, DqnV2 p1,
|
||||
|
||||
f32 invSignedAreaParallelogram = 1 / ((b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x));
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Scan and Render
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
for (scanP.y = min.y; scanP.y < max.y; scanP.y++)
|
||||
{
|
||||
|
||||
@ -590,14 +518,17 @@ FILE_SCOPE void DrawTriangle(PlatformRenderBuffer *const renderBuffer, DqnV2 p1,
|
||||
signedArea3 += signedArea3DeltaY;
|
||||
}
|
||||
|
||||
if (DR_DEBUG)
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Debug
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
if (DTR_DEBUG)
|
||||
{
|
||||
// Draw Bounding box
|
||||
{
|
||||
DrawLine(renderBuffer, DqnV2i_2i(min.x, min.y), DqnV2i_2i(min.x, max.y), color);
|
||||
DrawLine(renderBuffer, DqnV2i_2i(min.x, max.y), DqnV2i_2i(max.x, max.y), color);
|
||||
DrawLine(renderBuffer, DqnV2i_2i(max.x, max.y), DqnV2i_2i(max.x, min.y), color);
|
||||
DrawLine(renderBuffer, DqnV2i_2i(max.x, min.y), DqnV2i_2i(min.x, min.y), color);
|
||||
DTRRender_Line(renderBuffer, DqnV2i_2i(min.x, min.y), DqnV2i_2i(min.x, max.y), color);
|
||||
DTRRender_Line(renderBuffer, DqnV2i_2i(min.x, max.y), DqnV2i_2i(max.x, max.y), color);
|
||||
DTRRender_Line(renderBuffer, DqnV2i_2i(max.x, max.y), DqnV2i_2i(max.x, min.y), color);
|
||||
DTRRender_Line(renderBuffer, DqnV2i_2i(max.x, min.y), DqnV2i_2i(min.x, min.y), color);
|
||||
}
|
||||
|
||||
// Draw Triangle Coordinate Basis
|
||||
@ -606,8 +537,8 @@ FILE_SCOPE void DrawTriangle(PlatformRenderBuffer *const renderBuffer, DqnV2 p1,
|
||||
DqnV2 yAxis = DqnV2_2f(-xAxis.y, xAxis.x) * scale.y;
|
||||
DqnV4 coordSysColor = DqnV4_4f(0, 255, 255, 255);
|
||||
i32 axisLen = 50;
|
||||
DrawLine(renderBuffer, DqnV2i_V2(origin), DqnV2i_V2(origin) + DqnV2i_V2(xAxis * axisLen), coordSysColor);
|
||||
DrawLine(renderBuffer, DqnV2i_V2(origin), DqnV2i_V2(origin) + DqnV2i_V2(yAxis * axisLen), coordSysColor);
|
||||
DTRRender_Line(renderBuffer, DqnV2i_V2(origin), DqnV2i_V2(origin) + DqnV2i_V2(xAxis * axisLen), coordSysColor);
|
||||
DTRRender_Line(renderBuffer, DqnV2i_V2(origin), DqnV2i_V2(origin) + DqnV2i_V2(yAxis * axisLen), coordSysColor);
|
||||
}
|
||||
|
||||
// Draw axis point
|
||||
@ -616,116 +547,15 @@ FILE_SCOPE void DrawTriangle(PlatformRenderBuffer *const renderBuffer, DqnV2 p1,
|
||||
DqnV4 blue = DqnV4_4f(0, 0, 255, 255);
|
||||
DqnV4 purple = DqnV4_4f(255, 0, 255, 255);
|
||||
|
||||
DrawRectangle(renderBuffer, p1 - DqnV2_1f(5), p1 + DqnV2_1f(5), green);
|
||||
DrawRectangle(renderBuffer, p2 - DqnV2_1f(5), p2 + DqnV2_1f(5), blue);
|
||||
DrawRectangle(renderBuffer, p3 - DqnV2_1f(5), p3 + DqnV2_1f(5), purple);
|
||||
DTRRender_Rectangle(renderBuffer, p1 - DqnV2_1f(5), p1 + DqnV2_1f(5), green);
|
||||
DTRRender_Rectangle(renderBuffer, p2 - DqnV2_1f(5), p2 + DqnV2_1f(5), blue);
|
||||
DTRRender_Rectangle(renderBuffer, p3 - DqnV2_1f(5), p3 + DqnV2_1f(5), purple);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FILE_SCOPE void ClearRenderBuffer(PlatformRenderBuffer *const renderBuffer,
|
||||
DqnV3 color)
|
||||
{
|
||||
if (!renderBuffer) return;
|
||||
|
||||
DQN_ASSERT(color.r >= 0.0f && color.r <= 255.0f);
|
||||
DQN_ASSERT(color.g >= 0.0f && color.g <= 255.0f);
|
||||
DQN_ASSERT(color.b >= 0.0f && color.b <= 255.0f);
|
||||
|
||||
u32 *const bitmapPtr = (u32 *)renderBuffer->memory;
|
||||
for (i32 y = 0; y < renderBuffer->height; y++)
|
||||
{
|
||||
for (i32 x = 0; x < renderBuffer->width; x++)
|
||||
{
|
||||
u32 pixel = ((i32)color.r << 16) | ((i32)color.g << 8) |
|
||||
((i32)color.b << 0);
|
||||
bitmapPtr[x + (y * renderBuffer->width)] = pixel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FILE_SCOPE void BitmapFontCreate(const PlatformAPI api,
|
||||
PlatformMemory *const memory,
|
||||
DRFont *const font, const char *const path,
|
||||
const DqnV2i bitmapDim,
|
||||
const DqnV2i codepointRange,
|
||||
const f32 sizeInPt)
|
||||
{
|
||||
font->bitmapDim = bitmapDim;
|
||||
font->codepointRange = codepointRange;
|
||||
font->sizeInPt = sizeInPt;
|
||||
|
||||
DqnTempBuffer transientTempBufferRegion =
|
||||
DqnMemBuffer_BeginTempRegion(&memory->transientBuffer);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Load font data
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
PlatformFile file = {};
|
||||
bool result = api.FileOpen(path, &file, PlatformFilePermissionFlag_Read);
|
||||
DQN_ASSERT(result);
|
||||
|
||||
u8 *fontBuf = (u8 *)DqnMemBuffer_Allocate(&memory->transientBuffer, file.size);
|
||||
size_t bytesRead = api.FileRead(&file, fontBuf, file.size);
|
||||
DQN_ASSERT(bytesRead == file.size);
|
||||
api.FileClose(&file);
|
||||
|
||||
stbtt_fontinfo fontInfo = {};
|
||||
DQN_ASSERT(stbtt_InitFont(&fontInfo, fontBuf, 0) != 0);
|
||||
if (DR_DEBUG) DQN_ASSERT(stbtt_GetNumberOfFonts(fontBuf) == 1);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Pack font data to bitmap
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
font->bitmap = (u8 *)DqnMemBuffer_Allocate(
|
||||
&memory->permanentBuffer,
|
||||
(size_t)(font->bitmapDim.w * font->bitmapDim.h));
|
||||
|
||||
stbtt_pack_context fontPackContext = {};
|
||||
DQN_ASSERT(stbtt_PackBegin(&fontPackContext, font->bitmap, bitmapDim.w,
|
||||
bitmapDim.h, 0, 1, NULL) == 1);
|
||||
{
|
||||
// stbtt_PackSetOversampling(&fontPackContext, 2, 2);
|
||||
|
||||
i32 numCodepoints =
|
||||
(i32)((codepointRange.max + 1) - codepointRange.min);
|
||||
|
||||
font->atlas = (stbtt_packedchar *)DqnMemBuffer_Allocate(
|
||||
&memory->permanentBuffer, numCodepoints * sizeof(stbtt_packedchar));
|
||||
stbtt_PackFontRange(&fontPackContext, fontBuf, 0,
|
||||
STBTT_POINT_SIZE(sizeInPt), (i32)codepointRange.min,
|
||||
numCodepoints, font->atlas);
|
||||
}
|
||||
stbtt_PackEnd(&fontPackContext);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Premultiply Alpha of Bitmap
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
for (i32 y = 0; y < bitmapDim.h; y++)
|
||||
{
|
||||
for (i32 x = 0; x < bitmapDim.w; x++)
|
||||
{
|
||||
// NOTE: Bitmap from stb_truetype is 1BPP. So the actual color
|
||||
// value represents its' alpha value but also its' color.
|
||||
u32 index = x + (y * bitmapDim.w);
|
||||
f32 alpha = (f32)(font->bitmap[index]) / 255.0f;
|
||||
f32 color = alpha;
|
||||
f32 preMulAlphaColor = color * alpha;
|
||||
DQN_ASSERT(preMulAlphaColor >= 0.0f && preMulAlphaColor <= 255.0f);
|
||||
|
||||
font->bitmap[index] = (u8)(preMulAlphaColor * 255.0f);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DR_DEBUG_RENDER_FONT_BITMAP
|
||||
stbi_write_bmp("test.bmp", bitmapDim.w, bitmapDim.h, 1, font->bitmap);
|
||||
#endif
|
||||
|
||||
DqnMemBuffer_EndTempRegion(transientTempBufferRegion);
|
||||
}
|
||||
|
||||
FILE_SCOPE void DrawBitmap(PlatformRenderBuffer *const renderBuffer,
|
||||
DRBitmap *const bitmap, i32 x, i32 y)
|
||||
void DTRRender_Bitmap(PlatformRenderBuffer *const renderBuffer,
|
||||
DTRBitmap *const bitmap, i32 x, i32 y)
|
||||
{
|
||||
if (!bitmap || !bitmap->memory || !renderBuffer) return;
|
||||
|
||||
@ -763,201 +593,25 @@ FILE_SCOPE void DrawBitmap(PlatformRenderBuffer *const renderBuffer,
|
||||
}
|
||||
}
|
||||
|
||||
FILE_SCOPE bool BitmapLoad(const PlatformAPI api, DRBitmap *bitmap,
|
||||
const char *const path,
|
||||
DqnMemBuffer *const transientBuffer)
|
||||
void DTRRender_Clear(PlatformRenderBuffer *const renderBuffer,
|
||||
const DqnV3 color)
|
||||
{
|
||||
if (!bitmap) return false;
|
||||
if (!renderBuffer) return;
|
||||
|
||||
PlatformFile file = {};
|
||||
if (!api.FileOpen(path, &file, PlatformFilePermissionFlag_Read))
|
||||
return false;
|
||||
DQN_ASSERT(color.r >= 0.0f && color.r <= 255.0f);
|
||||
DQN_ASSERT(color.g >= 0.0f && color.g <= 255.0f);
|
||||
DQN_ASSERT(color.b >= 0.0f && color.b <= 255.0f);
|
||||
|
||||
DqnTempBuffer tempBuffer = DqnMemBuffer_BeginTempRegion(transientBuffer);
|
||||
u32 *const bitmapPtr = (u32 *)renderBuffer->memory;
|
||||
for (i32 y = 0; y < renderBuffer->height; y++)
|
||||
{
|
||||
u8 *const rawData =
|
||||
(u8 *)DqnMemBuffer_Allocate(transientBuffer, file.size);
|
||||
size_t bytesRead = api.FileRead(&file, rawData, file.size);
|
||||
api.FileClose(&file);
|
||||
|
||||
if (bytesRead != file.size)
|
||||
for (i32 x = 0; x < renderBuffer->width; x++)
|
||||
{
|
||||
DqnMemBuffer_EndTempRegion(tempBuffer);
|
||||
return false;
|
||||
u32 pixel = ((i32)color.r << 16) | ((i32)color.g << 8) |
|
||||
((i32)color.b << 0);
|
||||
bitmapPtr[x + (y * renderBuffer->width)] = pixel;
|
||||
}
|
||||
|
||||
bitmap->memory =
|
||||
stbi_load_from_memory(rawData, (i32)file.size, &bitmap->dim.w,
|
||||
&bitmap->dim.h, &bitmap->bytesPerPixel, 4);
|
||||
}
|
||||
DqnMemBuffer_EndTempRegion(tempBuffer);
|
||||
if (!bitmap->memory) return false;
|
||||
|
||||
const i32 pitch = bitmap->dim.w * bitmap->bytesPerPixel;
|
||||
for (i32 y = 0; y < bitmap->dim.h; y++)
|
||||
{
|
||||
u8 *const srcRow = bitmap->memory + (y * pitch);
|
||||
for (i32 x = 0; x < bitmap->dim.w; x++)
|
||||
{
|
||||
u32 *pixelPtr = (u32 *)srcRow;
|
||||
u32 pixel = pixelPtr[x];
|
||||
|
||||
DqnV4 color = {};
|
||||
color.a = (f32)(pixel >> 24);
|
||||
color.b = (f32)((pixel >> 16) & 0xFF);
|
||||
color.g = (f32)((pixel >> 8) & 0xFF);
|
||||
color.r = (f32)((pixel >> 0) & 0xFF);
|
||||
color = PreMultiplyAlpha(color);
|
||||
|
||||
pixel = (((u32)color.a << 24) |
|
||||
((u32)color.b << 16) |
|
||||
((u32)color.g << 8) |
|
||||
((u32)color.r << 0));
|
||||
|
||||
pixelPtr[x] = pixel;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void DebugDisplayMemBuffer(PlatformRenderBuffer *const renderBuffer,
|
||||
const char *const name,
|
||||
const DqnMemBuffer *const buffer,
|
||||
DqnV2 *const debugP, const DRFont font)
|
||||
{
|
||||
if (!name && !buffer && !debugP) return;
|
||||
|
||||
size_t totalUsed = 0;
|
||||
size_t totalSize = 0;
|
||||
size_t totalWasted = 0;
|
||||
i32 numBlocks = 0;
|
||||
|
||||
DqnMemBufferBlock *blockPtr = buffer->block;
|
||||
while (blockPtr)
|
||||
{
|
||||
totalUsed += blockPtr->used;
|
||||
totalSize += blockPtr->size;
|
||||
blockPtr = blockPtr->prevBlock;
|
||||
numBlocks++;
|
||||
}
|
||||
|
||||
size_t totalUsedKb = totalUsed / 1024;
|
||||
size_t totalSizeKb = totalSize / 1024;
|
||||
size_t totalWastedKb = totalWasted / 1024;
|
||||
|
||||
char str[128] = {};
|
||||
Dqn_sprintf(str, "%s: %d block(s): %_$lld/%_$lld", name, numBlocks, totalUsed,
|
||||
totalSize);
|
||||
|
||||
DrawText(renderBuffer, font, *debugP, str);
|
||||
debugP->y += globalDebug.displayYOffset;
|
||||
}
|
||||
|
||||
void DebugUpdate(DRState *const state, PlatformRenderBuffer *const renderBuffer,
|
||||
PlatformInput *const input, PlatformMemory *const memory)
|
||||
{
|
||||
if (DR_DEBUG)
|
||||
{
|
||||
DRDebug *const debug = &globalDebug;
|
||||
|
||||
if (input->executableReloaded || !memory->isInit)
|
||||
{
|
||||
debug->font = &state->font;
|
||||
debug->displayYOffset = -(i32)(state->font.sizeInPt + 0.5f);
|
||||
debug->displayP =
|
||||
DqnV2_2i(0, renderBuffer->height + globalDebug.displayYOffset);
|
||||
DQN_ASSERT(globalDebug.displayYOffset < 0);
|
||||
debug->renderBuffer = renderBuffer;
|
||||
}
|
||||
|
||||
debug->totalSetPixels += debug->setPixelsPerFrame;
|
||||
debug->totalSetPixels = DQN_MAX(0, debug->totalSetPixels);
|
||||
|
||||
// totalSetPixels
|
||||
{
|
||||
char str[128] = {};
|
||||
Dqn_sprintf(str, "%s: %'lld", "TotalSetPixels", debug->totalSetPixels);
|
||||
DrawText(debug->renderBuffer, *debug->font, debug->displayP, str);
|
||||
debug->displayP.y += globalDebug.displayYOffset;
|
||||
}
|
||||
|
||||
// setPixelsPerFrame
|
||||
{
|
||||
char str[128] = {};
|
||||
Dqn_sprintf(str, "%s: %'lld", "SetPixelsPerFrame", debug->setPixelsPerFrame);
|
||||
DrawText(debug->renderBuffer, *debug->font, debug->displayP, str);
|
||||
debug->displayP.y += globalDebug.displayYOffset;
|
||||
}
|
||||
|
||||
// memory
|
||||
{
|
||||
DebugDisplayMemBuffer(debug->renderBuffer, "PermBuffer",
|
||||
&memory->permanentBuffer, &debug->displayP,
|
||||
*debug->font);
|
||||
DebugDisplayMemBuffer(debug->renderBuffer, "TransBuffer",
|
||||
&memory->transientBuffer, &debug->displayP,
|
||||
*debug->font);
|
||||
}
|
||||
|
||||
debug->setPixelsPerFrame = 0;
|
||||
debug->displayP =
|
||||
DqnV2_2i(0, debug->renderBuffer->height + globalDebug.displayYOffset);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void DR_Update(PlatformRenderBuffer *const renderBuffer,
|
||||
PlatformInput *const input,
|
||||
PlatformMemory *const memory)
|
||||
{
|
||||
DRState *state = (DRState *)memory->context;
|
||||
if (!memory->isInit)
|
||||
{
|
||||
stbi_set_flip_vertically_on_load(true);
|
||||
memory->isInit = true;
|
||||
memory->context =
|
||||
DqnMemBuffer_Allocate(&memory->permanentBuffer, sizeof(DRState));
|
||||
DQN_ASSERT(memory->context);
|
||||
|
||||
state = (DRState *)memory->context;
|
||||
BitmapFontCreate(input->api, memory, &state->font, "Roboto-bold.ttf",
|
||||
DqnV2i_2i(256, 256), DqnV2i_2i(' ', '~'), 16);
|
||||
DQN_ASSERT(BitmapLoad(input->api, &state->bitmap, "lune_logo.png",
|
||||
&memory->transientBuffer));
|
||||
}
|
||||
|
||||
ClearRenderBuffer(renderBuffer, DqnV3_3f(0, 0, 0));
|
||||
DqnV4 colorRed = DqnV4_4i(180, 0, 0, 255);
|
||||
DqnV2i bufferMidP =
|
||||
DqnV2i_2f(renderBuffer->width * 0.5f, renderBuffer->height * 0.5f);
|
||||
i32 boundsOffset = 100;
|
||||
|
||||
DqnV2 t0[3] = {DqnV2_2i(10, 70), DqnV2_2i(50, 160), DqnV2_2i(70, 80)};
|
||||
DqnV2 t1[3] = {DqnV2_2i(180, 50), DqnV2_2i(150, 1), DqnV2_2i(70, 180)};
|
||||
DqnV2 t2[3] = {DqnV2_2i(180, 150), DqnV2_2i(120, 160), DqnV2_2i(130, 180)};
|
||||
LOCAL_PERSIST DqnV2 t3[3] = {
|
||||
DqnV2_2i(boundsOffset, boundsOffset),
|
||||
DqnV2_2i(bufferMidP.w, renderBuffer->height - boundsOffset),
|
||||
DqnV2_2i(renderBuffer->width - boundsOffset, boundsOffset)};
|
||||
|
||||
#if 1
|
||||
DrawTriangle(renderBuffer, t0[0], t0[1], t0[2], colorRed);
|
||||
DrawTriangle(renderBuffer, t1[0], t1[1], t1[2], colorRed);
|
||||
DrawTriangle(renderBuffer, t2[0], t2[1], t2[2], colorRed);
|
||||
#endif
|
||||
|
||||
DqnV4 colorRedHalfA = DqnV4_4i(255, 0, 0, 64);
|
||||
LOCAL_PERSIST f32 rotation = 0;
|
||||
rotation += input->deltaForFrame * 0.25f;
|
||||
DrawTriangle(renderBuffer, t3[0], t3[1], t3[2], colorRedHalfA,
|
||||
DqnV2_1f(1.0f), rotation, DqnV2_2f(0.33f, 0.33f));
|
||||
|
||||
DrawRectangle(renderBuffer, DqnV2_1f(300.0f), DqnV2_1f(300 + 20.0f),
|
||||
colorRed, DqnV2_1f(1.0f), 45 + rotation);
|
||||
|
||||
DqnV2 fontP = DqnV2_2i(200, 180);
|
||||
// DrawText(renderBuffer, state->font, fontP, "hello world!");
|
||||
|
||||
// DrawBitmap(renderBuffer, &state->bitmap, 300, 250);
|
||||
DebugUpdate(state, renderBuffer, input, memory);
|
||||
}
|
36
src/DTRendererRender.h
Normal file
36
src/DTRendererRender.h
Normal file
@ -0,0 +1,36 @@
|
||||
#ifndef DTRENDERER_RENDER_H
|
||||
#define DTRENDERER_RENDER_H
|
||||
|
||||
#include "dqn.h"
|
||||
|
||||
typedef struct PlatformRenderBuffer PlatformRenderBuffer;
|
||||
typedef struct DTRBitmap DTRBitmap;
|
||||
|
||||
inline DqnV4 DTRRender_PreMultiplyAlpha(const DqnV4 color);
|
||||
|
||||
void DTRRender_Text(PlatformRenderBuffer *const renderBuffer,
|
||||
const DTRFont font, DqnV2 pos, const char *const text,
|
||||
DqnV4 color = DqnV4_4f(255, 255, 255, 255), i32 len = -1);
|
||||
|
||||
void DTRRender_Line(PlatformRenderBuffer *const renderBuffer, DqnV2i a,
|
||||
DqnV2i b, DqnV4 color);
|
||||
|
||||
void DTRRender_Rectangle(PlatformRenderBuffer *const renderBuffer, DqnV2 min,
|
||||
DqnV2 max, DqnV4 color,
|
||||
const DqnV2 scale = DqnV2_1f(1.0f),
|
||||
const f32 rotation = 0,
|
||||
const DqnV2 anchor = DqnV2_1f(0.5f));
|
||||
|
||||
void DTRRender_Triangle(PlatformRenderBuffer *const renderBuffer, DqnV2 p1,
|
||||
DqnV2 p2, DqnV2 p3, DqnV4 color,
|
||||
const DqnV2 scale = DqnV2_1f(1.0f),
|
||||
const f32 rotation = 0,
|
||||
const DqnV2 anchor = DqnV2_1f(0.33f));
|
||||
|
||||
void DTRRender_Bitmap(PlatformRenderBuffer *const renderBuffer,
|
||||
DTRBitmap *const bitmap, i32 x, i32 y);
|
||||
|
||||
void DTRRender_Clear(PlatformRenderBuffer *const renderBuffer,
|
||||
const DqnV3 color);
|
||||
|
||||
#endif
|
@ -1 +1,3 @@
|
||||
#include "..\DRenderer.cpp"
|
||||
#include "..\DTRendererDebug.cpp"
|
||||
#include "..\DTRendererRender.cpp"
|
||||
#include "..\DTRenderer.cpp"
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include "DRenderer.h"
|
||||
#include "DRendererPlatform.h"
|
||||
#include "DTRenderer.h"
|
||||
#include "DTRendererPlatform.h"
|
||||
|
||||
#define DQN_IMPLEMENTATION
|
||||
#define DQN_WIN32_IMPLEMENTATION
|
||||
@ -8,6 +8,9 @@
|
||||
#define UNICODE
|
||||
#define _UNICODE
|
||||
|
||||
const char *const DLL_NAME = "dtrenderer.dll";
|
||||
const char *const DLL_TMP_NAME = "dtrenderer_temp.dll";
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Platform API Implementation
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -98,7 +101,7 @@ typedef struct Win32ExternalCode
|
||||
HMODULE dll;
|
||||
FILETIME lastWriteTime;
|
||||
|
||||
DR_UpdateFunction *DR_Update;
|
||||
DTR_UpdateFunction *DTR_Update;
|
||||
} Win32ExternalCode;
|
||||
|
||||
enum Win32Menu
|
||||
@ -147,13 +150,13 @@ FILE_SCOPE Win32ExternalCode Win32LoadExternalDLL(const char *const srcPath,
|
||||
result.lastWriteTime = lastWriteTime;
|
||||
CopyFile(srcPath, tmpPath, false);
|
||||
|
||||
DR_UpdateFunction *updateFunction = NULL;
|
||||
DTR_UpdateFunction *updateFunction = NULL;
|
||||
result.dll = LoadLibraryA(tmpPath);
|
||||
if (result.dll)
|
||||
{
|
||||
updateFunction =
|
||||
(DR_UpdateFunction *)GetProcAddress(result.dll, "DR_Update");
|
||||
if (updateFunction) result.DR_Update = updateFunction;
|
||||
(DTR_UpdateFunction *)GetProcAddress(result.dll, "DTR_Update");
|
||||
if (updateFunction) result.DTR_Update = updateFunction;
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -164,7 +167,7 @@ FILE_SCOPE void Win32UnloadExternalDLL(Win32ExternalCode *externalCode)
|
||||
|
||||
if (externalCode->dll) FreeLibrary(externalCode->dll);
|
||||
externalCode->dll = NULL;
|
||||
externalCode->DR_Update = NULL;
|
||||
externalCode->DTR_Update = NULL;
|
||||
}
|
||||
|
||||
FILE_SCOPE void Win32CreateMenu(HWND window)
|
||||
@ -484,11 +487,11 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
|
||||
DQN_ASSERT(lastSlashIndex + 1 < DQN_ARRAY_COUNT(exeDir));
|
||||
|
||||
exeDir[lastSlashIndex + 1] = 0;
|
||||
u32 numCopied = Dqn_sprintf(dllPath, "%s%s", exeDir, "drenderer.dll");
|
||||
u32 numCopied = Dqn_sprintf(dllPath, "%s%s", exeDir, DLL_NAME);
|
||||
DQN_ASSERT(numCopied < DQN_ARRAY_COUNT(dllPath));
|
||||
|
||||
numCopied =
|
||||
Dqn_sprintf(dllTmpPath, "%s%s", exeDir, "drenderer_temp.dll");
|
||||
Dqn_sprintf(dllTmpPath, "%s%s", exeDir, DLL_TMP_NAME);
|
||||
DQN_ASSERT(numCopied < DQN_ARRAY_COUNT(dllTmpPath));
|
||||
}
|
||||
|
||||
@ -537,9 +540,9 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
|
||||
platformBuffer.width = globalRenderBitmap.width;
|
||||
platformBuffer.bytesPerPixel = globalRenderBitmap.bytesPerPixel;
|
||||
|
||||
if (dllCode.DR_Update)
|
||||
if (dllCode.DTR_Update)
|
||||
{
|
||||
dllCode.DR_Update(&platformBuffer, &platformInput,
|
||||
dllCode.DTR_Update(&platformBuffer, &platformInput,
|
||||
&globalPlatformMemory);
|
||||
}
|
||||
}
|
@ -10,10 +10,13 @@ if %errorlevel%==1 (
|
||||
goto end
|
||||
)
|
||||
|
||||
REM Build tags file
|
||||
ctags -R
|
||||
REM Build tags file if you have ctags in path
|
||||
where /q ctags
|
||||
if %errorlevel%==0 (
|
||||
ctags -R
|
||||
)
|
||||
|
||||
set ProjectName=drenderer
|
||||
set ProjectName=dtrenderer
|
||||
ctime -begin ..\src\%ProjectName%.ctm
|
||||
|
||||
IF NOT EXIST ..\bin mkdir ..\bin
|
||||
@ -38,7 +41,7 @@ REM wd4189 local variable is initialised but not referenced
|
||||
REM wd4505 unreferenced local function not used will be removed
|
||||
set CompileFlags=-EHa- -GR- -Oi -MT -Z7 -W4 -wd4100 -wd4201 -wd4189 -wd4505 -Od -FAsc
|
||||
set DLLFlags=/Fm%ProjectName% /Fo%ProjectName% /Fa%ProjectName% /Fe%ProjectName%
|
||||
set Win32Flags=/FmWin32DRenderer /FeWin32DRenderer
|
||||
set Win32Flags=/FmWin32DTRenderer /FeWin32DTRenderer
|
||||
|
||||
REM Clean time necessary for hours <10, which produces H:MM:SS.SS where the
|
||||
REM first character of time is an empty space. CleanTime will pad a 0 if
|
||||
@ -57,8 +60,9 @@ REM ////////////////////////////////////////////////////////////////////////////
|
||||
REM Compile
|
||||
REM ////////////////////////////////////////////////////////////////////////////
|
||||
del *.pdb >NUL 2>NUL
|
||||
cl %CompileFlags% %Win32Flags% ..\src\Win32DRenderer.cpp /link %LinkLibraries% %LinkFlags%
|
||||
cl %CompileFlags% %DLLFlags% ..\src\UnityBuild\UnityBuild.cpp /LD /link /PDB:%ProjectName%_%TimeStamp%.pdb /export:DR_Update %LinkFlags%
|
||||
cl %CompileFlags% %Win32Flags% ..\src\Win32DTRenderer.cpp /link %LinkLibraries% %LinkFlags%
|
||||
cl %CompileFlags% %DLLFlags% ..\src\UnityBuild\UnityBuild.cpp /LD /link /PDB:%ProjectName%_%TimeStamp%.pdb /export:DTR_Update %LinkFlags%
|
||||
|
||||
popd
|
||||
set LastError=%ERRORLEVEL%
|
||||
ctime -end %ProjectName%.ctm %LastError%
|
||||
|
Loading…
Reference in New Issue
Block a user