diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..e993027 --- /dev/null +++ b/.clang-format @@ -0,0 +1,37 @@ +Language: Cpp +BasedOnStyle: LLVM + +AlignAfterOpenBracket: DontAlign +BreakConstructorInitializers: AfterColon +ConstructorInitializerAllOnOneLineOrOnePerLine: true +PointerAlignment: Left +SortIncludes: true +SpacesBeforeTrailingComments: 2 +UseTab: Always +MaxEmptyLinesToKeep: 5 + +TabWidth: 4 +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +IndentWidth: 4 +IndentCaseLabels: true + +ColumnLimit: 135 +AlwaysBreakTemplateDeclarations: Yes + +AllowShortFunctionsOnASingleLine: Empty +BreakBeforeBraces: Custom +BraceWrapping: + AfterClass: false + AfterControlStatement: false + AfterEnum: false + AfterExternBlock: false + AfterFunction: false + AfterNamespace: false + AfterStruct: false + AfterUnion: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true \ No newline at end of file diff --git a/src/Main.cpp b/src/Main.cpp index c738ddc..82e3657 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -3,36 +3,32 @@ #include #include -#include "Shader.h" #include "Renderer.h" +#include "Shader.h" #include -class Timer -{ -public: - Timer() { Reset(); } - void Reset() { m_Start = std::chrono::high_resolution_clock::now(); } - float Elapsed() const { return std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - m_Start).count() * 0.001f * 0.001f; } - float ElapsedMillis() const { return std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - m_Start).count() * 0.001f; } +constexpr int PARTICLE_COUNT = 64 * 5000; -private: - std::chrono::time_point m_Start; -}; - -class ScopedTimer -{ -public: - ScopedTimer(std::string_view name) : m_Name(name) {} - ~ScopedTimer() - { - float time = m_Timer.ElapsedMillis(); - std::cout << m_Name << " - " << time << "ms\n"; +class Timer { + public: + Timer() { + Reset(); + } + void Reset() { + m_Start = std::chrono::high_resolution_clock::now(); + } + float Elapsed() const { + return std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - m_Start).count() * + 0.001f * 0.001f; + } + float ElapsedMillis() const { + return std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - m_Start).count() * + 0.001f; } -private: - Timer m_Timer; - std::string m_Name; + private: + std::chrono::time_point m_Start; }; static uint32_t s_ComputeShader = -1; @@ -41,57 +37,51 @@ static const std::filesystem::path s_ComputeShaderPath = "Shaders/Compute.glsl"; static const std::filesystem::path s_VertexShaderPath = "Shaders/Vertex.glsl"; static const std::filesystem::path s_FragmentShaderPath = "Shaders/Fragment.glsl"; -static void ErrorCallback(int error, const char *description) -{ +static void ErrorCallback(int error, const char* description) { std::cerr << "Error: " << description << std::endl; } -static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods) -{ +static void KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods) { if (action != GLFW_PRESS) return; if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) glfwSetWindowShouldClose(window, GLFW_TRUE); - if (key == GLFW_KEY_R) - { + if (key == GLFW_KEY_R) { s_ComputeShader = ReloadComputeShader(s_ComputeShader, s_ComputeShaderPath); s_GraphicsShader = ReloadGraphicsShader(s_GraphicsShader, s_VertexShaderPath, s_FragmentShaderPath); } } -std::vector GenPoints(float x, float y) -{ - x /= 2; - y /= 2; - return { - x, y + 0.36f, - x - 0.5f, y - 0.5f, - x + 0.5f, y - 0.5f}; +static GLuint CreateDummyVAO() { + GLuint vertexArray; + glCreateVertexArrays(1, &vertexArray); + + GLuint vertexBuffer; + glCreateBuffers(1, &vertexBuffer); + + // Buffer with just one point + float vertices[] = {0.0f, 0.0f}; + glNamedBufferData(vertexBuffer, sizeof(vertices), vertices, GL_STATIC_DRAW); + glVertexArrayVertexBuffer(vertexArray, 0, vertexBuffer, 0, sizeof(float) * 2); + glEnableVertexArrayAttrib(vertexArray, 0); + glVertexArrayAttribFormat(vertexArray, 0, 2, GL_FLOAT, GL_FALSE, 0); + glVertexArrayAttribBinding(vertexArray, 0, 0); + + return vertexArray; } -std::vector GetPoints(int depth) -{ - std::vector result = {0.0f, 0.0f}; - std::size_t offset = 0; - std::size_t count = 1; - for (std::size_t i = 1; i < depth; i++) - { - for (std::size_t j = 0; j < count; j++) - { - std::size_t index = offset + j * 2; - auto newPoints = GenPoints(result[index], result[index + 1]); - result.insert(result.end(), newPoints.begin(), newPoints.end()); - } - offset += count * 2; - count *= 3; - } - return result; +static void CreateGpuBuffer(std::size_t a_Size) { + GLuint ssbo; + glGenBuffers(1, &ssbo); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, ssbo); + glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(float) * a_Size, nullptr, + GL_DYNAMIC_COPY); // sizeof(data) only works for statically sized C/C++ arrays. } -int main() -{ +static GLFWwindow* InitWindow() { glfwSetErrorCallback(ErrorCallback); if (!glfwInit()) @@ -103,9 +93,8 @@ int main() int width = 1280; int height = 720; - GLFWwindow *window = glfwCreateWindow(width, height, "Compute", NULL, NULL); - if (!window) - { + GLFWwindow* window = glfwCreateWindow(width, height, "", NULL, NULL); + if (!window) { glfwTerminate(); exit(EXIT_FAILURE); } @@ -117,61 +106,37 @@ int main() glfwSwapInterval(1); s_ComputeShader = CreateComputeShader(s_ComputeShaderPath); - if (s_ComputeShader == -1) - { + if (s_ComputeShader == -1) { std::cerr << "Compute shader failed\n"; - return -1; + return nullptr; } s_GraphicsShader = CreateGraphicsShader(s_VertexShaderPath, s_FragmentShaderPath); - if (s_GraphicsShader == -1) - { + if (s_GraphicsShader == -1) { std::cerr << "Graphics shader failed\n"; - return -1; + return nullptr; } - Texture computeShaderTexture = CreateTexture(width, height); - Framebuffer fb = CreateFramebufferWithTexture(computeShaderTexture); + return window; +} - GLuint vertexArray; - glCreateVertexArrays(1, &vertexArray); +int main() { + GLFWwindow* window = InitWindow(); + if (!window) + return -1; - GLuint vertexBuffer; - glCreateBuffers(1, &vertexBuffer); + auto vertexArray = CreateDummyVAO(); - constexpr int DEPTH = 6; - - auto vertices = GetPoints(DEPTH); - - glNamedBufferData(vertexBuffer, sizeof(float) * vertices.size(), vertices.data(), GL_STATIC_DRAW); - - glVertexArrayVertexBuffer(vertexArray, 0, vertexBuffer, 0, sizeof(float) * 2); - - glEnableVertexArrayAttrib(vertexArray, 0); - glEnableVertexArrayAttrib(vertexArray, 1); - - glVertexArrayAttribFormat(vertexArray, 0, 2, GL_FLOAT, GL_FALSE, 0); - - glVertexArrayAttribBinding(vertexArray, 0, 0); - glVertexArrayAttribBinding(vertexArray, 1, 0); - - Timer timer; - - constexpr int PARTICLE_COUNT = 64 * 5000; - - GLuint ssbo; - glGenBuffers(1, &ssbo); - glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, ssbo); - glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(float) * PARTICLE_COUNT, nullptr, GL_DYNAMIC_COPY); // sizeof(data) only works for statically sized C/C++ arrays. + CreateGpuBuffer(PARTICLE_COUNT); float lastTime = (float)glfwGetTime(); int fps = 0; float secondsTimer = 0.0f; - while (!glfwWindowShouldClose(window)) - { + glBindVertexArray(vertexArray); + + while (!glfwWindowShouldClose(window)) { // ScopedTimer timer("Main Loop"); float currentTime = (float)glfwGetTime(); @@ -179,8 +144,7 @@ int main() lastTime = currentTime; secondsTimer += dt; - if (secondsTimer >= 1.0f) - { + if (secondsTimer >= 1.0f) { std::string title = "FPS : " + std::to_string(fps); glfwSetWindowTitle(window, title.c_str()); @@ -188,18 +152,7 @@ int main() fps = 0; } - glfwGetFramebufferSize(window, &width, &height); - - // Resize texture - if (width != computeShaderTexture.Width || height != computeShaderTexture.Height) - { - glDeleteTextures(1, &computeShaderTexture.Handle); - computeShaderTexture = CreateTexture(width, height); - AttachTextureToFramebuffer(fb, computeShaderTexture); - } - // Compute - glUseProgram(s_ComputeShader); glDispatchCompute(PARTICLE_COUNT / 64, 1, 1); @@ -209,7 +162,6 @@ int main() // Graphics glUseProgram(s_GraphicsShader); - glBindVertexArray(vertexArray); glDrawArraysInstanced(GL_POINTS, 0, 1, PARTICLE_COUNT); glfwSwapBuffers(window); diff --git a/src/Renderer.cpp b/src/Renderer.cpp index e518a5f..5892fd5 100644 --- a/src/Renderer.cpp +++ b/src/Renderer.cpp @@ -5,8 +5,7 @@ #define STB_IMAGE_IMPLEMENTATION #include "stb_image.h" -Texture CreateTexture(int width, int height) -{ +Texture CreateTexture(int width, int height) { Texture result; result.Width = width; result.Height = height; @@ -24,21 +23,17 @@ Texture CreateTexture(int width, int height) return result; } -Texture LoadTexture(const std::filesystem::path& path) -{ +Texture LoadTexture(const std::filesystem::path& path) { int width, height, channels; std::string filepath = path.string(); unsigned char* data = stbi_load(filepath.c_str(), &width, &height, &channels, 0); - if (!data) - { + if (!data) { std::cerr << "Failed to load texture: " << filepath << "\n"; return {}; } - GLenum format = channels == 4 ? GL_RGBA : - channels == 3 ? GL_RGB : - channels == 1 ? GL_RED : 0; + GLenum format = channels == 4 ? GL_RGBA : channels == 3 ? GL_RGB : channels == 1 ? GL_RED : 0; Texture result; result.Width = width; @@ -47,7 +42,7 @@ Texture LoadTexture(const std::filesystem::path& path) glCreateTextures(GL_TEXTURE_2D, 1, &result.Handle); glTextureStorage2D(result.Handle, 1, (format == GL_RGBA ? GL_RGBA8 : GL_RGB8), width, height); - + glTextureSubImage2D(result.Handle, 0, 0, 0, width, height, format, GL_UNSIGNED_BYTE, data); glTextureParameteri(result.Handle, GL_TEXTURE_MIN_FILTER, GL_LINEAR); @@ -62,14 +57,12 @@ Texture LoadTexture(const std::filesystem::path& path) return result; } -Framebuffer CreateFramebufferWithTexture(const Texture texture) -{ +Framebuffer CreateFramebufferWithTexture(const Texture texture) { Framebuffer result; glCreateFramebuffers(1, &result.Handle); - if (!AttachTextureToFramebuffer(result, texture)) - { + if (!AttachTextureToFramebuffer(result, texture)) { glDeleteFramebuffers(1, &result.Handle); return {}; } @@ -77,12 +70,10 @@ Framebuffer CreateFramebufferWithTexture(const Texture texture) return result; } -bool AttachTextureToFramebuffer(Framebuffer& framebuffer, const Texture texture) -{ +bool AttachTextureToFramebuffer(Framebuffer& framebuffer, const Texture texture) { glNamedFramebufferTexture(framebuffer.Handle, GL_COLOR_ATTACHMENT0, texture.Handle, 0); - if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) - { + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { std::cerr << "Framebuffer is not complete!" << std::endl; return false; } @@ -91,12 +82,11 @@ bool AttachTextureToFramebuffer(Framebuffer& framebuffer, const Texture texture) return true; } -void BlitFramebufferToSwapchain(const Framebuffer framebuffer) -{ +void BlitFramebufferToSwapchain(const Framebuffer framebuffer) { glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer.Handle); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); // swapchain + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); // swapchain - glBlitFramebuffer(0, 0, framebuffer.ColorAttachment.Width, framebuffer.ColorAttachment.Height, // Source rect - 0, 0, framebuffer.ColorAttachment.Width, framebuffer.ColorAttachment.Height, // Destination rect + glBlitFramebuffer(0, 0, framebuffer.ColorAttachment.Width, framebuffer.ColorAttachment.Height, // Source rect + 0, 0, framebuffer.ColorAttachment.Width, framebuffer.ColorAttachment.Height, // Destination rect GL_COLOR_BUFFER_BIT, GL_NEAREST); } \ No newline at end of file diff --git a/src/Renderer.h b/src/Renderer.h index 139f971..f5c2b69 100644 --- a/src/Renderer.h +++ b/src/Renderer.h @@ -6,15 +6,13 @@ #include -struct Texture -{ +struct Texture { GLuint Handle = 0; uint32_t Width = 0; uint32_t Height = 0; }; -struct Framebuffer -{ +struct Framebuffer { GLuint Handle = 0; Texture ColorAttachment; }; diff --git a/src/Shader.cpp b/src/Shader.cpp index ab51998..f280121 100644 --- a/src/Shader.cpp +++ b/src/Shader.cpp @@ -1,17 +1,15 @@ #include "Shader.h" -#include #include +#include #include #include -static std::string ReadTextFile(const std::filesystem::path& path) -{ +static std::string ReadTextFile(const std::filesystem::path& path) { std::ifstream file(path); - if (!file.is_open()) - { + if (!file.is_open()) { std::cerr << "Failed to open file: " << path.string() << std::endl; return {}; } @@ -21,8 +19,7 @@ static std::string ReadTextFile(const std::filesystem::path& path) return contentStream.str(); } -uint32_t CreateComputeShader(const std::filesystem::path& path) -{ +uint32_t CreateComputeShader(const std::filesystem::path& path) { std::string shaderSource = ReadTextFile(path); GLuint shaderHandle = glCreateShader(GL_COMPUTE_SHADER); @@ -34,8 +31,7 @@ uint32_t CreateComputeShader(const std::filesystem::path& path) GLint isCompiled = 0; glGetShaderiv(shaderHandle, GL_COMPILE_STATUS, &isCompiled); - if (isCompiled == GL_FALSE) - { + if (isCompiled == GL_FALSE) { GLint maxLength = 0; glGetShaderiv(shaderHandle, GL_INFO_LOG_LENGTH, &maxLength); @@ -54,14 +50,13 @@ uint32_t CreateComputeShader(const std::filesystem::path& path) GLint isLinked = 0; glGetProgramiv(program, GL_LINK_STATUS, (int*)&isLinked); - if (isLinked == GL_FALSE) - { + if (isLinked == GL_FALSE) { GLint maxLength = 0; glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength); std::vector infoLog(maxLength); glGetProgramInfoLog(program, maxLength, &maxLength, &infoLog[0]); - + std::cerr << infoLog.data() << std::endl; glDeleteProgram(program); @@ -74,8 +69,7 @@ uint32_t CreateComputeShader(const std::filesystem::path& path) return program; } -uint32_t ReloadComputeShader(uint32_t shaderHandle, const std::filesystem::path& path) -{ +uint32_t ReloadComputeShader(uint32_t shaderHandle, const std::filesystem::path& path) { uint32_t newShaderHandle = CreateComputeShader(path); // Return old shader if compilation failed @@ -86,8 +80,7 @@ uint32_t ReloadComputeShader(uint32_t shaderHandle, const std::filesystem::path& return newShaderHandle; } -uint32_t CreateGraphicsShader(const std::filesystem::path& vertexPath, const std::filesystem::path& fragmentPath) -{ +uint32_t CreateGraphicsShader(const std::filesystem::path& vertexPath, const std::filesystem::path& fragmentPath) { std::string vertexShaderSource = ReadTextFile(vertexPath); std::string fragmentShaderSource = ReadTextFile(fragmentPath); @@ -102,8 +95,7 @@ uint32_t CreateGraphicsShader(const std::filesystem::path& vertexPath, const std GLint isCompiled = 0; glGetShaderiv(vertexShaderHandle, GL_COMPILE_STATUS, &isCompiled); - if (isCompiled == GL_FALSE) - { + if (isCompiled == GL_FALSE) { GLint maxLength = 0; glGetShaderiv(vertexShaderHandle, GL_INFO_LOG_LENGTH, &maxLength); @@ -127,8 +119,7 @@ uint32_t CreateGraphicsShader(const std::filesystem::path& vertexPath, const std isCompiled = 0; glGetShaderiv(fragmentShaderHandle, GL_COMPILE_STATUS, &isCompiled); - if (isCompiled == GL_FALSE) - { + if (isCompiled == GL_FALSE) { GLint maxLength = 0; glGetShaderiv(fragmentShaderHandle, GL_INFO_LOG_LENGTH, &maxLength); @@ -150,8 +141,7 @@ uint32_t CreateGraphicsShader(const std::filesystem::path& vertexPath, const std GLint isLinked = 0; glGetProgramiv(program, GL_LINK_STATUS, (int*)&isLinked); - if (isLinked == GL_FALSE) - { + if (isLinked == GL_FALSE) { GLint maxLength = 0; glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength); @@ -172,8 +162,8 @@ uint32_t CreateGraphicsShader(const std::filesystem::path& vertexPath, const std return program; } -uint32_t ReloadGraphicsShader(uint32_t shaderHandle, const std::filesystem::path& vertexPath, const std::filesystem::path& fragmentPath) -{ +uint32_t ReloadGraphicsShader( + uint32_t shaderHandle, const std::filesystem::path& vertexPath, const std::filesystem::path& fragmentPath) { uint32_t newShaderHandle = CreateGraphicsShader(vertexPath, fragmentPath); // Return old shader if compilation failed diff --git a/src/Shader.h b/src/Shader.h index 491d226..bd33acb 100644 --- a/src/Shader.h +++ b/src/Shader.h @@ -6,4 +6,5 @@ uint32_t CreateComputeShader(const std::filesystem::path& path); uint32_t ReloadComputeShader(uint32_t shaderHandle, const std::filesystem::path& path); uint32_t CreateGraphicsShader(const std::filesystem::path& vertexPath, const std::filesystem::path& fragmentPath); -uint32_t ReloadGraphicsShader(uint32_t shaderHandle, const std::filesystem::path& vertexPath, const std::filesystem::path& fragmentPath); \ No newline at end of file +uint32_t ReloadGraphicsShader( + uint32_t shaderHandle, const std::filesystem::path& vertexPath, const std::filesystem::path& fragmentPath); \ No newline at end of file