/* * Copyright (C) 2018 Tomasz Kramkowski * SPDX-License-Identifier: MIT */ #include #include #include "assets.h" #include "eprintf.h" #include "gl.h" #include "glprog.h" #include "linmath.h" #include "nelem.h" #include "model.h" enum { WIDTH = 800, HEIGHT = 600, }; # define PI 3.14159265358979323846 #define FOV (PI * 0.5) void viewport(GLuint proj, int width, int height) { mat4x4 pers; gl_viewport(0, 0, width, height); mat4x4_perspective(pers, FOV, (float)width / (float)height, 0.1, 100); gl_uni_setm4fv(proj, 1, GL_FALSE, pers[0]); } int main(int argc, char **argv) { bool running = true; SDL_Window *win; SDL_GLContext *glc; GLuint prog; struct { GLint model, view, proj; } uni; mat4x4 view; FILE *cube_file; struct fmd cube_fmd; struct model cube_model; vec3 pos = { 0, 0, 3 }; setprogname(argc >= 1 && argv[0] != NULL ? argv[0] : "faqe"); if (SDL_Init(SDL_INIT_VIDEO) != 0) eprintf("Failed to initialise SDL: %s", SDL_GetError()); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); win = SDL_CreateWindow("faqe", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WIDTH, HEIGHT, SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE); if (win == NULL) eprintf("Failed to create window: %s", SDL_GetError()); glc = SDL_GL_CreateContext(win); if (glc == NULL) eprintf("Failed to create OpenGL context: %s", SDL_GetError()); gl_load((gl_loadfunc *)SDL_GL_GetProcAddress); cube_file = fopen("cube.fmd", "rb"); if (cube_file == NULL) eprintf("Could not open 'cube.fmd':"); fmd_load(&cube_fmd, cube_file); model_load(&cube_model, &cube_fmd); fmd_free(&cube_fmd); fclose(cube_file); prog = glprog_load(2, (struct shdrdat []){ { GL_VERTEX_SHADER, vert_glsl.data, vert_glsl.size }, { GL_FRAGMENT_SHADER, frag_glsl.data, frag_glsl.size }, }, 3, (struct unidat []){ { "model", &uni.model }, { "view", &uni.view }, { "proj", &uni.proj }, }); gl_prog_use(prog); viewport(uni.proj, WIDTH, HEIGHT); gl_enable(GL_DEPTH_TEST); while (running) { mat4x4 model; SDL_Event ev; float secs; secs = SDL_GetTicks() * 0.0001; mat4x4_look_at(view, pos, (vec3){ 0, 0, 0 }, (vec3){ 0, 1, 0 }); gl_uni_setm4fv(uni.view, 1, GL_FALSE, view[0]); while (SDL_PollEvent(&ev)) { switch (ev.type) { case SDL_KEYDOWN: case SDL_KEYUP: if (ev.key.state != SDL_RELEASED || ev.key.keysym.sym != SDLK_ESCAPE) break; /* fallthrough */ case SDL_QUIT: running = false; break; case SDL_WINDOWEVENT: switch (ev.window.event) { case SDL_WINDOWEVENT_SIZE_CHANGED: viewport(uni.proj, ev.window.data1, ev.window.data2); } break; } } gl_clearcolor(0.2, 0.3, 0.3, 1.0); gl_clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); gl_prog_use(prog); mat4x4_identity(model); mat4x4_rotate_X(model, model, secs * 3); mat4x4_rotate_Y(model, model, secs * 2); mat4x4_rotate_Z(model, model, secs * 4); gl_uni_setm4fv(uni.model, 1, GL_FALSE, model[0]); model_render(&cube_model); gl_va_bind(0); SDL_GL_SwapWindow(win); } SDL_GL_DeleteContext(glc); SDL_DestroyWindow(win); SDL_Quit(); }