Add line rendering

This commit is contained in:
Doyle Thai 2017-05-10 18:48:27 +10:00
parent 0d5f4c6223
commit d9ce1e1079
5 changed files with 163 additions and 18 deletions

29
Win32DRenderer.sln Normal file
View 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

View File

@ -1,22 +1,132 @@
#include "DRenderer.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,
PlatformInput *const input,
PlatformMemory *const memory)
{
u32 *bitmapPtr = (u32 *)renderBuffer->memory;
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;
DR_ClearRenderBuffer(renderBuffer, DqnV3_3f(0, 0, 0));
u32 color = (red << 16) | (green << 8) | (blue << 0);
bitmapPtr[x + (y * renderBuffer->width)] = color;
}
}
DqnV3 colorRed = DqnV3_3i(255, 0, 0);
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);
}

View File

@ -375,6 +375,7 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
DqnWin32_DisplayLastError("CreateDIBSection() failed");
return -1;
}
////////////////////////////////////////////////////////////////////////////
// Make DLL Path
////////////////////////////////////////////////////////////////////////////
@ -393,7 +394,7 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
numCopied =
Dqn_sprintf(dllTmpPath, "%s%s", exeDir, "drenderer_temp.dll");
DQN_ASSERT(numCopied < DQN_ARRAY_COUNT(dllPath));
DQN_ASSERT(numCopied < DQN_ARRAY_COUNT(dllTmpPath));
}
////////////////////////////////////////////////////////////////////////////

View File

@ -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 DLLFlags=/Fm%ProjectName% /Fo%ProjectName% /Fa%ProjectName% /Fe%ProjectName%
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
set LinkLibraries=user32.lib kernel32.lib gdi32.lib

View File

@ -48,14 +48,14 @@ typedef float f32;
#define DQN_ASSERT(expr) if (!(expr)) { (*((i32 *)0)) = 0; }
#define DQN_PI 3.14159265359f
#define DQN_SQUARED(x) ((x) * (x))
#define DQN_ABS(x) (((x) < 0) ? (-(x)) : (x))
#define DQN_DEGREES_TO_RADIANS(x) ((x * (DQN_PI / 180.0f)))
#define DQN_RADIANS_TO_DEGREES(x) ((x * (180.0f / DQN_PI)))
#define DQN_MAX(a, b) ((a) < (b) ? (b) : (a))
#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
////////////////////////////////////////////////////////////////////////////////