commit 9bb91701d1f92b2f2ad4b7b34aaf21f1126902c2 Author: sam Date: Mon Nov 25 18:59:37 2024 +1300 messy first commit diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..c17e64a --- /dev/null +++ b/.clang-format @@ -0,0 +1,25 @@ +BasedOnStyle: WebKit +IndentWidth: 4 +TabWidth: 4 +UseTab: Never +AlignConsecutiveDeclarations: false +AlignConsecutiveAssignments: false +AlignTrailingComments: true +ColumnLimit: 105 +BreakBeforeBraces: Attach +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AllowShortFunctionsOnASingleLine: false +AllowShortLambdasOnASingleLine: false +PointerAlignment: Left +SpaceBeforeParens: Never +SpacesInParentheses: false +SpacesInConditionalStatement: false +SpacesInContainerLiterals: false +SpaceAfterCStyleCast: false +SpaceBeforeCpp11BracedList: false +SpaceBeforeSquareBrackets: false +SpacesBeforeTrailingComments: 2 +PenaltyBreakAssignment: 1000 +NamespaceIndentation: All + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8469928 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +# Xmake cache +.xmake/ +build/ + +# MacOS Cache +.DS_Store + +.cache/ +.compile_commands.json diff --git a/compile_commands.json b/compile_commands.json new file mode 100644 index 0000000..caabd63 --- /dev/null +++ b/compile_commands.json @@ -0,0 +1,6 @@ +[ +{ + "directory": "/home/sam/Documents/Projects/ember", + "arguments": ["/usr/bin/gcc", "-c", "-g", "-O0", "-std=c++20", "-Isrc", "-I", "/usr/include/X11/dri", "-I", "/home/sam/.xmake/packages/g/glad/v0.1.36/80c1f8a051e04d3388507894e8651024/include", "-o", "build/.objs/ember/linux/arm64/debug/src/main.cpp.o", "src/main.cpp"], + "file": "src/main.cpp" +}] diff --git a/shaders/basic.frag b/shaders/basic.frag new file mode 100644 index 0000000..dcf79c9 --- /dev/null +++ b/shaders/basic.frag @@ -0,0 +1,9 @@ +#version 460 core + +layout(location = 0) in vec4 vert_color; + +layout(location = 0) out vec4 frag_color; + +void main() { + frag_color = vert_color; +} diff --git a/shaders/basic.vert b/shaders/basic.vert new file mode 100644 index 0000000..3fbbd88 --- /dev/null +++ b/shaders/basic.vert @@ -0,0 +1,11 @@ +#version 460 core + +layout(location = 0) in vec3 attr_pos; +layout(location = 1) in vec3 attr_color; + +layout(location = 0) out vec4 vert_color; + +void main() { + vert_color = vec4(attr_color, 1.0); + gl_Position = vec4(attr_pos, 1.0); +} diff --git a/src/ember/keys.h b/src/ember/keys.h new file mode 100644 index 0000000..513b6ec --- /dev/null +++ b/src/ember/keys.h @@ -0,0 +1,125 @@ +#pragma once + +enum Keys { + SPACE = 32, + APOSTROPHE = 39, + COMMA = 44, + MINUS = 45, + PERIOD = 46, + SLASH = 47, + ZERO = 48, + ONE = 49, + TWO = 50, + THREE = 51, + FOUR = 52, + FIVE = 53, + SIX = 54, + SEVEN = 55, + EIGHT = 56, + NINE = 57, + SEMICOLON = 59, + EQUAL = 61, + A = 65, + B = 66, + C = 67, + D = 68, + E = 69, + F = 70, + G = 71, + H = 72, + I = 73, + J = 74, + K = 75, + L = 76, + M = 77, + N = 78, + O = 79, + P = 80, + Q = 81, + R = 82, + S = 83, + T = 84, + U = 85, + V = 86, + W = 87, + X = 88, + Y = 89, + Z = 90, + LEFT_BRACKET = 91, + BACKSLASH = 92, + RIGHT_BRACKET = 93, + GRAVE_ACCENT = 96, + WORLD_1 = 161, + WORLD_2 = 162, + ESCAPE = 256, + ENTER = 257, + TAB = 258, + BACKSPACE = 259, + INSERT = 260, + DELETE = 261, + RIGHT = 262, + LEFT = 263, + DOWN = 264, + UP = 265, + PAGE_UP = 266, + PAGE_DOWN = 267, + HOME = 268, + END = 269, + CAPS_LOCK = 280, + SCROLL_LOCK = 281, + NUM_LOCK = 282, + PRINT_SCREEN = 283, + PAUSE = 284, + F1 = 290, + F2 = 291, + F3 = 292, + F4 = 293, + F5 = 294, + F6 = 295, + F7 = 296, + F8 = 297, + F9 = 298, + F10 = 299, + F11 = 300, + F12 = 301, + F13 = 302, + F14 = 303, + F15 = 304, + F16 = 305, + F17 = 306, + F18 = 307, + F19 = 308, + F20 = 309, + F21 = 310, + F22 = 311, + F23 = 312, + F24 = 313, + F25 = 314, + KP_0 = 320, + KP_1 = 321, + KP_2 = 322, + KP_3 = 323, + KP_4 = 324, + KP_5 = 325, + KP_6 = 326, + KP_7 = 327, + KP_8 = 328, + KP_9 = 329, + KP_DECIMAL = 330, + KP_DIVIDE = 331, + KP_MULTIPLY = 332, + KP_SUBTRACT = 333, + KP_ADD = 334, + KP_ENTER = 335, + KP_EQUAL = 336, + LEFT_SHIFT = 340, + LEFT_CONTROL = 341, + LEFT_ALT = 342, + LEFT_SUPER = 343, + RIGHT_SHIFT = 344, + RIGHT_CONTROL = 345, + RIGHT_ALT = 346, + RIGHT_SUPER = 347, + MENU = 348, + COUNT, +}; diff --git a/src/ember/main.cpp b/src/ember/main.cpp new file mode 100644 index 0000000..174a2ce --- /dev/null +++ b/src/ember/main.cpp @@ -0,0 +1,370 @@ +#include + +class Window { +public: + static Window& Get() { + static Window window; + return window; + } + + Window(Window const&) = delete; + void operator=(Window const&) = delete; + + void SetTitle(const char* title) { + glfwSetWindowTitle(handle, title); + } + + bool ShouldClose() { + return glfwWindowShouldClose(handle); + } + + bool GetKey(int key) { + return glfwGetKey(handle, key); + } + + void SwapBuffers() { + glfwSwapBuffers(handle); + } + + GLFWwindow* GetHandle() { + return handle; + } + +private: + Window() { + handle = glfwCreateWindow(800, 600, "Ember", nullptr, nullptr); + glfwMakeContextCurrent(handle); + } + + ~Window() { + glfwDestroyWindow(handle); + } + + GLFWwindow* handle; +}; + +class Input { +public: + static Input& Get() { + static Input input; + return input; + } + + void Update() { + glfwPollEvents(); + + for(int key = Keys::SPACE; key < Keys::COUNT; key++) { + previous_keys[key] = current_keys[key]; + current_keys[key] = IsKeyDown(key); + } + } + + bool IsKeyDown(int key) { + return Window::Get().GetKey(key); + } + + bool IsKeyUp(int key) { + return !IsKeyDown(key); + } + + bool IsKeyPressed(int key) { + return current_keys[key] && !previous_keys[key]; + } + + bool IsKeyReleased(int key) { + return !current_keys[key] && previous_keys[key]; + } + +private: + Input() = default; + + bool current_keys[Keys::COUNT]; + bool previous_keys[Keys::COUNT]; +}; + +struct Type { + GLenum gl_type; + size_t size; +}; + +namespace Types { + const Type FLOAT = { GL_FLOAT, sizeof(float) }; +}; + +struct VertexBufferAttribute { + Type type; + GLint count; +}; + +class VertexBuffer { +public: + VertexBuffer() { + glCreateBuffers(1, &id); + } + + void SetData(void* data, GLsizeiptr size, GLenum usage) { + data_size = size; + glNamedBufferData(id, data_size, data, usage); + } + + void AddAttribute(Type type, GLint count) { + attributes.emplace_back(type, count); + } + + GLuint id; + GLsizeiptr data_size; + std::vector attributes; +}; + +class VertexArray { +public: + VertexArray() { + glCreateVertexArrays(1, &id); + } + + void AddVertexBuffer(VertexBuffer vertex_buffer) { + size_t stride = 0; + for(const VertexBufferAttribute& attrib : vertex_buffer.attributes) { + stride += attrib.type.size * attrib.count; + } + + glVertexArrayVertexBuffer(id, buffer_count, vertex_buffer.id, 0, stride); + + for(size_t i = 0; i < vertex_buffer.attributes.size(); i++) { + const VertexBufferAttribute& attrib = vertex_buffer.attributes[i]; + + glEnableVertexArrayAttrib(id, attribute_count); + glVertexArrayAttribFormat(id, attribute_count, attrib.count, attrib.type.gl_type, GL_FALSE, + i * attrib.type.size * attrib.count); + + glVertexArrayAttribBinding(id, attribute_count, buffer_count); + attribute_count++; + } + + buffer_count++; + } + + void Draw() { + glBindVertexArray(id); + glDrawArrays(GL_TRIANGLES, 0, 3); + } + +private: + GLuint id; + GLuint buffer_count = 0; + GLuint attribute_count = 0; +}; + +void GLFWCallback(int code, const char* message) { + std::cerr << std::format("[GLFW Error {}] {}", code, message) << std::endl; +} + +class File { +public: + File(const char* filename) { + file = fopen(filename, "rwb"); + this->filename = std::string(filename); + } + + std::string Read() { + fseek(file, 0, SEEK_END); + size_t size = ftell(file); + rewind(file); + + std::string buffer; + buffer.resize(size); + fread(&buffer[0], sizeof(char), size, file); + + return buffer; + } + + ~File() { + fclose(file); + } + + std::string filename; + +private: + FILE* file; +}; + +namespace Log { + void Log(std::ostream& stream, std::string category, std::string message) { + stream << std::format("[{}] {}", category, message) << std::endl; + } + + void Info(std::string message) { + Log(std::cout, "INFO", message); + } + + void Warning(std::string message) { + Log(std::cout, "WARNING", message); + } + + void Error(std::string message) { + Log(std::cerr, "ERROR", message); + } + + void Fatal(std::string message) { + Log(std::cerr, "FATAL", message); + exit(EXIT_FAILURE); + } + + void OpenGLMessage(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, + GLchar const* message, void const* user_param) { + const char* source_string; + switch(source) { + case GL_DEBUG_SOURCE_API: + source_string = "API"; + break; + case GL_DEBUG_SOURCE_WINDOW_SYSTEM: + source_string = "WINDOW SYSTEM"; + break; + case GL_DEBUG_SOURCE_SHADER_COMPILER: + source_string = "SHADER COMPILER"; + break; + case GL_DEBUG_SOURCE_THIRD_PARTY: + source_string = "THIRD PARTY"; + break; + case GL_DEBUG_SOURCE_APPLICATION: + source_string = "APPLICATION"; + break; + case GL_DEBUG_SOURCE_OTHER: + source_string = "OTHER"; + break; + } + + const char* type_string; + switch(type) { + case GL_DEBUG_TYPE_ERROR: + type_string = "ERROR"; + break; + case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: + type_string = "DEPRECATED_BEHAVIOR"; + break; + case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: + type_string = "UNDEFINED_BEHAVIOR"; + break; + case GL_DEBUG_TYPE_PORTABILITY: + type_string = "PORTABILITY"; + break; + case GL_DEBUG_TYPE_PERFORMANCE: + type_string = "PERFORMANCE"; + break; + case GL_DEBUG_TYPE_MARKER: + type_string = "MARKER"; + break; + case GL_DEBUG_TYPE_OTHER: + type_string = "OTHER"; + break; + } + + const char* severity_string; + switch(severity) { + case GL_DEBUG_SEVERITY_NOTIFICATION: + severity_string = "NOTIFICATION"; + break; + case GL_DEBUG_SEVERITY_LOW: + severity_string = "LOW"; + break; + case GL_DEBUG_SEVERITY_MEDIUM: + severity_string = "MEDIUM"; + break; + case GL_DEBUG_SEVERITY_HIGH: + severity_string = "HIGH"; + break; + } + + std::cout << std::format("[OpenGL {}] source: {}, severity: {}, type: {}, message: {}", id, + source_string, severity_string, type_string, message) + << std::endl; + } +} + +class Shader { +public: + Shader(File vs_file, File fs_file) { + GLuint vertex = glCreateShader(GL_VERTEX_SHADER); + GLuint fragment = glCreateShader(GL_FRAGMENT_SHADER); + + std::string vs_source = vs_file.Read(); + std::string fs_source = fs_file.Read(); + + const char* vs_cstr = vs_source.c_str(); + const char* fs_cstr = fs_source.c_str(); + + glShaderSource(vertex, 1, &vs_cstr, nullptr); + glShaderSource(fragment, 1, &fs_cstr, nullptr); + + Log::Info(std::format("Compiling vertex shader: {}", vs_file.filename)); + glCompileShader(vertex); + + Log::Info(std::format("Compiling fragment shader: {}", fs_file.filename)); + glCompileShader(fragment); + + id = glCreateProgram(); + glAttachShader(id, vertex); + glAttachShader(id, fragment); + glLinkProgram(id); + } + + void Use() { + glUseProgram(id); + } + +private: + GLuint id; +}; + +struct Vertex { + float pos[3]; + float color[3]; +}; + +int main(int argc, char** argv) { + glfwSetErrorCallback(GLFWCallback); + glfwInit(); + + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + + Window& window = Window::Get(); + Input& input = Input::Get(); + + gladLoadGLLoader((GLADloadproc)glfwGetProcAddress); + + glEnable(GL_DEBUG_OUTPUT); + glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); + glDebugMessageCallback(Log::OpenGLMessage, nullptr); + + Vertex vertices[] = { + { { -0.5f, 0.5f, 0.0f }, { 1.0f, 0.0f, 0.0f } }, + { { -0.5f, -0.5f, 0.0f }, { 0.0f, 1.0f, 0.0f } }, + { { 0.5f, -0.5f, 0.0f }, { 0.0f, 0.0f, 1.0f } }, + }; + + VertexBuffer buffer; + buffer.AddAttribute(Types::FLOAT, 3); + buffer.AddAttribute(Types::FLOAT, 3); + buffer.SetData(vertices, sizeof(vertices), GL_STATIC_DRAW); + + VertexArray array; + array.AddVertexBuffer(buffer); + + Shader basic(File("shaders/basic.vert"), File("shaders/basic.frag")); + + while(!window.ShouldClose()) { + input.Update(); + + glClearColor(0.3f, 0.5f, 0.4f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + + basic.Use(); + array.Draw(); + + window.SwapBuffers(); + } + + return 0; +} diff --git a/src/pch.h b/src/pch.h new file mode 100644 index 0000000..12bf700 --- /dev/null +++ b/src/pch.h @@ -0,0 +1,9 @@ +#include + +#include + +#include + +#include +#include +#include diff --git a/xmake.lua b/xmake.lua new file mode 100644 index 0000000..621fff6 --- /dev/null +++ b/xmake.lua @@ -0,0 +1,13 @@ +add_rules("mode.debug", "mode.release") + +add_requires("glfw") +add_requires("glad", { configs = { static = true, api = "gl=4.6", profile = "core" } }) + +target("ember") + set_kind("binary") + set_languages("c++20") + set_rundir(".") + set_pcxxheader("src/pch.h") + add_files("src/**.cpp") + add_includedirs("src") + add_packages("glfw", "glad")