165 lines
3.1 KiB
C
165 lines
3.1 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[] = {
|
|
{ { -1, -1 }, { 1, 0, 0 } },
|
|
{ { 1, -1 }, { 0, 1, 0 } },
|
|
{ { 1, 1 }, { 0, 0, 1 } },
|
|
{ { -1, 1 }, { 1, 1, 1 } },
|
|
};
|
|
|
|
static const uint16_t indices[] = { 0, 1, 2, 2, 3, 0 };
|
|
|
|
// clang-format off
|
|
#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, \
|
|
}
|
|
// clang-format on
|
|
|
|
static void
|
|
key_callback(GLFWwindow *window, int key, int scancode, int action, int mods)
|
|
{
|
|
(void)window;
|
|
(void)scancode;
|
|
(void)mods;
|
|
|
|
switch (key) {
|
|
case GLFW_KEY_Q:
|
|
if (action == GLFW_PRESS)
|
|
glfwSetWindowShouldClose(window, GL_TRUE);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void mul(mat4_t out, const mat4_t left, const mat4_t right)
|
|
{
|
|
for (unsigned y = 0; y < 4; ++y) {
|
|
for (unsigned x = 0; x < 4; ++x) {
|
|
out[y + 4 * x] = 0;
|
|
for (unsigned i = 0; i < 4; ++i)
|
|
out[y + 4 * x] += left[y + 4 * i] * right[i + 4 * x];
|
|
}
|
|
}
|
|
}
|
|
|
|
static void persp(mat4_t out, float aspect, float fov, float ncp, float fcp)
|
|
{
|
|
const float r = 2 * ncp * tanf(fov / 2);
|
|
const float t = r * aspect;
|
|
|
|
// clang-format off
|
|
const mat4_t m = {
|
|
ncp / t, 0, 0, 0,
|
|
0, -ncp / r, 0, 0,
|
|
0, 0, fcp / (fcp - ncp), 1,
|
|
0, 0, -fcp * ncp / (fcp - ncp), 0,
|
|
};
|
|
// clang-format on
|
|
|
|
memcpy(out, m, sizeof(mat4_t));
|
|
}
|
|
|
|
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 = ID,
|
|
.view = TRANSLATE(0, 0, 4.0),
|
|
};
|
|
persp(mvp.proj, (float)W / H, M_PI / 6, 0.1, 10.0);
|
|
|
|
const mat4_t rot = ROT_Y(M_PI / 128);
|
|
while (!glfwWindowShouldClose(window)) {
|
|
glfwPollEvents();
|
|
|
|
mat4_t tmp;
|
|
memcpy(tmp, mvp.model, sizeof(mat4_t));
|
|
mul(mvp.model, rot, tmp);
|
|
|
|
gpu_render(&gpu, &mvp);
|
|
}
|
|
|
|
// Clean up
|
|
gpu_cleanup(&gpu);
|
|
glfwDestroyWindow(window);
|
|
glfwTerminate();
|
|
|
|
return 0;
|
|
}
|