diff options
Diffstat (limited to 'source/sdlmain.cpp')
| -rw-r--r-- | source/sdlmain.cpp | 319 |
1 files changed, 319 insertions, 0 deletions
diff --git a/source/sdlmain.cpp b/source/sdlmain.cpp new file mode 100644 index 0000000..372758a --- /dev/null +++ b/source/sdlmain.cpp @@ -0,0 +1,319 @@ +#include <stdio.h> +#include <unistd.h> + +#include <SDL2/SDL.h> +#include <glad/glad.h> + +#include "glad.c" + +#include "fswatcher/fswatcher.h" +#include "fswatcher/fswatcher.cpp" + +#include "core.h" + +#if defined(_WIN32) +#define BUILD_GAME() system("build_game.bat") +#else +#define BUILD_GAME() system("sh build_game.sh") +#endif + +// GAME LIBRARY FUNCTIONS +typedef void (*GameHandleEvent)(GameState*, GameEventType); +typedef void (*GameSetup)(GameState*); +typedef void (*GameUpdateAndRender)(GameState*); + +struct GameLayer { + void *lib; + GameHandleEvent handle_event; + GameSetup setup; + GameUpdateAndRender update_and_render; +}; +internal GameLayer game_layer; + +bool load_game_layer() +{ + // @hack: recompile game here before load object call + BUILD_GAME(); + + SDL_UnloadObject(game_layer.lib); + game_layer.lib = SDL_LoadObject("build/libgame.so"); + if (game_layer.lib == NULL) { + return false; + } + game_layer.handle_event = + (GameHandleEvent)SDL_LoadFunction(game_layer.lib, + "game_handle_event"); + game_layer.setup = + (GameSetup)SDL_LoadFunction(game_layer.lib, + "game_setup"); + game_layer.update_and_render = + (GameUpdateAndRender)SDL_LoadFunction(game_layer.lib, + "game_update_and_render"); + + return true; +} + +bool game_file_update(fswatcher_event_handler *handler, + fswatcher_event_type evtype, + const char *src, + const char *dst) { + return load_game_layer(); +} + +//bool game_shader_update(fswatcher_event_handler *handler, +// fswatcher_event_type evtype, +// const char *src, +// const char *dst) { +//} + +u32 gl_shader_program(char *vs, char *fs) +{ + //============== + // Vertex Shader + u32 handle_vs = glCreateShader(GL_VERTEX_SHADER); + glShaderSource(handle_vs, 1, &vs, NULL); + glCompileShader(handle_vs); + + i32 vertex_compiled; + glGetShaderiv(handle_vs, + GL_COMPILE_STATUS, + &vertex_compiled); + + if (vertex_compiled != GL_TRUE) + { + i32 log_length = 0; + char message[1024]; + + glGetShaderInfoLog(handle_vs, 1024, &log_length, message); + + fprintf(stderr, "===Error compiling vertex shader===\n"); + fprintf(stderr, "%s\n", message); + } + + //================ + // Fragment Shader + u32 handle_fs = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(handle_fs, 1, &fs, NULL); + glCompileShader(handle_fs); + + i32 fragment_compiled; + glGetShaderiv(handle_fs, + GL_COMPILE_STATUS, + &fragment_compiled); + + if (fragment_compiled != GL_TRUE) + { + i32 log_length = 0; + char message[1024]; + + glGetShaderInfoLog(handle_fs, 1024, &log_length, message); + + fprintf(stderr, "===Error compiling fragment shader===\n"); + fprintf(stderr, "%s\n", message); + } + + //=============== + // Shader Program + u32 shader_program = glCreateProgram(); + + glAttachShader(shader_program, handle_vs); + glAttachShader(shader_program, handle_fs); + glLinkProgram(shader_program); + + GLint program_compiled; + glGetProgramiv(shader_program, GL_LINK_STATUS, &program_compiled); + + if (program_compiled != GL_TRUE) + { + i32 log_length = 0; + char message[1024]; + + glGetShaderInfoLog(shader_program, 1024, &log_length, message); + + fprintf(stderr, "===Error linking shader program===\n"); + fprintf(stderr, "%s\n", message); + } + + glDeleteShader(handle_vs); + glDeleteShader(handle_fs); + + return shader_program; +} + +u32 gl_shader_program_from_path(const char *vspath, const char *fspath) +{ + size_t read_count; + char *vs = (char *)SDL_LoadFile(vspath, &read_count); + if (vs == NULL) + { + const char *error_msg = SDL_GetError(); + fprintf(stderr, "Error loading file %s: %s\n", vspath, error_msg); + } + + read_count = 0; + char *fs = (char *)SDL_LoadFile(fspath, &read_count); + if (fs == NULL) + { + const char *error_msg = SDL_GetError(); + fprintf(stderr, "Error loading file %s: %s\n", fspath, error_msg); + } + + u32 shader_program = gl_shader_program(vs, fs); + + SDL_free(vs); + SDL_free(fs); + + return shader_program; +} + +int main(int argc, char *argv[]) +{ + i32 raw_width = 1920; + i32 raw_height = 1080; + i32 dpi_width; + i32 dpi_height; + r32 scale_width; + r32 scale_height; + i32 width; + i32 height; + + GameState state = {}; + + if (SDL_Init(SDL_INIT_VIDEO) != 0) + { + printf("Error initialising SDL2: %s\n", SDL_GetError()); + return 0; + }; + + 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); + + // initialise window with opengl flag + SDL_Window *window = SDL_CreateWindow("SDL Test", + SDL_WINDOWPOS_UNDEFINED, + SDL_WINDOWPOS_UNDEFINED, + raw_width, + raw_height, + SDL_WINDOW_OPENGL | + SDL_WINDOW_RESIZABLE|SDL_WINDOW_ALLOW_HIGHDPI); + + // create an opengl context + SDL_GLContext context = SDL_GL_CreateContext(window); + if (!context) + { + printf("OpenGL context creation failed: %s\n", SDL_GetError()); + return -1; + } + + // calculate correct window size due to scaling + SDL_GL_GetDrawableSize(window, &dpi_width, &dpi_height); + + scale_width = (r32)raw_width/(r32)dpi_width; + scale_height = (r32)raw_height/(r32)dpi_height; + + state.width = raw_width * scale_width; + state.height = raw_height * scale_height; + + SDL_SetWindowSize(window, state.width, state.height); + + // load glad + if (!gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress)) { + printf("Failed to initialize Glad\n"); + return 1; + } + + SDL_GL_SetSwapInterval(1); + + u32 shader_program = gl_shader_program_from_path("./shaders/quad.vs.glsl", + "./shaders/quad.fs.glsl"); + + state.triangle_sp = shader_program; + glUseProgram(state.triangle_sp); + + // @func: gl_setup_triangle + { + GLfloat vertices[9] = { + -0.5f, -0.5f, 0.0f, + 0.5f, -0.5f, 0.0f, + 0.0f, 0.5f, 0.0f + }; + + GLuint VBO, VAO; + glGenVertexArrays(1, &VAO); + glGenBuffers(1, &VBO); + + glBindVertexArray(VAO); + + glBindBuffer(GL_ARRAY_BUFFER, VBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0); + glEnableVertexAttribArray(0); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); + + state.triangle_vao = VAO; + state.triangle_vbo = VBO; + } + glUseProgram(0); + + // add file watcher + fswatcher_t game_watcher = fswatcher_create(FSWATCHER_CREATE_DEFAULT, + FSWATCHER_EVENT_MODIFY, + "source/game", NULL); + fswatcher_event_handler game_file_update_handler; + game_file_update_handler.callback = game_file_update; + // load game layer + if (!load_game_layer()) { + return -1; + } + + game_layer.setup(&state); + + for(;;) + { + SDL_Event ev; + while(SDL_PollEvent(&ev)) + { + if (ev.type == SDL_QUIT) + { + return 0; + } + if (ev.type == SDL_WINDOWEVENT) + { + if (ev.window.event == SDL_WINDOWEVENT_RESIZED) + { + state.width = ev.window.data1; + state.height = ev.window.data2; + game_layer.handle_event(&state, GAME_EVENT_RESIZE); + } + } + if (ev.type == SDL_KEYDOWN) { + if (ev.key.keysym.sym == SDLK_SPACE) { + } + } + } + fswatcher_poll(game_watcher, &game_file_update_handler, NULL); + + // opengl rendering code here + game_layer.update_and_render(&state); + SDL_GL_SwapWindow(window); + } + + // filewatcher + fswatcher_destroy(game_watcher); + + // opengl free calls + glDeleteVertexArrays(1, &state.triangle_vao); + glDeleteBuffers(1, &state.triangle_vbo); + glDeleteProgram(state.triangle_sp); + + // sdl free calls + SDL_GL_DeleteContext(context); + SDL_DestroyWindow(window); + SDL_Quit(); + return 0; +} + |
