diff --git a/src/main.cc b/src/main.cc new file mode 100644 index 0000000..fcbce97 --- /dev/null +++ b/src/main.cc @@ -0,0 +1,213 @@ +// GLAD +#include "glad/glad.h" + +// GLM +#define GLM_ENABLE_EXPERIMENTAL +#include "glm/ext/matrix_transform.hpp" +#include "glm/ext/vector_float3.hpp" +#include "glm/gtc/type_ptr.hpp" +#include "glm/trigonometric.hpp" +#include "glm/gtx/rotate_vector.hpp" +#include "glm/gtx/string_cast.hpp" + +// SDL +#include +#include +#include +#include +#include +#include +#include + +// STDLIB +#include +#include +#include +#include +#include + +#define WINDOW_WIDTH 1280 +#define WINDOW_HEIGHT 720 +#define WINDOW_HALF_WIDTH 640 +#define WINDOW_HALF_HEIGHT 360 + +enum exit_codes : int { + EXIT_CODE_SUCCESS, + EXIT_CODE_SDL_INIT_FAILED, + EXIT_CODE_WINDOW_CREATION_FAILED, + EXIT_CODE_OPENGL_CONTEXT_FAILED, + EXIT_CODE_GLAD_LOADER_FAILED, +}; + +std::string load_shader(const std::string &filepath); + +int main() { + if (SDL_Init(SDL_INIT_EVERYTHING) != 0) { + return EXIT_CODE_SDL_INIT_FAILED; + } + + SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 24); + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + 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); + + SDL_Window *window = SDL_CreateWindow("Window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, + WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE); + if (!window) { + return EXIT_CODE_WINDOW_CREATION_FAILED; + } + + SDL_GLContext context = SDL_GL_CreateContext(window); + if (!context) { + return EXIT_CODE_OPENGL_CONTEXT_FAILED; + } + + if (gladLoadGLLoader(SDL_GL_GetProcAddress) == 0) { + return EXIT_CODE_GLAD_LOADER_FAILED; + } + + glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT); + + std::vector vertices = { + -0.5f, -0.5f, 0.0f, // position + 1.0f, 0.0f, 0.0f, // colour + 0.5f, -0.5f, 0.0f, // position + 0.0f, 0.0f, 1.0f, // colour + 0.0f, 0.5f, 0.0f, // position + 0.0f, 1.0f, 0.0f, // colour + }; + + std::vector indices = {0, 1, 2}; + + GLuint vao = 0; + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); + + GLuint ebo = 0; + glGenBuffers(1, &ebo); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLuint), indices.data(), GL_STATIC_DRAW); + + GLuint vbo = 0; + glGenBuffers(1, &vbo); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(GLfloat), vertices.data(), GL_STATIC_DRAW); + + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (void *)0); + glEnableVertexAttribArray(0); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (void *)(3 * sizeof(GLfloat))); + glEnableVertexAttribArray(1); + + glBindVertexArray(0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glDisableVertexAttribArray(0); + glDisableVertexAttribArray(1); + + std::string vs_shader = load_shader("shaders/vert.glsl"); + const char *vs_source = vs_shader.c_str(); + GLuint vs = glCreateShader(GL_VERTEX_SHADER); + glShaderSource(vs, 1, &vs_source, NULL); + glCompileShader(vs); + GLint vs_compiled; + glGetShaderiv(vs, GL_COMPILE_STATUS, &vs_compiled); + if (vs_compiled != GL_TRUE) + { + GLsizei log_length = 0; + GLchar message[1024]; + glGetShaderInfoLog(vs, 1024, &log_length, message); + printf("Failed to compile vertex shader: %s\n", message); + } + + std::string fs_shader = load_shader("shaders/frag.glsl"); + const char *fs_source = fs_shader.c_str(); + GLuint fs = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(fs, 1, &fs_source, NULL); + glCompileShader(fs); + GLint fs_compiled; + glGetShaderiv(fs, GL_COMPILE_STATUS, &fs_compiled); + if (fs_compiled != GL_TRUE) + { + GLsizei log_length = 0; + GLchar message[1024]; + glGetShaderInfoLog(fs, 1024, &log_length, message); + printf("Failed to compile fragment shader: %s\n", message); + } + + GLuint program = glCreateProgram(); + glAttachShader(program, vs); + glAttachShader(program, fs); + glLinkProgram(program); + GLint program_linked; + glGetProgramiv(program, GL_LINK_STATUS, &program_linked); + if (program_linked != GL_TRUE) + { + GLsizei log_length = 0; + GLchar message[1024]; + glGetProgramInfoLog(program, 1024, &log_length, message); + printf("Failed to link program: %s\n", message); + } + + glDeleteShader(vs); + glDeleteShader(fs); + + bool running = true; + SDL_Event event = {}; + while (running) { + while (SDL_PollEvent(&event)) { + switch (event.type) { + case SDL_QUIT: + running = false; + break; + case SDL_KEYDOWN: + if (event.key.keysym.sym == SDLK_ESCAPE) { + running = false; + } + break; + case SDL_WINDOWEVENT: + if (event.window.event == SDL_WINDOWEVENT_RESIZED) { + SDL_Window *wnd = SDL_GetWindowFromID(event.window.windowID); + if (!wnd) { + continue; + } + int w, h; + SDL_GL_GetDrawableSize(wnd, &w, &h); + glViewport(0, 0, w, h); + } + break; + } + } + + glClearColor(0.2f, 0.3f, 0.3f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + + glUseProgram(program); + glBindVertexArray(vao); + glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, NULL); + + SDL_GL_SwapWindow(window); + } + + SDL_GL_DeleteContext(context); + SDL_DestroyWindow(window); + SDL_Quit(); + + return EXIT_CODE_SUCCESS; +} + +std::string load_shader(const std::string &filepath) { + FILE *fp = fopen(filepath.c_str(), "r"); + if (!fp) { + return ""; + } + + std::string output = {}; + + char buf[1024] = {0}; + while (fgets(buf, sizeof(buf), fp)) { + output += buf; + } + + return output; +}