Files
gpu-renderer/main.c
T

193 lines
3.5 KiB
C

#include "gpu.h"
#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
#ifndef M_PI
#define M_PI 3.14159265358979324
#endif
#define W 800
#define H 600
static const vertex_t vertices[] = {
{ { 0.000, 0.612, 0.000 }, { 1, 0, 0 } },
{ { -0.500, -0.204, -0.289 }, { 0, 1, 0 } },
{ { 0.500, -0.204, -0.289 }, { 0, 0, 1 } },
{ { 0.000, -0.204, 0.577 }, { 1, 1, 1 } },
};
static const uint16_t indices[] = {
0, 3, 1, 0, 1, 2, 0, 2, 3, 3, 2, 1,
};
typedef enum {
AXIS_X,
AXIS_Y,
AXIS_Z,
} axis_t;
static axis_t rot_axis = AXIS_Y;
#define ID \
{ \
{ 1, 0, 0, 0 }, \
{ 0, 1, 0, 0 }, \
{ 0, 0, 1, 0 }, \
{ 0, 0, 0, 1 }, \
}
#define SCALE(sf) \
{ \
{ sf, 0, 0, 0 }, \
{ 0, sf, 0, 0 }, \
{ 0, 0, sf, 0 }, \
{ 0, 0, 0, 1 }, \
}
#define TRANSLATE(x, y, z) \
{ \
{ 1, 0, 0, 0 }, \
{ 0, 1, 0, 0 }, \
{ 0, 0, 1, 0 }, \
{ x, y, z, 1 }, \
}
#define ROT_X(a) \
{ \
{ 1, 0, 0, 0 }, \
{ 0, cosf(a), sinf(a), 0 }, \
{ 0, -sinf(a), cosf(a), 0 }, \
{ 0, 0, 0, 1 }, \
}
#define ROT_Y(a) \
{ \
{ cosf(a), 0, -sinf(a), 0 }, \
{ 0, 1, 0, 0 }, \
{ sinf(a), 0, cosf(a), 0 }, \
{ 0, 0, 0, 1 }, \
}
#define ROT_Z(a) \
{ \
{ cosf(a), sinf(a), 0, 0 }, \
{ -sinf(a), cosf(a), 0, 0 }, \
{ 0, 0, 1, 0 }, \
{ 0, 0, 0, 1 }, \
}
static void
key_callback(GLFWwindow *window, int key, int scancode, int action, int mods)
{
(void)window;
(void)scancode;
(void)mods;
if (action != GLFW_PRESS)
return;
switch (key) {
case GLFW_KEY_Q:
glfwSetWindowShouldClose(window, GL_TRUE);
break;
case GLFW_KEY_X:
rot_axis = AXIS_X;
break;
case GLFW_KEY_Y:
rot_axis = AXIS_Y;
break;
case GLFW_KEY_Z:
rot_axis = AXIS_Z;
break;
}
}
static mat4_t mul(mat4_t m, mat4_t n)
{
#define ELEM(i, j) \
m.x.i *n.j.x + m.y.i *n.j.y + m.z.i *n.j.z + m.w.i *n.j.w
return (mat4_t) {
{ ELEM(x, x), ELEM(y, x), ELEM(z, x), ELEM(w, x) },
{ ELEM(x, y), ELEM(y, y), ELEM(z, y), ELEM(w, y) },
{ ELEM(x, z), ELEM(y, z), ELEM(z, z), ELEM(w, z) },
{ ELEM(x, w), ELEM(y, w), ELEM(z, w), ELEM(w, w) },
};
#undef MUL_ELEM
}
static mat4_t persp(float aspect, float fov, float ncp, float fcp)
{
const float r = 2 * ncp * tanf(fov / 2);
const float t = r * aspect;
return (mat4_t) {
{ ncp / t, 0, 0, 0 },
{ 0, -ncp / r, 0, 0 },
{ 0, 0, fcp / (fcp - ncp), 1 },
{ 0, 0, -fcp * ncp / (fcp - ncp), 0 },
};
}
int main()
{
// Set up window
glfwInit();
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
GLFWwindow *window = glfwCreateWindow(W, H, "Foo", nullptr, nullptr);
assert(window);
// Register input callbacks
glfwSetKeyCallback(window, key_callback);
// Initialise GPU
const gpu_config_t gpu_config = {
.application_name = "Foo",
.window = window,
.vertex_data = vertices,
.vertex_data_size = sizeof(vertices),
.index_data = indices,
.index_data_size = sizeof(indices),
};
gpu_ctx_t gpu;
gpu_init(&gpu, &gpu_config);
mvp_t mvp = {
.model = SCALE(2),
.view = TRANSLATE(0, 0, 4.0),
.proj = persp((float)W / H, M_PI / 6, 0.1, 10.0),
};
const mat4_t rotx = ROT_X(M_PI / 128);
const mat4_t roty = ROT_Y(M_PI / 128);
const mat4_t rotz = ROT_Z(M_PI / 128);
while (!glfwWindowShouldClose(window)) {
glfwPollEvents();
switch (rot_axis) {
case AXIS_X:
mvp.model = mul(rotx, mvp.model);
break;
case AXIS_Y:
mvp.model = mul(roty, mvp.model);
break;
case AXIS_Z:
mvp.model = mul(rotz, mvp.model);
break;
}
gpu_render(&gpu, &mvp);
}
// Clean up
gpu_cleanup(&gpu);
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}