3D cube render, basic interpolation, culling
This commit is contained in:
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
.vs/
|
||||||
|
x64/
|
||||||
|
|
||||||
|
*.sln
|
||||||
|
*.vcxproj*
|
||||||
BIN
assets/cat.png
Normal file
BIN
assets/cat.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.7 MiB |
162
main.cpp
Normal file
162
main.cpp
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
#include "main.h"
|
||||||
|
#include "platform.h"
|
||||||
|
#include "math.h"
|
||||||
|
#include "stb_image.h"
|
||||||
|
|
||||||
|
|
||||||
|
// TODO:
|
||||||
|
// Perspective correct interpolation
|
||||||
|
// Texture mapping
|
||||||
|
// Counter clockwise triangle culling
|
||||||
|
// Reading OBJ
|
||||||
|
|
||||||
|
struct Face {
|
||||||
|
int p[3];
|
||||||
|
};
|
||||||
|
|
||||||
|
GLOBAL Vec3 cube_vertices[] = {
|
||||||
|
{-1,1,1}, {1,1,1}, {1,-1,1}, {-1,-1,1},
|
||||||
|
{-1,1,-1}, {1,1,-1}, {1,-1,-1}, {-1,-1,-1},
|
||||||
|
};
|
||||||
|
|
||||||
|
GLOBAL Face cube_faces[] = {
|
||||||
|
{4,1,2}, {4,2,3},
|
||||||
|
{8,4,3}, {8,3,7},
|
||||||
|
{8,5,1}, {8,1,4},
|
||||||
|
{3,2,6}, {3,6,7},
|
||||||
|
{7,6,5}, {7,5,8},
|
||||||
|
{1,5,6}, {1,6,2}
|
||||||
|
};
|
||||||
|
|
||||||
|
FUNCTION
|
||||||
|
void DrawRect(Image* dst, float X, float Y, float w, float h) {
|
||||||
|
int max_x = (int)(MIN(X + w, dst->x) + 0.5f);
|
||||||
|
int max_y = (int)(MIN(Y + h, dst->y) + 0.5f);
|
||||||
|
int min_x = (int)(MAX(0, X) + 0.5f);
|
||||||
|
int min_y = (int)(MAX(0, Y) + 0.5f);
|
||||||
|
|
||||||
|
for (int y = min_y; y < max_y; y++) {
|
||||||
|
for (int x = min_x; x < max_x; x++) {
|
||||||
|
dst->pixels[x + y * dst->x] = 0xffff0000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FUNCTION
|
||||||
|
float EdgeFunction(Vec3 vecp0, Vec3 vecp1, Vec3 p) {
|
||||||
|
float result = (vecp1.y - vecp0.y) * (p.x - vecp0.x) - (vecp1.x - vecp0.x) * (p.y - vecp0.y);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
FUNCTION
|
||||||
|
void DrawTriangle(Image* dst, Vec3 p0, Vec3 p1, Vec3 p2) {
|
||||||
|
float min_x = (float)(MIN(p0.x, MIN(p1.x, p2.x)) + 0.5f);
|
||||||
|
float min_y = (float)(MIN(p0.y, MIN(p1.y, p2.y)) + 0.5f);
|
||||||
|
float max_x = (float)(MAX(p0.x, MAX(p1.x, p2.x)) + 0.5f);
|
||||||
|
float max_y = (float)(MAX(p0.y, MAX(p1.y, p2.y)) + 0.5f);
|
||||||
|
min_x = MAX(0, min_x);
|
||||||
|
min_y = MAX(0, min_y);
|
||||||
|
max_x = MIN(dst->x-1, max_x);
|
||||||
|
max_y = MIN(dst->y-1, max_y);
|
||||||
|
|
||||||
|
float area = EdgeFunction(p0, p1, p2);
|
||||||
|
for (float y = min_y; y < max_y; y++) {
|
||||||
|
for (float x = min_x; x < max_x; x++) {
|
||||||
|
float edge1 = EdgeFunction(p0, p1, { x,y });
|
||||||
|
float edge2 = EdgeFunction(p1, p2, { x,y });
|
||||||
|
float edge3 = EdgeFunction(p2, p0, { x,y });
|
||||||
|
|
||||||
|
if (edge1 <= 0 && edge2 <= 0 && edge3 <= 0) {
|
||||||
|
int xi = (int)(x + 0.5f);
|
||||||
|
int yi = (int)(y + 0.5f);
|
||||||
|
float w1 = edge1 / area;
|
||||||
|
float w2 = edge2 / area;
|
||||||
|
float w3 = edge3 / area;
|
||||||
|
float r = 1 * w1 + 0 * w2 + 0 * w3;
|
||||||
|
float g = 0 * w1 + 1 * w2 + 0 * w3;
|
||||||
|
float b = 0 * w1 + 0 * w2 + 1 * w3;
|
||||||
|
uint8_t r8 = (uint8_t)((r * 255.f) + 0.5f);
|
||||||
|
uint8_t g8 = (uint8_t)((g * 255.f) + 0.5f);
|
||||||
|
uint8_t b8 = (uint8_t)((b * 255.f) + 0.5f);
|
||||||
|
dst->pixels[xi + yi * dst->x] = r8 << 16 | g8 << 8 | b8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DrawRect(dst, p0.x-4, p0.y-4, 8,8);
|
||||||
|
DrawRect(dst, p1.x-4, p1.y-4, 8,8);
|
||||||
|
DrawRect(dst, p2.x-4, p2.y-4, 8,8);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawLine(Image *dst, float x0, float y0, float x1, float y1) {
|
||||||
|
float delta_x = (x1 - x0);
|
||||||
|
float delta_y = (y1 - y0);
|
||||||
|
float longest_side_length = (fabsf(delta_x) >= fabsf(delta_y)) ? fabsf(delta_x) : fabsf(delta_y);
|
||||||
|
float x_inc = delta_x / (float)longest_side_length;
|
||||||
|
float y_inc = delta_y / (float)longest_side_length;
|
||||||
|
float current_x = (float)x0;
|
||||||
|
float current_y = (float)y0;
|
||||||
|
for (int i = 0; i <= longest_side_length; i++) {
|
||||||
|
int x = (int)(current_x + 0.5f);
|
||||||
|
int y = (int)(current_y + 0.5f);
|
||||||
|
dst->pixels[x + y * dst->x] = 0xffffffff;
|
||||||
|
current_x += x_inc;
|
||||||
|
current_y += y_inc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
OS_Init({.window_x=1280, .window_y=720});
|
||||||
|
float rotation = 0;
|
||||||
|
Vec3 camera_pos = {0,0,-5};
|
||||||
|
while (OS_GameLoop()) {
|
||||||
|
for (int y = 0; y < screen.y; y++) {
|
||||||
|
for (int x = 0; x < screen.x; x++) {
|
||||||
|
screen.pixels[x + y * screen.x] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Mat4 transform = Mat4RotationZ(rotation);
|
||||||
|
transform = transform * Mat4RotationX(rotation);
|
||||||
|
if (keydown_a) rotation += 0.05f;
|
||||||
|
if (keydown_b) rotation -= 0.05f;
|
||||||
|
for (int i = 0; i < ARRAY_CAP(cube_faces); i++) {
|
||||||
|
Face* face = cube_faces + i;
|
||||||
|
Vec3 pos[3] = {
|
||||||
|
cube_vertices[face->p[0] - 1],
|
||||||
|
cube_vertices[face->p[1] - 1],
|
||||||
|
cube_vertices[face->p[2] - 1],
|
||||||
|
};
|
||||||
|
|
||||||
|
//@Note: Transform
|
||||||
|
for (int j = 0; j < 3; j++) {
|
||||||
|
pos[j] = transform * pos[j];
|
||||||
|
}
|
||||||
|
//@Note: Cull
|
||||||
|
Vec3 p0_to_camera = camera_pos - pos[0];
|
||||||
|
Vec3 p0_to_p1 = pos[1] - pos[0];
|
||||||
|
Vec3 p0_to_p2 = pos[2] - pos[0];
|
||||||
|
Vec3 normal = Cross(p0_to_p1, p0_to_p2);
|
||||||
|
if (Dot(normal, p0_to_camera) < 0) {
|
||||||
|
for (int j = 0; j < 3; j++) {
|
||||||
|
//@Note: Camera
|
||||||
|
pos[j].x -= camera_pos.x;
|
||||||
|
pos[j].y -= camera_pos.y;
|
||||||
|
pos[j].z -= camera_pos.z;
|
||||||
|
//@Note: Perspective
|
||||||
|
pos[j].x /= pos[j].z;
|
||||||
|
pos[j].y /= pos[j].z;
|
||||||
|
//@Note: To pixel space
|
||||||
|
pos[j].x *= screen.x / 2;
|
||||||
|
pos[j].y *= screen.y / 2;
|
||||||
|
pos[j].x += screen.x / 2;
|
||||||
|
pos[j].y += screen.y / 2;
|
||||||
|
}
|
||||||
|
DrawTriangle(&screen, pos[0], pos[1], pos[2]);
|
||||||
|
DrawLine(&screen, pos[0].x, pos[0].y, pos[1].x, pos[1].y);
|
||||||
|
DrawLine(&screen, pos[1].x, pos[1].y, pos[2].x, pos[2].y);
|
||||||
|
DrawLine(&screen, pos[2].x, pos[2].y, pos[0].x, pos[0].y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
7
main.h
Normal file
7
main.h
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
#define ASSERT(x) if(!(x)) *(volatile int *)0=0;
|
||||||
|
#define ARRAY_CAP(x) sizeof((x))/sizeof(*(x))
|
||||||
|
#define FUNCTION static
|
||||||
|
#define GLOBAL static
|
||||||
|
#define MIN(x,y) (x)>(y)?(y):(x)
|
||||||
|
#define MAX(x,y) (x)>(y)?(x):(y)
|
||||||
179
math.h
Normal file
179
math.h
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
#include "main.h"
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
struct Mat4 {
|
||||||
|
float p[4][4];
|
||||||
|
};
|
||||||
|
|
||||||
|
union Vec3 {
|
||||||
|
struct { float x, y, z; };
|
||||||
|
struct { float r, g, b; };
|
||||||
|
};
|
||||||
|
|
||||||
|
union Vec4 {
|
||||||
|
struct { float x, y, z, w; };
|
||||||
|
struct { float r, g, b, a; };
|
||||||
|
struct { Vec3 xyz; };
|
||||||
|
};
|
||||||
|
|
||||||
|
FUNCTION
|
||||||
|
Mat4 Mat4Identity() {
|
||||||
|
Mat4 result = {
|
||||||
|
1,0,0,0,
|
||||||
|
0,1,0,0,
|
||||||
|
0,0,1,0,
|
||||||
|
0,0,0,1,
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
FUNCTION
|
||||||
|
Mat4 Mat4RotationZ(float rotation) {
|
||||||
|
float s = sinf(rotation);
|
||||||
|
float c = cosf(rotation);
|
||||||
|
Mat4 result = {
|
||||||
|
c, s, 0, 0,
|
||||||
|
-s, c, 0, 0,
|
||||||
|
0, 0, 1, 0,
|
||||||
|
0, 0, 0, 1,
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
FUNCTION
|
||||||
|
Mat4 Mat4RotationY(float rotation) {
|
||||||
|
float s = sinf(rotation);
|
||||||
|
float c = cosf(rotation);
|
||||||
|
Mat4 result = {
|
||||||
|
c, 0, -s, 0,
|
||||||
|
0, 1, 0, 0,
|
||||||
|
s, 0, c, 0,
|
||||||
|
0, 0, 0, 1,
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
FUNCTION
|
||||||
|
Mat4 Mat4RotationX(float rotation) {
|
||||||
|
float s = sinf(rotation);
|
||||||
|
float c = cosf(rotation);
|
||||||
|
Mat4 result = {
|
||||||
|
1, 0, 0, 0,
|
||||||
|
0, c, s, 0,
|
||||||
|
0, -s, c, 0,
|
||||||
|
0, 0, 0, 1,
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
FUNCTION
|
||||||
|
Mat4 Mat4Translate(Mat4 a, Vec3 translation) {
|
||||||
|
a.p[0][0] += translation.x;
|
||||||
|
a.p[0][1] += translation.y;
|
||||||
|
a.p[0][2] += translation.z;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
FUNCTION
|
||||||
|
Vec4 operator-(Vec4 a, Vec4 b) {
|
||||||
|
Vec4 result = {
|
||||||
|
a.x - b.x,
|
||||||
|
a.y - b.y,
|
||||||
|
a.z - b.z,
|
||||||
|
a.w - b.w
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
FUNCTION
|
||||||
|
Vec4 operator+(Vec4 a, Vec4 b) {
|
||||||
|
Vec4 result = {
|
||||||
|
a.x + b.x,
|
||||||
|
a.y + b.y,
|
||||||
|
a.z + b.z,
|
||||||
|
a.w + b.w
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
FUNCTION
|
||||||
|
Vec3 operator-(Vec3 a, Vec3 b) {
|
||||||
|
Vec3 result = {
|
||||||
|
a.x - b.x,
|
||||||
|
a.y - b.y,
|
||||||
|
a.z - b.z,
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
FUNCTION
|
||||||
|
Vec3 operator+(Vec3 a, Vec3 b) {
|
||||||
|
Vec3 result = {
|
||||||
|
a.x + b.x,
|
||||||
|
a.y + b.y,
|
||||||
|
a.z + b.z,
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FUNCTION
|
||||||
|
Vec4 operator*(Mat4 a, Vec4 b) {
|
||||||
|
Vec4 result = {
|
||||||
|
a.p[0][0] * b.x + a.p[0][1] * b.y + a.p[0][2] * b.z + a.p[0][3] * b.w,
|
||||||
|
a.p[1][0] * b.x + a.p[1][1] * b.y + a.p[1][2] * b.z + a.p[1][3] * b.w,
|
||||||
|
a.p[2][0] * b.x + a.p[2][1] * b.y + a.p[2][2] * b.z + a.p[2][3] * b.w,
|
||||||
|
a.p[3][0] * b.x + a.p[3][1] * b.y + a.p[3][2] * b.z + a.p[3][3] * b.w,
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
FUNCTION
|
||||||
|
Vec3 operator*(Mat4 a, Vec3 b) {
|
||||||
|
Vec4 result= {
|
||||||
|
a.p[0][0] * b.x + a.p[0][1] * b.y + a.p[0][2] * b.z + a.p[0][3] * 1,
|
||||||
|
a.p[1][0] * b.x + a.p[1][1] * b.y + a.p[1][2] * b.z + a.p[1][3] * 1,
|
||||||
|
a.p[2][0] * b.x + a.p[2][1] * b.y + a.p[2][2] * b.z + a.p[2][3] * 1,
|
||||||
|
a.p[3][0] * b.x + a.p[3][1] * b.y + a.p[3][2] * b.z + a.p[3][3] * 1,
|
||||||
|
};
|
||||||
|
ASSERT(result.w == 1);
|
||||||
|
return result.xyz;
|
||||||
|
}
|
||||||
|
|
||||||
|
FUNCTION
|
||||||
|
Mat4 operator*(Mat4 a, Mat4 b) {
|
||||||
|
Mat4 result;
|
||||||
|
for (int y = 0; y < 4; y++) {
|
||||||
|
for (int x = 0; x < 4; x++) {
|
||||||
|
result.p[y][x] = a.p[y][0] * b.p[0][x] + a.p[y][1] * b.p[1][x] + a.p[y][2] * b.p[2][x] + a.p[y][3] * b.p[3][x];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
FUNCTION
|
||||||
|
float Dot(Vec3 a, Vec3 b) {
|
||||||
|
float result = a.x * b.x + a.y * b.y + a.z * b.z;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
FUNCTION
|
||||||
|
Vec3 Cross(Vec3 a, Vec3 b) {
|
||||||
|
Vec3 result = {
|
||||||
|
a.y * b.z - a.z * b.y,
|
||||||
|
a.z * b.x - a.x * b.z,
|
||||||
|
a.x * b.y - a.y * b.x,
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
FUNCTION
|
||||||
|
uint32_t ColorToU32ARGB(Vec4 a) {
|
||||||
|
uint8_t r8 = (uint8_t)(a.r * 255.f + 0.5f);
|
||||||
|
uint8_t g8 = (uint8_t)(a.g * 255.f + 0.5f);
|
||||||
|
uint8_t b8 = (uint8_t)(a.b * 255.f + 0.5f);
|
||||||
|
uint8_t a8 = (uint8_t)(a.a * 255.f + 0.5f);
|
||||||
|
uint32_t result = a8 << 24 | r8 << 16 | g8 << 8 | b8;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
146
platform.cpp
Normal file
146
platform.cpp
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
#include "platform.h"
|
||||||
|
#include <windows.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
Image screen;
|
||||||
|
float* depth_buffer;
|
||||||
|
bool keydown_a;
|
||||||
|
bool keydown_b;
|
||||||
|
|
||||||
|
GLOBAL bool g_app_is_running = true;
|
||||||
|
GLOBAL HBITMAP g_screen_dib;
|
||||||
|
GLOBAL HDC g_screen_dc;
|
||||||
|
GLOBAL HDC g_window_dc;
|
||||||
|
GLOBAL HWND g_hwnd;
|
||||||
|
GLOBAL HINSTANCE g_hinstance;
|
||||||
|
GLOBAL int g_cmdshow;
|
||||||
|
|
||||||
|
#include <shellscalingapi.h>
|
||||||
|
typedef HRESULT tSetProcessDpiAwareness(PROCESS_DPI_AWARENESS);
|
||||||
|
|
||||||
|
FUNCTION
|
||||||
|
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
|
||||||
|
LRESULT result = 0;
|
||||||
|
switch (uMsg) {
|
||||||
|
case WM_CLOSE: DestroyWindow(hwnd); g_app_is_running = false; break;
|
||||||
|
case WM_DESTROY: PostQuitMessage(0); g_app_is_running = false; break;
|
||||||
|
case WM_SYSKEYDOWN:
|
||||||
|
case WM_KEYDOWN: {
|
||||||
|
switch (wParam) {
|
||||||
|
case VK_ESCAPE: g_app_is_running = false; break;
|
||||||
|
case 0x4F: keydown_a = true; break;
|
||||||
|
case 0x50: keydown_b = true; break;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case WM_SYSKEYUP:
|
||||||
|
case WM_KEYUP: {
|
||||||
|
switch (wParam) {
|
||||||
|
case 0x4F: keydown_a = false; break;
|
||||||
|
case 0x50: keydown_b = false; break;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
default: result = DefWindowProc(hwnd, uMsg, wParam, lParam);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
FUNCTION
|
||||||
|
void Win32_ScreenInit(int window_x, int window_y) {
|
||||||
|
BITMAPINFO bminfo = {};
|
||||||
|
bminfo.bmiHeader.biSize = sizeof(bminfo.bmiHeader);
|
||||||
|
bminfo.bmiHeader.biWidth = window_x;
|
||||||
|
bminfo.bmiHeader.biHeight = -window_y;
|
||||||
|
bminfo.bmiHeader.biPlanes = 1;
|
||||||
|
bminfo.bmiHeader.biBitCount = 32;
|
||||||
|
bminfo.bmiHeader.biCompression = BI_RGB; // AA RR GG BB
|
||||||
|
bminfo.bmiHeader.biXPelsPerMeter = 1;
|
||||||
|
bminfo.bmiHeader.biYPelsPerMeter = 1;
|
||||||
|
|
||||||
|
void* mem = 0;
|
||||||
|
g_screen_dib = CreateDIBSection(g_window_dc, &bminfo, DIB_RGB_COLORS, (void**)&mem, 0, 0);
|
||||||
|
g_screen_dc = CreateCompatibleDC(g_window_dc);
|
||||||
|
screen.pixels = (uint32_t*)mem;
|
||||||
|
depth_buffer = (float*)malloc(window_x * window_y * sizeof(float));
|
||||||
|
screen.x = window_x;
|
||||||
|
screen.y = window_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OS_Init(OSInitArgs i) {
|
||||||
|
HMODULE shcore = LoadLibraryA("Shcore.dll");
|
||||||
|
if (shcore) {
|
||||||
|
tSetProcessDpiAwareness* set_dpi_awr = (tSetProcessDpiAwareness*)GetProcAddress(shcore, "SetProcessDpiAwareness");
|
||||||
|
if (set_dpi_awr) {
|
||||||
|
HRESULT hr = set_dpi_awr(PROCESS_PER_MONITOR_DPI_AWARE);
|
||||||
|
ASSERT(SUCCEEDED(hr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const wchar_t CLASS_NAME[] = L"Hello!";
|
||||||
|
WNDCLASS wc = { };
|
||||||
|
wc.lpfnWndProc = WindowProc;
|
||||||
|
wc.hInstance = g_hinstance;
|
||||||
|
wc.lpszClassName = CLASS_NAME;
|
||||||
|
RegisterClass(&wc);
|
||||||
|
|
||||||
|
g_hwnd = CreateWindowEx(
|
||||||
|
0, // Optional window styles.
|
||||||
|
CLASS_NAME, // Window class
|
||||||
|
L"Have a wonderful day!", // Window text
|
||||||
|
WS_OVERLAPPEDWINDOW, // Window style
|
||||||
|
CW_USEDEFAULT, CW_USEDEFAULT, i.window_x, i.window_y, // Size and position
|
||||||
|
NULL, // Parent window
|
||||||
|
NULL, // Menu
|
||||||
|
g_hinstance, // Instance handle
|
||||||
|
NULL // Additional application data
|
||||||
|
);
|
||||||
|
ASSERT(g_hwnd != 0);
|
||||||
|
|
||||||
|
ShowWindow(g_hwnd, g_cmdshow);
|
||||||
|
RECT rect;
|
||||||
|
GetWindowRect(g_hwnd, &rect);
|
||||||
|
g_window_dc = GetWindowDC(g_hwnd);
|
||||||
|
Win32_ScreenInit(rect.right - rect.left, rect.bottom - rect.top);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OS_GameLoop() {
|
||||||
|
MSG msg = { };
|
||||||
|
while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE) > 0) {
|
||||||
|
TranslateMessage(&msg);
|
||||||
|
DispatchMessage(&msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Note: Free the screen on window resize
|
||||||
|
RECT rect;
|
||||||
|
GetWindowRect(g_hwnd, &rect);
|
||||||
|
int new_width = rect.right - rect.left;
|
||||||
|
int new_height = rect.bottom - rect.top;
|
||||||
|
if (new_width != screen.x || new_height != screen.y) {
|
||||||
|
screen.x = new_width;
|
||||||
|
screen.y = new_height;
|
||||||
|
if (screen.pixels) {
|
||||||
|
screen.pixels = 0;
|
||||||
|
free(depth_buffer);
|
||||||
|
DeleteDC(g_screen_dc);
|
||||||
|
DeleteObject(g_screen_dib);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Note: Create drawable screen
|
||||||
|
if (!screen.pixels) {
|
||||||
|
Win32_ScreenInit((LONG)screen.x, (LONG)screen.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// @Note; Draw screen to window
|
||||||
|
SelectObject(g_screen_dc, g_screen_dib);
|
||||||
|
BitBlt(g_window_dc, 0, 0, screen.x, screen.y, g_screen_dc, 0, 0, SRCCOPY);
|
||||||
|
Sleep(16);
|
||||||
|
return g_app_is_running;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main();
|
||||||
|
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow) {
|
||||||
|
g_hinstance = hInstance;
|
||||||
|
g_cmdshow = nCmdShow;
|
||||||
|
return main();
|
||||||
|
}
|
||||||
20
platform.h
Normal file
20
platform.h
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#include "main.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
struct Image {
|
||||||
|
uint32_t* pixels;
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OSInitArgs {
|
||||||
|
int window_x;
|
||||||
|
int window_y;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern Image screen;
|
||||||
|
extern float* depth_buffer;
|
||||||
|
extern bool keydown_a;
|
||||||
|
extern bool keydown_b;
|
||||||
|
|
||||||
|
bool OS_GameLoop();
|
||||||
|
void OS_Init(OSInitArgs);
|
||||||
2
stb_image.cpp
Normal file
2
stb_image.cpp
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
|
#include "stb_image.h"
|
||||||
8007
stb_image.h
Normal file
8007
stb_image.h
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user