Add line rendering
This commit is contained in:
parent
0d5f4c6223
commit
d9ce1e1079
29
Win32DRenderer.sln
Normal file
29
Win32DRenderer.sln
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio 15
|
||||||
|
VisualStudioVersion = 15.0.26403.3
|
||||||
|
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
|
||||||
|
RemoteMachine = THAI-PC
|
||||||
|
StartingDirectory = C:\git\drenderer\bin
|
||||||
|
Environment = Default
|
||||||
|
LaunchingEngine = 00000000-0000-0000-0000-000000000000
|
||||||
|
UseLegacyDebugEngines = No
|
||||||
|
LaunchSQLEngine = No
|
||||||
|
AttachLaunchAction = No
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Release|x64 = Release|x64
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{6A9F3AE0-4D5E-4F89-8572-B868AC43C38A}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
@ -1,22 +1,132 @@
|
|||||||
#include "DRenderer.h"
|
#include "DRenderer.h"
|
||||||
|
|
||||||
#include "DRendererPlatform.h"
|
#include "DRendererPlatform.h"
|
||||||
|
|
||||||
|
#define DQN_IMPLEMENTATION
|
||||||
|
#include "dqn.h"
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
FILE_SCOPE void DR_DrawLine(PlatformRenderBuffer *const renderBuffer, DqnV2i a,
|
||||||
|
DqnV2i b, DqnV3 color)
|
||||||
|
{
|
||||||
|
if (!renderBuffer) return;
|
||||||
|
|
||||||
|
bool yTallerThanX = false;
|
||||||
|
if (DQN_ABS(a.x - b.x) < DQN_ABS(a.y - b.y))
|
||||||
|
{
|
||||||
|
// NOTE(doyle): Enforce that the X component is always longer than the
|
||||||
|
// Y component. When drawing this we just reverse the order back.
|
||||||
|
// This is to ensure that the gradient is always < 1, such that we can
|
||||||
|
// use the gradient to calculate the distance from the pixel origin, and
|
||||||
|
// at which point we want to increment the y.
|
||||||
|
yTallerThanX = true;
|
||||||
|
DQN_SWAP(i32, a.x, a.y);
|
||||||
|
DQN_SWAP(i32, b.x, b.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (b.x < a.x) DQN_SWAP(DqnV2i, a, b);
|
||||||
|
|
||||||
|
i32 rise = b.y - a.y;
|
||||||
|
i32 run = b.x - a.x;
|
||||||
|
|
||||||
|
i32 delta = (b.y > a.y) ? 1 : -1;
|
||||||
|
i32 numIterations = b.x - a.x;
|
||||||
|
|
||||||
|
i32 distFromPixelOrigin = DQN_ABS(rise) * 2;
|
||||||
|
i32 distAccumulator = 0;
|
||||||
|
|
||||||
|
i32 newX = a.x;
|
||||||
|
i32 newY = a.y;
|
||||||
|
|
||||||
|
// Unflip the points if we did for plotting the pixels
|
||||||
|
i32 *plotX, *plotY;
|
||||||
|
if (yTallerThanX)
|
||||||
|
{
|
||||||
|
plotX = &newY;
|
||||||
|
plotY = &newX;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
plotX = &newX;
|
||||||
|
plotY = &newY;
|
||||||
|
}
|
||||||
|
|
||||||
|
const u32 pitchInU32 =
|
||||||
|
(renderBuffer->width * renderBuffer->bytesPerPixel) / 4;
|
||||||
|
u32 *const bitmapPtr = (u32 *)renderBuffer->memory;
|
||||||
|
u32 pixel = ((i32)color.r << 16) | ((i32)color.g << 8) | ((i32)color.b << 0);
|
||||||
|
for (i32 iterateX = 0; iterateX < numIterations; iterateX++)
|
||||||
|
{
|
||||||
|
newX = a.x + iterateX;
|
||||||
|
bitmapPtr[*plotX + (*plotY * pitchInU32)] = pixel;
|
||||||
|
|
||||||
|
distAccumulator += distFromPixelOrigin;
|
||||||
|
if (distAccumulator > run)
|
||||||
|
{
|
||||||
|
newY += delta;
|
||||||
|
distAccumulator -= (run * 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE_SCOPE void DR_DrawTriangle(PlatformRenderBuffer *const renderBuffer,
|
||||||
|
DqnV2 p1, DqnV2 p2, DqnV2 p3, DqnV3 color)
|
||||||
|
{
|
||||||
|
DR_DrawLine(renderBuffer, p1, p2, color);
|
||||||
|
DR_DrawLine(renderBuffer, p2, p3, color);
|
||||||
|
DR_DrawLine(renderBuffer, p3, p1, color);
|
||||||
|
|
||||||
|
// NOTE(doyle): This is just an desc sort using bubble sort on 3 elements
|
||||||
|
if (p1.y < p2.y) DQN_SWAP(DqnV2i, p1, p2);
|
||||||
|
if (p2.y < p3.y) DQN_SWAP(DqnV2i, p1, p3);
|
||||||
|
if (p1.y < p2.y) DQN_SWAP(DqnV2i, p2, p3);
|
||||||
|
|
||||||
|
i32 y1i = (i32)(p1.y + 0.5f);
|
||||||
|
i32 y2i = (i32)(p2.y + 0.5f);
|
||||||
|
i32 y3i = (i32)(p3.y + 0.5f);
|
||||||
|
|
||||||
|
if (y1i == y3i) return; // Zero height triangle
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE_SCOPE void DR_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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" void DR_Update(PlatformRenderBuffer *const renderBuffer,
|
extern "C" void DR_Update(PlatformRenderBuffer *const renderBuffer,
|
||||||
PlatformInput *const input,
|
PlatformInput *const input,
|
||||||
PlatformMemory *const memory)
|
PlatformMemory *const memory)
|
||||||
{
|
{
|
||||||
u32 *bitmapPtr = (u32 *)renderBuffer->memory;
|
DR_ClearRenderBuffer(renderBuffer, DqnV3_3f(0, 0, 0));
|
||||||
for (i32 y = 0; y < renderBuffer->height; y++)
|
|
||||||
{
|
|
||||||
for (i32 x = 0; x < renderBuffer->width; x++)
|
|
||||||
{
|
|
||||||
u8 red = 255;
|
|
||||||
u8 green = 0;
|
|
||||||
u8 blue = 0;
|
|
||||||
|
|
||||||
u32 color = (red << 16) | (green << 8) | (blue << 0);
|
DqnV3 colorRed = DqnV3_3i(255, 0, 0);
|
||||||
bitmapPtr[x + (y * renderBuffer->width)] = color;
|
DqnV2i bufferMidP = DqnV2i_2f(renderBuffer->width * 0.5f, renderBuffer->height * 0.5f);
|
||||||
}
|
i32 boundsOffset = 50;
|
||||||
}
|
|
||||||
|
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)};
|
||||||
|
DqnV2 t3[3] = {
|
||||||
|
DqnV2_2i(boundsOffset, boundsOffset),
|
||||||
|
DqnV2_2i(bufferMidP.w, renderBuffer->height - boundsOffset),
|
||||||
|
DqnV2_2i(renderBuffer->width - boundsOffset, boundsOffset)};
|
||||||
|
|
||||||
|
DR_DrawTriangle(renderBuffer, t0[0], t0[1], t0[2], colorRed);
|
||||||
|
// DR_DrawTriangle(renderBuffer, t1[0], t1[1], t1[2], colorRed);
|
||||||
|
// DR_DrawTriangle(renderBuffer, t2[0], t2[1], t2[2], colorRed);
|
||||||
|
// DR_DrawTriangle(renderBuffer, t3[0], t3[1], t3[2], colorRed);
|
||||||
}
|
}
|
||||||
|
@ -375,6 +375,7 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
|
|||||||
DqnWin32_DisplayLastError("CreateDIBSection() failed");
|
DqnWin32_DisplayLastError("CreateDIBSection() failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
// Make DLL Path
|
// Make DLL Path
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
@ -393,7 +394,7 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
|
|||||||
|
|
||||||
numCopied =
|
numCopied =
|
||||||
Dqn_sprintf(dllTmpPath, "%s%s", exeDir, "drenderer_temp.dll");
|
Dqn_sprintf(dllTmpPath, "%s%s", exeDir, "drenderer_temp.dll");
|
||||||
DQN_ASSERT(numCopied < DQN_ARRAY_COUNT(dllPath));
|
DQN_ASSERT(numCopied < DQN_ARRAY_COUNT(dllTmpPath));
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -39,7 +39,12 @@ 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 CompileFlags=-EHa- -GR- -Oi -MT -Z7 -W4 -wd4100 -wd4201 -wd4189 -wd4505 -Od -FAsc
|
||||||
set DLLFlags=/Fm%ProjectName% /Fo%ProjectName% /Fa%ProjectName% /Fe%ProjectName%
|
set DLLFlags=/Fm%ProjectName% /Fo%ProjectName% /Fa%ProjectName% /Fe%ProjectName%
|
||||||
set Win32Flags=/FmWin32DRenderer /FeWin32DRenderer
|
set Win32Flags=/FmWin32DRenderer /FeWin32DRenderer
|
||||||
set TimeStamp=%date:~10,4%%date:~7,2%%date:~4,2%_%time:~0,2%%time:~3,2%%time:~6,2%
|
|
||||||
|
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
|
||||||
|
REM necessary.
|
||||||
|
set CleanTime=%time: =0%
|
||||||
|
set TimeStamp=%date:~10,4%%date:~7,2%%date:~4,2%_%CleanTime:~0,2%%CleanTime:~3,2%%CleanTime:~6,2%
|
||||||
|
|
||||||
REM Link libraries
|
REM Link libraries
|
||||||
set LinkLibraries=user32.lib kernel32.lib gdi32.lib
|
set LinkLibraries=user32.lib kernel32.lib gdi32.lib
|
||||||
|
@ -48,14 +48,14 @@ typedef float f32;
|
|||||||
#define DQN_ASSERT(expr) if (!(expr)) { (*((i32 *)0)) = 0; }
|
#define DQN_ASSERT(expr) if (!(expr)) { (*((i32 *)0)) = 0; }
|
||||||
|
|
||||||
#define DQN_PI 3.14159265359f
|
#define DQN_PI 3.14159265359f
|
||||||
|
#define DQN_SQUARED(x) ((x) * (x))
|
||||||
#define DQN_ABS(x) (((x) < 0) ? (-(x)) : (x))
|
#define DQN_ABS(x) (((x) < 0) ? (-(x)) : (x))
|
||||||
#define DQN_DEGREES_TO_RADIANS(x) ((x * (DQN_PI / 180.0f)))
|
#define DQN_DEGREES_TO_RADIANS(x) ((x * (DQN_PI / 180.0f)))
|
||||||
#define DQN_RADIANS_TO_DEGREES(x) ((x * (180.0f / DQN_PI)))
|
#define DQN_RADIANS_TO_DEGREES(x) ((x * (180.0f / DQN_PI)))
|
||||||
|
|
||||||
#define DQN_MAX(a, b) ((a) < (b) ? (b) : (a))
|
#define DQN_MAX(a, b) ((a) < (b) ? (b) : (a))
|
||||||
#define DQN_MIN(a, b) ((a) < (b) ? (a) : (b))
|
#define DQN_MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||||
#define DQN_SQUARED(x) ((x) * (x))
|
#define DQN_SWAP(type, a, b) do { type tmp = a; a = b; b = tmp; } while(0)
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// DqnMem - Memory
|
// DqnMem - Memory
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
Loading…
Reference in New Issue
Block a user