#include "gpu.h" #include #include #include #include #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; }