diff options
Diffstat (limited to 'mons_exe/src/main.c')
-rw-r--r-- | mons_exe/src/main.c | 247 |
1 files changed, 247 insertions, 0 deletions
diff --git a/mons_exe/src/main.c b/mons_exe/src/main.c new file mode 100644 index 0000000..fab3b8d --- /dev/null +++ b/mons_exe/src/main.c @@ -0,0 +1,247 @@ +#include <stdio.h> +#include <time.h> +#include <stdlib.h> +#include <math.h> +#include <X11/X.h> +#include <X11/Xlib.h> +#include "glad/gl.h" +#include "glad/glx.h" +#include "vertex.h" +#include "mons_math/vec4.h" +#include "mons_math/quat.h" +#include "embedded/shaders/basic.vert.glsl.h" +#include "embedded/shaders/basic_lit.frag.glsl.h" +#include "shader.h" +#include "mesh.h" +#include "qoi.h" +#include "texture.h" +#include "transform.h" +#include "model.h" +#include "projection.h" +#include "json.h" +#include "hashmap.h" +#include "gltf.h" +#include "input.h" +#include "camera.h" +#include <memory.h> +#include "color.h" +#include "light.h" + +struct timespec current_time; +double delta_time = 0; + +int main(void) { + // Make Window + Display *display = XOpenDisplay(NULL); + if (display == NULL) { + printf("Cannot connect to X server\n"); + return EXIT_FAILURE; + } + + int screen = DefaultScreen(display); + + int glx_version = gladLoaderLoadGLX(display, screen); + if (!glx_version) { + printf("Unable to load GLX\n"); + return EXIT_FAILURE; + } + printf("Loaded GLX %d.%d\n", GLAD_VERSION_MAJOR(glx_version), + GLAD_VERSION_MINOR(glx_version)); + + Window root = RootWindow(display, screen); + + GLint visual_attributes[] = {GLX_RGBA, GLX_DOUBLEBUFFER, GLX_DEPTH_SIZE, 24, + None}; + XVisualInfo *visual_info = + glXChooseVisual(display, screen, visual_attributes); + + Colormap colormap = + XCreateColormap(display, root, visual_info->visual, AllocNone); + + XSetWindowAttributes attributes; + attributes.event_mask = + ExposureMask | KeyPressMask | KeyReleaseMask | StructureNotifyMask; + attributes.colormap = colormap; + + Window window = XCreateWindow( + display, root, 0, 0, 640, 480, 0, visual_info->depth, InputOutput, + visual_info->visual, CWColormap | CWEventMask, &attributes); + + // XSizeHints hints = { + // .flags = PMinSize | PMaxSize, + // .min_width = 640, + // .min_height = 480, + // .max_width = 640, + // .max_height = 480, + // }; + // XSetWMNormalHints(display, window, &hints); + XMapWindow(display, window); + XStoreName(display, window, "Hello World!"); + + if (!window) { + printf("Unable to create window\n"); + return EXIT_FAILURE; + } + + GLXContext context = glXCreateContext(display, visual_info, NULL, GL_TRUE); + glXMakeCurrent(display, window, context); + + // Load GL + int version = gladLoaderLoadGL(); + if (!version) { + printf("Unable to load GL\n"); + return EXIT_FAILURE; + } + printf("Loaded GL %d.%d\n", GLAD_VERSION_MAJOR(version), + GLAD_VERSION_MINOR(version)); + + XWindowAttributes gwa; + XGetWindowAttributes(display, window, &gwa); + glViewport(0, 0, gwa.width, gwa.height); + + // Setup Shaders + mons_shader vertex_shader = mons_create_shader( + MONS_SHADER_TYPE_VERTEX, (char *)__embed_shaders_basic_vert_glsl, + __embed_shaders_basic_vert_glsl_len); + mons_shader fragment_shader = mons_create_shader( + MONS_SHADER_TYPE_FRAGMENT, (char *)__embed_shaders_basic_lit_frag_glsl, + __embed_shaders_basic_lit_frag_glsl_len); + mons_program shader_program = + mons_create_program(vertex_shader, fragment_shader); + + FILE *texture_file = fopen("test.qoi", "rb"); + mons_texture texture = mons_texture_load(texture_file); + + mons_camera camera = { + .projection = + { + .near = 0.01f, + .far = 100.0f, + .fov = M_PI / 4.0f, + .aspect_ratio = gwa.width / (float)gwa.height, + }, + .transform = { + .translation = mons_vec3_mul_i(MONS_VEC3_Z, 3), + .rotation = MONS_QUAT_IDENTITY, + .scale = MONS_VEC3_ONE, }}; clock_gettime(CLOCK_MONOTONIC_RAW, ¤t_time); + mons_model *models = NULL; + int model_count = 0; + mons_load_gltf("marble_bust/marble_bust_01_4k.gltf", shader_program, + &models, &model_count); + + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + + mons_directional_light light = { + .transform = (mons_transform) { + .translation = (mons_vec3) { 0.0f, 0.0f, 3.0f }, + .rotation = MONS_QUAT_IDENTITY, + .scale = MONS_VEC3_ONE, + }, + .color = MONS_COLOR_WHITE, + }; + mons_shader_set_vec4_global("light_color", light.color); + mons_shader_set_vec3_global("light_position", light.transform.translation); + + float ambient_light = 0.1f; + mons_shader_set_float_global("ambient_strength", ambient_light); + + // Main Loop + bool key_pressed[256] = {false}; + bool key_just_pressed[256] = {false}; + bool quit = false; + while (!quit) { + memset(key_just_pressed, false, 256); + while (XPending(display)) { + XEvent xev; + XNextEvent(display, &xev); + switch (xev.type) { + case KeyPress: + key_pressed[xev.xkey.keycode] = true; + key_just_pressed[xev.xkey.keycode] = true; + break; + case KeyRelease: + key_pressed[xev.xkey.keycode] = false; + break; + case ConfigureNotify: + if (xev.xconfigure.window == window) { + camera.projection.aspect_ratio = + xev.xconfigure.width / (float)xev.xconfigure.height; + glViewport(0, 0, xev.xconfigure.width, + xev.xconfigure.height); + } + default: + break; + } + } + + glClearColor(0.0, 0.0, 0.0, 1.0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + struct timespec new_time; + clock_gettime(CLOCK_MONOTONIC_RAW, &new_time); + delta_time = (new_time.tv_sec - current_time.tv_sec) + + (new_time.tv_nsec - current_time.tv_nsec) / 1.0e9; + current_time = new_time; + + mons_shader_set_mat4_global("view", mons_mat4_inverse(mons_transform_matrix(camera.transform)), GL_TRUE); + mons_shader_set_mat4_global("projection", mons_projection_matrix(camera.projection), GL_FALSE); + for (int i = 0; i < model_count; i++) { + mons_model_draw(models[i]); + mons_transform_rotate(&models[i].transform, mons_quat_from_axis_angle(MONS_VEC3_Y, (M_PI / 4.0f) * delta_time)); + } + + glBindVertexArray(0); + + + if (key_pressed[MONS_KEY_ESCAPE]) { + quit = true; + } + + int x_axis_input = key_pressed[MONS_KEY_D] - key_pressed[MONS_KEY_A]; + mons_transform_translate( + &camera.transform, + mons_vec3_mul_f(mons_transform_right(camera.transform), delta_time * x_axis_input)); + int y_axis_input = + key_pressed[MONS_KEY_SPACE] - key_pressed[MONS_KEY_LSHIFT]; + mons_transform_translate( + &camera.transform, + mons_vec3_mul_f(mons_transform_up(camera.transform), delta_time * y_axis_input)); + int z_axis_input = key_pressed[MONS_KEY_W] - key_pressed[MONS_KEY_S]; + mons_transform_translate( + &camera.transform, + mons_vec3_mul_f(mons_transform_forward(camera.transform), delta_time * -z_axis_input)); + int y_rot_input = + key_pressed[MONS_KEY_RIGHT] - key_pressed[MONS_KEY_LEFT]; + mons_transform_rotate( + &camera.transform, + mons_quat_from_axis_angle(MONS_VEC3_Y, + -M_PI / 2.0f * y_rot_input * delta_time)); + int x_rot_input = key_pressed[MONS_KEY_UP] - key_pressed[MONS_KEY_DOWN]; + mons_transform_rotate( + &camera.transform, + mons_quat_from_axis_angle(MONS_VEC3_X, + M_PI / 2.0f * x_rot_input * delta_time)); + + int fov_input = key_pressed[MONS_KEY_MINUS] - key_pressed[MONS_KEY_EQUAL]; + camera.projection.fov += (fov_input * M_PI / 8.0 * delta_time); + if(key_just_pressed[MONS_KEY_BACKSPACE]) { + mons_transform_look_at(&camera.transform, MONS_VEC3_ZERO, MONS_VEC3_Y); + } + glXSwapBuffers(display, window); + } + + glDeleteShader(vertex_shader); + glDeleteShader(fragment_shader); + + glXMakeCurrent(display, 0, 0); + glXDestroyContext(display, context); + + XDestroyWindow(display, window); + XFreeColormap(display, colormap); + XCloseDisplay(display); + + gladLoaderUnloadGLX(); + + return EXIT_SUCCESS; +} |