diff --git a/.github/workflows/clang_build_win.yml b/.github/workflows/clang_build_win.yml index 4e37ed5c..9da8914f 100644 --- a/.github/workflows/clang_build_win.yml +++ b/.github/workflows/clang_build_win.yml @@ -8,6 +8,7 @@ on: env: BUILD_TYPE: Release + BUILD_DIR: build jobs: build: @@ -17,7 +18,7 @@ jobs: - name: Install Vulkan SDK uses: jakoch/install-vulkan-sdk-action@v1.0.0 with: - vulkan_version: 1.3.231.1 + vulkan_version: 1.3.296.0 optional_components: com.lunarg.vulkan.vma install_runtime: true cache: true @@ -33,7 +34,10 @@ jobs: generator: Ninja c-compiler: clang cxx-compiler: clang++ - build-dir: build + build-dir: ${{env.BUILD_DIR}} - name: Build - run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} + run: cmake --build ${{github.workspace}}/${{env.BUILD_DIR}} --config ${{env.BUILD_TYPE}} + + - name: Run Core Unit Tests + run: cmake --build ${{github.workspace}}/${{env.BUILD_DIR}} --target run_core_tests \ No newline at end of file diff --git a/.github/workflows/gcc_build_ubuntu.yml b/.github/workflows/gcc_build_ubuntu.yml new file mode 100644 index 00000000..65c1f03e --- /dev/null +++ b/.github/workflows/gcc_build_ubuntu.yml @@ -0,0 +1,45 @@ +name: Ubuntu GCC Build + +on: + push: + branches: [ "master", "dev" ] + pull_request: + branches: [ "master", "dev" ] + +env: + BUILD_TYPE: Release + BUILD_DIR: build + CMAKE_C_COMPILER: gcc-13 + CMAKE_CPP_COMPILER: g++-13 + +jobs: + build: + runs-on: ubuntu-24.04 + + steps: + - uses: actions/checkout@v1 + with: + submodules: recursive + + - name: Install Vulkan SDK + uses: jakoch/install-vulkan-sdk-action@v1.0.0 + with: + optional_components: com.lunarg.vulkan.vma + install_runtime: true + cache: true + stripdown: true + + - name: Install GCC 13 + run: sudo apt-get update && sudo apt-get -y install g++-13 + + - name: Install Ninja + run: sudo apt install ninja-build + + - name: Configure CMake + run: cmake -B ${{env.BUILD_DIR}} -D CMAKE_C_COMPILER=/usr/bin/gcc-13 -D CMAKE_CXX_COMPILER=/usr/bin/g++-13 -G Ninja + + - name: Build + run: cmake --build ${{github.workspace}}/${{env.BUILD_DIR}} --config ${{env.BUILD_TYPE}} + + - name: Run Core Unit Tests + run: cmake --build ${{github.workspace}}/${{env.BUILD_DIR}} --target run_core_tests \ No newline at end of file diff --git a/.github/workflows/mingw_gcc_build_win.yml b/.github/workflows/mingw_gcc_build_win.yml index ca536c74..d03e7f15 100644 --- a/.github/workflows/mingw_gcc_build_win.yml +++ b/.github/workflows/mingw_gcc_build_win.yml @@ -8,6 +8,7 @@ on: env: BUILD_TYPE: Release + BUILD_DIR: build jobs: build: @@ -17,7 +18,7 @@ jobs: - name: Install Vulkan SDK uses: jakoch/install-vulkan-sdk-action@v1.0.0 with: - vulkan_version: 1.3.231.1 + vulkan_version: 1.3.296.0 optional_components: com.lunarg.vulkan.vma install_runtime: true cache: true @@ -33,7 +34,10 @@ jobs: generator: Ninja c-compiler: gcc cxx-compiler: g++ - build-dir: build + build-dir: ${{env.BUILD_DIR}} - name: Build - run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} + run: cmake --build ${{github.workspace}}/${{env.BUILD_DIR}} --config ${{env.BUILD_TYPE}} + + - name: Run Core Unit Tests + run: cmake --build ${{github.workspace}}/${{env.BUILD_DIR}} --target run_core_tests \ No newline at end of file diff --git a/.github/workflows/ubuntu-latest.yml b/.github/workflows/ubuntu-latest.yml deleted file mode 100644 index f4829642..00000000 --- a/.github/workflows/ubuntu-latest.yml +++ /dev/null @@ -1,45 +0,0 @@ -name: Ubuntu Build - -on: - push: - branches: [ "master", "dev" ] - pull_request: - branches: [ "master", "dev" ] - -env: - BUILD_TYPE: Release - -jobs: - build: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v1 - with: - submodules: recursive - - - name: Install prerequisites - run: sudo apt-get update && sudo apt-get install libxrandr-dev xorg-dev - - - name: Install Vulkan 0 - run: wget -qO- https://packages.lunarg.com/lunarg-signing-key-pub.asc | sudo tee /etc/apt/trusted.gpg.d/lunarg.asc - - - name: Install Vulkan 1 - run: sudo wget -qO /etc/apt/sources.list.d/lunarg-vulkan-jammy.list http://packages.lunarg.com/vulkan/lunarg-vulkan-jammy.list - - - name: Install Vulkan 2 - run: sudo apt update - - - name: Install Vulkan 3 - run: sudo apt install vulkan-sdk - - - name: Configure CMake - uses: threeal/cmake-action@v1.3.0 - with: - generator: Ninja - c-compiler: gcc - cxx-compiler: g++ - build-dir: build - - - name: Build - run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} diff --git a/.gitignore b/.gitignore index 8c557ffc..c58c2f65 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,6 @@ build /.idea/ make.bat test.bat -imgui.ini \ No newline at end of file +imgui.ini +.vs +./out \ No newline at end of file diff --git a/.gitmodules b/.gitmodules index d556ed06..abd1d5e6 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,19 +4,16 @@ [submodule "3dparty/glad"] path = 3dparty/glad url = https://github.com/Maksasj/glad -[submodule "3dparty/Vulkan-Headers"] - path = 3dparty/Vulkan-Headers - url = https://github.com/Maksasj/Vulkan-Headers.git -[submodule "3dparty/omni_types"] - path = 3dparty/omni_types - url = https://github.com/Maksasj/omni_types - [submodule "3dparty/stb"] path = 3dparty/stb url = https://github.com/Maksasj/stb -[submodule "3dparty/imgui"] - path = 3dparty/imgui - url = https://github.com/Maksasj/imgui [submodule "3dparty/glslang"] path = 3dparty/glslang url = https://github.com/Maksasj/glslang +[submodule "3dparty/miniaudio"] + path = 3dparty/miniaudio + url = https://github.com/Maksasj/miniaudio +[submodule "3dparty/google-test"] + path = 3dparty/google-test + url = https://github.com/Soskar1/googletest.git + branch = v1.14.x diff --git a/3dparty/CMakeLists.txt b/3dparty/CMakeLists.txt index f6bbbd30..2d5ab77e 100644 --- a/3dparty/CMakeLists.txt +++ b/3dparty/CMakeLists.txt @@ -1,9 +1,5 @@ add_subdirectory(glad) -set(OMNI_GLAD_INTEGRATION ON) -include_directories("glad/include") -add_subdirectory(omni_types) - set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE) set(GLFW_INSTALL OFF CACHE BOOL "" FORCE) set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) @@ -15,8 +11,8 @@ set(SHADERC_SKIP_EXAMPLES ON) set(SHADERC_SKIP_COPYRIGHT_CHECK ON) add_subdirectory(glslang) -add_subdirectory("Vulkan-Headers") - add_subdirectory(stb) +add_subdirectory(miniaudio) -add_subdirectory(imgui) +add_subdirectory(google-test) +include_directories(${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR}) \ No newline at end of file diff --git a/3dparty/Vulkan-Headers b/3dparty/Vulkan-Headers deleted file mode 160000 index a3b68365..00000000 --- a/3dparty/Vulkan-Headers +++ /dev/null @@ -1 +0,0 @@ -Subproject commit a3b683653e6a498514ef8a1865594810e91c594c diff --git a/3dparty/glslang b/3dparty/glslang index 0015dc93..7c4d91e7 160000 --- a/3dparty/glslang +++ b/3dparty/glslang @@ -1 +1 @@ -Subproject commit 0015dc9345ff9572af60801948c82b7ebce5ddb3 +Subproject commit 7c4d91e7819a1d27213aa3499953d54ae1a00e8f diff --git a/3dparty/google-test b/3dparty/google-test new file mode 160000 index 00000000..f8d7d77c --- /dev/null +++ b/3dparty/google-test @@ -0,0 +1 @@ +Subproject commit f8d7d77c06936315286eb55f8de22cd23c188571 diff --git a/3dparty/imgui b/3dparty/imgui deleted file mode 160000 index 5f40784f..00000000 --- a/3dparty/imgui +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 5f40784f4794d7fd6a4f330f277e0f10f7b96f77 diff --git a/3dparty/miniaudio b/3dparty/miniaudio new file mode 160000 index 00000000..b487e015 --- /dev/null +++ b/3dparty/miniaudio @@ -0,0 +1 @@ +Subproject commit b487e015d220570f648347cadef05dca18212127 diff --git a/3dparty/omni_types b/3dparty/omni_types deleted file mode 160000 index 6fa7d38f..00000000 --- a/3dparty/omni_types +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 6fa7d38f621aa7ff80e2643579b9b08becbf2564 diff --git a/3dparty/stb b/3dparty/stb index 0763cb3b..ae3bde09 160000 --- a/3dparty/stb +++ b/3dparty/stb @@ -1 +1 @@ -Subproject commit 0763cb3b70c8475f8d351f35a93adf8f3ad97baf +Subproject commit ae3bde090e8e317b7dbaa76c84ed78507b52d0c9 diff --git a/CMakeLists.txt b/CMakeLists.txt index f23a7704..df453ae0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,10 +3,10 @@ project(Bebone) # Bebone versions set(BEBONE_VERSION_MAJOR 0 CACHE STRING "Bebone major version") -set(BEBONE_VERSION_MINOR 1 CACHE STRING "Bebone minor version") -set(BEBONE_VERSION_PATCH 1 CACHE STRING "Bebone patch version") +set(BEBONE_VERSION_MINOR 2 CACHE STRING "Bebone minor version") +set(BEBONE_VERSION_PATCH 0 CACHE STRING "Bebone patch version") -set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD_REQUIRED ON) if(NOT CMAKE_BUILD_TYPE) @@ -22,9 +22,9 @@ if(CMAKE_BUILD_TYPE MATCHES Release) endif() if(MSVC) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4 /WX") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4") else() - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -std=c++2b") endif() # Bebone build options @@ -34,9 +34,10 @@ option(BEBONE_TESTS "Bebone build all tests" ON) option(BEBONE_BUILD_CORE "Bebone build core module" ON) option(BEBONE_BUILD_ASSETS "Bebone build assets module" ON) option(BEBONE_BUILD_GFX "Bebone build gfx module" ON) +option(BEBONE_BUILD_RENDERER "Bebone build renderer module" ON) +option(BEBONE_BUILD_SOUND "Bebone build sound module" ON) add_subdirectory(3dparty) - add_subdirectory(src) if(BEBONE_EXAMPLES) @@ -45,4 +46,4 @@ endif() if(BEBONE_TESTS) add_subdirectory(tests) -endif() +endif() \ No newline at end of file diff --git a/LICENSE.md b/LICENSE.md index 828dfe8a..7dc91c9a 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,21 +1,201 @@ -MIT License - -Copyright (c) 2023 Maksim Jaroslavcevas, Oskaras Vištorskis, Vadim Elkin - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2024 [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md index 0df65664..93b401e2 100644 --- a/README.md +++ b/README.md @@ -1,110 +1,129 @@ -# Bebone -Bebone - Is a framework/engine aimed for flexible and comfortable game development, written in C++. -In other words Bebone is a set of useful game development libraries, written and integrated -in Bebone framework ecosystem. +# bebone 💀 -> Bebone is not a new javascript framework btw. It is a game development one! +Modular game development framework/engine written with **C++**. **Bebone** implements **high-level** abstractions, as well as provides access to **low-level** internal abstractions for **flexible** and **highly customizable** game development + +- **Modular code base**, every **bebone** module is a self contained library with **minimal** dependency on **third-party** libraries. All **bebone** abstractions inherit same **interfaces**, for better integration with user defined abstractions +- **Designed with real-world use in mind** for small hobby projects, as well as professional/enterprise projects. +- **User-Friendly** for **all experience levels**. Designed to be intuitive and easy to use for **beginners**, as well as experienced professionals + +> **Bebone** is not a new javascript framework btw. It is a game development one! Cool looking widgets -stars -build -build - -## Features -* Core module - * Arena allocator & container - * Logger - * Types library - * Event submodule - * Listener system (Java style) - * Action delegate (C# style) - * Input system - * Meta programming module -* Graphics module - * OpenGL abstraction layer - * Vulkan abstraction layer (in development) - * Shaders - * Window - * Begui (Dear ImGui abstraction layer) -## Build -For now there is two methods how you can use bebone is your project(build locally). -1. **Build manually**
- First of all requirements: - - Cmake (At least version 3.21) - - Ninja (At least version 1.11.1) - - C++ compiler (Have test with Clang 15.0.5 and GCC 12.2.0) - - *Vulkan SDK (if you want to build gfx module)* - - Firstly lets clone bebone locally(note that you also need to clone all bebone git submodules). - - Secondly lets configure our Cmake configuration with - ```bash - cmake -B build -G Ninja - ``` - - Finally you can simply build project with cmake - ```bash - cmake --build build - ``` - -2. **Using docker**
- Currently the docker image is not available, but we are planning to release it towards bebone 0.2v. - -Note that bebone is only a **set** of useful libraries/modules, some modules can be used separately. - -## Testing -The testing process is similar to the **Building**. After a successful build, all you have to do is run CTest from ```build\tests\unit``` directory. - -## Dependencies -For convenience, we try to reduce the use of third-party libraries, as it complicates code management and readability. -At the moment, bebone is only dependent on these libraries: - - [Glad](https://github.com/Maksasj/glad/tree/all-extensions) *(opengl function header)* - - [Vulkan-Headers](https://github.com/Maksasj/Vulkan-Headers/tree/main) *(vulkan function header)* - - [GLFW](https://github.com/Maksasj/glfw/tree/master) *(window management library)* +![GitHub Repo stars](https://img.shields.io/github/stars/Maksasj/bebone) +![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/Maksasj/bebone/clang_build_win.yml) +![GitHub License](https://img.shields.io/github/license/Maksasj/bebone) +![Discord](https://img.shields.io/discord/1156584129190711326?logo=discord) + +### Links +1. Source code available at [github.com/Maksasj/bebone](https://github.com/Maksasj/bebone) +2. Community Discord [discord.gg/bebone](https://discord.gg/v4mcTmuDTb) +3. **Bebone** documentation available at [github.com/Maksasj/bebone](github.com/Maksasj/bebone/docs/DOCUMENTATION.md) + +## Architecture ⚙️ + +**Bebone** provides multi layer APIs where each level build on top of previous: + +- **[Abstraction]()** - basic abstraction layer. Abstracts most basic things, such as OpenGL or Vulkan +- **[System]()** - advance abstraction layer. Implements generalized systems on top of abstraction layer, such as Renderer +- **[App]()** - complete application layer. Combines multiple systems into self-contained application + +## Features ✨ + +For now **bebone** has several modules: + +* [Core module](). Core **bebone** module implements most important abstractions which are widely used across all other modules. Implements **Memory, Debug, Types, Event, Input** abstractions +* [Graphics module (GFX module)](). **Abstraction layer** module, implements basic abstractions on top of **Graphical APIs** such as **OpenGL** and **Vulkan**. **GFX module** + depends on **Core**, **Assets** modules +* [Assets module](). Module designed for loading and managing different **assets** such as **images**, **models**, **materals**. **Assets module** depends on **Core module** only +* [Renderer module]() **System layer** module, provides high-level generalized graphical functionality. It abstracts all low-level **OpenGL** or **Vulkan** under one convenient interface. This module is build on top of **GFX module** +* [Sound module]() *Todo* + +### Planned modules +* [Physics module]() +* [Entity component system module (ECS module)]() +* [App module]() + +## Build 🛠 + +First of all requirements + - [CMake](https://cmake.org/) (At least version 3.21) + - [Ninja](https://github.com/ninja-build/ninja) (At least version 1.11.1) + - C++ compiler (Have test with Clang 15.0.5 and GCC 12.2.0) + - *[Vulkan SDK](https://www.lunarg.com/vulkan-sdk/) (if you want to build [GFX module]())* + + Firstly lets clone **bebone** locally *(note that you also need to clone all bebone git submodules with `--recursive` flag)* + + ```bash + git clone --recursive git@github.com:Maksasj/bebone.git + ``` + + Secondly lets configure our **CMake** configuration with + ```bash + cmake -B build -G Ninja + ``` + + Finally you can simply build project with cmake + ```bash + cmake --build build + ``` + +## Testing 💊 +### Unit testing +The testing process is similar to the **Building**. After a successful build, all you have to do is run [CTest](https://cmake.org/cmake/help/book/mastering-cmake/chapter/Testing%20With%20CMake%20and%20CTest.html) from ```build\tests\unit``` directory + +### Integration testing +As for integration tests we use our examples, so see **[Examples]()** section + +## Dependencies 🗃 +For convenience, we tried to reduce the use of third-party libraries, as it complicates code management and readability. +At the moment, bebone is only dependent on these third-party libraries: + - [Glad](https://github.com/Maksasj/glad/tree/all-extensions) *(OpenGL function header)* + - [Vulkan-Headers](https://github.com/Maksasj/Vulkan-Headers/tree/main) *(Vulkan function header)* + - [GLFW](https://github.com/Maksasj/glfw/tree/master) *(Window management library)* - [Glslang](https://github.com/KhronosGroup/glslang/tree/main) *(SPIR-V shader compiler library)* - - [imgui](https://github.com/Maksasj/imgui/tree/master) *(Debug gui library)* - - [omni_types](https://github.com/Maksasj/omni_types/tree/master) *(Type library)* + - [imgui](https://github.com/Maksasj/imgui/tree/master) *(Debug GUI library)* - [stb](https://github.com/Maksasj/stb/tree/master) *(Image management library and others)* + - [miniaudio](https://github.com/Maksasj/miniaudio/tree/master) *(Sound and Music library)* -## Examples -Bebone hello world example: +## Examples 🤡 +You can find examples in [examples](https://github.com/Maksasj/bebone/tree/master/examples) directory. + +### Minimal example ```c++ #include "bebone/bebone.h" +using namespace bebone::renderer; using namespace bebone::gfx; -using namespace bebone::gfx::opengl; int main() { - GLFWContext::init(); - - auto window = WindowFactory::create_window("Example", 800, 600, GfxAPI::OPENGL); - - GLContext::load_opengl(); - GLContext::set_viewport(0, 0, SCR_WIDTH, SCR_HEIGHT); - - while (!window->closing()) { - GLContext::clear_color(0.2f, 0.2f, 0.2f, 1.0f); - GLContext::clear(GL_COLOR_BUFFER_BIT); + auto window = WindowFactory::create_window("Example", 800, 600); + auto renderer = RendererFactory::create_renderer(window); - // Your game code + auto sprite = renderer->load_sprite("sprite.png"); - GLFWContext::swap_buffers(*window); - GLFWContext::poll_events(); - window->execute_input_actions(); + while(!window->closing()) { + renderer->render(sprite, { .position = Vec3f::zero }); + renderer->present(); } - GLFWContext::terminate(); return 0; } - ``` -You can find other examples in [examples](https://github.com/Maksasj/bebone/tree/master/examples) directory. +## Documentation 📑 + - [Core module](https://github.com/Maksasj/bebone/blob/master/docs/core/CORE.md) + - [Assets module](https://github.com/Maksasj/bebone/blob/master/docs/assets/ASSETS.md) + - [GFX module](https://github.com/Maksasj/bebone/blob/master/docs/gfx/GFX.md) + - [Renderer module](https://github.com/Maksasj/bebone/blob/master/docs/renderer/RENDERER.md) + - [Sound module](https://github.com/Maksasj/bebone/blob/master/docs/sound/SOUND.md) + +For full documentation see [DOCUMENTATION.md](https://github.com/Maksasj/bebone/blob/master/docs/DOCUMENTATION.md) file + +## Contribution 🫶 +Since for now no one cares about **bebone** we do not have any instructions or pull request templates, so just open [issue](https://github.com/Maksasj/bebone/issues). -## Documentation - - [Core module](https://github.com/Maksasj/bebone/blob/master/docs/Core.md) - - [GFX module](https://github.com/Maksasj/bebone/blob/master/docs/Gfx.md) +## License 🛡 +**Bebone** is free and open source game development framework. All code in this repository is licensed under +- Apache-2.0 license ([LICENSE.md](https://github.com/Maksasj/bebone/blob/master/LICENSE.md) or http://www.apache.org/licenses/LICENSE-2.0) -## License -Bebone is free, open source game development framework. All code in this repository FOR NOW is licensed under -- MIT License ([LICENSE.md](https://github.com/Maksasj/bebone/blob/master/LICENSE.md) or https://opensource.org/license/mit/) +*Copyright 2023 © Maksim Jaroslavcevas, Oskaras Vištorskis* \ No newline at end of file diff --git a/docs/DOCUMENTATION.md b/docs/DOCUMENTATION.md new file mode 100644 index 00000000..2809866a --- /dev/null +++ b/docs/DOCUMENTATION.md @@ -0,0 +1,9 @@ +# bebone documentation + +### Sections +- [Core]() + - [Events]() + - [Input]() +- [Gfx]() + - [OpenGL]() + - [Vulkan]() \ No newline at end of file diff --git a/docs/core/CORE.md b/docs/core/CORE.md new file mode 100644 index 00000000..5eea07b1 --- /dev/null +++ b/docs/core/CORE.md @@ -0,0 +1,5 @@ +# Core module + +### Articles +- [Events]() +- [Input]() \ No newline at end of file diff --git a/docs/Core.md b/docs/core/EVENTS.md similarity index 89% rename from docs/Core.md rename to docs/core/EVENTS.md index 68bbaf96..59c3eb50 100644 --- a/docs/Core.md +++ b/docs/core/EVENTS.md @@ -1,4 +1,4 @@ -# Core module +# Events ## Action delegate(C# style) Action delegate is a function object container which can subscribe to the specific functions or unsubscribe from them. Also, it can execute all functions to which action is subscribed. Action delegate can subscribe only to those functions who have void return type and some arguments (or without arguments) Action delegate is similar to the C# Action. @@ -121,14 +121,15 @@ In Bebone you can use event-based input system to add some actions to your keys. Input system works with ```Action<>``` delegate. Because of this feature, you will subscribe/unsubscribe your keyboard keys and mouse buttons to the 'in-game actions' (such as jumping, running, etc.). You can do this with these two methods: ```c++ -void register_key_action(const KeyCode& keyCode, std::function& action, const InputType& inputType = InputType::PRESS); -void remove_key_action(const KeyCode& keyCode, std::function& action, const InputType& inputType = InputType::PRESS); +void register_key_action(const KeyCode& key_code, std::function& action, const InputType& input_type = InputType::Press); +void remove_key_action(const KeyCode& key_code, std::function& action, const InputType& input_type = InputType::Press); ``` * KeyCode — enum, which specifies the key to which you can subscribe an action * action — 'in-game action' -* inputType — enum, which specifies in which case the action will be executed (by default it is set to PRESS) +* input_type — enum, which specifies in which case the action will be executed (by default it is set to Press) + +Add this command line inside the window loop to allow the framework to handle all the user input: -All that is left to do is to add one command line inside the window loop to allow the framework to handle all the user input (maybe we will change it later): ```c++ window->execute_input_actions(); ``` @@ -141,12 +142,11 @@ const unsigned int SCR_WIDTH = 800; const unsigned int SCR_HEIGHT = 600; using namespace bebone::gfx; -using namespace bebone::gfx::opengl; int main() { glfwInit(); - auto window = WindowFactory::create_window("0. Input example", SCR_WIDTH, SCR_HEIGHT, GfxAPI::OPENGL); + auto window = WindowFactory::create_window("0. Input example", SCR_WIDTH, SCR_HEIGHT, OpenGL); GLContext::load_opengl(); GLContext::set_viewport(0, 0, SCR_WIDTH, SCR_HEIGHT); @@ -173,4 +173,4 @@ int main() { glfwTerminate(); return 0; } -``` \ No newline at end of file +``` diff --git a/docs/core/INPUT.md b/docs/core/INPUT.md new file mode 100644 index 00000000..bd8f0c3c --- /dev/null +++ b/docs/core/INPUT.md @@ -0,0 +1,60 @@ +# Input + +## Input System +In Bebone you can use event-based input system to add some actions to your keys. Input class — is a singleton class, so you can get it's instance anywhere in your codebase. + +Input system works with ```Action<>``` delegate. Because of this feature, you will subscribe/unsubscribe your keyboard keys and mouse buttons to the 'in-game actions' (such as jumping, running, etc.). You can do this with these two methods: +```c++ +void register_key_action(const KeyCode& key_code, std::function& action, const InputType& input_type = InputType::Press); +void remove_key_action(const KeyCode& key_code, std::function& action, const InputType& input_type = InputType::Press); +``` +* KeyCode — enum, which specifies the key to which you can subscribe an action +* action — 'in-game action' +* input_type — enum, which specifies in which case the action will be executed (by default it is set to Press) + +All that is left to do is to add one command line inside the window loop to allow the framework to handle all the user input (maybe we will change it later): +```c++ +window->execute_input_actions(); +``` + +Example usage: +```с++ +#include "bebone/bebone.h" + +const unsigned int SCR_WIDTH = 800; +const unsigned int SCR_HEIGHT = 600; + +using namespace bebone::gfx; +using namespace bebone::gfx::opengl; + +int main() { + glfwInit(); + + auto window = WindowFactory::create_window("0. Input example", SCR_WIDTH, SCR_HEIGHT, GfxAPI::OpenGL); + + GLContext::load_opengl(); + GLContext::set_viewport(0, 0, SCR_WIDTH, SCR_HEIGHT); + + // in-game action + std::function keyPress = []() { + std::cout << "key press\n"; + }; + + // registering the key + Input::get_instance().register_key_action(KeyCode::A, keyPress); + + while (!window->closing()) { + GLContext::clear_color(0.2f, 0.2f, 0.2f, 1.0f); + GLContext::clear(GL_COLOR_BUFFER_BIT); + + // without this your input will not work! + window->execute_input_actions(); + + glfwSwapBuffers(window->get_backend()); + glfwPollEvents(); + } + + glfwTerminate(); + return 0; +} +``` \ No newline at end of file diff --git a/docs/gfx/GFX.md b/docs/gfx/GFX.md new file mode 100644 index 00000000..90f7bc1d --- /dev/null +++ b/docs/gfx/GFX.md @@ -0,0 +1,5 @@ +# GFX module + +### Articles +- [OpenGL]() +- [Vulkan]() \ No newline at end of file diff --git a/docs/Gfx.md b/docs/gfx/OPENGL.md similarity index 94% rename from docs/Gfx.md rename to docs/gfx/OPENGL.md index 96ea64f4..612bf56f 100644 --- a/docs/Gfx.md +++ b/docs/gfx/OPENGL.md @@ -19,12 +19,11 @@ const unsigned int SCR_WIDTH = 800; const unsigned int SCR_HEIGHT = 600; using namespace bebone::gfx; -using namespace bebone::gfx::opengl; int main() { glfwInit(); - auto window = WindowFactory::create_window("0. OpenGL window example", SCR_WIDTH, SCR_HEIGHT, GfxAPI::OPENGL); + auto window = WindowFactory::create_window("0. OpenGL window example", SCR_WIDTH, SCR_HEIGHT, OpenGL); GLContext::load_opengl(); GLContext::set_viewport(0, 0, SCR_WIDTH, SCR_HEIGHT); @@ -117,14 +116,14 @@ To use shaders in OpenGL Bebone you will need to use the GLShaderFactory, GLShad ### GLShaderFactory GLShaderFactory creates shader objects (GLShader) which later need to be assigned to the shader program (GLShaderProgram). GLShaderFactory has only one public method for shader creation: ```c++ -static GLShader create_shader(const std::string& path, const ShaderType& shaderType, const GLShaderProperties& properties = NONE); +static GLShader create_shader(const std::string& path, const ShaderType& shaderType, const GLShaderProperties& properties = None); ``` You need to specify the path to the glsl shader, it's type (vertex/fragment shader) and other properties (enable uniforms or not) Simple example usage: ```c++ -GLShader vertexShader = GLShaderFactory::create_shader("vertex.glsl", ShaderTypes::VERTEX_SHADER); -GLShader fragmentShader = GLShaderFactory::create_shader("fragment.glsl", ShaderTypes::FRAGMENT_SHADER); +GLShader vertexShader = GLShaderFactory::create_shader("vertex.glsl", VertexShader); +GLShader fragmentShader = GLShaderFactory::create_shader("fragment.glsl", FragmentShader); ``` ### GLShader @@ -132,14 +131,14 @@ In OpenGL, a Shader is a user-defined program designed to run on some stage of a Firstly lets create our shader. The easiest and simplest way to create a shader is to use GLShaderFactory, like this: ```c++ -auto vertexShader = GLShaderFactory::create_shader("vertex.glsl", ShaderTypes::VERTEX_SHADER); -auto fragmentShader = GLShaderFactory::create_shader("fragment.glsl", ShaderTypes::FRAGMENT_SHADER); +auto vertexShader = GLShaderFactory::create_shader("vertex.glsl", VertexShader); +auto fragmentShader = GLShaderFactory::create_shader("fragment.glsl", FragmentShader); ``` As you see you need only to specify path to shader source code and shader type, after this you can use your shader for creating your shader program. Second way is using GLShader constructor: ```c++ -GLShader(const ShaderCode& code, const ShaderType& shaderType, const GLShaderProperties& properties = NONE); +GLShader(const ShaderCode& code, const ShaderType& shaderType, const GLShaderProperties& properties = None); ``` As you see there you have a bit more controll on creating your opengl shader. You can compile your opengl shader code manually using ShaderCompiler and then use shader code as input for GLShader constructor. @@ -168,7 +167,6 @@ const unsigned int SCR_WIDTH = 800; const unsigned int SCR_HEIGHT = 600; using namespace bebone::gfx; -using namespace bebone::gfx::opengl; const std::vector vertices = { {-0.5f, -0.5f, 0.0f}, @@ -183,13 +181,13 @@ const std::vector indices = { int main() { GLFWContext::init(); - auto window = WindowFactory::create_window("1. OpenGL hello triangle example", SCR_WIDTH, SCR_HEIGHT, GfxAPI::OPENGL); + auto window = WindowFactory::create_window("1. OpenGL hello triangle example", SCR_WIDTH, SCR_HEIGHT, OpenGL); GLContext::load_opengl(); GLContext::set_viewport(0, 0, SCR_WIDTH, SCR_HEIGHT); - GLShader vertexShader = GLShaderFactory::create_shader("vertex.glsl", ShaderTypes::VERTEX_SHADER); - GLShader fragmentShader = GLShaderFactory::create_shader("fragment.glsl", ShaderTypes::FRAGMENT_SHADER); + GLShader vertexShader = GLShaderFactory::create_shader("vertex.glsl", VertexShader); + GLShader fragmentShader = GLShaderFactory::create_shader("fragment.glsl", FragmentShader); GLShaderProgram shaderProgram(vertexShader, fragmentShader); vertexShader.destroy(); @@ -253,7 +251,6 @@ const unsigned int SCR_WIDTH = 800; const unsigned int SCR_HEIGHT = 600; using namespace bebone::gfx; -using namespace bebone::gfx::opengl; struct Vertex { Vec3f pos; @@ -276,13 +273,13 @@ const std::vector indices { int main() { GLFWContext::init(); - auto window = WindowFactory::create_window("2. OpenGL texture example", SCR_WIDTH, SCR_HEIGHT, GfxAPI::OPENGL); + auto window = WindowFactory::create_window("2. OpenGL texture example", SCR_WIDTH, SCR_HEIGHT, OpenGL); GLContext::load_opengl(); GLContext::set_viewport(0, 0, SCR_WIDTH, SCR_HEIGHT); - auto vertexShader = GLShaderFactory::create_shader("vertex.glsl", ShaderTypes::VERTEX_SHADER); - auto fragmentShader = GLShaderFactory::create_shader("fragment.glsl", ShaderTypes::FRAGMENT_SHADER); + auto vertexShader = GLShaderFactory::create_shader("vertex.glsl", VertexShader); + auto fragmentShader = GLShaderFactory::create_shader("fragment.glsl", FragmentShader); GLShaderProgram shaderProgram(vertexShader, fragmentShader); vertexShader.destroy(); diff --git a/docs/gfx/VULKAN.md b/docs/gfx/VULKAN.md new file mode 100644 index 00000000..e69de29b diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 3a0b578a..47338be2 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,15 +1,8 @@ cmake_minimum_required(VERSION 3.21) project(BeboneExamples) -include_directories("./") -include_directories("../src") -include_directories("../3dparty/glad/include") -include_directories("../3dparty/glfw/include") -include_directories("../3dparty/Vulkan-Headers/include") -include_directories("../3dparty/omni_types/src") -include_directories("../3dparty/stb") -include_directories("../3dparty/imgui") - -add_subdirectory(gfx) add_subdirectory(assets) add_subdirectory(core) +add_subdirectory(gfx) +add_subdirectory(renderer) +add_subdirectory(sound) diff --git a/examples/assets/0_assets_image_basic/CMakeLists.txt b/examples/assets/0_assets_image_basic/CMakeLists.txt index dda6bb40..3c36a2f4 100644 --- a/examples/assets/0_assets_image_basic/CMakeLists.txt +++ b/examples/assets/0_assets_image_basic/CMakeLists.txt @@ -1,7 +1,7 @@ file(GLOB_RECURSE BEBONE_EXAMPLE_ASSETS_0_IMAGE_BASIC *.cpp) -include_directories("../../src") include_directories("./") +include_directories(${BEBONE_INCLUDES}) add_executable(Bebone_Example_Assets_0_Image_Basic ${BEBONE_EXAMPLE_ASSETS_0_IMAGE_BASIC}) target_link_libraries(Bebone_Example_Assets_0_Image_Basic bebone) \ No newline at end of file diff --git a/examples/assets/0_assets_image_basic/main.cpp b/examples/assets/0_assets_image_basic/main.cpp index e74f395d..61f7391a 100644 --- a/examples/assets/0_assets_image_basic/main.cpp +++ b/examples/assets/0_assets_image_basic/main.cpp @@ -2,16 +2,15 @@ #include -const unsigned int SCR_WIDTH = 512; -const unsigned int SCR_HEIGHT = 512; +const unsigned int screen_width = 512; +const unsigned int screen_height = 512; using namespace bebone::assets; using namespace bebone::gfx; -using namespace bebone::gfx::opengl; struct Vertex { Vec3f pos; - Vec2f texCord; + Vec2f tex_coords; }; const std::vector vertices { @@ -27,20 +26,18 @@ const std::vector indices { }; int main() { - GLFWContext::init(); - - auto window = WindowFactory::create_window("0. Image example basic", SCR_WIDTH, SCR_HEIGHT, GfxAPI::OPENGL); + auto window = WindowFactory::create_window("0. Image example basic", screen_width, screen_height, OpenGL); GLContext::load_opengl(); - GLContext::set_viewport(0, 0, SCR_WIDTH, SCR_HEIGHT); + GLContext::set_viewport(0, 0, screen_width, screen_height); - auto vertexShader = GLShaderFactory::create_shader("vertex.glsl", ShaderTypes::VERTEX_SHADER); - auto fragmentShader = GLShaderFactory::create_shader("fragment.glsl", ShaderTypes::FRAGMENT_SHADER); - GLShaderProgram shaderProgram(vertexShader, fragmentShader); - shaderProgram.set_uniform("ourTexture", 0); + auto vertex_shader = GLShaderFactory::create_shader("vertex.glsl", ShaderType::VertexShader); + auto fragment_shader = GLShaderFactory::create_shader("fragment.glsl", ShaderType::FragmentShader); + GLShaderProgram shader_program(vertex_shader, fragment_shader); + shader_program.set_uniform("ourTexture", 0); - vertexShader.destroy(); - fragmentShader.destroy(); + vertex_shader.destroy(); + fragment_shader.destroy(); GLVertexArrayObject vao; vao.bind(); @@ -49,7 +46,7 @@ int main() { GLElementBufferObject ebo(indices.data(), indices.size() * sizeof(u32)); vao.link_attributes(vbo, 0, 3, GL_FLOAT, sizeof(Vertex), offsetof(Vertex, pos)); - vao.link_attributes(vbo, 1, 2, GL_FLOAT, sizeof(Vertex), offsetof(Vertex, texCord)); + vao.link_attributes(vbo, 1, 2, GL_FLOAT, sizeof(Vertex), offsetof(Vertex, tex_coords)); vao.unbind(); vbo.unbind(); @@ -64,14 +61,14 @@ int main() { auto texture = make_shared(image); window->add_listener([&](InputMouseButtonEvent& event) { - double xPos, yPos; - glfwGetCursorPos(window->get_backend(), &xPos, &yPos); + double x_pos, y_pos; + glfwGetCursorPos(window->get_backend(), &x_pos, &y_pos); if(event.button == GLFW_MOUSE_BUTTON_LEFT) { - painter.paint_circle(xPos, yPos, 20, ColorRGBA::RED); + painter.paint_circle(x_pos, y_pos, 20, ColorRGBA::RED); texture = make_shared(image); } else if(event.button == GLFW_MOUSE_BUTTON_RIGHT) { - painter.paint_square(xPos, yPos, 5, 5, ColorRGBA::BLUE); + painter.paint_square(x_pos, y_pos, 5, 5, ColorRGBA::BLUE); texture = make_shared(image); } }); @@ -82,15 +79,11 @@ int main() { } }); - GLContext::enable(GL_CULL_FACE); - GLContext::cull_face(GL_BACK); - GLContext::front_face(GL_CW); - while (!window->closing()) { GLContext::clear_color(0.2f, 0.2f, 0.2f, 1.0f); GLContext::clear(GL_COLOR_BUFFER_BIT); - shaderProgram.enable(); + shader_program.enable(); texture->bind(); vao.bind(); @@ -98,10 +91,8 @@ int main() { GLContext::draw_elements(GL_TRIANGLES, static_cast(indices.size()), GL_UNSIGNED_INT, nullptr); glfwSwapBuffers(window->get_backend()); - GLFWContext::poll_events(); + window->pull_events(); } - GLFWContext::terminate(); - return 0; } diff --git a/examples/assets/1_assets_image_advance/CMakeLists.txt b/examples/assets/1_assets_image_advance/CMakeLists.txt index 410b9a80..9e6e1585 100644 --- a/examples/assets/1_assets_image_advance/CMakeLists.txt +++ b/examples/assets/1_assets_image_advance/CMakeLists.txt @@ -1,7 +1,7 @@ file(GLOB_RECURSE BEBONE_EXAMPLE_ASSETS_1_IMAGE_ADVANCE *.cpp) -include_directories("../../src") include_directories("./") +include_directories(${BEBONE_INCLUDES}) add_executable(Bebone_Example_Assets_1_Image_Advance ${BEBONE_EXAMPLE_ASSETS_1_IMAGE_ADVANCE}) target_link_libraries(Bebone_Example_Assets_1_Image_Advance bebone) \ No newline at end of file diff --git a/examples/assets/1_assets_image_advance/main.cpp b/examples/assets/1_assets_image_advance/main.cpp index e88d84bb..fde6d276 100644 --- a/examples/assets/1_assets_image_advance/main.cpp +++ b/examples/assets/1_assets_image_advance/main.cpp @@ -7,11 +7,10 @@ const unsigned int SCR_HEIGHT = 512; using namespace bebone::assets; using namespace bebone::gfx; -using namespace bebone::gfx::opengl; struct Vertex { Vec3f pos; - Vec2f texCord; + Vec2f tex_coords; }; const std::vector vertices { @@ -27,20 +26,18 @@ const std::vector indices { }; int main() { - GLFWContext::init(); - - auto window = WindowFactory::create_window("1. Image example advance", SCR_WIDTH, SCR_HEIGHT, GfxAPI::OPENGL); + auto window = WindowFactory::create_window("1. Image example advance", SCR_WIDTH, SCR_HEIGHT, OpenGL); GLContext::load_opengl(); GLContext::set_viewport(0, 0, SCR_WIDTH, SCR_HEIGHT); - auto vertexShader = GLShaderFactory::create_shader("vertex.glsl", ShaderTypes::VERTEX_SHADER); - auto fragmentShader = GLShaderFactory::create_shader("fragment.glsl", ShaderTypes::FRAGMENT_SHADER); - GLShaderProgram shaderProgram(vertexShader, fragmentShader); - shaderProgram.set_uniform("ourTexture", 0); + auto vertex_shader = GLShaderFactory::create_shader("vertex.glsl", ShaderType::VertexShader); + auto fragment_shader = GLShaderFactory::create_shader("fragment.glsl", ShaderType::FragmentShader); + GLShaderProgram shader_program(vertex_shader, fragment_shader); + shader_program.set_uniform("ourTexture", 0); - vertexShader.destroy(); - fragmentShader.destroy(); + vertex_shader.destroy(); + fragment_shader.destroy(); GLVertexArrayObject vao; vao.bind(); @@ -49,7 +46,7 @@ int main() { GLElementBufferObject ebo(indices.data(), indices.size() * sizeof(u32)); vao.link_attributes(vbo, 0, 3, GL_FLOAT, sizeof(Vertex), offsetof(Vertex, pos)); - vao.link_attributes(vbo, 1, 2, GL_FLOAT, sizeof(Vertex), offsetof(Vertex, texCord)); + vao.link_attributes(vbo, 1, 2, GL_FLOAT, sizeof(Vertex), offsetof(Vertex, tex_coords)); vao.unbind(); vbo.unbind(); @@ -65,15 +62,11 @@ int main() { auto texture = make_shared(image); - GLContext::enable(GL_CULL_FACE); - GLContext::cull_face(GL_BACK); - GLContext::front_face(GL_CW); - while (!window->closing()) { GLContext::clear_color(0.2f, 0.2f, 0.2f, 1.0f); GLContext::clear(GL_COLOR_BUFFER_BIT); - shaderProgram.enable(); + shader_program.enable(); texture->bind(); vao.bind(); @@ -81,10 +74,8 @@ int main() { GLContext::draw_elements(GL_TRIANGLES, static_cast(indices.size()), GL_UNSIGNED_INT, nullptr); glfwSwapBuffers(window->get_backend()); - GLFWContext::poll_events(); + window->pull_events(); } - GLFWContext::terminate(); - return 0; } diff --git a/examples/core/events/0_events_event_listeners/CMakeLists.txt b/examples/core/events/0_events_event_listeners/CMakeLists.txt index c5178e23..e80aa1fe 100644 --- a/examples/core/events/0_events_event_listeners/CMakeLists.txt +++ b/examples/core/events/0_events_event_listeners/CMakeLists.txt @@ -1,7 +1,7 @@ file(GLOB_RECURSE BEBONE_EXAMPLE_EVENTS_0_EVENT_LISTENERS *.cpp) -include_directories("../../src") -include_directories(".") +include_directories("./") +include_directories(${BEBONE_INCLUDES}) add_executable(Bebone_Example_Events_0_Event_Listeners ${BEBONE_EXAMPLE_EVENTS_0_EVENT_LISTENERS}) target_link_libraries(Bebone_Example_Events_0_Event_Listeners bebone) \ No newline at end of file diff --git a/examples/core/events/0_events_event_listeners/main.cpp b/examples/core/events/0_events_event_listeners/main.cpp index b2c21659..3ce034c9 100644 --- a/examples/core/events/0_events_event_listeners/main.cpp +++ b/examples/core/events/0_events_event_listeners/main.cpp @@ -1,10 +1,9 @@ #include "bebone/bebone.h" -const unsigned int SCR_WIDTH = 800; -const unsigned int SCR_HEIGHT = 600; +const unsigned int screen_width = 800; +const unsigned int screen_height = 600; using namespace bebone::gfx; -using namespace bebone::gfx::opengl; void window_resize_event_listener(WindowSizeEvent&) { std::cout << "Window resize event !\n"; @@ -19,7 +18,7 @@ struct WindowPosEventListener : EventListener { int main() { glfwInit(); - auto window = WindowFactory::create_window("0. OpenGL window example", SCR_WIDTH, SCR_HEIGHT, GfxAPI::OPENGL); + auto window = WindowFactory::create_window("0. OpenGL window example", screen_width, screen_height, OpenGL); WindowPosEventListener listener; window->add_listener(listener); @@ -33,7 +32,7 @@ int main() { window->fire(WindowPosEvent(0, 0)); GLContext::load_opengl(); - GLContext::set_viewport(0, 0, SCR_WIDTH, SCR_HEIGHT); + GLContext::set_viewport(0, 0, screen_width, screen_height); while (!window->closing()) { GLContext::clear_color(0.2f, 0.2f, 0.2f, 1.0f); diff --git a/examples/core/events/1_events_action_delegate/CMakeLists.txt b/examples/core/events/1_events_action_delegate/CMakeLists.txt index c87a9de4..b7d1b493 100644 --- a/examples/core/events/1_events_action_delegate/CMakeLists.txt +++ b/examples/core/events/1_events_action_delegate/CMakeLists.txt @@ -1,7 +1,7 @@ file(GLOB_RECURSE BEBONE_EXAMPLE_EVENTS_1_ACTION_DELEGATE *.cpp) -include_directories("../../src") -include_directories(".") +include_directories("./") +include_directories(${BEBONE_INCLUDES}) add_executable(Bebone_Example_Events_1_Action_Delegate ${BEBONE_EXAMPLE_EVENTS_1_ACTION_DELEGATE}) target_link_libraries(Bebone_Example_Events_1_Action_Delegate bebone) \ No newline at end of file diff --git a/examples/core/input/0_input_keyboard/CMakeLists.txt b/examples/core/input/0_input_keyboard/CMakeLists.txt index 5a13e227..e2b8d36e 100644 --- a/examples/core/input/0_input_keyboard/CMakeLists.txt +++ b/examples/core/input/0_input_keyboard/CMakeLists.txt @@ -1,7 +1,7 @@ file(GLOB_RECURSE BEBONE_EXAMPLE_INPUT_0_KEYBOARD *.cpp) -include_directories("../../src") -include_directories(".") +include_directories("./") +include_directories(${BEBONE_INCLUDES}) add_executable(Bebone_Example_Input_0_Keyboard ${BEBONE_EXAMPLE_INPUT_0_KEYBOARD}) target_link_libraries(Bebone_Example_Input_0_Keyboard bebone) \ No newline at end of file diff --git a/examples/core/input/0_input_keyboard/main.cpp b/examples/core/input/0_input_keyboard/main.cpp index 1b906c2a..03b84450 100644 --- a/examples/core/input/0_input_keyboard/main.cpp +++ b/examples/core/input/0_input_keyboard/main.cpp @@ -1,30 +1,38 @@ #include "bebone/bebone.h" -const unsigned int SCR_WIDTH = 800; -const unsigned int SCR_HEIGHT = 600; +const unsigned int screen_width = 800; +const unsigned int screen_height = 600; using namespace bebone::gfx; -using namespace bebone::gfx::opengl; int main() { glfwInit(); - auto window = WindowFactory::create_window("0. Input example", SCR_WIDTH, SCR_HEIGHT, GfxAPI::OPENGL); + auto window = WindowFactory::create_window("0. Input example", screen_width, screen_height, OpenGL); GLContext::load_opengl(); - GLContext::set_viewport(0, 0, SCR_WIDTH, SCR_HEIGHT); + GLContext::set_viewport(0, 0, screen_width, screen_height); - std::function keyPress = []() { + std::function key_press = []() { std::cout << "key press\n"; }; - Input::get_instance().register_key_action(KeyCode::A, keyPress); + auto input = std::make_shared(); + auto input_executor = std::make_shared(input); + + KeyListener key_listener(input_executor); + MouseListener mouse_listener(input_executor); + + window->add_listener(key_listener); + window->add_listener(mouse_listener); + + input->register_key_action(KeyCode::A, key_press); while (!window->closing()) { GLContext::clear_color(0.2f, 0.2f, 0.2f, 1.0f); GLContext::clear(GL_COLOR_BUFFER_BIT); - window->execute_input_actions(); + input_executor->execute_input_actions(); glfwSwapBuffers(window->get_backend()); glfwPollEvents(); diff --git a/examples/core/input/1_input_utility_functions/CMakeLists.txt b/examples/core/input/1_input_utility_functions/CMakeLists.txt new file mode 100644 index 00000000..ff6c4337 --- /dev/null +++ b/examples/core/input/1_input_utility_functions/CMakeLists.txt @@ -0,0 +1,7 @@ +file(GLOB_RECURSE BEBONE_EXAMPLE_INPUT_1_UTILITY_FUNCTIONS *.cpp) + +include_directories("./") +include_directories(${BEBONE_INCLUDES}) + +add_executable(Bebone_Example_Input_1_Utility_Functions ${BEBONE_EXAMPLE_INPUT_1_UTILITY_FUNCTIONS}) +target_link_libraries(Bebone_Example_Input_1_Utility_Functions bebone) \ No newline at end of file diff --git a/examples/core/input/1_input_utility_functions/main.cpp b/examples/core/input/1_input_utility_functions/main.cpp new file mode 100644 index 00000000..c4a2f3af --- /dev/null +++ b/examples/core/input/1_input_utility_functions/main.cpp @@ -0,0 +1,50 @@ +#include "bebone/bebone.h" + +const unsigned int screen_width = 800; +const unsigned int screen_height = 600; + +using namespace bebone::gfx; + +int main() { + glfwInit(); + + auto window = WindowFactory::create_window("1. Input utility functions example", screen_width, screen_height, OpenGL); + + GLContext::load_opengl(); + GLContext::set_viewport(0, 0, screen_width, screen_height); + + auto input = std::make_shared(); + auto input_executor = std::make_shared(input); + + KeyListener key_listener(input_executor); + window->add_listener(key_listener); + + while (!window->closing()) { + GLContext::clear_color(0.2f, 0.2f, 0.2f, 1.0f); + GLContext::clear(GL_COLOR_BUFFER_BIT); + + if (input_executor->is_key_down(KeyCode::A)) { + std::cout << "key A is down\n"; + } + + if (input_executor->is_key_up(KeyCode::A)) { + std::cout << "key A is up\n"; + } + + if (input_executor->is_key_pressed(KeyCode::A)) { + std::cout << "Key A is pressed\n"; + } + + if (input_executor->is_key_released(KeyCode::A)) { + std::cout << "Key A is released\n"; + } + + input_executor->execute_input_actions(); + + glfwSwapBuffers(window->get_backend()); + glfwPollEvents(); + } + + glfwTerminate(); + return 0; +} diff --git a/examples/core/input/CMakeLists.txt b/examples/core/input/CMakeLists.txt index 1c4de317..391e9c63 100644 --- a/examples/core/input/CMakeLists.txt +++ b/examples/core/input/CMakeLists.txt @@ -1 +1,2 @@ -add_subdirectory(0_input_keyboard) \ No newline at end of file +add_subdirectory(0_input_keyboard) +add_subdirectory(1_input_utility_functions) \ No newline at end of file diff --git a/examples/gfx/CMakeLists.txt b/examples/gfx/CMakeLists.txt index fb0ee40e..3d486edc 100644 --- a/examples/gfx/CMakeLists.txt +++ b/examples/gfx/CMakeLists.txt @@ -1,3 +1,2 @@ add_subdirectory(vulkan) add_subdirectory(opengl) -add_subdirectory(begui) diff --git a/examples/gfx/begui/0_begui_node_graph/CMakeLists.txt b/examples/gfx/begui/0_begui_node_graph/CMakeLists.txt deleted file mode 100644 index 3dd60360..00000000 --- a/examples/gfx/begui/0_begui_node_graph/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -file(GLOB_RECURSE BEBONE_EXAMPLE_BEGUI_0_NODE_GRAPH *.cpp) - -include_directories("../../src") -include_directories(".") - -add_executable(Bebone_Example_Begui_0_Node_Graph ${BEBONE_EXAMPLE_BEGUI_0_NODE_GRAPH}) -target_link_libraries(Bebone_Example_Begui_0_Node_Graph bebone) \ No newline at end of file diff --git a/examples/gfx/begui/0_begui_node_graph/fragment.glsl b/examples/gfx/begui/0_begui_node_graph/fragment.glsl deleted file mode 100644 index a1b650a9..00000000 --- a/examples/gfx/begui/0_begui_node_graph/fragment.glsl +++ /dev/null @@ -1,9 +0,0 @@ -#version 450 core - -layout (location = 0) out vec4 FragColor; - -layout (location = 0) in vec3 outColor; - -void main() { - FragColor = vec4(outColor, 1.0f); -} \ No newline at end of file diff --git a/examples/gfx/begui/0_begui_node_graph/imgui_node_graph_test.h b/examples/gfx/begui/0_begui_node_graph/imgui_node_graph_test.h deleted file mode 100644 index 544546fb..00000000 --- a/examples/gfx/begui/0_begui_node_graph/imgui_node_graph_test.h +++ /dev/null @@ -1,220 +0,0 @@ -#include - -#define OMNI_TYPES_MATRIX_COLLUM_MAJOR_ORDER -#define OMNI_TYPES_MATRIX4X4_PROJECTION_MATRIX_INVERSE_Y_AXIS -#include "bebone/bebone.h" - -static inline ImVec2 operator+(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x + rhs.x, lhs.y + rhs.y); } -static inline ImVec2 operator-(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x - rhs.x, lhs.y - rhs.y); } - -void ShowExampleAppCustomNodeGraph(bool* opened) { - ImGui::SetNextWindowSize(ImVec2(700, 600), ImGuiCond_FirstUseEver); - if (!ImGui::Begin("Example: Custom Node Graph", opened)) { - ImGui::End(); - return; - } - - struct Node { - int ID; - std::string Name; - ImVec2 Pos, Size; - float Value; - ImVec4 Color; - int InputsCount, OutputsCount; - - Node(int id, std::string name, const ImVec2& pos, float value, const ImVec4& color, int inputs_count, int outputs_count) { - ID = id; - Name = name; - Pos = pos; - Value = value; - Color = color; - InputsCount = inputs_count; - OutputsCount = outputs_count; - } - - ImVec2 GetInputSlotPos(int slot_no) const { return ImVec2(Pos.x, Pos.y + Size.y * ((float)slot_no + 1) / ((float)InputsCount + 1)); } - ImVec2 GetOutputSlotPos(int slot_no) const { return ImVec2(Pos.x + Size.x, Pos.y + Size.y * ((float)slot_no + 1) / ((float)OutputsCount + 1)); } - }; - struct NodeLink { - int InputIdx; - int InputSlot; - int OutputIdx; - int OutputSlot; - - NodeLink(int input_idx, int input_slot, int output_idx, int output_slot) { InputIdx = input_idx; InputSlot = input_slot; OutputIdx = output_idx; OutputSlot = output_slot; } - }; - - static ImVector nodes; - static ImVector links; - static ImVec2 scrolling = ImVec2(0.0f, 0.0f); - static bool inited = false; - static bool show_grid = true; - static int node_selected = -1; - - // Initialization - ImGuiIO& io = ImGui::GetIO(); - if (!inited) { - nodes.push_back(Node(0, "MainTex", ImVec2(40, 50), 0.5f, ImColor(255, 100, 100), 1, 1)); - nodes.push_back(Node(1, "BumpMap", ImVec2(40, 150), 0.42f, ImColor(200, 100, 200), 1, 1)); - nodes.push_back(Node(2, "Combine", ImVec2(270, 80), 1.0f, ImColor(0, 200, 100), 2, 2)); - links.push_back(NodeLink(0, 0, 2, 0)); - links.push_back(NodeLink(1, 0, 2, 1)); - inited = true; - } - - // Draw a list of nodes on the left side - bool open_context_menu = false; - int node_hovered_in_list = -1; - int node_hovered_in_scene = -1; - ImGui::BeginChild("node_list", ImVec2(100, 0)); - ImGui::Text("Nodes"); - ImGui::Separator(); - for (int node_idx = 0; node_idx < nodes.Size; node_idx++) { - Node* node = &nodes[node_idx]; - ImGui::PushID(node->ID); - if (ImGui::Selectable(node->Name.c_str(), node->ID == node_selected)) - node_selected = node->ID; - if (ImGui::IsItemHovered()) { - node_hovered_in_list = node->ID; - open_context_menu |= ImGui::IsMouseClicked(1); - } - ImGui::PopID(); - } - ImGui::EndChild(); - - ImGui::SameLine(); - ImGui::BeginGroup(); - - const float NODE_SLOT_RADIUS = 4.0f; - const ImVec2 NODE_WINDOW_PADDING(8.0f, 8.0f); - - // Create our child canvas - ImGui::Text("Hold middle mouse button to scroll (%.2f,%.2f)", scrolling.x, scrolling.y); - ImGui::SameLine(ImGui::GetWindowWidth() - 100); - ImGui::Checkbox("Show grid", &show_grid); - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(1, 1)); - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0)); - ImGui::PushStyleColor(ImGuiCol_ChildBg, IM_COL32(60, 60, 70, 200)); - ImGui::BeginChild("scrolling_region", ImVec2(0, 0), true, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoMove); - ImGui::PopStyleVar(); // WindowPadding - ImGui::PushItemWidth(120.0f); - - const ImVec2 offset = ImGui::GetCursorScreenPos() + scrolling; - ImDrawList* draw_list = ImGui::GetWindowDrawList(); - - if (show_grid) { - ImU32 GRID_COLOR = IM_COL32(200, 200, 200, 40); - float GRID_SZ = 64.0f; - ImVec2 win_pos = ImGui::GetCursorScreenPos(); - ImVec2 canvas_sz = ImGui::GetWindowSize(); - for (float x = fmodf(scrolling.x, GRID_SZ); x < canvas_sz.x; x += GRID_SZ) - draw_list->AddLine(ImVec2(x, 0.0f) + win_pos, ImVec2(x, canvas_sz.y) + win_pos, GRID_COLOR); - for (float y = fmodf(scrolling.y, GRID_SZ); y < canvas_sz.y; y += GRID_SZ) - draw_list->AddLine(ImVec2(0.0f, y) + win_pos, ImVec2(canvas_sz.x, y) + win_pos, GRID_COLOR); - } - - draw_list->ChannelsSplit(2); - draw_list->ChannelsSetCurrent(0); // Background - for (int link_idx = 0; link_idx < links.Size; link_idx++) { - NodeLink* link = &links[link_idx]; - Node* node_inp = &nodes[link->InputIdx]; - Node* node_out = &nodes[link->OutputIdx]; - ImVec2 p1 = offset + node_inp->GetOutputSlotPos(link->InputSlot); - ImVec2 p2 = offset + node_out->GetInputSlotPos(link->OutputSlot); - - draw_list->AddBezierCubic(p1, p1 + ImVec2(+50, 0), p2 + ImVec2(-50, 0), p2, IM_COL32(200, 200, 100, 255), 3.0f); - // draw_list->AddLine(p1, p2, IM_COL32(200, 200, 100, 255), 3.0f); - } - - for (int node_idx = 0; node_idx < nodes.Size; node_idx++) { - Node* node = &nodes[node_idx]; - ImGui::PushID(node->ID); - ImVec2 node_rect_min = offset + node->Pos; - - // Display node contents first - draw_list->ChannelsSetCurrent(1); // Foreground - bool old_any_active = ImGui::IsAnyItemActive(); - ImGui::SetCursorScreenPos(node_rect_min + NODE_WINDOW_PADDING); - ImGui::BeginGroup(); // Lock horizontal position - ImGui::Text("%s", node->Name.c_str()); - ImGui::SliderFloat("##value", &node->Value, 0.0f, 1.0f, "Alpha %.2f"); - ImGui::ColorEdit3("##color", &node->Color.x); - ImGui::EndGroup(); - - // Save the size of what we have emitted and whether any of the widgets are being used - bool node_widgets_active = (!old_any_active && ImGui::IsAnyItemActive()); - node->Size = ImGui::GetItemRectSize() + NODE_WINDOW_PADDING + NODE_WINDOW_PADDING; - ImVec2 node_rect_max = node_rect_min + node->Size; - - // Display node box - draw_list->ChannelsSetCurrent(0); // Background - ImGui::SetCursorScreenPos(node_rect_min); - ImGui::InvisibleButton("node", node->Size); - if (ImGui::IsItemHovered()) { - node_hovered_in_scene = node->ID; - open_context_menu |= ImGui::IsMouseClicked(1); - } - bool node_moving_active = ImGui::IsItemActive(); - if (node_widgets_active || node_moving_active) - node_selected = node->ID; - if (node_moving_active && ImGui::IsMouseDragging(ImGuiMouseButton_Left)) - node->Pos = node->Pos + io.MouseDelta; - - ImU32 node_bg_color = (node_hovered_in_list == node->ID || node_hovered_in_scene == node->ID || (node_hovered_in_list == -1 && node_selected == node->ID)) ? IM_COL32(75, 75, 75, 255) : IM_COL32(60, 60, 60, 255); - draw_list->AddRectFilled(node_rect_min, node_rect_max, node_bg_color, 4.0f); - draw_list->AddRect(node_rect_min, node_rect_max, IM_COL32(100, 100, 100, 255), 4.0f); - for (int slot_idx = 0; slot_idx < node->InputsCount; slot_idx++) - draw_list->AddCircleFilled(offset + node->GetInputSlotPos(slot_idx), NODE_SLOT_RADIUS, IM_COL32(150, 150, 150, 150)); - for (int slot_idx = 0; slot_idx < node->OutputsCount; slot_idx++) - draw_list->AddCircleFilled(offset + node->GetOutputSlotPos(slot_idx), NODE_SLOT_RADIUS, IM_COL32(150, 150, 150, 150)); - - ImGui::PopID(); - } - draw_list->ChannelsMerge(); - - // Open context menu - if (ImGui::IsMouseReleased(ImGuiMouseButton_Right)) - if (ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup) || !ImGui::IsAnyItemHovered()) { - node_selected = node_hovered_in_list = node_hovered_in_scene = -1; - open_context_menu = true; - } - if (open_context_menu) { - ImGui::OpenPopup("context_menu"); - if (node_hovered_in_list != -1) - node_selected = node_hovered_in_list; - if (node_hovered_in_scene != -1) - node_selected = node_hovered_in_scene; - } - - // Draw context menu - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(8, 8)); - if (ImGui::BeginPopup("context_menu")) - { - Node* node = node_selected != -1 ? &nodes[node_selected] : NULL; - ImVec2 scene_pos = ImGui::GetMousePosOnOpeningCurrentPopup() - offset; - - if (node) { - ImGui::Text("Node '%s'", node->Name.c_str()); - ImGui::Separator(); - if (ImGui::MenuItem("Rename..", NULL, false, false)) {} - if (ImGui::MenuItem("Delete", NULL, false, false)) {} - if (ImGui::MenuItem("Copy", NULL, false, false)) {} - } else { - if (ImGui::MenuItem("Add")) { nodes.push_back(Node(nodes.Size, "New node", scene_pos, 0.5f, ImColor(100, 100, 200), 2, 2)); } - if (ImGui::MenuItem("Paste", NULL, false, false)) {} - } - ImGui::EndPopup(); - } - ImGui::PopStyleVar(); - - if (ImGui::IsWindowHovered() && !ImGui::IsAnyItemActive() && ImGui::IsMouseDragging(ImGuiMouseButton_Middle, 0.0f)) - scrolling = scrolling + io.MouseDelta; - - ImGui::PopItemWidth(); - ImGui::EndChild(); - ImGui::PopStyleColor(); - ImGui::PopStyleVar(); - ImGui::EndGroup(); - - ImGui::End(); -} diff --git a/examples/gfx/begui/0_begui_node_graph/main.cpp b/examples/gfx/begui/0_begui_node_graph/main.cpp deleted file mode 100644 index a3a58fac..00000000 --- a/examples/gfx/begui/0_begui_node_graph/main.cpp +++ /dev/null @@ -1,71 +0,0 @@ -#include "imgui_node_graph_test.h" - -const unsigned int SCR_WIDTH = 800; -const unsigned int SCR_HEIGHT = 600; - -using namespace bebone::gfx; -using namespace bebone::gfx::opengl; - -int main() { - BEBONE_PROFILE_RECORD(MAIN) - - GLFWContext::init(); - - auto window = WindowFactory::create_window("0. Begui Node graph example", SCR_WIDTH, SCR_HEIGHT, GfxAPI::OPENGL); - - window->add_listener([&](InputKeyEvent& event) { - if(event.key == GLFW_KEY_ENTER && event.action == GLFW_RELEASE) { - BEBONE_PROFILE_RECORD(EVENT) - - std::cout << "Called event !\n"; - - BEBONE_PROFILE_STOP(EVENT) - } - }); - - GLContext::load_opengl(); - GLContext::set_viewport(0, 0, SCR_WIDTH, SCR_HEIGHT); - glfwSwapInterval(0); - - auto vertexShader = GLShaderFactory::create_shader("vertex.glsl", ShaderTypes::VERTEX_SHADER); - auto fragmentShader = GLShaderFactory::create_shader("fragment.glsl", ShaderTypes::FRAGMENT_SHADER); - GLShaderProgram shaderProgram(vertexShader, fragmentShader); - - vertexShader.destroy(); - fragmentShader.destroy(); - - GLContext::enable(GL_DEPTH_TEST); - - BeGUI::init(window); - - while (!window->closing()) { - BEBONE_PROFILE_RECORD(LOOP) - - BEBONE_PROFILE_RECORD(CLEAR) - GLContext::clear_color(0.2f, 0.2f, 0.2f, 1.0f); - GLContext::clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - BEBONE_PROFILE_STOP(CLEAR) - - BEBONE_PROFILE_RECORD(BEGUI) - BeGUI::begin(); - ShowExampleAppCustomNodeGraph(nullptr); - ImGui::ShowDemoWindow(); - BeGUI::show_profiler(); - BeGUI::end(); - BEBONE_PROFILE_STOP(BEGUI) - - GLFWContext::swap_buffers(*window); // Todo make this not a reference - GLFWContext::poll_events(); - - BEBONE_PROFILE_STOP(LOOP) - } - - shaderProgram.destroy(); - - GLFWContext::terminate(); - - BEBONE_PROFILE_STOP(MAIN) - std::cout << BEBONE_PROFILER_SUM_UP() << "\n"; - - return 0; -} diff --git a/examples/gfx/begui/0_begui_node_graph/vertex.glsl b/examples/gfx/begui/0_begui_node_graph/vertex.glsl deleted file mode 100644 index e94b6d3a..00000000 --- a/examples/gfx/begui/0_begui_node_graph/vertex.glsl +++ /dev/null @@ -1,22 +0,0 @@ -#version 450 core - -layout (location = 0) in vec3 aPos; -layout (location = 1) in vec3 aColor; - -layout (location = 0) out vec3 outColor; - -layout(binding = 0) uniform Transform { - mat4 translation; - mat4 scale; - mat4 rotation; -}; - -layout(binding = 1) uniform Camera { - mat4 proj; - mat4 view; -}; - -void main() { - gl_Position = proj * view * translation * rotation * scale * vec4(aPos, 1.0); - outColor = aColor; -} \ No newline at end of file diff --git a/examples/gfx/begui/CMakeLists.txt b/examples/gfx/begui/CMakeLists.txt deleted file mode 100644 index 9fc74fcd..00000000 --- a/examples/gfx/begui/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ -add_subdirectory(0_begui_node_graph) \ No newline at end of file diff --git a/examples/gfx/opengl/0_opengl_window/CMakeLists.txt b/examples/gfx/opengl/0_opengl_window/CMakeLists.txt index 25521bd8..df0f2e6d 100644 --- a/examples/gfx/opengl/0_opengl_window/CMakeLists.txt +++ b/examples/gfx/opengl/0_opengl_window/CMakeLists.txt @@ -1,7 +1,7 @@ file(GLOB_RECURSE BEBONE_EXAMPLE_GFX_OPENGL_0_OPENGL_WINDOW *.cpp) -include_directories("../../src") include_directories("./") +include_directories(${BEBONE_INCLUDES}) add_executable(Bebone_Example_Gfx_0_Opengl_Window ${BEBONE_EXAMPLE_GFX_OPENGL_0_OPENGL_WINDOW}) target_link_libraries(Bebone_Example_Gfx_0_Opengl_Window bebone) \ No newline at end of file diff --git a/examples/gfx/opengl/0_opengl_window/main.cpp b/examples/gfx/opengl/0_opengl_window/main.cpp index 2185161a..07bef287 100644 --- a/examples/gfx/opengl/0_opengl_window/main.cpp +++ b/examples/gfx/opengl/0_opengl_window/main.cpp @@ -1,27 +1,30 @@ #include "bebone/bebone.h" -const unsigned int SCR_WIDTH = 800; -const unsigned int SCR_HEIGHT = 600; +const unsigned int screen_width = 800; +const unsigned int screen_height = 600; using namespace bebone::gfx; -using namespace bebone::gfx::opengl; int main() { - GLFWContext::init(); - - auto window = WindowFactory::create_window("0. OpenGL window example", SCR_WIDTH, SCR_HEIGHT, GfxAPI::OPENGL); + LOG_TRACE("Test message"); + LOG_DEBUG("Test message"); + LOG_INFORMATION("Test message"); + LOG_WARNING("Test message"); + LOG_ERROR("Test message"); + LOG_CRITICAL("Test message"); + + auto window = WindowFactory::create_window("0. OpenGL window example", screen_width, screen_height, OpenGL); GLContext::load_opengl(); - GLContext::set_viewport(0, 0, SCR_WIDTH, SCR_HEIGHT); + GLContext::set_viewport(0, 0, screen_width, screen_height); while (!window->closing()) { GLContext::clear_color(0.2f, 0.2f, 0.2f, 1.0f); GLContext::clear(GL_COLOR_BUFFER_BIT); GLFWContext::swap_buffers(*window); - GLFWContext::poll_events(); + window->pull_events(); } - GLFWContext::terminate(); return 0; } diff --git a/examples/gfx/opengl/1_opengl_hello_triangle/CMakeLists.txt b/examples/gfx/opengl/1_opengl_hello_triangle/CMakeLists.txt index 199ffbb4..68c2f69f 100644 --- a/examples/gfx/opengl/1_opengl_hello_triangle/CMakeLists.txt +++ b/examples/gfx/opengl/1_opengl_hello_triangle/CMakeLists.txt @@ -1,7 +1,7 @@ file(GLOB_RECURSE BEBONE_EXAMPLE_GFX_OPENGL_1_OPENGL_HELLO_TRIANGLE *.cpp) -include_directories("../../src") include_directories("./") +include_directories(${BEBONE_INCLUDES}) add_executable(Bebone_Example_Gfx_1_Opengl_Hello_Triangle ${BEBONE_EXAMPLE_GFX_OPENGL_1_OPENGL_HELLO_TRIANGLE}) target_link_libraries(Bebone_Example_Gfx_1_Opengl_Hello_Triangle bebone) \ No newline at end of file diff --git a/examples/gfx/opengl/1_opengl_hello_triangle/fragment.glsl b/examples/gfx/opengl/1_opengl_hello_triangle/fragment.glsl index 119963d8..8904deb8 100644 --- a/examples/gfx/opengl/1_opengl_hello_triangle/fragment.glsl +++ b/examples/gfx/opengl/1_opengl_hello_triangle/fragment.glsl @@ -1,7 +1,7 @@ #version 450 core -layout (location = 0) out vec4 FragColor; +layout (location = 0) out vec4 out_color; void main() { - FragColor = vec4(0.6f, 0.9f, 0.6f, 1.0f); + out_color = vec4(0.6f, 0.9f, 0.6f, 1.0f); } diff --git a/examples/gfx/opengl/1_opengl_hello_triangle/main.cpp b/examples/gfx/opengl/1_opengl_hello_triangle/main.cpp index cbe7de52..31382600 100644 --- a/examples/gfx/opengl/1_opengl_hello_triangle/main.cpp +++ b/examples/gfx/opengl/1_opengl_hello_triangle/main.cpp @@ -2,36 +2,26 @@ #include "bebone/bebone.h" -const unsigned int SCR_WIDTH = 800; -const unsigned int SCR_HEIGHT = 600; +const unsigned int screen_width = 800; +const unsigned int screen_height = 600; using namespace bebone::gfx; -using namespace bebone::gfx::opengl; -const std::vector vertices = { - {-0.5f, -0.5f, 0.0f}, - {0.5f, -0.5f, 0.0f}, - {0.0f, 0.5f, 0.0f} -}; - -const std::vector indices = { - 0, 1, 2, -}; +const std::vector vertices = { {-0.5f, -0.5f, 0.0f}, {0.5f, -0.5f, 0.0f}, {0.0f, 0.5f, 0.0f} }; +const std::vector indices = { 0, 1, 2, }; int main() { - GLFWContext::init(); - - auto window = WindowFactory::create_window("1. OpenGL hello triangle example", SCR_WIDTH, SCR_HEIGHT, GfxAPI::OPENGL); + auto window = WindowFactory::create_window("1. OpenGL hello triangle example", screen_width, screen_height, OpenGL); GLContext::load_opengl(); - GLContext::set_viewport(0, 0, SCR_WIDTH, SCR_HEIGHT); + GLContext::set_viewport(0, 0, screen_width, screen_height); - GLShader vertexShader = GLShaderFactory::create_shader("vertex.glsl", ShaderTypes::VERTEX_SHADER); - GLShader fragmentShader = GLShaderFactory::create_shader("fragment.glsl", ShaderTypes::FRAGMENT_SHADER); - GLShaderProgram shaderProgram(vertexShader, fragmentShader); + GLShader vertex_shader = GLShaderFactory::create_shader("vertex.glsl", ShaderType::VertexShader); + GLShader fragment_shader = GLShaderFactory::create_shader("fragment.glsl", ShaderType::FragmentShader); + GLShaderProgram shader_program(vertex_shader, fragment_shader); - vertexShader.destroy(); - fragmentShader.destroy(); + vertex_shader.destroy(); + fragment_shader.destroy(); GLVertexArrayObject vao; vao.bind(); @@ -45,24 +35,25 @@ int main() { vbo.unbind(); ebo.unbind(); + GLContext::disable(GL_DEPTH_TEST); + while(!window->closing()) { GLContext::clear_color(0.2f, 0.2f, 0.2f, 1.0f); GLContext::clear(GL_COLOR_BUFFER_BIT); - shaderProgram.enable(); + shader_program.enable(); vao.bind(); GLContext::draw_arrays(GL_TRIANGLES, 0, 3); glfwSwapBuffers(window->get_backend()); - GLFWContext::poll_events(); + window->pull_events(); } vao.destroy(); vbo.destroy(); ebo.destroy(); - shaderProgram.destroy(); + shader_program.destroy(); - GLFWContext::terminate(); return 0; } diff --git a/examples/gfx/opengl/2_opengl_texture/CMakeLists.txt b/examples/gfx/opengl/2_opengl_texture/CMakeLists.txt index d407252e..ec321f73 100644 --- a/examples/gfx/opengl/2_opengl_texture/CMakeLists.txt +++ b/examples/gfx/opengl/2_opengl_texture/CMakeLists.txt @@ -1,7 +1,7 @@ file(GLOB_RECURSE BEBONE_EXAMPLE_GFX_OPENGL_2_OPENGL_TEXTURE *.cpp) -include_directories("../../src") include_directories("./") +include_directories(${BEBONE_INCLUDES}) add_executable(Bebone_Example_Gfx_2_Opengl_Texture ${BEBONE_EXAMPLE_GFX_OPENGL_2_OPENGL_TEXTURE}) target_link_libraries(Bebone_Example_Gfx_2_Opengl_Texture bebone) \ No newline at end of file diff --git a/examples/gfx/opengl/2_opengl_texture/fragment.glsl b/examples/gfx/opengl/2_opengl_texture/fragment.glsl index 84667cb0..469169d5 100644 --- a/examples/gfx/opengl/2_opengl_texture/fragment.glsl +++ b/examples/gfx/opengl/2_opengl_texture/fragment.glsl @@ -2,7 +2,6 @@ layout (location = 0) out vec4 FragColor; -layout (location = 0) in vec3 ourColor; layout (location = 1) in vec2 TexCoord; layout (binding = 0) uniform sampler2D ourTexture; diff --git a/examples/gfx/opengl/2_opengl_texture/main.cpp b/examples/gfx/opengl/2_opengl_texture/main.cpp index db14ee38..428b903b 100644 --- a/examples/gfx/opengl/2_opengl_texture/main.cpp +++ b/examples/gfx/opengl/2_opengl_texture/main.cpp @@ -2,44 +2,37 @@ #include -const unsigned int SCR_WIDTH = 800; -const unsigned int SCR_HEIGHT = 600; +const unsigned int screen_width = 800; +const unsigned int screen_height = 600; using namespace bebone::gfx; -using namespace bebone::gfx::opengl; struct Vertex { Vec3f pos; - Vec3f color; - Vec2f texCord; + Vec2f tex_coords; }; const std::vector vertices { - {{0.5f, 0.5f, 0.0f}, {1.0f, 0.0f, 0.0f}, {1.0f, 1.0f}}, - {{0.5f, -0.5f, 0.0f}, {0.0f, 1.0f, 0.0f}, {1.0f, 0.0f}}, - {{-0.5f, -0.5f, 0.0f}, {0.0f, 0.0f, 1.0f}, {0.0f, 0.0f}}, - {{-0.5f, 0.5f, 0.0f}, {1.0f, 1.0f, 0.0f}, {0.0f, 1.0f}} + {{0.5f, 0.5f, 0.0f}, {1.0f, 1.0f}}, + {{0.5f, -0.5f, 0.0f}, {1.0f, 0.0f}}, + {{-0.5f, -0.5f, 0.0f}, {0.0f, 0.0f}}, + {{-0.5f, 0.5f, 0.0f}, {0.0f, 1.0f}} }; -const std::vector indices { - 0, 1, 3, - 1, 2, 3 -}; +const std::vector indices { 0, 3, 1, 3, 2, 1 }; int main() { - GLFWContext::init(); - - auto window = WindowFactory::create_window("2. OpenGL texture example", SCR_WIDTH, SCR_HEIGHT, GfxAPI::OPENGL); + auto window = WindowFactory::create_window("2. OpenGL texture example", screen_width, screen_height, OpenGL); GLContext::load_opengl(); - GLContext::set_viewport(0, 0, SCR_WIDTH, SCR_HEIGHT); + GLContext::set_viewport(0, 0, screen_width, screen_height); - auto vertexShader = GLShaderFactory::create_shader("vertex.glsl", ShaderTypes::VERTEX_SHADER); - auto fragmentShader = GLShaderFactory::create_shader("fragment.glsl", ShaderTypes::FRAGMENT_SHADER); - GLShaderProgram shaderProgram(vertexShader, fragmentShader); + auto vertex_shader = GLShaderFactory::create_shader("vertex.glsl", ShaderType::VertexShader); + auto fragment_shader = GLShaderFactory::create_shader("fragment.glsl", ShaderType::FragmentShader); + GLShaderProgram shader_program(vertex_shader, fragment_shader); - vertexShader.destroy(); - fragmentShader.destroy(); + vertex_shader.destroy(); + fragment_shader.destroy(); GLVertexArrayObject vao; vao.bind(); @@ -48,26 +41,22 @@ int main() { GLElementBufferObject ebo(indices.data(), indices.size() * sizeof(u32)); vao.link_attributes(vbo, 0, 3, GL_FLOAT, sizeof(Vertex), offsetof(Vertex, pos)); - vao.link_attributes(vbo, 1, 3, GL_FLOAT, sizeof(Vertex), offsetof(Vertex, color)); - vao.link_attributes(vbo, 2, 2, GL_FLOAT, sizeof(Vertex), offsetof(Vertex, texCord)); + vao.link_attributes(vbo, 1, 2, GL_FLOAT, sizeof(Vertex), offsetof(Vertex, tex_coords)); vao.unbind(); vbo.unbind(); ebo.unbind(); GLTexture2D texture("image.png"); + shader_program.set_uniform("ourTexture", 0); - shaderProgram.set_uniform("ourTexture", 0); - - GLContext::enable(GL_CULL_FACE); - GLContext::cull_face(GL_BACK); - GLContext::front_face(GL_CW); + GLContext::disable(GL_DEPTH_TEST); while (!window->closing()) { GLContext::clear_color(0.2f, 0.2f, 0.2f, 1.0f); GLContext::clear(GL_COLOR_BUFFER_BIT); - shaderProgram.enable(); + shader_program.enable(); texture.bind(); vao.bind(); @@ -75,10 +64,8 @@ int main() { GLContext::draw_elements(GL_TRIANGLES, static_cast(indices.size()), GL_UNSIGNED_INT, nullptr); glfwSwapBuffers(window->get_backend()); - GLFWContext::poll_events(); + window->pull_events(); } - GLFWContext::terminate(); - return 0; } diff --git a/examples/gfx/opengl/2_opengl_texture/vertex.glsl b/examples/gfx/opengl/2_opengl_texture/vertex.glsl index 35f0ac1b..d49b9afe 100644 --- a/examples/gfx/opengl/2_opengl_texture/vertex.glsl +++ b/examples/gfx/opengl/2_opengl_texture/vertex.glsl @@ -1,14 +1,11 @@ #version 450 core layout (location = 0) in vec3 aPos; -layout (location = 1) in vec3 aColor; -layout (location = 2) in vec2 aTexCoord; +layout (location = 1) in vec2 aTexCoord; -layout (location = 0) out vec3 ourColor; layout (location = 1) out vec2 TexCoord; void main() { gl_Position = vec4(aPos, 1.0); - ourColor = aColor; TexCoord = aTexCoord; } \ No newline at end of file diff --git a/examples/gfx/opengl/3_opengl_3d_cube/CMakeLists.txt b/examples/gfx/opengl/3_opengl_3d_cube/CMakeLists.txt index 88373d09..2721dfff 100644 --- a/examples/gfx/opengl/3_opengl_3d_cube/CMakeLists.txt +++ b/examples/gfx/opengl/3_opengl_3d_cube/CMakeLists.txt @@ -1,7 +1,7 @@ file(GLOB_RECURSE BEBONE_EXAMPLE_GFX_OPENGL_3_OPENGL_3D_CUBE *.cpp) -include_directories("../../src") include_directories("./") +include_directories(${BEBONE_INCLUDES}) add_executable(Bebone_Example_Gfx_3_Opengl_3D_Cube ${BEBONE_EXAMPLE_GFX_OPENGL_3_OPENGL_3D_CUBE}) target_link_libraries(Bebone_Example_Gfx_3_Opengl_3D_Cube bebone) \ No newline at end of file diff --git a/examples/gfx/opengl/3_opengl_3d_cube/main.cpp b/examples/gfx/opengl/3_opengl_3d_cube/main.cpp index f7a5aa8f..ef23fffc 100644 --- a/examples/gfx/opengl/3_opengl_3d_cube/main.cpp +++ b/examples/gfx/opengl/3_opengl_3d_cube/main.cpp @@ -1,126 +1,111 @@ -#include - -#define OMNI_TYPES_MATRIX_COLLUM_MAJOR_ORDER -#define OMNI_TYPES_MATRIX4X4_PROJECTION_MATRIX_INVERSE_Y_AXIS -#include "bebone/bebone.h" - -const unsigned int SCR_WIDTH = 800; -const unsigned int SCR_HEIGHT = 600; - -using namespace bebone::gfx; -using namespace bebone::gfx::opengl; - -struct Vertex { - Vec3f pos; - ColorRGBA color; -}; - -const std::vector vertices { - {{-1.0, -1.0, 1.0}, ColorRGBA::WHITE }, - {{ 1.0, -1.0, 1.0}, ColorRGBA::YELLOW }, - {{ 1.0, 1.0, 1.0}, ColorRGBA::MAGENTA}, - {{-1.0, 1.0, 1.0}, ColorRGBA::RED }, - {{-1.0, -1.0, -1.0}, ColorRGBA::CYAN }, - {{ 1.0, -1.0, -1.0}, ColorRGBA::GREEN }, - {{ 1.0, 1.0, -1.0}, ColorRGBA::BLUE }, - {{-1.0, 1.0, -1.0}, ColorRGBA::BLACK } -}; - -const std::vector indices { - 0, 1, 2, 2, 3, 0, - 1, 5, 6, 6, 2, 1, - 7, 6, 5, 5, 4, 7, - 4, 0, 3, 3, 7, 4, - 4, 5, 1, 1, 0, 4, - 3, 2, 6, 6, 7, 3 -}; - -struct Transform { - Mat4f translation; - Mat4f scale; - Mat4f rotation; -}; - -struct Camera { - Mat4f proj; - Mat4f view; -}; - -int main() { - glfwInit(); - - auto window = WindowFactory::create_window("3. OpenGL 3D cube example", SCR_WIDTH, SCR_HEIGHT, GfxAPI::OPENGL); - - GLContext::load_opengl(); - GLContext::set_viewport(0, 0, SCR_WIDTH, SCR_HEIGHT); - - auto vertexShader = GLShaderFactory::create_shader("vertex.glsl", ShaderTypes::VERTEX_SHADER); - auto fragmentShader = GLShaderFactory::create_shader("fragment.glsl", ShaderTypes::FRAGMENT_SHADER); - GLShaderProgram shaderProgram(vertexShader, fragmentShader); - - vertexShader.destroy(); - fragmentShader.destroy(); - - GLVertexArrayObject vao; - vao.bind(); - - GLVertexBufferObject vbo(vertices.data(), vertices.size() * sizeof(Vertex)); - GLElementBufferObject ebo(indices.data(), indices.size() * sizeof(u32)); - - vao.link_attributes(vbo, 0, 3, GL_FLOAT, sizeof(Vertex), offsetof(Vertex, pos)); - vao.link_attributes(vbo, 1, 4, GL_FLOAT, sizeof(Vertex), offsetof(Vertex, color)); - - vao.unbind(); - vbo.unbind(); - ebo.unbind(); - - GLUniformBufferObject transformUbo(sizeof(Transform)); - GLUniformBufferObject cameraUbo(sizeof(Camera)); - - transformUbo.bind(); - shaderProgram.bind_buffer("Transform", 0, transformUbo); - auto transformPtr = static_cast(transformUbo.map()); - transformPtr->translation = Mat4f::translation(Vec3f::zero); - transformPtr->scale = Mat4f::identity(); - - cameraUbo.bind(); - shaderProgram.bind_buffer("Camera", 1, cameraUbo); - auto cameraPtr = static_cast(cameraUbo.map()); - cameraPtr->proj = Mat4f::perspective(1, window->get_aspect(), 0.1f, 100.0f); - cameraPtr->view = Mat4f::translation(Vec3f(0, 0, 5)); - cameraUbo.unmap(); - cameraUbo.unbind(); - - GLContext::enable(GL_DEPTH_TEST); - - f32 t = 0.0f; - while (!window->closing()) { - ++t; - - GLContext::clear_color(0.2f, 0.2f, 0.2f, 1.0f); - GLContext::clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - transformPtr->rotation = trait_bryan_angle_yxz(Vec3f(t * 0.01f, t * 0.01f, 0.0f)); - - shaderProgram.enable(); - - vao.bind(); - - GLContext::draw_elements(GL_TRIANGLES, static_cast(indices.size()), GL_UNSIGNED_INT, nullptr); - - GLFWContext::swap_buffers(*window); - GLFWContext::poll_events(); - } - - transformUbo.unmap(); - transformUbo.unbind(); - - vao.destroy(); - vbo.destroy(); - ebo.destroy(); - shaderProgram.destroy(); - - GLFWContext::terminate(); - - return 0; -} +#include +#include "bebone/bebone.h" + +const unsigned int screen_width = 800; +const unsigned int screen_height = 600; + +using namespace bebone::gfx; + +struct Vertex { + Vec3f pos; + ColorRGBA color; +}; + +const vector vertices { + {{ -1.0, -1.0, 1.0 }, ColorRGBA::WHITE }, + {{ 1.0, -1.0, 1.0 }, ColorRGBA::YELLOW }, + {{ 1.0, 1.0, 1.0 }, ColorRGBA::MAGENTA}, + {{ -1.0, 1.0, 1.0 }, ColorRGBA::RED }, + {{ -1.0, -1.0, -1.0 }, ColorRGBA::CYAN }, + {{ 1.0, -1.0, -1.0 }, ColorRGBA::GREEN }, + {{ 1.0, 1.0, -1.0 }, ColorRGBA::BLUE }, + {{ -1.0, 1.0, -1.0 }, ColorRGBA::BLACK } +}; + +const vector indices { + 0, 1, 2, 2, 3, 0, 1, 5, 6, 6, 2, 1, 7, 6, 5, 5, 4, 7, 4, 0, 3, 3, 7, 4, 4, 5, 1, 1, 0, 4, 3, 2, 6, 6, 7, 3 +}; + +struct Transform { + Mat4f translation; + Mat4f rotation; +}; + +int main() { + glfwInit(); + + auto window = WindowFactory::create_window("3. OpenGL 3D cube example", screen_width, screen_height, OpenGL); + + GLContext::load_opengl(); + GLContext::set_viewport(0, 0, screen_width, screen_height); + + auto vertex_shader = GLShaderFactory::create_shader("vertex.glsl", ShaderType::VertexShader); + auto fragment_shader = GLShaderFactory::create_shader("fragment.glsl", ShaderType::FragmentShader); + GLShaderProgram shader_program(vertex_shader, fragment_shader); + + vertex_shader.destroy(); + fragment_shader.destroy(); + + GLVertexArrayObject vao; + vao.bind(); + + GLVertexBufferObject vbo(vertices.data(), vertices.size() * sizeof(Vertex)); + GLElementBufferObject ebo(indices.data(), indices.size() * sizeof(u32)); + + vao.link_attributes(vbo, 0, 3, GL_FLOAT, sizeof(Vertex), offsetof(Vertex, pos)); + vao.link_attributes(vbo, 1, 4, GL_FLOAT, sizeof(Vertex), offsetof(Vertex, color)); + + vao.unbind(); + vbo.unbind(); + ebo.unbind(); + + GLUniformBufferObject transform_ubo(sizeof(Mat4f)); + GLUniformBufferObject camera_ubo(sizeof(Mat4f)); + + auto transform = Transform {}; + transform.translation = Mat4f::translation(Vec3f(0.0f, 0.0f, 10.0f)); + transform.rotation = Mat4f::identity(); + + transform_ubo.bind(); + shader_program.bind_buffer("Transform", 0, transform_ubo); + auto transform_ptr = static_cast(transform_ubo.map()); + *transform_ptr = transform.translation * transform.rotation; + + camera_ubo.bind(); + shader_program.bind_buffer("Camera", 1, camera_ubo); + auto camera_ptr = static_cast(camera_ubo.map()); + *camera_ptr = Mat4f::perspective(1, window->get_aspect(), 0.1f, 100.0f) * Mat4f::look_at(Vec3f(0, 0, -10.0f), Vec3f(0.0f, 0.0f, 0.0f), Vec3f::up); + camera_ubo.unmap(); + camera_ubo.unbind(); + + while (!window->closing()) { + GLContext::clear_color(0.2f, 0.2f, 0.2f, 1.0f); + GLContext::clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + const auto t = static_cast(Time::get_seconds_elapsed()); + transform.rotation = trait_bryan_angle_yxz(Vec3f(t, t, 0.0f)); + *transform_ptr = transform.translation * transform.rotation; + + auto time = Time::get_seconds_elapsed(); + auto pos = Vec3f((sin(time)) * 5.0f, 0.0f, (sin(time)) * 5.0f); + transform.translation = Mat4f::translation(pos); + + shader_program.enable(); + vao.bind(); + + GLContext::draw_elements(GL_TRIANGLES, static_cast(indices.size()), GL_UNSIGNED_INT, nullptr); + + GLFWContext::swap_buffers(*window); + window->pull_events(); + } + + transform_ubo.unmap(); + transform_ubo.unbind(); + + vao.destroy(); + vbo.destroy(); + ebo.destroy(); + shader_program.destroy(); + + return 0; +} diff --git a/examples/gfx/opengl/3_opengl_3d_cube/vertex.glsl b/examples/gfx/opengl/3_opengl_3d_cube/vertex.glsl index dabbf589..906ceec1 100644 --- a/examples/gfx/opengl/3_opengl_3d_cube/vertex.glsl +++ b/examples/gfx/opengl/3_opengl_3d_cube/vertex.glsl @@ -5,18 +5,10 @@ layout (location = 1) in vec4 aColor; layout (location = 0) out vec4 outColor; -layout(binding = 0) uniform Transform { - mat4 translation; - mat4 scale; - mat4 rotation; -}; - -layout(binding = 1) uniform Camera { - mat4 proj; - mat4 view; -}; +layout(binding = 0) uniform Transform { mat4 transform; }; +layout(binding = 1) uniform Camera { mat4 cam; }; void main() { - gl_Position = proj * view * translation * rotation * scale * vec4(aPos, 1.0); + gl_Position = cam * transform * vec4(aPos, 1.0); outColor = aColor; } \ No newline at end of file diff --git a/examples/gfx/opengl/4_opengl_bexel/CMakeLists.txt b/examples/gfx/opengl/4_opengl_bexel/CMakeLists.txt index 76254437..f2b1f605 100644 --- a/examples/gfx/opengl/4_opengl_bexel/CMakeLists.txt +++ b/examples/gfx/opengl/4_opengl_bexel/CMakeLists.txt @@ -1,7 +1,7 @@ file(GLOB_RECURSE BEBONE_EXAMPLE_GFX_OPENGL_4_OPENGL_BEXEL *.cpp) -include_directories("../../src") include_directories("./") +include_directories(${BEBONE_INCLUDES}) add_executable(Bebone_Example_Gfx_4_Opengl_Bexel ${BEBONE_EXAMPLE_GFX_OPENGL_4_OPENGL_BEXEL}) target_link_libraries(Bebone_Example_Gfx_4_Opengl_Bexel bebone) diff --git a/examples/gfx/opengl/4_opengl_bexel/bebone.h b/examples/gfx/opengl/4_opengl_bexel/bebone.h deleted file mode 100644 index a7f83546..00000000 --- a/examples/gfx/opengl/4_opengl_bexel/bebone.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef BEBONE_H -#define BEBONE_H - -#define OMNI_TYPES_MATRIX_COLLUM_MAJOR_ORDER -// #define OMNI_TYPES_MATRIX4X4_PROJECTION_MATRIX_INVERSE_Y_AXIS -#include "bebone/bebone.h" - -#endif diff --git a/examples/gfx/opengl/4_opengl_bexel/bexel.cpp b/examples/gfx/opengl/4_opengl_bexel/bexel.cpp index cb165eb0..6aec6c29 100644 --- a/examples/gfx/opengl/4_opengl_bexel/bexel.cpp +++ b/examples/gfx/opengl/4_opengl_bexel/bexel.cpp @@ -1,85 +1,60 @@ #include "bexel.h" namespace bexel { - Bexel::Bexel() : m_window(nullptr), m_shader(nullptr), m_world(nullptr) { + Bexel::Bexel() : window(nullptr), shader(nullptr), world(nullptr) { } void Bexel::init() { - BEBONE_PROFILE_RECORD(BEXEL_INIT) - - GLFWContext::init(); - - m_window = WindowFactory::create_window("4. Opengl Bexel example", GAME_WIDTH, GAME_HEIGHT, GfxAPI::OPENGL, { - .enableResize = true + window = WindowFactory::create_window("4. Opengl Bexel example", game_width, game_height, OpenGL, { + .enable_resize = true }); GLContext::load_opengl(); glfwSwapInterval(0); - - BEBONE_PROFILE_STOP(BEXEL_INIT) } void Bexel::load() { - BEBONE_PROFILE_RECORD(BEXEL_LOAD) + const auto shader_flags = EnableUniforms; - const auto shaderFlags = ENABLE_UNIFORMS; + auto vertex_shader = GLShaderFactory::create_shader("assets/vertex.glsl", ShaderType::VertexShader, shader_flags); + auto fragment_shader = GLShaderFactory::create_shader("assets/fragment.glsl", ShaderType::FragmentShader, shader_flags); - auto vertexShader = GLShaderFactory::create_shader("assets/vertex.glsl", ShaderTypes::VERTEX_SHADER, shaderFlags); - auto fragmentShader = GLShaderFactory::create_shader("assets/fragment.glsl", ShaderTypes::FRAGMENT_SHADER, shaderFlags); + shader = make_unique(vertex_shader, fragment_shader); - m_shader = make_unique(vertexShader, fragmentShader); + camera = make_unique(Vec3f(0.0, -24.0f, 0.0f), 12); + world = make_unique(); - m_camera = make_unique(Vec3f(0.0, -24.0f, 0.0f), 12); - m_world = make_unique(); - - m_texture = make_unique("assets/texture.png"); - - BEBONE_PROFILE_STOP(BEXEL_LOAD) + texture = make_unique("assets/texture.png"); } void Bexel::run() { - BEBONE_PROFILE_RECORD(BEXEL_RUN) - - GLContext::enable(GL_DEPTH_TEST); - GLContext::enable(GL_CULL_FACE); - GLContext::cull_face(GL_BACK); - GLContext::front_face(GL_CW); + shader->set_uniform("inTexture", 0); - m_shader->set_uniform("inTexture", 0); - - while (!m_window->closing()) { - BEBONE_PROFILE_RECORD(BEXEL_UPDATE_LOOP) - - GLContext::set_viewport(0, 0, m_window->get_width(), m_window->get_height()); + while (!window->closing()) { + GLContext::set_viewport(0, 0, window->get_width(), window->get_height()); GLContext::clear_color(0.47f, 0.65f, 1.0f, 1.0f); GLContext::clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - m_camera->update(m_window); - m_world->update(m_camera); - - m_shader->enable(); + camera->update(window); + world->update(camera); - m_texture->bind(); + shader->enable(); - m_camera->bind(m_shader); - m_world->render(m_shader); + texture->bind(); - GLFWContext::swap_buffers(*m_window); - GLFWContext::poll_events(); + camera->bind(shader); + world->render(shader); - BEBONE_PROFILE_STOP(BEXEL_UPDATE_LOOP) + GLFWContext::swap_buffers(*window); + window->pull_events(); } - - BEBONE_PROFILE_STOP(BEXEL_RUN) } void Bexel::unload() { - m_camera = nullptr; - m_world = nullptr; - - m_shader->destroy(); + camera = nullptr; + world = nullptr; - GLFWContext::terminate(); + shader->destroy(); } } diff --git a/examples/gfx/opengl/4_opengl_bexel/bexel.h b/examples/gfx/opengl/4_opengl_bexel/bexel.h index cdf25ba8..1cf5a445 100644 --- a/examples/gfx/opengl/4_opengl_bexel/bexel.h +++ b/examples/gfx/opengl/4_opengl_bexel/bexel.h @@ -1,22 +1,22 @@ #ifndef BEXEL_BEXEL_H #define BEXEL_BEXEL_H -#include "gfx/opengl/4_opengl_bexel/world/world.h" +#include "world/world.h" #include "camera.h" namespace bexel { - static const u64 GAME_WIDTH = 800; - static const u64 GAME_HEIGHT = 600; + static const u64 game_width = 800; + static const u64 game_height = 600; class Bexel { private: - shared_ptr m_window; + shared_ptr window; - unique_ptr m_shader; - unique_ptr m_texture; + unique_ptr shader; + unique_ptr texture; - unique_ptr m_camera; - unique_ptr m_world; + unique_ptr camera; + unique_ptr world; public: Bexel(); diff --git a/examples/gfx/opengl/4_opengl_bexel/camera.cpp b/examples/gfx/opengl/4_opengl_bexel/camera.cpp index 33f21b24..174ee37c 100644 --- a/examples/gfx/opengl/4_opengl_bexel/camera.cpp +++ b/examples/gfx/opengl/4_opengl_bexel/camera.cpp @@ -1,114 +1,86 @@ #include "camera.h" namespace bexel { - Camera::Camera(const Vec3f& position, const i32& renderDistance) { - m_renderDistance = renderDistance; + Camera::Camera(const Vec3f& position, const i32& render_distance) { + this->render_distance = render_distance; - m_position = position; - m_rotation = Vec3f::zero; - m_direction = Vec3f::zero; + this->position = position; + rotation = Vec3f::zero; + direction = Vec3f::zero; - m_mouseLocked = true; + mouse_locked = true; - m_viewMatrix = Mat4f::identity(); - m_projMatrix = Mat4f::identity(); - } - - Mat4f Camera::calculate_view_matrix() const { - const static auto upVector = Vec3f::down; - - const auto w = m_direction.normalize(); - const auto u = w.cross(upVector).normalize(); - const auto v = w.cross(u); - - Mat4f viewMatrix = Mat4f::identity(); - viewMatrix[0 * 4 + 0] = u.x; - viewMatrix[1 * 4 + 0] = u.y; - viewMatrix[2 * 4 + 0] = u.z; - viewMatrix[0 * 4 + 1] = v.x; - viewMatrix[1 * 4 + 1] = v.y; - viewMatrix[2 * 4 + 1] = v.z; - viewMatrix[0 * 4 + 2] = w.x; - viewMatrix[1 * 4 + 2] = w.y; - viewMatrix[2 * 4 + 2] = w.z; - viewMatrix[3 * 4 + 0] = -1.0f * (u).dot(m_position); - viewMatrix[3 * 4 + 1] = -1.0f * (v).dot(m_position); - viewMatrix[3 * 4 + 2] = -1.0f * (w).dot(m_position); - - return viewMatrix; + view_matrix = Mat4f::identity(); + proj_matrix = Mat4f::identity(); } void Camera::update(shared_ptr& window) { - BEBONE_PROFILE_RECORD(BEXEL_CAMERA_UPDATE) - const f32 speed = 0.5f; if (glfwGetKey(window->get_backend(), 'W') == GLFW_PRESS) - m_position += Vec3f(1.0f, 0.0f, 1.0f) * m_direction.normalize() * speed; + position += Vec3f(1.0f, 0.0f, 1.0f) * direction.normalize() * speed; if (glfwGetKey(window->get_backend(), 'S') == GLFW_PRESS) - m_position -= Vec3f(1.0f, 0.0f, 1.0f) * m_direction.normalize() * speed; + position -= Vec3f(1.0f, 0.0f, 1.0f) * direction.normalize() * speed; if (glfwGetKey(window->get_backend(), 'A') == GLFW_PRESS) - m_position -= Vec3f(m_direction.z, 0.0f, -m_direction.x).normalize() * speed; + position -= Vec3f(direction.z, 0.0f, -direction.x).normalize() * speed; if (glfwGetKey(window->get_backend(), 'D') == GLFW_PRESS) - m_position += Vec3f(m_direction.z, 0.0f, -m_direction.x).normalize() * speed; + position += Vec3f(direction.z, 0.0f, -direction.x).normalize() * speed; if (glfwGetKey(window->get_backend(), GLFW_KEY_SPACE) == GLFW_PRESS) - m_position.y += speed; + position.y += speed; if (glfwGetKey(window->get_backend(), GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS) - m_position.y -= speed; + position.y -= speed; - bool oldMouseLockState = m_mouseLocked; - static auto buttonPressed = false; - const auto isDebugButtonPressed = (glfwGetKey(window->get_backend(), GLFW_KEY_ENTER) == GLFW_RELEASE); - m_mouseLocked = (isDebugButtonPressed && !buttonPressed) ? !m_mouseLocked : m_mouseLocked; - buttonPressed = isDebugButtonPressed; + bool old_mouse_lock_state = mouse_locked; + static auto button_pressed = false; + const auto is_debug_button_pressed = (glfwGetKey(window->get_backend(), GLFW_KEY_ENTER) == GLFW_RELEASE); + mouse_locked = (is_debug_button_pressed && !button_pressed) ? !mouse_locked : mouse_locked; + button_pressed = is_debug_button_pressed; - if(oldMouseLockState != m_mouseLocked) + if(old_mouse_lock_state != mouse_locked) glfwSetCursorPos(window->get_backend(), window->get_width() / 2.0f, window->get_height() / 2.0f); - if(m_mouseLocked) { + if(mouse_locked) { glfwSetInputMode(window->get_backend(), GLFW_CURSOR, GLFW_CURSOR_HIDDEN); - const f64 centerXPos = window->get_width() / 2.0f; - const f64 centerYPos = window->get_height() / 2.0f; + const f64 center_x_pos = window->get_width() / 2.0f; + const f64 center_y_pos = window->get_height() / 2.0f; - f64 xPos, yPos; - glfwGetCursorPos(window->get_backend(), &xPos, &yPos); + f64 x_pos, y_pos; + glfwGetCursorPos(window->get_backend(), &x_pos, &y_pos); - const f32 deltaX = floor(centerXPos) - xPos; - const f32 deltaY = floor(centerYPos) - yPos; + const f32 delta_x = floor(center_x_pos) - x_pos; + const f32 delta_y = floor(center_y_pos) - y_pos; - m_rotation.x += deltaY * 0.005f; - m_rotation.y += deltaX * 0.005f; // If this is confusing just think that we rotate Y axis cause of movement mouse a long X axis, actual this make sense + rotation.x += delta_y * 0.005f; + rotation.y += delta_x * 0.005f; // If this is confusing just think that we rotate Y axis cause of movement mouse a long X axis, actual this make sense - glfwSetCursorPos(window->get_backend(), centerXPos, centerYPos); + glfwSetCursorPos(window->get_backend(), center_x_pos, center_y_pos); } else glfwSetInputMode(window->get_backend(), GLFW_CURSOR, GLFW_CURSOR_NORMAL); - m_direction.x = cos(m_rotation.y) * cos(m_rotation.x); - m_direction.y = sin(m_rotation.x); - m_direction.z = sin(m_rotation.y) * cos(m_rotation.x); - - m_viewMatrix = calculate_view_matrix(); - m_projMatrix = Mat4f::perspective(1.0472, window->get_aspect(), 0.1f, 2000.0f); + direction.x = cos(rotation.y) * cos(rotation.x); + direction.y = sin(rotation.x); + direction.z = sin(rotation.y) * cos(rotation.x); - BEBONE_PROFILE_STOP(BEXEL_CAMERA_UPDATE) + view_matrix = Mat4f::view(position, direction); + proj_matrix = Mat4f::perspective(1.0472, window->get_aspect(), 0.1f, 2000.0f); } void Camera::bind(unique_ptr& shader) { - shader->set_uniform("proj", m_projMatrix); - shader->set_uniform("view", m_viewMatrix); + shader->set_uniform("proj", proj_matrix); + shader->set_uniform("view", view_matrix); } const Vec3f& Camera::get_position() const { - return m_position; + return position; } const i32& Camera::get_render_distance() const { - return m_renderDistance; + return render_distance; } } diff --git a/examples/gfx/opengl/4_opengl_bexel/camera.h b/examples/gfx/opengl/4_opengl_bexel/camera.h index e627cd93..42911c4e 100644 --- a/examples/gfx/opengl/4_opengl_bexel/camera.h +++ b/examples/gfx/opengl/4_opengl_bexel/camera.h @@ -1,26 +1,26 @@ #ifndef BEXEL_CAMERA_H #define BEXEL_CAMERA_H -#include "gfx/opengl/4_opengl_bexel/mesh/vertex.h" +#include "mesh/vertex.h" namespace bexel { + using namespace bebone; + class Camera : private core::NonCopyable { private: - i32 m_renderDistance; - - Vec3f m_position; - Vec3f m_rotation; - Vec3f m_direction; + i32 render_distance; - bool m_mouseLocked; + Vec3f position; + Vec3f rotation; + Vec3f direction; - Mat4f m_viewMatrix; - Mat4f m_projMatrix; + bool mouse_locked; - Mat4f calculate_view_matrix() const; + Mat4f view_matrix; + Mat4f proj_matrix; public: - Camera(const Vec3f& position, const i32& renderDistance); + Camera(const Vec3f& position, const i32& render_distance); void update(shared_ptr& window); void bind(unique_ptr& shader); diff --git a/examples/gfx/opengl/4_opengl_bexel/direction.h b/examples/gfx/opengl/4_opengl_bexel/direction.h index 1666849f..38de5a9d 100644 --- a/examples/gfx/opengl/4_opengl_bexel/direction.h +++ b/examples/gfx/opengl/4_opengl_bexel/direction.h @@ -3,12 +3,12 @@ namespace bexel { enum Direction { - UP, - DOWN, - LEFT, - RIGHT, - FORWARD, - BACK + Up, + Down, + Left, + Right, + Forward, + Back }; } diff --git a/examples/gfx/opengl/4_opengl_bexel/main.cpp b/examples/gfx/opengl/4_opengl_bexel/main.cpp index b1efd0ce..853d05ca 100644 --- a/examples/gfx/opengl/4_opengl_bexel/main.cpp +++ b/examples/gfx/opengl/4_opengl_bexel/main.cpp @@ -5,8 +5,6 @@ using namespace bexel; int main() { - BEBONE_PROFILE_RECORD(BEXEL_MAIN) - Bexel bexel; bexel.init(); @@ -14,9 +12,5 @@ int main() { bexel.run(); bexel.unload(); - BEBONE_PROFILE_STOP(BEXEL_MAIN) - - bebone::core::Profiler::get_instance().result(); - return 0; } diff --git a/examples/gfx/opengl/4_opengl_bexel/mesh/mesh.cpp b/examples/gfx/opengl/4_opengl_bexel/mesh/mesh.cpp index 428e050f..3238deaa 100644 --- a/examples/gfx/opengl/4_opengl_bexel/mesh/mesh.cpp +++ b/examples/gfx/opengl/4_opengl_bexel/mesh/mesh.cpp @@ -1,24 +1,24 @@ #include "mesh.h" namespace bexel { - Mesh::Mesh(const vector& vertices, const vector& indices) : m_vertices(vertices), m_indices(indices) { - m_vao = make_unique(); - m_vao->bind(); + Mesh::Mesh(const vector& vertices, const vector& indices) : vertices(vertices), indices(indices) { + vao = make_unique(); + vao->bind(); - m_vbo = make_unique(m_vertices.data(), m_vertices.size() * sizeof(Vertex)); - m_ebo = make_unique(m_indices.data(), m_indices.size() * sizeof(u32)); + vbo = make_unique(vertices.data(), vertices.size() * sizeof(Vertex)); + ebo = make_unique(indices.data(), indices.size() * sizeof(u32)); - m_vao->link_attributes(*m_vbo, 0, 3, GL_FLOAT, sizeof(Vertex), (void*) offsetof(Vertex, pos)); - m_vao->link_attributes(*m_vbo, 1, 2, GL_FLOAT, sizeof(Vertex), (void*) offsetof(Vertex, tex)); + vao->link_attributes(*vbo, 0, 3, GL_FLOAT, sizeof(Vertex), (void*) offsetof(Vertex, pos)); + vao->link_attributes(*vbo, 1, 2, GL_FLOAT, sizeof(Vertex), (void*) offsetof(Vertex, tex)); - m_vao->unbind(); - m_vbo->unbind(); - m_ebo->unbind(); + vao->unbind(); + vbo->unbind(); + ebo->unbind(); } void Mesh::render() const { - m_vao->bind(); + vao->bind(); - GLContext::draw_elements(GL_TRIANGLES, static_cast(m_indices.size()), GL_UNSIGNED_INT, nullptr); + GLContext::draw_elements(GL_TRIANGLES, static_cast(indices.size()), GL_UNSIGNED_INT, nullptr); } } diff --git a/examples/gfx/opengl/4_opengl_bexel/mesh/mesh.h b/examples/gfx/opengl/4_opengl_bexel/mesh/mesh.h index bffae034..02c7869b 100644 --- a/examples/gfx/opengl/4_opengl_bexel/mesh/mesh.h +++ b/examples/gfx/opengl/4_opengl_bexel/mesh/mesh.h @@ -7,14 +7,16 @@ #include "vertex.h" namespace bexel { + using namespace bebone; + class Mesh final : private core::NonCopyable { private: - vector m_vertices; - vector m_indices; + vector vertices; + vector indices; - unique_ptr m_vao; - unique_ptr m_vbo; - unique_ptr m_ebo; + unique_ptr vao; + unique_ptr vbo; + unique_ptr ebo; public: Mesh(const vector& vertices, const vector& indices); diff --git a/examples/gfx/opengl/4_opengl_bexel/mesh/mesh_builder.cpp b/examples/gfx/opengl/4_opengl_bexel/mesh/mesh_builder.cpp index 8335d60f..0d7e541b 100644 --- a/examples/gfx/opengl/4_opengl_bexel/mesh/mesh_builder.cpp +++ b/examples/gfx/opengl/4_opengl_bexel/mesh/mesh_builder.cpp @@ -1,11 +1,11 @@ #include "mesh_builder.h" namespace bexel { - MeshBuilder::MeshBuilder() : m_indexOffset(0) { + MeshBuilder::MeshBuilder() : index_offset(0) { } unique_ptr MeshBuilder::build() { - return make_unique(m_vertices, m_indices); + return make_unique(vertices, indices); } } \ No newline at end of file diff --git a/examples/gfx/opengl/4_opengl_bexel/mesh/mesh_builder.h b/examples/gfx/opengl/4_opengl_bexel/mesh/mesh_builder.h index e50d6edb..602e5f83 100644 --- a/examples/gfx/opengl/4_opengl_bexel/mesh/mesh_builder.h +++ b/examples/gfx/opengl/4_opengl_bexel/mesh/mesh_builder.h @@ -11,63 +11,63 @@ namespace bexel { class MeshBuilder { private: - vector m_vertices; - vector m_indices; + vector vertices; + vector indices; - u32 m_indexOffset; + u32 index_offset; public: MeshBuilder(); - template - MeshBuilder& append(const _MeshData& meshData, const Transform& transform) { - for(auto vertex : meshData.get_vertices()) { + template + MeshBuilder& append(const MeshData& mesh_data, const Transform& transform) { + for(auto vertex : mesh_data.get_vertices()) { vertex.rotate(transform.rotation); vertex.translate(transform.translation); vertex.scale(transform.scale); - m_vertices.push_back(vertex); + vertices.push_back(vertex); } - u32 maxIndex = 0; - for(const auto& index : meshData.get_indices()) { - m_indices.push_back(index + m_indexOffset); + u32 max_index = 0; + for(const auto& index : mesh_data.get_indices()) { + indices.push_back(index + index_offset); - if(index > maxIndex) - maxIndex = index; + if(index > max_index) + max_index = index; } - m_indexOffset += maxIndex + 1; + index_offset += max_index + 1; return *this; } - template - MeshBuilder& append(const _MeshData& meshData, const vector& textureCoords, const Transform& transform) { - const auto size = meshData.get_vertices().size(); - const auto& vertices = meshData.get_vertices(); + template + MeshBuilder& append(const MeshData& mesh_data, const vector& texture_coords, const Transform& transform) { + const auto size = mesh_data.get_vertices().size(); + const auto& mesh_vertices = mesh_data.get_vertices(); for(size_t i = 0; i < size; ++i) { - auto vertex = vertices[i]; + auto vertex = mesh_vertices[i]; vertex.rotate(transform.rotation); vertex.translate(transform.translation); vertex.scale(transform.scale); - vertex.tex = textureCoords[i]; + vertex.tex = texture_coords[i]; - m_vertices.push_back(vertex); + vertices.push_back(vertex); } - u32 maxIndex = 0; - for(const auto& index : meshData.get_indices()) { - m_indices.push_back(index + m_indexOffset); + u32 max_index = 0; + for(const auto& index : mesh_data.get_indices()) { + indices.push_back(index + index_offset); - if(index > maxIndex) - maxIndex = index; + if(index > max_index) + max_index = index; } - m_indexOffset += maxIndex + 1; + index_offset += max_index + 1; return *this; } diff --git a/examples/gfx/opengl/4_opengl_bexel/mesh/vertex.h b/examples/gfx/opengl/4_opengl_bexel/mesh/vertex.h index 89cdb967..901d62f4 100644 --- a/examples/gfx/opengl/4_opengl_bexel/mesh/vertex.h +++ b/examples/gfx/opengl/4_opengl_bexel/mesh/vertex.h @@ -1,14 +1,12 @@ #ifndef BEXEL_VERTEX_H #define BEXEL_VERTEX_H -#include "bebone.h" +#include "bebone/bebone.h" namespace bexel { - using namespace bebone::core; - using namespace bebone; using namespace std; + using namespace bebone::core; using namespace bebone::gfx; - using namespace bebone::gfx::opengl; struct Vertex { Vec3f pos; @@ -23,18 +21,18 @@ namespace bexel { } void rotate(const Mat4f& matrix) { - f32 resultX = pos.x * matrix.e[0 * 4 + 0] + pos.y * matrix.e[1 * 4 + 0] + pos.z * matrix.e[2 * 4 + 0] + 1.0f * matrix.e[3 * 4 + 0]; - f32 resultY = pos.x * matrix.e[0 * 4 + 1] + pos.y * matrix.e[1 * 4 + 1] + pos.z * matrix.e[2 * 4 + 1] + 1.0f * matrix.e[3 * 4 + 1]; - f32 resultZ = pos.x * matrix.e[0 * 4 + 2] + pos.y * matrix.e[1 * 4 + 2] + pos.z * matrix.e[2 * 4 + 2] + 1.0f * matrix.e[3 * 4 + 2]; - const f32 resultW = pos.x * matrix.e[0 * 4 + 3] + pos.y * matrix.e[1 * 4 + 3] + pos.z * matrix.e[2 * 4 + 3] + 1.0f * matrix.e[3 * 4 + 3]; - - if (resultW != 0.0f) { - resultX /= resultW; - resultY /= resultW; - resultZ /= resultW; + f32 result_x = Vec3f::dot(pos, (Vec3f)matrix[0]) + matrix(3, 0); + f32 result_y = Vec3f::dot(pos, (Vec3f)matrix[1]) + matrix(3, 1); + f32 result_z = Vec3f::dot(pos, (Vec3f)matrix[2]) + matrix(3, 2); + const f32 result_w = Vec3f::dot(pos, (Vec3f)matrix[3]) + matrix(3, 3); + + if (result_w != 0.0f) { + result_x /= result_w; + result_y /= result_w; + result_z /= result_w; } - pos = Vec3f(resultX, resultY, resultZ); + pos = Vec3f(result_x, result_y, result_z); } }; } diff --git a/examples/gfx/opengl/4_opengl_bexel/mesh/wall_mesh.h b/examples/gfx/opengl/4_opengl_bexel/mesh/wall_mesh.h index 9df940ba..5a850f92 100644 --- a/examples/gfx/opengl/4_opengl_bexel/mesh/wall_mesh.h +++ b/examples/gfx/opengl/4_opengl_bexel/mesh/wall_mesh.h @@ -16,7 +16,7 @@ namespace bexel { }; template<> - struct WallMesh { + struct WallMesh { const vector& get_vertices() const { static const vector vertices = { {{0.5f, 0.5f, 0.5f}, {1.0f, 1.0f}}, @@ -35,7 +35,7 @@ namespace bexel { }; template<> - struct WallMesh { + struct WallMesh { const vector& get_vertices() const { static const vector vertices = { {{0.5f, -0.5f, 0.5f}, {1.0f, 1.0f}}, @@ -54,7 +54,7 @@ namespace bexel { }; template<> - struct WallMesh { + struct WallMesh { const vector& get_vertices() const { static const vector vertices = { {{0.5f, 0.5f, 0.5f}, {1.0f, 1.0f}}, @@ -73,7 +73,7 @@ namespace bexel { }; template<> - struct WallMesh { + struct WallMesh { const vector& get_vertices() const { static const vector vertices = { {{-0.5f, 0.5f, -0.5f}, {1.0f, 1.0f}}, @@ -92,7 +92,7 @@ namespace bexel { }; template<> - struct WallMesh { + struct WallMesh { const vector& get_vertices() const { static const vector vertices = { {{-0.5f, 0.5f, 0.5f}, {1.0f, 1.0f}}, @@ -111,7 +111,7 @@ namespace bexel { }; template<> - struct WallMesh { + struct WallMesh { const vector& get_vertices() const { static const vector vertices = { {{0.5f, 0.5f, -0.5f}, {1.0f, 1.0f}}, diff --git a/examples/gfx/opengl/4_opengl_bexel/renderable.h b/examples/gfx/opengl/4_opengl_bexel/renderable.h index 3507d52f..290c9ce5 100644 --- a/examples/gfx/opengl/4_opengl_bexel/renderable.h +++ b/examples/gfx/opengl/4_opengl_bexel/renderable.h @@ -1,7 +1,7 @@ #ifndef BEXEL_RENDERABLE_H #define BEXEL_RENDERABLE_H -#include "gfx/opengl/4_opengl_bexel/mesh/vertex.h" +#include "mesh/vertex.h" namespace bexel { class Renderable { diff --git a/examples/gfx/opengl/4_opengl_bexel/transform.h b/examples/gfx/opengl/4_opengl_bexel/transform.h index 481053eb..8770895b 100644 --- a/examples/gfx/opengl/4_opengl_bexel/transform.h +++ b/examples/gfx/opengl/4_opengl_bexel/transform.h @@ -1,7 +1,7 @@ #ifndef BEXEL_TRANSFORM_H #define BEXEL_TRANSFORM_H -#include "gfx/opengl/4_opengl_bexel/mesh/vertex.h" +#include "mesh/vertex.h" namespace bexel { struct Transform { diff --git a/examples/gfx/opengl/4_opengl_bexel/world/block_id.h b/examples/gfx/opengl/4_opengl_bexel/world/block_id.h index 46c8b9d9..790f9399 100644 --- a/examples/gfx/opengl/4_opengl_bexel/world/block_id.h +++ b/examples/gfx/opengl/4_opengl_bexel/world/block_id.h @@ -3,9 +3,9 @@ namespace bexel { enum BlockID { - UNDEFINED, - AIR, - SOLID + Undefined, + Air, + Solid }; } diff --git a/examples/gfx/opengl/4_opengl_bexel/world/chunk.cpp b/examples/gfx/opengl/4_opengl_bexel/world/chunk.cpp index 97912de8..813fddbc 100644 --- a/examples/gfx/opengl/4_opengl_bexel/world/chunk.cpp +++ b/examples/gfx/opengl/4_opengl_bexel/world/chunk.cpp @@ -2,34 +2,30 @@ #include "world.h" namespace bexel { - Chunk::Chunk(const Vec3f& pos) : m_mesh(nullptr) { - m_transform.translation = pos; - m_transform.rotation = Mat4f::identity(); - m_transform.scale = Vec3f::one; + Chunk::Chunk(const Vec3f& pos) : mesh(nullptr) { + transform.translation = pos; + transform.rotation = Mat4f::identity(); + transform.scale = Vec3f::one; } Chunk::~Chunk() { for(i32 x = 0; x < CHUNK_SIZE_X; ++x) { for(i32 z = 0; z < CHUNK_SIZE_Z; ++z) { for(i32 y = 0; y < CHUNK_SIZE_Y; ++y) { - delete m_voxels[x][y][z]; + delete voxels[x][y][z]; } } } } - void Chunk::generate_chunk(unique_ptr& worldGenerator) { - BEBONE_PROFILE_RECORD(BEXEL_CHUNK_GENERATE_CHUNK) - + void Chunk::generate_chunk(unique_ptr& world_generator) { for(i32 x = 0; x < CHUNK_SIZE_X; ++x) { for(i32 z = 0; z < CHUNK_SIZE_Z; ++z) { for(i32 y = 0; y < CHUNK_SIZE_Y; ++y) { - m_voxels[x][y][z] = worldGenerator->create_voxel_at(*this, Vec3i(x, y, z)); + voxels[x][y][z] = world_generator->create_voxel_at(*this, Vec3i(x, y, z)); } } } - - BEBONE_PROFILE_STOP(BEXEL_CHUNK_GENERATE_CHUNK) } TileBlock* Chunk::get_voxel(const i32& x, const i32& y, const i32& z) { @@ -37,17 +33,15 @@ namespace bexel { if(y < 0 || y >= CHUNK_SIZE_Y) return nullptr; if(z < 0 || z >= CHUNK_SIZE_Z) return nullptr; - return m_voxels[x][y][z]; + return voxels[x][y][z]; } const Vec3f& Chunk::get_pos() const { - return m_transform.translation; + return transform.translation; } void Chunk::generate_mesh(World& world) { - BEBONE_PROFILE_RECORD(BEXEL_CHUNK_GENERATE_MESH) - - MeshBuilder meshBuilder; + MeshBuilder mesh_builder; for(i32 x = 0; x < CHUNK_SIZE_X; ++x) { for(i32 z = 0; z < CHUNK_SIZE_Z; ++z) { @@ -55,28 +49,22 @@ namespace bexel { auto voxel = get_voxel(x, y, z); if(voxel != nullptr) - voxel->append_mesh(meshBuilder, world, *this); + voxel->append_mesh(mesh_builder, world, *this); } } } - m_mesh = meshBuilder.build(); - - BEBONE_PROFILE_STOP(BEXEL_CHUNK_GENERATE_MESH) + mesh = mesh_builder.build(); } const Transform& Chunk::get_transform() const { - return m_transform; + return transform; } void Chunk::render(unique_ptr& shader) { - BEBONE_PROFILE_RECORD(BEXEL_CHUNK_RENDER) - - shader->set_uniform("transform", m_transform.calc_matrix()); - - if(m_mesh != nullptr) - m_mesh->render(); + shader->set_uniform("transform", transform.calc_matrix()); - BEBONE_PROFILE_STOP(BEXEL_CHUNK_RENDER) + if(mesh != nullptr) + mesh->render(); } } diff --git a/examples/gfx/opengl/4_opengl_bexel/world/chunk.h b/examples/gfx/opengl/4_opengl_bexel/world/chunk.h index 8093b941..184df227 100644 --- a/examples/gfx/opengl/4_opengl_bexel/world/chunk.h +++ b/examples/gfx/opengl/4_opengl_bexel/world/chunk.h @@ -9,7 +9,7 @@ #include "../transform.h" #include "world_generator.h" -#include "gfx/opengl/4_opengl_bexel/world/tiles/tile_block.h" +#include "world/tiles/tile_block.h" #define CHUNK_SIZE_X 16 #define CHUNK_SIZE_Y 32 @@ -20,16 +20,16 @@ namespace bexel { class Chunk final : public Renderable, private core::NonCopyable { private: - array, CHUNK_SIZE_Y>, CHUNK_SIZE_X> m_voxels; - Transform m_transform; + array, CHUNK_SIZE_Y>, CHUNK_SIZE_X> voxels; + Transform transform; - unique_ptr m_mesh; + unique_ptr mesh; public: Chunk(const Vec3f& pos); ~Chunk(); - void generate_chunk(unique_ptr& worldGenerator); + void generate_chunk(unique_ptr& world_generator); void generate_mesh(World& world); TileBlock* get_voxel(const i32& x, const i32& y, const i32& z); diff --git a/examples/gfx/opengl/4_opengl_bexel/world/tiles/block.cpp b/examples/gfx/opengl/4_opengl_bexel/world/tiles/block.cpp index c136db41..d925abd3 100644 --- a/examples/gfx/opengl/4_opengl_bexel/world/tiles/block.cpp +++ b/examples/gfx/opengl/4_opengl_bexel/world/tiles/block.cpp @@ -1,61 +1,61 @@ #include "block.h" -#include "gfx/opengl/4_opengl_bexel/world/chunk.h" -#include "gfx/opengl/4_opengl_bexel/world/world.h" +#include "world/chunk.h" +#include "world/world.h" namespace bexel { - Block::Block(const Vec3f& chunkPosition) : TileBlock(false), m_chunkPosition(chunkPosition) { + Block::Block(const Vec3f& chunk_position) : TileBlock(false), chunk_position(chunk_position) { } - void Block::append_mesh(MeshBuilder& meshBuilder, World& world, Chunk& chunk) { - const auto chunkPos = chunk.get_pos(); + void Block::append_mesh(MeshBuilder& mesh_builder, World& world, Chunk& chunk) { + const auto chunk_pos = chunk.get_pos(); - const auto& x = m_chunkPosition.x + chunkPos.x; - const auto& y = m_chunkPosition.y + chunkPos.y; - const auto& z = m_chunkPosition.z + chunkPos.z; + const auto& x = chunk_position.x + chunk_pos.x; + const auto& y = chunk_position.y + chunk_pos.y; + const auto& z = chunk_position.z + chunk_pos.z; - auto upBlock = world.get_voxel_at(Vec3f(x, y + 1.0f, z)); - auto downBlock = world.get_voxel_at(Vec3f(x, y - 1.0f, z)); - auto leftBlock = world.get_voxel_at(Vec3f(x + 1.0f, y, z)); - auto rightBlock = world.get_voxel_at(Vec3f(x - 1.0f, y, z)); - auto forwardBlock = world.get_voxel_at(Vec3f(x, y, z + 1.0f)); - auto backBlock = world.get_voxel_at(Vec3f(x, y, z - 1.0f)); + auto up_block = world.get_voxel_at(Vec3f(x, y + 1.0f, z)); + auto down_block = world.get_voxel_at(Vec3f(x, y - 1.0f, z)); + auto left_block = world.get_voxel_at(Vec3f(x + 1.0f, y, z)); + auto right_block = world.get_voxel_at(Vec3f(x - 1.0f, y, z)); + auto forward_block = world.get_voxel_at(Vec3f(x, y, z + 1.0f)); + auto back_block = world.get_voxel_at(Vec3f(x, y, z - 1.0f)); - if(upBlock != SOLID) - meshBuilder.append( - WallMesh{}, - Transform{m_chunkPosition,Mat4f::identity(),Vec3f::one} + if(up_block != Solid) + mesh_builder.append( + WallMesh{}, + Transform{chunk_position, Mat4f::identity(), Vec3f::one} ); - if(downBlock != SOLID) - meshBuilder.append( - WallMesh{}, - Transform{m_chunkPosition,Mat4f::identity(),Vec3f::one} + if(down_block != Solid) + mesh_builder.append( + WallMesh{}, + Transform{chunk_position, Mat4f::identity(), Vec3f::one} ); - if(leftBlock != SOLID) - meshBuilder.append( - WallMesh{}, - Transform{m_chunkPosition,Mat4f::identity(),Vec3f::one} + if(left_block != Solid) + mesh_builder.append( + WallMesh{}, + Transform{chunk_position, Mat4f::identity(), Vec3f::one} ); - if(rightBlock != SOLID) - meshBuilder.append( - WallMesh{}, - Transform{m_chunkPosition,Mat4f::identity(),Vec3f::one} + if(right_block != Solid) + mesh_builder.append( + WallMesh{}, + Transform{chunk_position, Mat4f::identity(), Vec3f::one} ); - if(forwardBlock != SOLID) - meshBuilder.append( - WallMesh{}, - Transform{m_chunkPosition,Mat4f::identity(),Vec3f::one} + if(forward_block != Solid) + mesh_builder.append( + WallMesh{}, + Transform{chunk_position, Mat4f::identity(), Vec3f::one} ); - if(backBlock != SOLID) - meshBuilder.append( - WallMesh{}, - Transform{m_chunkPosition,Mat4f::identity(),Vec3f::one} + if(back_block != Solid) + mesh_builder.append( + WallMesh{}, + Transform{chunk_position, Mat4f::identity(), Vec3f::one} ); } } diff --git a/examples/gfx/opengl/4_opengl_bexel/world/tiles/block.h b/examples/gfx/opengl/4_opengl_bexel/world/tiles/block.h index fb2fe6b7..dd6171d4 100644 --- a/examples/gfx/opengl/4_opengl_bexel/world/tiles/block.h +++ b/examples/gfx/opengl/4_opengl_bexel/world/tiles/block.h @@ -8,12 +8,12 @@ namespace bexel { private: protected: - Vec3f m_chunkPosition; + Vec3f chunk_position; public: - Block(const Vec3f& chunkPosition); + Block(const Vec3f& chunk_position); - void append_mesh(MeshBuilder& meshBuilder, World& world, Chunk& chunk) override; + void append_mesh(MeshBuilder& mesh_builder, World& world, Chunk& chunk) override; }; } diff --git a/examples/gfx/opengl/4_opengl_bexel/world/tiles/directional_block.cpp b/examples/gfx/opengl/4_opengl_bexel/world/tiles/directional_block.cpp index b9639f7f..8a58a020 100644 --- a/examples/gfx/opengl/4_opengl_bexel/world/tiles/directional_block.cpp +++ b/examples/gfx/opengl/4_opengl_bexel/world/tiles/directional_block.cpp @@ -4,69 +4,69 @@ #include "../world.h" namespace bexel { - DirectionalBlock::DirectionalBlock(const Vec3f& chunkPosition) : Block(chunkPosition) { + DirectionalBlock::DirectionalBlock(const Vec3f& chunk_position) : Block(chunk_position) { } - void DirectionalBlock::append_mesh(MeshBuilder& meshBuilder, World& world, Chunk& chunk) { - const auto chunkPos = chunk.get_pos(); + void DirectionalBlock::append_mesh(MeshBuilder& mesh_builder, World& world, Chunk& chunk) { + const auto chunk_pos = chunk.get_pos(); - const auto& x = m_chunkPosition.x + chunkPos.x; - const auto& y = m_chunkPosition.y + chunkPos.y; - const auto& z = m_chunkPosition.z + chunkPos.z; + const auto& x = chunk_position.x + chunk_pos.x; + const auto& y = chunk_position.y + chunk_pos.y; + const auto& z = chunk_position.z + chunk_pos.z; - auto upBlock = world.get_voxel_at(Vec3f(x, y + 1.0f, z)); - auto downBlock = world.get_voxel_at(Vec3f(x, y - 1.0f, z)); - auto leftBlock = world.get_voxel_at(Vec3f(x + 1.0f, y, z)); - auto rightBlock = world.get_voxel_at(Vec3f(x - 1.0f, y, z)); - auto forwardBlock = world.get_voxel_at(Vec3f(x, y, z + 1.0f)); - auto backBlock = world.get_voxel_at(Vec3f(x, y, z - 1.0f)); + auto up_block = world.get_voxel_at(Vec3f(x, y + 1.0f, z)); + auto down_block = world.get_voxel_at(Vec3f(x, y - 1.0f, z)); + auto left_block = world.get_voxel_at(Vec3f(x + 1.0f, y, z)); + auto right_block = world.get_voxel_at(Vec3f(x - 1.0f, y, z)); + auto forward_block = world.get_voxel_at(Vec3f(x, y, z + 1.0f)); + auto back_block = world.get_voxel_at(Vec3f(x, y, z - 1.0f)); - if(upBlock != SOLID) { - meshBuilder.append( - WallMesh{}, + if(up_block != Solid) { + mesh_builder.append( + WallMesh{}, get_up_tex_coords(), - Transform{m_chunkPosition,Mat4f::identity(),Vec3f::one + Transform{chunk_position, Mat4f::identity(), Vec3f::one }); } - if(downBlock != SOLID) { - meshBuilder.append( - WallMesh{}, + if(down_block != Solid) { + mesh_builder.append( + WallMesh{}, get_down_tex_coords(), - Transform{m_chunkPosition,Mat4f::identity(),Vec3f::one + Transform{chunk_position, Mat4f::identity(), Vec3f::one }); } - if(leftBlock != SOLID) { - meshBuilder.append( - WallMesh{}, + if(left_block != Solid) { + mesh_builder.append( + WallMesh{}, get_left_tex_coords(), - Transform{m_chunkPosition,Mat4f::identity(),Vec3f::one + Transform{chunk_position, Mat4f::identity(), Vec3f::one }); } - if(rightBlock != SOLID) { - meshBuilder.append( - WallMesh{}, + if(right_block != Solid) { + mesh_builder.append( + WallMesh{}, get_right_tex_coords(), - Transform{m_chunkPosition,Mat4f::identity(),Vec3f::one + Transform{chunk_position, Mat4f::identity(), Vec3f::one }); } - if(forwardBlock != SOLID) { - meshBuilder.append( - WallMesh{}, + if(forward_block != Solid) { + mesh_builder.append( + WallMesh{}, get_forward_tex_coords(), - Transform{m_chunkPosition,Mat4f::identity(),Vec3f::one + Transform{chunk_position, Mat4f::identity(), Vec3f::one }); } - if(backBlock != SOLID) { - meshBuilder.append( - WallMesh{}, + if(back_block != Solid) { + mesh_builder.append( + WallMesh{}, get_back_tex_coords(), - Transform{m_chunkPosition,Mat4f::identity(),Vec3f::one + Transform{chunk_position, Mat4f::identity(), Vec3f::one }); } } diff --git a/examples/gfx/opengl/4_opengl_bexel/world/tiles/directional_block.h b/examples/gfx/opengl/4_opengl_bexel/world/tiles/directional_block.h index 5383976a..700b47db 100644 --- a/examples/gfx/opengl/4_opengl_bexel/world/tiles/directional_block.h +++ b/examples/gfx/opengl/4_opengl_bexel/world/tiles/directional_block.h @@ -8,7 +8,7 @@ namespace bexel { private: public: - DirectionalBlock(const Vec3f& chunkPosition); + DirectionalBlock(const Vec3f& chunk_position); virtual const vector& get_up_tex_coords() = 0; virtual const vector& get_down_tex_coords() = 0; @@ -17,7 +17,7 @@ namespace bexel { virtual const vector& get_forward_tex_coords() = 0; virtual const vector& get_back_tex_coords() = 0; - void append_mesh(MeshBuilder& meshBuilder, World& world, Chunk& chunk) override; + void append_mesh(MeshBuilder& mesh_builder, World& world, Chunk& chunk) override; }; } diff --git a/examples/gfx/opengl/4_opengl_bexel/world/tiles/grass_block.cpp b/examples/gfx/opengl/4_opengl_bexel/world/tiles/grass_block.cpp index d212f7e5..d01f9692 100644 --- a/examples/gfx/opengl/4_opengl_bexel/world/tiles/grass_block.cpp +++ b/examples/gfx/opengl/4_opengl_bexel/world/tiles/grass_block.cpp @@ -1,7 +1,7 @@ #include "grass_block.h" namespace bexel { - GrassBlock::GrassBlock(const Vec3f& chunkPosition) : SideDirectionalBlock(chunkPosition) { + GrassBlock::GrassBlock(const Vec3f& chunk_position) : SideDirectionalBlock(chunk_position) { } } diff --git a/examples/gfx/opengl/4_opengl_bexel/world/tiles/grass_block.h b/examples/gfx/opengl/4_opengl_bexel/world/tiles/grass_block.h index d2f75537..515358de 100644 --- a/examples/gfx/opengl/4_opengl_bexel/world/tiles/grass_block.h +++ b/examples/gfx/opengl/4_opengl_bexel/world/tiles/grass_block.h @@ -8,7 +8,7 @@ namespace bexel { private: public: - GrassBlock(const Vec3f &chunkPosition); + GrassBlock(const Vec3f &chunk_position); const vector& get_up_tex_coords() override { static const vector coordinates = { diff --git a/examples/gfx/opengl/4_opengl_bexel/world/tiles/side_directional_block.cpp b/examples/gfx/opengl/4_opengl_bexel/world/tiles/side_directional_block.cpp index 8e7e6f7b..f9ebef6d 100644 --- a/examples/gfx/opengl/4_opengl_bexel/world/tiles/side_directional_block.cpp +++ b/examples/gfx/opengl/4_opengl_bexel/world/tiles/side_directional_block.cpp @@ -1,7 +1,7 @@ #include "side_directional_block.h" namespace bexel { - SideDirectionalBlock::SideDirectionalBlock(const Vec3f& chunkPosition) : DirectionalBlock(chunkPosition) { + SideDirectionalBlock::SideDirectionalBlock(const Vec3f& chunk_position) : DirectionalBlock(chunk_position) { } } diff --git a/examples/gfx/opengl/4_opengl_bexel/world/tiles/side_directional_block.h b/examples/gfx/opengl/4_opengl_bexel/world/tiles/side_directional_block.h index b2c13707..b703dab7 100644 --- a/examples/gfx/opengl/4_opengl_bexel/world/tiles/side_directional_block.h +++ b/examples/gfx/opengl/4_opengl_bexel/world/tiles/side_directional_block.h @@ -8,7 +8,7 @@ namespace bexel { private: public: - SideDirectionalBlock(const Vec3f& chunkPosition); + SideDirectionalBlock(const Vec3f& chunk_position); const vector& get_left_tex_coords() override { return get_forward_tex_coords(); diff --git a/examples/gfx/opengl/4_opengl_bexel/world/tiles/tile_block.h b/examples/gfx/opengl/4_opengl_bexel/world/tiles/tile_block.h index 1ab4bea2..e0f68526 100644 --- a/examples/gfx/opengl/4_opengl_bexel/world/tiles/tile_block.h +++ b/examples/gfx/opengl/4_opengl_bexel/world/tiles/tile_block.h @@ -1,8 +1,8 @@ #ifndef BEXEL_TILE_BLOCK_H #define BEXEL_TILE_BLOCK_H -#include "gfx/opengl/4_opengl_bexel/mesh/vertex.h" -#include "gfx/opengl/4_opengl_bexel/mesh/mesh_builder.h" +#include "mesh/vertex.h" +#include "mesh/mesh_builder.h" namespace bexel { class Chunk; @@ -10,20 +10,20 @@ namespace bexel { class TileBlock { private: - bool m_opaque; + bool opaque; public: - TileBlock(const bool& opaque) : m_opaque(opaque) { + TileBlock(const bool& opaque) : opaque(opaque) { } virtual ~TileBlock() = default; const bool& is_opaque() const { - return m_opaque; + return opaque; } - virtual void append_mesh(MeshBuilder& meshBuilder, World& world, Chunk& chunk) = 0; + virtual void append_mesh(MeshBuilder& mesh_builder, World& world, Chunk& chunk) = 0; }; } diff --git a/examples/gfx/opengl/4_opengl_bexel/world/world.cpp b/examples/gfx/opengl/4_opengl_bexel/world/world.cpp index cc116b97..8df8a394 100644 --- a/examples/gfx/opengl/4_opengl_bexel/world/world.cpp +++ b/examples/gfx/opengl/4_opengl_bexel/world/world.cpp @@ -1,64 +1,56 @@ #include "world.h" namespace bexel { - World::World() : m_worldGenerator(nullptr) { - m_worldGenerator = make_unique(123); + World::World() : world_generator(nullptr) { + world_generator = make_unique(123); } - BlockID World::get_voxel_at(const Vec3f& voxelPos) const { - return m_worldGenerator->get_voxel_at(voxelPos); + BlockID World::get_voxel_at(const Vec3f& voxel_pos) const { + return world_generator->get_voxel_at(voxel_pos); } bool World::chunk_exist(const Vec2i& pos) const { - return m_chunks.find(pos) != m_chunks.end(); + return chunks.find(pos) != chunks.end(); } void World::update(unique_ptr& camera) { - BEBONE_PROFILE_RECORD(BEXEL_WORLD_UPDATE) - const auto pos = camera->get_position(); - const auto camChunkPos = Vec2i( + const auto cam_chunk_pos = Vec2i( static_cast(pos.x) / CHUNK_SIZE_X, static_cast(pos.z) / CHUNK_SIZE_Z ); - static auto prevChunkPos = Vec2i(camChunkPos.x + 1, camChunkPos.x); + static auto prev_chunk_pos = Vec2i(cam_chunk_pos.x + 1, cam_chunk_pos.x); - if(prevChunkPos == camChunkPos) + if(prev_chunk_pos == cam_chunk_pos) return; - const auto renderDistance = camera->get_render_distance(); + const auto render_distance = camera->get_render_distance(); - for(auto x = -renderDistance; x < renderDistance; ++x) { - for(auto z = -renderDistance; z < renderDistance; ++z) { - const auto toCheck = camChunkPos + Vec2i(x, z); + for(auto x = -render_distance; x < render_distance; ++x) { + for(auto z = -render_distance; z < render_distance; ++z) { + const auto to_check = cam_chunk_pos + Vec2i(x, z); - if(chunk_exist(toCheck)) + if(chunk_exist(to_check)) continue; - const auto createChunkPos = Vec3f( - static_cast(toCheck.x) * CHUNK_SIZE_X, + const auto create_chunk_pos = Vec3f( + static_cast(to_check.x) * CHUNK_SIZE_X, 0.0f, - static_cast(toCheck.y) * CHUNK_SIZE_Z + static_cast(to_check.y) * CHUNK_SIZE_Z ); - m_chunks[toCheck] = make_unique(createChunkPos); - m_chunks[toCheck]->generate_chunk(m_worldGenerator); - m_chunks[toCheck]->generate_mesh(*this); + chunks[to_check] = make_unique(create_chunk_pos); + chunks[to_check]->generate_chunk(world_generator); + chunks[to_check]->generate_mesh(*this); } } - - BEBONE_PROFILE_STOP(BEXEL_WORLD_UPDATE) } void World::render(unique_ptr& shader) { - BEBONE_PROFILE_RECORD(BEXEL_WORLD_RENDER) - - for_each(m_chunks.begin(), m_chunks.end(), [&](const auto& tuple) { + for_each(chunks.begin(), chunks.end(), [&](const auto& tuple) { const auto& chunk = tuple.second; chunk->render(shader); }); - - BEBONE_PROFILE_STOP(BEXEL_WORLD_RENDER) }; } diff --git a/examples/gfx/opengl/4_opengl_bexel/world/world.h b/examples/gfx/opengl/4_opengl_bexel/world/world.h index ef6e2da2..faf20e4e 100644 --- a/examples/gfx/opengl/4_opengl_bexel/world/world.h +++ b/examples/gfx/opengl/4_opengl_bexel/world/world.h @@ -12,15 +12,15 @@ namespace bexel { class World final : public Renderable, private core::NonCopyable { private: - unique_ptr m_worldGenerator; - unordered_map> m_chunks; + unique_ptr world_generator; + unordered_map> chunks; bool chunk_exist(const Vec2i& pos) const; public: World(); - BlockID get_voxel_at(const Vec3f& voxelPos) const; + BlockID get_voxel_at(const Vec3f& voxel_pos) const; void update(unique_ptr& camera); void render(unique_ptr& shader) override; diff --git a/examples/gfx/opengl/4_opengl_bexel/world/world_generator.cpp b/examples/gfx/opengl/4_opengl_bexel/world/world_generator.cpp index c8845d9d..d0089253 100644 --- a/examples/gfx/opengl/4_opengl_bexel/world/world_generator.cpp +++ b/examples/gfx/opengl/4_opengl_bexel/world/world_generator.cpp @@ -2,40 +2,40 @@ #include "chunk.h" namespace bexel { - WorldGenerator::WorldGenerator(const i32& seed) : m_seed(seed) { + WorldGenerator::WorldGenerator(const i32& seed) : seed(seed) { } - BlockID WorldGenerator::get_voxel_at(const Vec3f& voxelPosF) const { - const auto& x = voxelPosF.x; - const auto& y = voxelPosF.y; - const auto& z = voxelPosF.z; + BlockID WorldGenerator::get_voxel_at(const Vec3f& voxel_pos_f) const { + const auto& x = voxel_pos_f.x; + const auto& y = voxel_pos_f.y; + const auto& z = voxel_pos_f.z; - auto v0 = stb_perlin_noise3_seed(x * 0.05f, 0, z * 0.05f,0, 0, 0, m_seed) * 0.5f + 0.5f; - auto v1 = stb_perlin_noise3_seed(x * 0.01f, 0, z * 0.01f,0, 0, 0, m_seed) * 0.5f + 0.5f; + auto v0 = stb_perlin_noise3_seed(x * 0.05f, 0, z * 0.05f,0, 0, 0, seed) * 0.5f + 0.5f; + auto v1 = stb_perlin_noise3_seed(x * 0.01f, 0, z * 0.01f,0, 0, 0, seed) * 0.5f + 0.5f; const auto v = v0 * 8.0f + v1 * 24.0f; if(y > v) - return AIR; + return Air; - return SOLID; + return Solid; } - TileBlock* WorldGenerator::create_voxel_at(const Chunk& chunk, const Vec3i& voxelPosI) const { - const auto voxelPosF = Vec3f( - static_cast(voxelPosI.x), - static_cast(voxelPosI.y), - static_cast(voxelPosI.z) + TileBlock* WorldGenerator::create_voxel_at(const Chunk& chunk, const Vec3i& voxel_pos_i) const { + const auto voxel_pos_f = Vec3f( + static_cast(voxel_pos_i.x), + static_cast(voxel_pos_i.y), + static_cast(voxel_pos_i.z) ); - const auto& chunkPos = chunk.get_pos(); - const auto globalPos = chunkPos + voxelPosF; + const auto& chunk_pos = chunk.get_pos(); + const auto global_pos = chunk_pos + voxel_pos_f; - const auto blockID = get_voxel_at(globalPos); + const auto block_id = get_voxel_at(global_pos); - switch (blockID) { - case SOLID: return new GrassBlock(voxelPosF); + switch (block_id) { + case Solid: return new GrassBlock(voxel_pos_f); default: return nullptr; } } diff --git a/examples/gfx/opengl/4_opengl_bexel/world/world_generator.h b/examples/gfx/opengl/4_opengl_bexel/world/world_generator.h index 2721f8a5..99401d71 100644 --- a/examples/gfx/opengl/4_opengl_bexel/world/world_generator.h +++ b/examples/gfx/opengl/4_opengl_bexel/world/world_generator.h @@ -11,13 +11,13 @@ namespace bexel { class WorldGenerator { private: - const i32 m_seed; + const i32 seed; public: WorldGenerator(const i32& seed); - BlockID get_voxel_at(const Vec3f& voxelPosF) const; - TileBlock* create_voxel_at(const Chunk& chunk, const Vec3i& voxelPosI) const; + BlockID get_voxel_at(const Vec3f& voxel_pos_f) const; + TileBlock* create_voxel_at(const Chunk& chunk, const Vec3i& voxel_pos_i) const; }; } diff --git a/examples/gfx/opengl/5_opengl_flappy_bird/CMakeLists.txt b/examples/gfx/opengl/5_opengl_flappy_bird/CMakeLists.txt index 65f503ff..578ed9b0 100644 --- a/examples/gfx/opengl/5_opengl_flappy_bird/CMakeLists.txt +++ b/examples/gfx/opengl/5_opengl_flappy_bird/CMakeLists.txt @@ -1,7 +1,7 @@ file(GLOB_RECURSE BEBONE_EXAMPLE_GFX_OPENGL_5_OPENGL_FLAPPY_BIRD *.cpp) -include_directories("../../src") include_directories("./") +include_directories(${BEBONE_INCLUDES}) add_executable(Bebone_Example_Gfx_5_Opengl_Flappy_Bird ${BEBONE_EXAMPLE_GFX_OPENGL_5_OPENGL_FLAPPY_BIRD}) target_link_libraries(Bebone_Example_Gfx_5_Opengl_Flappy_Bird bebone) diff --git a/examples/gfx/opengl/5_opengl_flappy_bird/assets/vertex.glsl b/examples/gfx/opengl/5_opengl_flappy_bird/assets/vertex.glsl index b0f997ef..40446c4d 100644 --- a/examples/gfx/opengl/5_opengl_flappy_bird/assets/vertex.glsl +++ b/examples/gfx/opengl/5_opengl_flappy_bird/assets/vertex.glsl @@ -7,11 +7,10 @@ layout (location = 2) in float a_TextureUnit; layout (location = 0) out vec2 v_TexCoords; layout (location = 1) out flat float v_TextureUnit; -uniform mat4 u_Model; uniform mat4 u_Projection; void main() { v_TexCoords = a_TexCoords; v_TextureUnit = a_TextureUnit; - gl_Position = u_Projection * u_Model * vec4(a_Position, 1.0); + gl_Position = u_Projection * vec4(a_Position, 1.0); } \ No newline at end of file diff --git a/examples/gfx/opengl/5_opengl_flappy_bird/core/batch.cpp b/examples/gfx/opengl/5_opengl_flappy_bird/core/batch.cpp index 0c6b47c4..90713b75 100644 --- a/examples/gfx/opengl/5_opengl_flappy_bird/core/batch.cpp +++ b/examples/gfx/opengl/5_opengl_flappy_bird/core/batch.cpp @@ -1,29 +1,29 @@ #include "batch.h" namespace game::core { - Batch::Batch(shared_ptr& shaderProgram, shared_ptr& camera, const size_t& quadLimit) : - camera(camera), shaderProgram(shaderProgram), cachedTextureUnits(map, int>()), texturesToDraw(vector>()), currentTextureUnitIndex(0), indicesSize(0), quadSize(0), quadLimit(quadLimit) { - - textureUnitCapacity = min({GLGpuProperties::texture_unit_capacity(), MAX_TEXTURE_UNITS}); + Batch::Batch(shared_ptr& shader_program, shared_ptr& camera, const size_t& quad_limit) : + camera(camera), shader_program(shader_program), cached_texture_units(map, int>()), textures_to_draw(vector>()), current_texture_unit_index(0), indices_size(0), quad_size(0), quad_limit(quad_limit) { + + texture_unit_capacity = min({GLGpuProperties::texture_unit_capacity(), max_texture_units}); - size_t indexLimit = quadLimit * 6; - size_t vertexLimit = quadLimit * 4; + size_t index_limit = quad_limit * 6; + size_t vertex_limit = quad_limit * 4; vao = make_shared(); vao->bind(); - vbo = make_shared(nullptr, vertexLimit * sizeof(ShaderVertex), GL_DYNAMIC_DRAW); - ebo = make_shared(nullptr, indexLimit * sizeof(u32), GL_DYNAMIC_DRAW); + vbo = make_shared(nullptr, vertex_limit * sizeof(ShaderVertex), GL_DYNAMIC_DRAW); + ebo = make_shared(nullptr, index_limit * sizeof(u32), GL_DYNAMIC_DRAW); vao->link_attributes(*vbo, 0, 3, GL_FLOAT, sizeof(ShaderVertex), (void*)offsetof(ShaderVertex, position)); - vao->link_attributes(*vbo, 1, 2, GL_FLOAT, sizeof(ShaderVertex), (void*)offsetof(ShaderVertex, textureCoordinates)); - vao->link_attributes(*vbo, 2, 1, GL_INT, sizeof(ShaderVertex), (void*)offsetof(ShaderVertex, textureUnit)); + vao->link_attributes(*vbo, 1, 2, GL_FLOAT, sizeof(ShaderVertex), (void*)offsetof(ShaderVertex, texture_coordinates)); + vao->link_attributes(*vbo, 2, 1, GL_INT, sizeof(ShaderVertex), (void*)offsetof(ShaderVertex, texture_unit)); vao->unbind(); vbo->unbind(); ebo->unbind(); #ifdef BATCH_DEBUG - drawCalls = 0; + draw_calls = 0; #endif } @@ -37,75 +37,69 @@ namespace game::core { ebo->destroy(); ebo = nullptr; - shaderProgram->destroy(); - shaderProgram = nullptr; + shader_program->destroy(); + shader_program = nullptr; } - void Batch::add(const shared_ptr& gameObject) { - if (gameObjectsToDraw.find(gameObject) == gameObjectsToDraw.end()) { - auto renderer = gameObject->get_component(); + void Batch::add(const shared_ptr& game_object) { + if (game_objects_to_draw.find(game_object) == game_objects_to_draw.end()) { + auto renderer = game_object->get_component(); if (renderer != nullptr) { - gameObjectsToDraw[gameObject] = renderer; + game_objects_to_draw[game_object] = renderer; } else { - cout << gameObject->get_name() << " does not have a SpriteRenderer!"; + cout << game_object->get_name() << " does not have a SpriteRenderer!"; } } } - void Batch::remove(const shared_ptr& gameObject) { - gameObjectsToDraw.erase(gameObject); + void Batch::remove(const shared_ptr& game_object) { + game_objects_to_draw.erase(game_object); } void Batch::render() { - gameObjectsToDrawIterator = gameObjectsToDraw.begin(); + game_objects_to_draw_iterator = game_objects_to_draw.begin(); #ifdef BATCH_DEBUG - drawCalls = 0; + draw_calls = 0; #endif - while (gameObjectsToDrawIterator != gameObjectsToDraw.end()) { + while (game_objects_to_draw_iterator != game_objects_to_draw.end()) { upload_textures(); - shaderProgram->enable(); - - Mat4f model = Mat4f::identity(); - model = model * model.scale(1.0f); - model = model * omni::types::trait_bryan_angle_yxz(Vec3f(0.0f, 0.0f, 0.0f)); - model = model * model.translation(Vec3f(0.0f, 0.0f, 0.0f)); + shader_program->enable(); - for (auto texture : texturesToDraw) { - texture->bind_texture_unit(cachedTextureUnits[texture]); + for (const auto& texture : textures_to_draw) { + texture->bind_texture_unit(cached_texture_units[texture]); } vao->bind(); - shaderProgram->set_uniform("u_Model", model); - shaderProgram->set_uniform("u_Projection", camera->get_projection_matrix()); - shaderProgram->set_uniform("u_Textures", textureUnitCapacity, samplers); - GLContext::draw_elements(GL_TRIANGLES, static_cast(indicesSize), GL_UNSIGNED_INT, nullptr); + shader_program->set_uniform("u_Projection", camera->get_projection_matrix()); + shader_program->set_uniform("u_Textures", texture_unit_capacity, samplers); + GLContext::draw_elements(GL_TRIANGLES, static_cast(indices_size), GL_UNSIGNED_INT, nullptr); vao->unbind(); - quadSize = 0; - indicesSize = 0; - currentTextureUnitIndex = 0; - cachedTextureUnits.clear(); - texturesToDraw.clear(); + quad_size = 0; + indices_size = 0; + current_texture_unit_index = 0; + cached_texture_units.clear(); + textures_to_draw.clear(); #ifdef BATCH_DEBUG - ++drawCalls; + ++draw_calls; #endif } } void Batch::upload_textures() { - while (gameObjectsToDrawIterator != gameObjectsToDraw.end()) { - if (quadSize + 1 > quadLimit) { + while (game_objects_to_draw_iterator != game_objects_to_draw.end()) { + if (quad_size + 1 > quad_limit) { return; } - auto gameObject = gameObjectsToDrawIterator->first; - auto renderer = gameObjectsToDrawIterator->second; + auto game_object = game_objects_to_draw_iterator->first; + auto renderer = game_objects_to_draw_iterator->second; - auto transform = gameObject->get_transform(); + auto transform = game_object->get_transform(); auto sprite = renderer->get_sprite(); auto texture = sprite->get_texture(); @@ -113,33 +107,33 @@ namespace game::core { return; } - auto quad = create_quad(sprite, transform, cachedTextureUnits[texture]); - size_t verticesSize = quad.size() * sizeof(ShaderVertex); + auto quad = create_quad(sprite, transform, cached_texture_units[texture]); + size_t vertices_size = quad.size() * sizeof(ShaderVertex); - vbo->buffer_sub_data(quadSize * verticesSize, verticesSize, quad.data()); - ++quadSize; + vbo->buffer_sub_data(quad_size * vertices_size, vertices_size, quad.data()); + ++quad_size; add_indices(); - ++gameObjectsToDrawIterator; + ++game_objects_to_draw_iterator; } } bool Batch::try_cache_texture(const shared_ptr& texture) { - if (currentTextureUnitIndex >= textureUnitCapacity) { + if (current_texture_unit_index >= texture_unit_capacity) { return false; } - if (cachedTextureUnits.find(texture) == cachedTextureUnits.end()) { - cachedTextureUnits[texture] = currentTextureUnitIndex; - ++currentTextureUnitIndex; + if (cached_texture_units.find(texture) == cached_texture_units.end()) { + cached_texture_units[texture] = current_texture_unit_index; + ++current_texture_unit_index; - texturesToDraw.push_back(texture); + textures_to_draw.push_back(texture); } return true; } - array Batch::create_quad(const shared_ptr& sprite, const shared_ptr& transform, const int& textureUnit) { + array Batch::create_quad(const shared_ptr& sprite, const shared_ptr& transform, const int& texture_unit) { Vec3f position = transform->get_position(); f32 scale = transform->get_scale(); f32 rotation = transform->get_rotation(); @@ -149,62 +143,62 @@ namespace game::core { Vec2f tmp; ShaderVertex v0; - tmp = rotateVertex( {-width, -height}, rotation); + tmp = rotate_vertex({-width, -height}, rotation); v0.position = Vec3f(position.x + tmp.x, position.y + tmp.y, position.z); - v0.textureCoordinates = { 0.0f, 0.0f }; - v0.textureUnit = textureUnit; + v0.texture_coordinates = {0.0f, 0.0f }; + v0.texture_unit = texture_unit; ShaderVertex v1; - tmp = rotateVertex( {-width, height}, rotation); + tmp = rotate_vertex({-width, height}, rotation); v1.position = Vec3f(position.x + tmp.x, position.y + tmp.y, position.z); - v1.textureCoordinates = { 0.0f, 1.0f }; - v1.textureUnit = textureUnit; + v1.texture_coordinates = {0.0f, 1.0f }; + v1.texture_unit = texture_unit; ShaderVertex v2; - tmp = rotateVertex( {width, height}, rotation); + tmp = rotate_vertex({width, height}, rotation); v2.position = Vec3f(position.x + tmp.x, position.y + tmp.y, position.z); - v2.textureCoordinates = { 1.0f, 1.0f }; - v2.textureUnit = textureUnit; + v2.texture_coordinates = {1.0f, 1.0f }; + v2.texture_unit = texture_unit; ShaderVertex v3; - tmp = rotateVertex( {width, -height}, rotation); + tmp = rotate_vertex({width, -height}, rotation); v3.position = Vec3f(position.x + tmp.x, position.y + tmp.y, position.z); - v3.textureCoordinates = { 1.0f, 0.0f }; - v3.textureUnit = textureUnit; + v3.texture_coordinates = {1.0f, 0.0f }; + v3.texture_unit = texture_unit; return { v0, v1, v2, v3 }; } - Vec2f Batch::rotateVertex(const Vec2f& v, const f32& angle) const { - Vec2f newV = v; + Vec2f Batch::rotate_vertex(const Vec2f& v, const f32& angle) const { + Vec2f new_v = v; double radian = Math::deg_to_rad(angle); - newV.x = v.x * cos(radian) - v.y * sin(radian); - newV.y = v.x * sin(radian) + v.y * cos(radian); - return newV; + new_v.x = v.x * cos(radian) - v.y * sin(radian); + new_v.y = v.x * sin(radian) + v.y * cos(radian); + return new_v; } void Batch::add_indices() { unsigned int indices[6]; - size_t totalVerticesSize = quadSize * 4; + size_t total_vertices_size = quad_size * 4; - indices[0] = totalVerticesSize - 4; - indices[1] = totalVerticesSize - 3; - indices[2] = totalVerticesSize - 1; + indices[0] = total_vertices_size - 4; + indices[1] = total_vertices_size - 3; + indices[2] = total_vertices_size - 1; - indices[3] = totalVerticesSize - 3; - indices[4] = totalVerticesSize - 2; - indices[5] = totalVerticesSize - 1; + indices[3] = total_vertices_size - 3; + indices[4] = total_vertices_size - 2; + indices[5] = total_vertices_size - 1; - ebo->buffer_sub_data(indicesSize * sizeof(unsigned int), sizeof(indices), indices); + ebo->buffer_sub_data(indices_size * sizeof(unsigned int), sizeof(indices), indices); - indicesSize += 6; + indices_size += 6; } #pragma region debug #ifdef BATCH_DEBUG size_t Batch::get_draw_call_count() const { - return drawCalls; + return draw_calls; } #endif #pragma endregion diff --git a/examples/gfx/opengl/5_opengl_flappy_bird/core/batch.h b/examples/gfx/opengl/5_opengl_flappy_bird/core/batch.h index 001df85c..345f5b3a 100644 --- a/examples/gfx/opengl/5_opengl_flappy_bird/core/batch.h +++ b/examples/gfx/opengl/5_opengl_flappy_bird/core/batch.h @@ -20,51 +20,51 @@ namespace game::core { using namespace bebone::core; using namespace std; - using namespace bebone::gfx::opengl; + using namespace bebone::gfx; using namespace ecs; class Batch : private NonCopyable { private: shared_ptr camera; - shared_ptr shaderProgram; + shared_ptr shader_program; shared_ptr vao; shared_ptr vbo; shared_ptr ebo; - const int MAX_TEXTURE_UNITS = 32; - int textureUnitCapacity; + const int max_texture_units = 32; + int texture_unit_capacity; int samplers[32] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}; - map, shared_ptr> gameObjectsToDraw; - map, shared_ptr>::iterator gameObjectsToDrawIterator; + map, shared_ptr> game_objects_to_draw; + map, shared_ptr>::iterator game_objects_to_draw_iterator; - map, int> cachedTextureUnits; - vector> texturesToDraw; - int currentTextureUnitIndex; + map, int> cached_texture_units; + vector> textures_to_draw; + int current_texture_unit_index; - size_t indicesSize; - size_t quadSize; - size_t quadLimit; + size_t indices_size; + size_t quad_size; + size_t quad_limit; #pragma region debug #ifdef BATCH_DEBUG - size_t drawCalls; + size_t draw_calls; #endif #pragma endregion - array create_quad(const shared_ptr& sprite, const shared_ptr& transform, const int& textureUnit); + array create_quad(const shared_ptr& sprite, const shared_ptr& transform, const int& texture_unit); void add_indices(); void upload_textures(); - Vec2f rotateVertex(const Vec2f& v, const f32& angle) const; + Vec2f rotate_vertex(const Vec2f& v, const f32& angle) const; bool try_cache_texture(const shared_ptr& texture); public: - Batch(shared_ptr& shaderProgram, shared_ptr& camera, const size_t& quadLimit); + Batch(shared_ptr& shader_program, shared_ptr& camera, const size_t& quad_limit); ~Batch(); - void add(const shared_ptr& gameObject); - void remove(const shared_ptr& gameObject); + void add(const shared_ptr& game_object); + void remove(const shared_ptr& game_object); void render(); #pragma region debug diff --git a/examples/gfx/opengl/5_opengl_flappy_bird/core/entity_component_system/components/collider.cpp b/examples/gfx/opengl/5_opengl_flappy_bird/core/entity_component_system/components/collider.cpp index 1bb22c6d..9386a0e4 100644 --- a/examples/gfx/opengl/5_opengl_flappy_bird/core/entity_component_system/components/collider.cpp +++ b/examples/gfx/opengl/5_opengl_flappy_bird/core/entity_component_system/components/collider.cpp @@ -1,22 +1,22 @@ #include "collider.h" namespace game::core::ecs { - Collider::Collider(const Vec2f& localTopLeft, const Vec2f& localBottomRight, const bool& isTrigger) : topLeft(localTopLeft), bottomRight(localBottomRight), isTrigger(isTrigger) { } + Collider::Collider(const Vec2f& local_top_left, const Vec2f& local_bottom_right, const bool& is_trigger) : top_left(local_top_left), bottom_right(local_bottom_right), trigger(is_trigger) { } Vec2f Collider::get_top_left() const { - return topLeft; + return top_left; } Vec2f Collider::get_bottom_right() const { - return bottomRight; + return bottom_right; } bool Collider::is_trigger() const { - return isTrigger; + return trigger; } void Collider::enter_trigger() { - if (isTrigger) { + if (trigger) { triggered = true; } } @@ -26,7 +26,7 @@ namespace game::core::ecs { } bool Collider::is_triggered() const { - if (isTrigger) { + if (trigger) { return triggered; } diff --git a/examples/gfx/opengl/5_opengl_flappy_bird/core/entity_component_system/components/collider.h b/examples/gfx/opengl/5_opengl_flappy_bird/core/entity_component_system/components/collider.h index 6d48ad8e..33863331 100644 --- a/examples/gfx/opengl/5_opengl_flappy_bird/core/entity_component_system/components/collider.h +++ b/examples/gfx/opengl/5_opengl_flappy_bird/core/entity_component_system/components/collider.h @@ -10,14 +10,14 @@ namespace game::core::ecs { class Collider : public Component { private: - Vec2f topLeft; - Vec2f bottomRight; + Vec2f top_left; + Vec2f bottom_right; - bool isTrigger; + bool trigger; bool triggered = false; public: - Collider(const Vec2f& localTopLeft, const Vec2f& localBottomRight, const bool& isTrigger = false); + Collider(const Vec2f& local_top_left, const Vec2f& local_bottom_right, const bool& is_trigger = false); void update() override { } [[nodiscard]] Vec2f get_top_left() const; diff --git a/examples/gfx/opengl/5_opengl_flappy_bird/core/entity_component_system/components/cyclic_movement.cpp b/examples/gfx/opengl/5_opengl_flappy_bird/core/entity_component_system/components/cyclic_movement.cpp index 2c9c2486..7f04396d 100644 --- a/examples/gfx/opengl/5_opengl_flappy_bird/core/entity_component_system/components/cyclic_movement.cpp +++ b/examples/gfx/opengl/5_opengl_flappy_bird/core/entity_component_system/components/cyclic_movement.cpp @@ -1,24 +1,23 @@ #include "cyclic_movement.h" -#include "../../game_time.h" #include "../../rng.h" namespace game::core::ecs { - CyclicMovement::CyclicMovement(const float& endXPoint, const float& startXPoint, const bool& randomizeY) : - randomizeY(randomizeY), endXPoint(endXPoint), startXPoint(startXPoint) { } + CyclicMovement::CyclicMovement(const float& end_x_point, const float& start_x_point, const bool& randomize_y) : + randomize_y(randomize_y), end_x_point(end_x_point), start_x_point(start_x_point) { } void CyclicMovement::update() { - Vec3f movement = Vec3f::left * speed * Time::deltaTime; + Vec3f movement = Vec3f::left * speed * Time::get_delta_time(); auto& transform = get_transform(); - if (transform->get_position().x + movement.x < endXPoint) { + if (transform->get_position().x + movement.x < end_x_point) { float y = transform->get_position().y; - if (randomizeY) { - y = Random::rand(minY, maxY); + if (randomize_y) { + y = Random::rand(min_y, max_y); } - transform->set_position(Vec3f(startXPoint, y, transform->get_position().z)); + transform->set_position(Vec3f(start_x_point, y, transform->get_position().z)); } else { transform->move(movement); } diff --git a/examples/gfx/opengl/5_opengl_flappy_bird/core/entity_component_system/components/cyclic_movement.h b/examples/gfx/opengl/5_opengl_flappy_bird/core/entity_component_system/components/cyclic_movement.h index 9b6e3295..1c7fa26d 100644 --- a/examples/gfx/opengl/5_opengl_flappy_bird/core/entity_component_system/components/cyclic_movement.h +++ b/examples/gfx/opengl/5_opengl_flappy_bird/core/entity_component_system/components/cyclic_movement.h @@ -16,15 +16,15 @@ namespace game::core::ecs { private: float speed = 2.5f; - bool randomizeY = false; - float minY = -3.0f; - float maxY = 4.5f; + bool randomize_y = false; + float min_y = -3.0f; + float max_y = 4.5f; - float endXPoint; - float startXPoint; + float end_x_point; + float start_x_point; public: - CyclicMovement(const float& endXPoint, const float& startXPoint, const bool& randomizeY = false); + CyclicMovement(const float& end_x_point, const float& start_x_point, const bool& randomize_y = false); void update() override; }; diff --git a/examples/gfx/opengl/5_opengl_flappy_bird/core/entity_component_system/components/flying.cpp b/examples/gfx/opengl/5_opengl_flappy_bird/core/entity_component_system/components/flying.cpp index 5b91eef9..73b7408c 100644 --- a/examples/gfx/opengl/5_opengl_flappy_bird/core/entity_component_system/components/flying.cpp +++ b/examples/gfx/opengl/5_opengl_flappy_bird/core/entity_component_system/components/flying.cpp @@ -3,40 +3,40 @@ #include namespace game::core::ecs { - Flying::Flying(const float& flyForce) : velocityY(0.0f), flyForce(flyForce) { - flyFunction = std::function([this]() { - set_velocity(this->flyForce); + Flying::Flying(const float& fly_force, const shared_ptr& input) : velocity_y(0.0f), fly_force(fly_force), input(input) { + fly_function = std::function([this]() { + set_velocity(this->fly_force); }); } void Flying::update() { - velocityY += Time::deltaTime * -gravity; + velocity_y += Time::get_delta_time() * -gravity; auto& transform = get_transform(); - transform->set_position(Vec3f(transform->get_position().x, transform->get_position().y + velocityY, transform->get_position().z)); + transform->set_position(Vec3f(transform->get_position().x, transform->get_position().y + velocity_y, transform->get_position().z)); - if (velocityY < 0) { - float rotZ = transform->get_rotation(); - rotZ += rotZAlterationSpeed * Time::deltaTime * std::abs(velocityY * 2); + if (velocity_y < 0) { + float rot_z = transform->get_rotation(); + rot_z += rot_z_alteration_speed * Time::get_delta_time() * std::abs(velocity_y * 2); - if (rotZ > minRotZ) { - transform->set_rotation(rotZ); + if (rot_z > min_rot_z) { + transform->set_rotation(rot_z); } } } void Flying::set_velocity(const float& velocity) { - velocityY = velocity; - get_transform()->set_rotation(this->maxRotZ); + velocity_y = velocity; + get_transform()->set_rotation(this->max_rot_z); } void Flying::enable() { Component::enable(); - Input::get_instance().register_key_action(KeyCode::MOUSE_BUTTON_LEFT, flyFunction); + input->register_key_action(KeyCode::MouseButtonLeft, fly_function); } void Flying::disable() { Component::disable(); - Input::get_instance().remove_key_action(KeyCode::MOUSE_BUTTON_LEFT, flyFunction); + input->remove_key_action(KeyCode::MouseButtonLeft, fly_function); } } \ No newline at end of file diff --git a/examples/gfx/opengl/5_opengl_flappy_bird/core/entity_component_system/components/flying.h b/examples/gfx/opengl/5_opengl_flappy_bird/core/entity_component_system/components/flying.h index bd06f798..cd549768 100644 --- a/examples/gfx/opengl/5_opengl_flappy_bird/core/entity_component_system/components/flying.h +++ b/examples/gfx/opengl/5_opengl_flappy_bird/core/entity_component_system/components/flying.h @@ -8,26 +8,26 @@ #include "../game_object.h" #include "../transform.h" -#include "../../game_time.h" - namespace game::core::ecs { using namespace bebone::core; using namespace std; class Flying : public Component { private: - float velocityY; + float velocity_y; const float gravity = 0.1f; - float flyForce; + float fly_force; + + float rot_z_alteration_speed = -550.0f; + float min_rot_z = -85.0f; + float max_rot_z = 25.0f; - float rotZAlterationSpeed = -550.0f; - float minRotZ = -85.0f; - float maxRotZ = 25.0f; + std::shared_ptr input; - std::function flyFunction; + std::function fly_function; public: - explicit Flying(const float& flyForce); + explicit Flying(const float& fly_force, const std::shared_ptr& input); void update() override; diff --git a/examples/gfx/opengl/5_opengl_flappy_bird/core/entity_component_system/game_object.cpp b/examples/gfx/opengl/5_opengl_flappy_bird/core/entity_component_system/game_object.cpp index c3089832..1c3bc510 100644 --- a/examples/gfx/opengl/5_opengl_flappy_bird/core/entity_component_system/game_object.cpp +++ b/examples/gfx/opengl/5_opengl_flappy_bird/core/entity_component_system/game_object.cpp @@ -20,18 +20,18 @@ namespace game::core::ecs { } void GameObject::update() { - for (auto mapIt = components.begin(); mapIt != components.end(); ++mapIt) { - auto v = (*mapIt).second; - auto vIt = v.begin(); + for (auto map_it = components.begin(); map_it != components.end(); ++map_it) { + auto v = (*map_it).second; + auto v_it = v.begin(); - while (vIt != v.end()) { - auto component = *vIt; + while (v_it != v.end()) { + auto component = *v_it; if (component->is_enabled()) { component->update(); } - ++vIt; + ++v_it; } } } diff --git a/examples/gfx/opengl/5_opengl_flappy_bird/core/entity_component_system/game_object.h b/examples/gfx/opengl/5_opengl_flappy_bird/core/entity_component_system/game_object.h index 9fac6ec7..b3e2e5af 100644 --- a/examples/gfx/opengl/5_opengl_flappy_bird/core/entity_component_system/game_object.h +++ b/examples/gfx/opengl/5_opengl_flappy_bird/core/entity_component_system/game_object.h @@ -61,13 +61,13 @@ namespace game::core::ecs { template vector> get_components() { auto v = components[typeid(T)]; - auto vOut = vector>(); + auto v_out = vector>(); for (auto & it : v) { - vOut.push_back(dynamic_pointer_cast(it)); + v_out.push_back(dynamic_pointer_cast(it)); } - return vOut; + return v_out; } }; diff --git a/examples/gfx/opengl/5_opengl_flappy_bird/core/entity_component_system/transform.cpp b/examples/gfx/opengl/5_opengl_flappy_bird/core/entity_component_system/transform.cpp index 09c8362b..d88372cf 100644 --- a/examples/gfx/opengl/5_opengl_flappy_bird/core/entity_component_system/transform.cpp +++ b/examples/gfx/opengl/5_opengl_flappy_bird/core/entity_component_system/transform.cpp @@ -14,24 +14,24 @@ namespace game::core::ecs { return position; } - void Transform::set_position(const Vec3f& newPosition) { - position = newPosition; + void Transform::set_position(const Vec3f& new_position) { + position = new_position; } const f32& Transform::get_rotation() const { return rotation; } - void Transform::set_rotation(const f32& newRotation) { - rotation = newRotation; + void Transform::set_rotation(const f32& new_rotation) { + rotation = new_rotation; } const f32& Transform::get_scale() const { return scale; } - void Transform::set_scale(const f32& newScale) { - scale = newScale; + void Transform::set_scale(const f32& new_scale) { + scale = new_scale; } void Transform::move(const Vec3f& v) { diff --git a/examples/gfx/opengl/5_opengl_flappy_bird/core/entity_component_system/transform.h b/examples/gfx/opengl/5_opengl_flappy_bird/core/entity_component_system/transform.h index f14076d1..becf8f4a 100644 --- a/examples/gfx/opengl/5_opengl_flappy_bird/core/entity_component_system/transform.h +++ b/examples/gfx/opengl/5_opengl_flappy_bird/core/entity_component_system/transform.h @@ -18,13 +18,13 @@ namespace game::core::ecs { Transform(const Vec3f& position, const f32& rotation, const f32& scale); const Vec3f& get_position() const; - void set_position(const Vec3f& newPosition); + void set_position(const Vec3f& new_position); const f32& get_rotation() const; - void set_rotation(const f32& newRotation); + void set_rotation(const f32& new_rotation); const f32& get_scale() const; - void set_scale(const f32& newScale); + void set_scale(const f32& new_scale); void move(const Vec3f& v); }; diff --git a/examples/gfx/opengl/5_opengl_flappy_bird/core/finite_state_machine/state_machine.cpp b/examples/gfx/opengl/5_opengl_flappy_bird/core/finite_state_machine/state_machine.cpp index 4abae451..87a9e563 100644 --- a/examples/gfx/opengl/5_opengl_flappy_bird/core/finite_state_machine/state_machine.cpp +++ b/examples/gfx/opengl/5_opengl_flappy_bird/core/finite_state_machine/state_machine.cpp @@ -1,19 +1,19 @@ #include "state_machine.h" namespace game::core::fsm { - std::shared_ptr StateMachine::currentState = nullptr; + std::shared_ptr StateMachine::current_state = nullptr; void StateMachine::set_state(std::shared_ptr state) { - if (currentState != nullptr) { - currentState->exit(); + if (current_state != nullptr) { + current_state->exit(); } state->enter(); - currentState = state; + current_state = state; } void StateMachine::update_current_state() { - currentState->update(); + current_state->update(); } } diff --git a/examples/gfx/opengl/5_opengl_flappy_bird/core/finite_state_machine/state_machine.h b/examples/gfx/opengl/5_opengl_flappy_bird/core/finite_state_machine/state_machine.h index 28e1e8f7..70e06a16 100644 --- a/examples/gfx/opengl/5_opengl_flappy_bird/core/finite_state_machine/state_machine.h +++ b/examples/gfx/opengl/5_opengl_flappy_bird/core/finite_state_machine/state_machine.h @@ -9,7 +9,7 @@ namespace game::core::fsm { class StateMachine : private bebone::core::NonCopyable { private: - static std::shared_ptr currentState; + static std::shared_ptr current_state; public: void static set_state(std::shared_ptr state); diff --git a/examples/gfx/opengl/5_opengl_flappy_bird/core/finite_state_machine/states/end_game_state.cpp b/examples/gfx/opengl/5_opengl_flappy_bird/core/finite_state_machine/states/end_game_state.cpp index afe097bf..5dc4eeb1 100644 --- a/examples/gfx/opengl/5_opengl_flappy_bird/core/finite_state_machine/states/end_game_state.cpp +++ b/examples/gfx/opengl/5_opengl_flappy_bird/core/finite_state_machine/states/end_game_state.cpp @@ -5,30 +5,30 @@ #include "../../score.h" namespace game::core::fsm { - EndGameState::EndGameState(shared_ptr flappyBird) : menuState(nullptr), flappyBird(std::move(flappyBird)) { - transitionFunction = [this]() { - StateMachine::set_state(menuState); + EndGameState::EndGameState(shared_ptr flappy_bird, const shared_ptr& input) : menu_state(nullptr), flappy_bird(std::move(flappy_bird)), input(input) { + transition_function = [this]() { + StateMachine::set_state(menu_state); }; } EndGameState::~EndGameState() { - menuState = nullptr; - flappyBird = nullptr; + menu_state = nullptr; + flappy_bird = nullptr; } void EndGameState::enter() { cout << "Game Over" << endl; cout << "Your score: " << Score::get_score() << endl; - Input::get_instance().register_key_action(KeyCode::MOUSE_BUTTON_LEFT, transitionFunction); + input->register_key_action(KeyCode::MouseButtonLeft, transition_function); } void EndGameState::exit() { - Input::get_instance().remove_key_action(KeyCode::MOUSE_BUTTON_LEFT, transitionFunction); + input->remove_key_action(KeyCode::MouseButtonLeft, transition_function); Score::clear(); } void EndGameState::set_menu_state(shared_ptr menuState) { - this->menuState = std::move(menuState); + this->menu_state = std::move(menuState); } } \ No newline at end of file diff --git a/examples/gfx/opengl/5_opengl_flappy_bird/core/finite_state_machine/states/end_game_state.h b/examples/gfx/opengl/5_opengl_flappy_bird/core/finite_state_machine/states/end_game_state.h index 4288c98e..0d2c1c63 100644 --- a/examples/gfx/opengl/5_opengl_flappy_bird/core/finite_state_machine/states/end_game_state.h +++ b/examples/gfx/opengl/5_opengl_flappy_bird/core/finite_state_machine/states/end_game_state.h @@ -16,19 +16,20 @@ namespace game::core::fsm { class EndGameState : public State { private: - shared_ptr menuState; - shared_ptr flappyBird; + shared_ptr menu_state; + shared_ptr flappy_bird; + shared_ptr input; - std::function transitionFunction; + std::function transition_function; public: - EndGameState(shared_ptr flappyBird); + EndGameState(shared_ptr flappy_bird, const shared_ptr& input); ~EndGameState() override; void enter() override; void update() override {}; void exit() override; - void set_menu_state(shared_ptr menuState); + void set_menu_state(shared_ptr menu_state); }; } diff --git a/examples/gfx/opengl/5_opengl_flappy_bird/core/finite_state_machine/states/game_state.cpp b/examples/gfx/opengl/5_opengl_flappy_bird/core/finite_state_machine/states/game_state.cpp index 56d60ec9..2fc67cec 100644 --- a/examples/gfx/opengl/5_opengl_flappy_bird/core/finite_state_machine/states/game_state.cpp +++ b/examples/gfx/opengl/5_opengl_flappy_bird/core/finite_state_machine/states/game_state.cpp @@ -12,58 +12,60 @@ namespace game::core::fsm { #define FLY_FORCE 0.06f - GameState::GameState(const shared_ptr& flappyBird) : endGameState(nullptr), flappyBird(flappyBird) { + GameState::GameState(const shared_ptr& flappy_bird, const shared_ptr& input) + : end_game_state(nullptr), flappy_bird(flappy_bird), input(input) { + ground1 = Game::find_game_object_by_name("Ground1"); ground2 = Game::find_game_object_by_name("Ground2"); pipe1 = Game::find_game_object_by_name("Pipe1"); pipe2 = Game::find_game_object_by_name("Pipe2"); - auto groundSprite = ground2->get_component()->get_sprite(); + auto ground_sprite = ground2->get_component()->get_sprite(); - float endPoint = -groundSprite->get_unit_width() + 0.05f; - float startPoint = -endPoint; + float end_point = -ground_sprite->get_unit_width() + 0.05f; + float start_point = -end_point; - ground1->add_component(endPoint, startPoint)->disable(); - ground2->add_component(endPoint, startPoint)->disable(); + ground1->add_component(end_point, start_point)->disable(); + ground2->add_component(end_point, start_point)->disable(); pipe1->add_component(-6.2f, 6.2f, true)->disable(); pipe2->add_component(-6.2f, 6.2f, true)->disable(); - auto pipeSprite = pipe1->get_component()->get_sprite(); - float emptySpace = 1.45f; // hardcoded value - Vec2f topPipeColliderTopLeftPoint = { -pipeSprite->get_unit_width() / 2.0f, pipeSprite->get_unit_height() / 2.0f }; - Vec2f topPipeColliderBottomRightPoint = { pipeSprite->get_unit_width() / 2.0f, emptySpace }; - pipe1->add_component(topPipeColliderTopLeftPoint, topPipeColliderBottomRightPoint); - pipe2->add_component(topPipeColliderTopLeftPoint, topPipeColliderBottomRightPoint); + auto pipe_sprite = pipe1->get_component()->get_sprite(); + float empty_space = 1.45f; // hardcoded value + Vec2f top_pipe_collider_top_left_point = { -pipe_sprite->get_unit_width() / 2.0f, pipe_sprite->get_unit_height() / 2.0f }; + Vec2f top_pipe_collider_bottom_right_point = { pipe_sprite->get_unit_width() / 2.0f, empty_space }; + pipe1->add_component(top_pipe_collider_top_left_point, top_pipe_collider_bottom_right_point); + pipe2->add_component(top_pipe_collider_top_left_point, top_pipe_collider_bottom_right_point); - Vec2f bottomPipeColliderTopLeftPoint = { -pipeSprite->get_unit_width() / 2.0f, -emptySpace }; - Vec2f bottomPipeColliderBottomRightPoint = { pipeSprite->get_unit_width() / 2.0f, -pipeSprite->get_unit_height() / 2.0f }; - pipe1->add_component(bottomPipeColliderTopLeftPoint, bottomPipeColliderBottomRightPoint); - pipe2->add_component(bottomPipeColliderTopLeftPoint, bottomPipeColliderBottomRightPoint); + Vec2f bottom_pipe_collider_top_left_point = { -pipe_sprite->get_unit_width() / 2.0f, -empty_space }; + Vec2f bottom_pipe_collider_bottom_right_point = { pipe_sprite->get_unit_width() / 2.0f, -pipe_sprite->get_unit_height() / 2.0f }; + pipe1->add_component(bottom_pipe_collider_top_left_point, bottom_pipe_collider_bottom_right_point); + pipe2->add_component(bottom_pipe_collider_top_left_point, bottom_pipe_collider_bottom_right_point); - Vec2f emptySpaceTriggerTopLeftPoint = { -pipeSprite->get_unit_width() / 3.5f, emptySpace }; - Vec2f emptySpaceTriggerBottomRightPoint = { pipeSprite->get_unit_width() / 3.5f, -emptySpace }; - pipe1->add_component(emptySpaceTriggerTopLeftPoint, emptySpaceTriggerBottomRightPoint, true); - pipe2->add_component(emptySpaceTriggerTopLeftPoint, emptySpaceTriggerBottomRightPoint, true); + Vec2f empty_space_trigger_top_left_point = { -pipe_sprite->get_unit_width() / 3.5f, empty_space }; + Vec2f empty_space_trigger_bottom_right_point = { pipe_sprite->get_unit_width() / 3.5f, -empty_space }; + pipe1->add_component(empty_space_trigger_top_left_point, empty_space_trigger_bottom_right_point, true); + pipe2->add_component(empty_space_trigger_top_left_point, empty_space_trigger_bottom_right_point, true); - flappyBird->add_component(FLY_FORCE)->disable(); + flappy_bird->add_component(FLY_FORCE, input)->disable(); - auto flappyBirdSprite = flappyBird->get_component()->get_sprite(); - Vec2f flappyBirdColliderTopLeftPoint = { -flappyBirdSprite->get_unit_width() / 2.0f, flappyBirdSprite->get_unit_height() / 2.0f }; - Vec2f flappyBirdColliderBottomRightPoint = { flappyBirdSprite->get_unit_width() / 2.0f, -flappyBirdSprite->get_unit_height() / 2.0f}; - flappyBird->add_component(flappyBirdColliderTopLeftPoint, flappyBirdColliderBottomRightPoint); + auto flappy_bird_sprite = flappy_bird->get_component()->get_sprite(); + Vec2f flappy_bird_collider_top_left_point = { -flappy_bird_sprite->get_unit_width() / 2.0f, flappy_bird_sprite->get_unit_height() / 2.0f }; + Vec2f flappy_bird_collider_bottom_right_point = { flappy_bird_sprite->get_unit_width() / 2.0f, -flappy_bird_sprite->get_unit_height() / 2.0f}; + flappy_bird->add_component(flappy_bird_collider_top_left_point, flappy_bird_collider_bottom_right_point); - groundY = ground1->get_transform()->get_position().y + groundSprite->get_unit_height() / 2; - airY = -(ground1->get_transform()->get_position().y - groundSprite->get_unit_height() / 2) - 0.1f; + ground_y = ground1->get_transform()->get_position().y + ground_sprite->get_unit_height() / 2; + air_y = -(ground1->get_transform()->get_position().y - ground_sprite->get_unit_height() / 2) - 0.1f; } GameState::~GameState() { - endGameState = nullptr; - flappyBird = nullptr; + end_game_state = nullptr; + flappy_bird = nullptr; } void GameState::enter() { - auto flying = flappyBird->get_component(); + auto flying = flappy_bird->get_component(); flying->set_velocity(FLY_FORCE); flying->enable(); @@ -75,11 +77,11 @@ namespace game::core::fsm { } void GameState::update() { - if (flappyBird->get_transform()->get_position().y <= groundY) { + if (flappy_bird->get_transform()->get_position().y <= ground_y) { transition_to_end_game_state(); } - if (flappyBird->get_transform()->get_position().y >= airY) { + if (flappy_bird->get_transform()->get_position().y >= air_y) { transition_to_end_game_state(); } @@ -88,24 +90,24 @@ namespace game::core::fsm { } } - bool GameState::pipe_player_collision_check(shared_ptr gameObject) const { - auto objColliders = gameObject->get_components(); - auto objTransform = gameObject->get_transform(); + bool GameState::pipe_player_collision_check(shared_ptr game_object) const { + auto obj_colliders = game_object->get_components(); + auto obj_transform = game_object->get_transform(); - auto playerCollider = flappyBird->get_component(); - auto playerTransform = flappyBird->get_transform(); + auto player_collider = flappy_bird->get_component(); + auto player_transform = flappy_bird->get_transform(); - Vec2f playerTopLeft = playerCollider->get_top_left() + playerTransform->get_position(); - Vec2f playerBottomRight = playerCollider->get_bottom_right() + playerTransform->get_position(); + Vec2f player_top_left = player_collider->get_top_left() + (Vec2f)player_transform->get_position(); + Vec2f player_bottom_right = player_collider->get_bottom_right() + (Vec2f)player_transform->get_position(); - for (const auto& collider : objColliders) { - Vec2f objTopLeft = collider->get_top_left() + objTransform->get_position(); - Vec2f objBottomRight = collider->get_bottom_right() + objTransform->get_position(); + for (const auto& collider : obj_colliders) { + Vec2f obj_top_left = collider->get_top_left() + (Vec2f)obj_transform->get_position(); + Vec2f obj_bottom_right = collider->get_bottom_right() + (Vec2f)obj_transform->get_position(); - bool collision = objTopLeft.x <= playerBottomRight.x && - objBottomRight.x >= playerTopLeft.x && - objTopLeft.y >= playerBottomRight.y && - objBottomRight.y <= playerTopLeft.y; + bool collision = obj_top_left.x <= player_bottom_right.x && + obj_bottom_right.x >= player_top_left.x && + obj_top_left.y >= player_bottom_right.y && + obj_bottom_right.y <= player_top_left.y; if (collision && collider->is_trigger() && !collider->is_triggered()) { collider->enter_trigger(); @@ -121,7 +123,7 @@ namespace game::core::fsm { } void GameState::exit() { - flappyBird->get_component()->disable(); + flappy_bird->get_component()->disable(); ground1->get_component()->disable(); ground2->get_component()->disable(); pipe1->get_component()->disable(); @@ -129,10 +131,10 @@ namespace game::core::fsm { } void GameState::set_end_game_state(shared_ptr endGameState) { - this->endGameState = std::move(endGameState); + this->end_game_state = std::move(endGameState); } void GameState::transition_to_end_game_state() { - StateMachine::set_state(endGameState); + StateMachine::set_state(end_game_state); } } \ No newline at end of file diff --git a/examples/gfx/opengl/5_opengl_flappy_bird/core/finite_state_machine/states/game_state.h b/examples/gfx/opengl/5_opengl_flappy_bird/core/finite_state_machine/states/game_state.h index 53c62eb3..3414440f 100644 --- a/examples/gfx/opengl/5_opengl_flappy_bird/core/finite_state_machine/states/game_state.h +++ b/examples/gfx/opengl/5_opengl_flappy_bird/core/finite_state_machine/states/game_state.h @@ -14,29 +14,31 @@ namespace game::core::fsm { class GameState : public State { private: - shared_ptr endGameState; - shared_ptr flappyBird; + shared_ptr end_game_state; + shared_ptr flappy_bird; shared_ptr ground1; shared_ptr ground2; shared_ptr pipe1; shared_ptr pipe2; - float groundY; - float airY; + shared_ptr input; - bool pipe_player_collision_check(shared_ptr gameObject) const; + float ground_y; + float air_y; + + bool pipe_player_collision_check(shared_ptr game_object) const; void transition_to_end_game_state(); public: - explicit GameState(const shared_ptr& flappyBird); + explicit GameState(const shared_ptr& flappy_bird, const shared_ptr& input); ~GameState() override; void enter() override; void update() override; void exit() override; - void set_end_game_state(shared_ptr endGameState); + void set_end_game_state(shared_ptr end_game_state); }; } diff --git a/examples/gfx/opengl/5_opengl_flappy_bird/core/finite_state_machine/states/main_menu_state.cpp b/examples/gfx/opengl/5_opengl_flappy_bird/core/finite_state_machine/states/main_menu_state.cpp index 5e89d3a1..95a66bd0 100644 --- a/examples/gfx/opengl/5_opengl_flappy_bird/core/finite_state_machine/states/main_menu_state.cpp +++ b/examples/gfx/opengl/5_opengl_flappy_bird/core/finite_state_machine/states/main_menu_state.cpp @@ -6,32 +6,34 @@ #include "../../rng.h" namespace game::core::fsm { - MainMenuState::MainMenuState(shared_ptr flappyBird) : gameState(nullptr), flappyBird(std::move(flappyBird)) { - transitionFunction = std::function([this]() { - StateMachine::set_state(gameState); + MainMenuState::MainMenuState(shared_ptr flappy_bird, const shared_ptr& input) + : game_state(nullptr), flappy_bird(std::move(flappy_bird)), input(input) { + + transition_function = std::function([this]() { + StateMachine::set_state(game_state); }); } MainMenuState::~MainMenuState() { - gameState = nullptr; - flappyBird = nullptr; + game_state = nullptr; + flappy_bird = nullptr; } void MainMenuState::enter() { - flappyBird->get_transform()->set_position(Vec3f::splat(0.0f)); - flappyBird->get_transform()->set_rotation(0.0f); + flappy_bird->get_transform()->set_position(Vec3f::splat(0.0f)); + flappy_bird->get_transform()->set_rotation(0.0f); Game::find_game_object_by_name("Pipe1")->get_transform()->set_position(Vec3f(6.2f, Random::rand(-3.0f, 4.5f), 2.0f)); Game::find_game_object_by_name("Pipe2")->get_transform()->set_position(Vec3f(12.0f, Random::rand(-3.0f, 4.5f), 2.0f)); - Input::get_instance().register_key_action(KeyCode::MOUSE_BUTTON_LEFT, transitionFunction); + input->register_key_action(KeyCode::MouseButtonLeft, transition_function); } void MainMenuState::exit() { - Input::get_instance().remove_key_action(KeyCode::MOUSE_BUTTON_LEFT, transitionFunction); + input->remove_key_action(KeyCode::MouseButtonLeft, transition_function); } void MainMenuState::set_game_state(shared_ptr gameState) { - this->gameState = std::move(gameState); + this->game_state = std::move(gameState); } } \ No newline at end of file diff --git a/examples/gfx/opengl/5_opengl_flappy_bird/core/finite_state_machine/states/main_menu_state.h b/examples/gfx/opengl/5_opengl_flappy_bird/core/finite_state_machine/states/main_menu_state.h index d0dee284..cf52b7e5 100644 --- a/examples/gfx/opengl/5_opengl_flappy_bird/core/finite_state_machine/states/main_menu_state.h +++ b/examples/gfx/opengl/5_opengl_flappy_bird/core/finite_state_machine/states/main_menu_state.h @@ -16,19 +16,20 @@ namespace game::core::fsm { class MainMenuState : public State { private: - shared_ptr gameState; - shared_ptr flappyBird; + shared_ptr game_state; + shared_ptr flappy_bird; + shared_ptr input; - std::function transitionFunction; + std::function transition_function; public: - MainMenuState(shared_ptr flappyBird); + MainMenuState(shared_ptr flappy_bird, const shared_ptr& input); ~MainMenuState() override; void enter() override; void update() override {}; void exit() override; - void set_game_state(shared_ptr gameState); + void set_game_state(shared_ptr game_state); }; } diff --git a/examples/gfx/opengl/5_opengl_flappy_bird/core/game.cpp b/examples/gfx/opengl/5_opengl_flappy_bird/core/game.cpp index 1b8c83e3..d635a520 100644 --- a/examples/gfx/opengl/5_opengl_flappy_bird/core/game.cpp +++ b/examples/gfx/opengl/5_opengl_flappy_bird/core/game.cpp @@ -11,44 +11,44 @@ namespace game::core { using namespace ecs; using namespace fsm; - vector> Game::gameObjects = vector>(); + vector> Game::game_objects = vector>(); - Game::Game(const unsigned int& width, const unsigned int& height) { + Game::Game(const unsigned int& width, const unsigned int& height, const shared_ptr& input) : input(input) { const auto aspect = static_cast(width) / static_cast(height); camera = make_shared(aspect * -7.0f, aspect * 7.0f, 7.0, -7.0, -7.0f, 7.0f); - const auto shaderFlags = ENABLE_UNIFORMS; + const auto shader_flags = EnableUniforms; - auto vertexShader = GLShaderFactory::create_shader("assets/vertex.glsl", ShaderTypes::VERTEX_SHADER, shaderFlags); - auto fragmentShader = GLShaderFactory::create_shader("assets/fragment.glsl", ShaderTypes::FRAGMENT_SHADER, shaderFlags); - auto shaderProgram = make_shared(vertexShader, fragmentShader); + auto vertex_shader = GLShaderFactory::create_shader("assets/vertex.glsl", ShaderType::VertexShader, shader_flags); + auto fragment_shader = GLShaderFactory::create_shader("assets/fragment.glsl", ShaderType::FragmentShader, shader_flags); + auto shader_program = make_shared(vertex_shader, fragment_shader); TextureLoader::load_textures("assets/gfx"); - batch = make_shared(shaderProgram, camera, 1024); + batch = make_shared(shader_program, camera, 1024); auto bg = instantiate("Background", Vec3f(0.0f, 0.0f, 3.0f)); add_renderer_component(bg, "bg", 32); bg->get_transform()->set_scale(0.6f); batch->add(bg); - auto flappyBird = instantiate("Flappy Bird"); - add_renderer_component(flappyBird, "flappy_bird", 32); - batch->add(flappyBird); + auto flappy_bird = instantiate("Flappy Bird"); + add_renderer_component(flappy_bird, "flappy_bird", 32); + batch->add(flappy_bird); auto ground1 = instantiate("Ground1", Vec3f(0, -7.0f, 1.0f)); - auto ground1Transform = ground1->get_transform(); + auto ground1_transform = ground1->get_transform(); add_renderer_component(ground1, "ground", 32); batch->add(ground1); - ground1Transform->set_scale(0.5f); + ground1_transform->set_scale(0.5f); - auto groundSprite = ground1->get_component()->get_sprite(); + auto ground_sprite = ground1->get_component()->get_sprite(); - Vec3f ground2Position = ground1Transform->get_position(); - ground2Position.x = groundSprite->get_unit_width(); + Vec3f ground2_position = ground1_transform->get_position(); + ground2_position.x = ground_sprite->get_unit_width(); - auto ground2 = instantiate("Ground2", ground2Position); + auto ground2 = instantiate("Ground2", ground2_position); add_renderer_component(ground2, "ground", 32); batch->add(ground2); ground2->get_transform()->set_scale(0.5f); @@ -63,27 +63,27 @@ namespace game::core { batch->add(pipe2); pipe2->get_transform()->set_scale(0.5f); - mainMenuState = make_shared(flappyBird); - gameState = make_shared(flappyBird); - endGameState = make_shared(flappyBird); + main_menu_state = make_shared(flappy_bird, input); + game_state = make_shared(flappy_bird, input); + end_game_state = make_shared(flappy_bird, input); - mainMenuState->set_game_state(gameState); - gameState->set_end_game_state(endGameState); - endGameState->set_menu_state(mainMenuState); + main_menu_state->set_game_state(game_state); + game_state->set_end_game_state(end_game_state); + end_game_state->set_menu_state(main_menu_state); - StateMachine::set_state(mainMenuState); + StateMachine::set_state(main_menu_state); } - shared_ptr Game::instantiate(const string& gameObjectName, const Vec3f& position) { - auto gameObject = make_shared(gameObjectName, position); - gameObjects.push_back(gameObject); + shared_ptr Game::instantiate(const string& game_object_name, const Vec3f& position) { + auto game_object = make_shared(game_object_name, position); + game_objects.push_back(game_object); - return gameObject; + return game_object; } - void Game::add_renderer_component(shared_ptr& gameObject, const string& textureName, const unsigned int& pixelsPerUnit) { - auto sprite = make_shared(textureName, pixelsPerUnit); - gameObject->add_component(sprite); + void Game::add_renderer_component(shared_ptr& game_object, const string& texture_name, const unsigned int& pixels_per_unit) { + auto sprite = make_shared(texture_name, pixels_per_unit); + game_object->add_component(sprite); } void Game::update() { @@ -94,17 +94,17 @@ namespace game::core { } void Game::update_game_objects() { - for (auto it = gameObjects.begin(); it != gameObjects.end(); ++it) { + for (auto it = game_objects.begin(); it != game_objects.end(); ++it) { (*it)->update(); } } - shared_ptr Game::find_game_object_by_name(const string& gameObjectName) { - for (auto it = gameObjects.begin(); it != gameObjects.end(); ++it) { - auto gameObject = *it; + shared_ptr Game::find_game_object_by_name(const string& game_object_name) { + for (auto it = game_objects.begin(); it != game_objects.end(); ++it) { + auto game_object = *it; - if (gameObject->get_name() == gameObjectName) { - return gameObject; + if (game_object->get_name() == game_object_name) { + return game_object; } } diff --git a/examples/gfx/opengl/5_opengl_flappy_bird/core/game.h b/examples/gfx/opengl/5_opengl_flappy_bird/core/game.h index ccb64379..3b79d5f9 100644 --- a/examples/gfx/opengl/5_opengl_flappy_bird/core/game.h +++ b/examples/gfx/opengl/5_opengl_flappy_bird/core/game.h @@ -6,7 +6,6 @@ #include #include "bebone/bebone.h" -#include "game_time.h" #include "batch.h" #include "sprite.h" @@ -27,21 +26,23 @@ namespace game::core { shared_ptr batch; shared_ptr camera; - shared_ptr mainMenuState; - shared_ptr gameState; - shared_ptr endGameState; + shared_ptr main_menu_state; + shared_ptr game_state; + shared_ptr end_game_state; - static vector> gameObjects; + shared_ptr input; - shared_ptr instantiate(const string& gameObjectName, const Vec3f& position = {0.0f, 0.0f, 0.0f}); - void add_renderer_component(shared_ptr& gameObject, const string& textureName, const unsigned int& pixelsPerUnit); + static vector> game_objects; + + shared_ptr instantiate(const string& game_object_name, const Vec3f& position = {0.0f, 0.0f, 0.0f}); + void add_renderer_component(shared_ptr& game_object, const string& texture_name, const unsigned int& pixels_per_unit); void update_game_objects(); public: - Game(const unsigned int& width, const unsigned int& height); + Game(const unsigned int& width, const unsigned int& height, const shared_ptr& input); void update(); - static shared_ptr find_game_object_by_name(const string& gameObjectName); + static shared_ptr find_game_object_by_name(const string& game_object_name); }; } diff --git a/examples/gfx/opengl/5_opengl_flappy_bird/core/game_time.cpp b/examples/gfx/opengl/5_opengl_flappy_bird/core/game_time.cpp deleted file mode 100644 index 57f6bfee..00000000 --- a/examples/gfx/opengl/5_opengl_flappy_bird/core/game_time.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include "game_time.h" - -namespace game::core { - const steady_clock::time_point Time::startupTime = steady_clock::now(); - double Time::deltaTime = -1; - - double Time::get_time() { - auto now = steady_clock::now(); - return duration_cast(now - startupTime).count() / 1000000.0; - } -} \ No newline at end of file diff --git a/examples/gfx/opengl/5_opengl_flappy_bird/core/game_time.h b/examples/gfx/opengl/5_opengl_flappy_bird/core/game_time.h deleted file mode 100644 index 5638baf2..00000000 --- a/examples/gfx/opengl/5_opengl_flappy_bird/core/game_time.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef _GAME_TIME_H_ -#define _GAME_TIME_H_ - -#include - -namespace game::core { - using namespace std::chrono; - - class Time { - public: - static const steady_clock::time_point startupTime; - static double deltaTime; - - static double get_time(); - }; -} - -#endif diff --git a/examples/gfx/opengl/5_opengl_flappy_bird/core/orthographic_camera.h b/examples/gfx/opengl/5_opengl_flappy_bird/core/orthographic_camera.h index 466f2ef3..f943df54 100644 --- a/examples/gfx/opengl/5_opengl_flappy_bird/core/orthographic_camera.h +++ b/examples/gfx/opengl/5_opengl_flappy_bird/core/orthographic_camera.h @@ -3,7 +3,7 @@ #include "bebone/bebone.h" -using namespace omni::types; +using namespace bebone::core; namespace game::core { class OrthographicCamera { diff --git a/examples/gfx/opengl/5_opengl_flappy_bird/core/rng.cpp b/examples/gfx/opengl/5_opengl_flappy_bird/core/rng.cpp index 3beee268..2e752b3d 100644 --- a/examples/gfx/opengl/5_opengl_flappy_bird/core/rng.cpp +++ b/examples/gfx/opengl/5_opengl_flappy_bird/core/rng.cpp @@ -1,8 +1,8 @@ #include "rng.h" namespace game::core { - random_device Random::randomDevice; - mt19937 Random::generator(Random::randomDevice()); + random_device Random::random; + mt19937 Random::generator(Random::random()); float Random::rand(const float& min, const float& max) { uniform_real_distribution distribution(min, max); diff --git a/examples/gfx/opengl/5_opengl_flappy_bird/core/rng.h b/examples/gfx/opengl/5_opengl_flappy_bird/core/rng.h index 51561870..30cc194d 100644 --- a/examples/gfx/opengl/5_opengl_flappy_bird/core/rng.h +++ b/examples/gfx/opengl/5_opengl_flappy_bird/core/rng.h @@ -10,7 +10,7 @@ namespace game::core { class Random : private bebone::core::NonCopyable { private: - static random_device randomDevice; + static random_device random; static mt19937 generator; public: diff --git a/examples/gfx/opengl/5_opengl_flappy_bird/core/shader_vertex.h b/examples/gfx/opengl/5_opengl_flappy_bird/core/shader_vertex.h index 81b50eaf..0e05f9c6 100644 --- a/examples/gfx/opengl/5_opengl_flappy_bird/core/shader_vertex.h +++ b/examples/gfx/opengl/5_opengl_flappy_bird/core/shader_vertex.h @@ -8,8 +8,8 @@ namespace game::core { struct ShaderVertex { Vec3f position; - Vec2f textureCoordinates; - int textureUnit; + Vec2f texture_coordinates; + int texture_unit; }; } diff --git a/examples/gfx/opengl/5_opengl_flappy_bird/core/sprite.cpp b/examples/gfx/opengl/5_opengl_flappy_bird/core/sprite.cpp index 7aa427b3..c0855c11 100644 --- a/examples/gfx/opengl/5_opengl_flappy_bird/core/sprite.cpp +++ b/examples/gfx/opengl/5_opengl_flappy_bird/core/sprite.cpp @@ -4,21 +4,21 @@ namespace game::core { using namespace std; - Sprite::Sprite() : texture(nullptr), pixelsPerUnit(32) {} + Sprite::Sprite() : texture(nullptr), pixels_per_unit(32) {} - Sprite::Sprite(const std::string& textureName, const unsigned int& pixelsPerUnit) : pixelsPerUnit(pixelsPerUnit) { - set_texture(textureName); + Sprite::Sprite(const std::string& texture_name, const unsigned int& pixels_per_unit) : pixels_per_unit(pixels_per_unit) { + set_texture(texture_name); - unitWidth = get_width() / (float)pixelsPerUnit; - unitHeight = get_height() / (float)pixelsPerUnit; + unit_width = get_width() / (float)pixels_per_unit; + unit_height = get_height() / (float)pixels_per_unit; } const shared_ptr& Sprite::get_texture() const { return texture; } - void Sprite::set_texture(const std::string& textureName) { - texture = TextureLoader::get_texture(textureName); + void Sprite::set_texture(const std::string& texture_name) { + texture = TextureLoader::get_texture(texture_name); } int Sprite::get_height() const { @@ -30,14 +30,14 @@ namespace game::core { } unsigned int Sprite::get_pixels_per_unit() const { - return pixelsPerUnit; + return pixels_per_unit; } float Sprite::get_unit_width() const { - return unitWidth; + return unit_width; } float Sprite::get_unit_height() const { - return unitHeight; + return unit_height; } } \ No newline at end of file diff --git a/examples/gfx/opengl/5_opengl_flappy_bird/core/sprite.h b/examples/gfx/opengl/5_opengl_flappy_bird/core/sprite.h index 7564df30..ec4a16bd 100644 --- a/examples/gfx/opengl/5_opengl_flappy_bird/core/sprite.h +++ b/examples/gfx/opengl/5_opengl_flappy_bird/core/sprite.h @@ -5,7 +5,7 @@ #include #include -using namespace bebone::gfx::opengl; +using namespace bebone::gfx; namespace game::core { using namespace std; @@ -13,13 +13,13 @@ namespace game::core { class Sprite : private NonCopyable { private: shared_ptr texture; - unsigned int pixelsPerUnit; + unsigned int pixels_per_unit; - float unitWidth; - float unitHeight; + float unit_width; + float unit_height; public: Sprite(); - Sprite(const std::string& textureName, const unsigned int& pixelsPerUnit); + Sprite(const std::string& texture_name, const unsigned int& pixels_per_unit); const shared_ptr& get_texture() const; void set_texture(const std::string& textureName); diff --git a/examples/gfx/opengl/5_opengl_flappy_bird/core/texture_loader.cpp b/examples/gfx/opengl/5_opengl_flappy_bird/core/texture_loader.cpp index 344728b8..34293fd0 100644 --- a/examples/gfx/opengl/5_opengl_flappy_bird/core/texture_loader.cpp +++ b/examples/gfx/opengl/5_opengl_flappy_bird/core/texture_loader.cpp @@ -1,23 +1,23 @@ #include "texture_loader.h" namespace game::core { - std::string TextureLoader::assetsPath; - std::map> TextureLoader::loadedTextures; + std::string TextureLoader::assets_path; + std::unordered_map> TextureLoader::loaded_textures; - void TextureLoader::load_textures(const std::string& assetsPath) { - TextureLoader::assetsPath = assetsPath; + void TextureLoader::load_textures(const std::string& path) { + TextureLoader::assets_path = path; - for (const auto& entry : std::filesystem::directory_iterator(assetsPath)) { + for (const auto& entry : std::filesystem::directory_iterator(path)) { auto texture = std::make_shared(entry.path().string()); - std::string fileName = entry.path().stem().string(); - loadedTextures[fileName] = texture; + std::string file_name = entry.path().stem().string(); + loaded_textures[file_name] = texture; } } - std::shared_ptr TextureLoader::get_texture(const std::string& fileName) { - if (loadedTextures.find(fileName) != loadedTextures.end()) - return loadedTextures[fileName]; + std::shared_ptr TextureLoader::get_texture(const std::string& file_name) { + if (loaded_textures.find(file_name) != loaded_textures.end()) + return loaded_textures[file_name]; return nullptr; } diff --git a/examples/gfx/opengl/5_opengl_flappy_bird/core/texture_loader.h b/examples/gfx/opengl/5_opengl_flappy_bird/core/texture_loader.h index ae684077..d9ba08f3 100644 --- a/examples/gfx/opengl/5_opengl_flappy_bird/core/texture_loader.h +++ b/examples/gfx/opengl/5_opengl_flappy_bird/core/texture_loader.h @@ -11,17 +11,17 @@ #include namespace game::core { - using namespace bebone::gfx::opengl; + using namespace bebone::gfx; using namespace bebone::core; class TextureLoader : private NonCopyable { private: - static std::map> loadedTextures; - static std::string assetsPath; + static std::unordered_map> loaded_textures; + static std::string assets_path; public: - static void load_textures(const std::string& assetsPath); - static std::shared_ptr get_texture(const std::string& fileName); + static void load_textures(const std::string& path); + static std::shared_ptr get_texture(const std::string& file_name); }; } diff --git a/examples/gfx/opengl/5_opengl_flappy_bird/main.cpp b/examples/gfx/opengl/5_opengl_flappy_bird/main.cpp index c89a0b0c..1cf5a356 100644 --- a/examples/gfx/opengl/5_opengl_flappy_bird/main.cpp +++ b/examples/gfx/opengl/5_opengl_flappy_bird/main.cpp @@ -1,12 +1,9 @@ -#define OMNI_TYPES_MATRIX_COLLUM_MAJOR_ORDER -#define OMNI_TYPES_MATRIX4X4_PROJECTION_MATRIX_INVERSE_Y_AXIS #include "bebone/bebone.h" #include "core/game.h" -#include "core/game_time.h" -const unsigned int SCR_WIDTH = 600; -const unsigned int SCR_HEIGHT = 800; +const unsigned int screen_width = 600; +const unsigned int screen_height = 800; using namespace bebone::core; using namespace bebone::gfx; @@ -16,10 +13,10 @@ using namespace game::core; int main() { glfwInit(); - auto window = WindowFactory::create_window("5. Flappy Bird", SCR_WIDTH, SCR_HEIGHT, GfxAPI::OPENGL); + auto window = WindowFactory::create_window("5. Flappy Bird", screen_width, screen_height, OpenGL); GLContext::load_opengl(); - GLContext::set_viewport(0, 0, SCR_WIDTH, SCR_HEIGHT); + GLContext::set_viewport(0, 0, screen_width, screen_height); glfwSwapInterval(1); glEnable(GL_DEPTH_TEST); @@ -27,29 +24,30 @@ int main() { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - Game game(SCR_WIDTH, SCR_HEIGHT); + auto input = std::make_shared(); + auto input_executor = std::make_shared(input); - double beginTime = Time::get_time(); - double endTime; + KeyListener key_listener(input_executor); + MouseListener mouse_listener(input_executor); + + window->add_listener(key_listener); + window->add_listener(mouse_listener); + + Game game(screen_width, screen_height, input); while (!window->closing()) { GLContext::clear_color(0.2f, 0.2f, 0.2f, 1.0f); GLContext::clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - window->execute_input_actions(); + input_executor->execute_input_actions(); - if (Time::deltaTime >= 0) { - game.update(); - } + game.update(); glfwSwapBuffers(window->get_backend()); - GLFWContext::poll_events(); + window->pull_events(); - endTime = Time::get_time(); - Time::deltaTime = endTime - beginTime; - beginTime = endTime; + window->end_frame(); } - GLFWContext::terminate(); return 0; } diff --git a/examples/gfx/opengl/6_opengl_imgui/CMakeLists.txt b/examples/gfx/opengl/6_opengl_imgui/CMakeLists.txt deleted file mode 100644 index 5cd31f35..00000000 --- a/examples/gfx/opengl/6_opengl_imgui/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -file(GLOB_RECURSE BEBONE_EXAMPLE_GFX_OPENGL_6_OPENGL_IMGUI *.cpp) - -include_directories("../../src") -include_directories("./") - -add_executable(Bebone_Example_Gfx_6_Opengl_Imgui ${BEBONE_EXAMPLE_GFX_OPENGL_6_OPENGL_IMGUI}) -target_link_libraries(Bebone_Example_Gfx_6_Opengl_Imgui bebone) \ No newline at end of file diff --git a/examples/gfx/opengl/6_opengl_imgui/fragment.glsl b/examples/gfx/opengl/6_opengl_imgui/fragment.glsl deleted file mode 100644 index a1b650a9..00000000 --- a/examples/gfx/opengl/6_opengl_imgui/fragment.glsl +++ /dev/null @@ -1,9 +0,0 @@ -#version 450 core - -layout (location = 0) out vec4 FragColor; - -layout (location = 0) in vec3 outColor; - -void main() { - FragColor = vec4(outColor, 1.0f); -} \ No newline at end of file diff --git a/examples/gfx/opengl/6_opengl_imgui/main.cpp b/examples/gfx/opengl/6_opengl_imgui/main.cpp deleted file mode 100644 index 8242dfcd..00000000 --- a/examples/gfx/opengl/6_opengl_imgui/main.cpp +++ /dev/null @@ -1,148 +0,0 @@ -#include - -#define OMNI_TYPES_MATRIX_COLLUM_MAJOR_ORDER -#define OMNI_TYPES_MATRIX4X4_PROJECTION_MATRIX_INVERSE_Y_AXIS -#include "bebone/bebone.h" - -const unsigned int SCR_WIDTH = 800; -const unsigned int SCR_HEIGHT = 600; - -using namespace bebone::gfx; -using namespace bebone::gfx::opengl; - -struct Vertex { - Vec3f pos; - Vec3f color; -}; - -const std::vector vertices { - {{-0.5, -0.5, 0.5}, {1.0f, 1.0f, 1.0f}}, - {{ 0.5, -0.5, 0.5}, {1.0f, 1.0f, 0.0f}}, - {{ 0.5, 0.5, 0.5}, {1.0f, 0.0f, 1.0f}}, - {{-0.5, 0.5, 0.5}, {1.0f, 0.0f, 0.0f}}, - {{-0.5, -0.5, -0.5}, {0.0f, 1.0f, 1.0f}}, - {{ 0.5, -0.5, -0.5}, {0.0f, 1.0f, 0.0f}}, - {{ 0.5, 0.5, -0.5}, {0.0f, 0.0f, 1.0f}}, - {{-0.5, 0.5, -0.5}, {0.0f, 0.0f, 0.0f}} -}; - -const std::vector indices { - 0, 1, 2, 2, 3, 0, - 1, 5, 6, 6, 2, 1, - 7, 6, 5, 5, 4, 7, - 4, 0, 3, 3, 7, 4, - 4, 5, 1, 1, 0, 4, - 3, 2, 6, 6, 7, 3 -}; - -struct Transform { - Mat4f translation; - Mat4f scale; - Mat4f rotation; -}; - -struct Camera { - Mat4f proj; - Mat4f view; -}; - -int main() { - GLFWContext::init(); - - auto window = WindowFactory::create_window("6. OpenGL Imgui example", SCR_WIDTH, SCR_HEIGHT, GfxAPI::OPENGL); - - GLContext::load_opengl(); - GLContext::set_viewport(0, 0, SCR_WIDTH, SCR_HEIGHT); - glfwSwapInterval(0); - - auto vertexShader = GLShaderFactory::create_shader("vertex.glsl", ShaderTypes::VERTEX_SHADER); - auto fragmentShader = GLShaderFactory::create_shader("fragment.glsl", ShaderTypes::FRAGMENT_SHADER); - GLShaderProgram shaderProgram(vertexShader, fragmentShader); - - vertexShader.destroy(); - fragmentShader.destroy(); - - GLVertexArrayObject vao; - vao.bind(); - - GLVertexBufferObject vbo(vertices.data(), sizeof(Vertex) * vertices.size()); - GLElementBufferObject ebo(indices.data(), indices.size() * sizeof(u32)); - - vao.link_attributes(vbo, 0, 3, GL_FLOAT, sizeof(Vertex), offsetof(Vertex, pos)); - vao.link_attributes(vbo, 1, 3, GL_FLOAT, sizeof(Vertex), offsetof(Vertex, color)); - - vao.unbind(); - vbo.unbind(); - ebo.unbind(); - - GLUniformBufferObject transformUbo(sizeof(Transform)); - GLUniformBufferObject cameraUbo(sizeof(Camera)); - - transformUbo.bind(); - shaderProgram.bind_buffer("Transform", 0, transformUbo); - auto transformPtr = static_cast(transformUbo.map()); - transformPtr->translation = Mat4f::translation(Vec3f(0, 0, 0)); - transformPtr->scale = Mat4f::identity(); - - cameraUbo.bind(); - shaderProgram.bind_buffer("Camera", 1, cameraUbo); - auto cameraPtr = static_cast(cameraUbo.map()); - cameraPtr->proj = Mat4f::perspective(1, window->get_aspect(), 0.1f, 100.0f); - cameraPtr->view = Mat4f::translation(Vec3f(0, 0, 5)); - cameraUbo.unmap(); - cameraUbo.unbind(); - - float t = 0; - - GLContext::enable(GL_DEPTH_TEST); - - IMGUI_CHECKVERSION(); - ImGui::CreateContext(); - - ImGuiIO& io = ImGui::GetIO(); - io.ConfigFlags |= ImGuiConfigFlags_None; - - ImGui::CreateContext(); - ImGui::StyleColorsDark(); - ImGui_ImplGlfw_InitForOpenGL(window->get_backend(), true); - ImGui_ImplOpenGL3_Init("#version 330"); - - while (!window->closing()) { - ++t; - - GLContext::clear_color(0.2f, 0.2f, 0.2f, 1.0f); - GLContext::clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - ImGui_ImplOpenGL3_NewFrame(); - ImGui_ImplGlfw_NewFrame(); - ImGui::NewFrame(); - - ImGui::ShowDemoWindow(); - - transformPtr->rotation = trait_bryan_angle_yxz(Vec3f(t * 0.001f, t * 0.001f, 0.0f)); - - shaderProgram.enable(); - - vao.bind(); - - GLContext::draw_elements(GL_TRIANGLES, static_cast(indices.size()), GL_UNSIGNED_INT, nullptr); - - ImGui::Render(); - ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); - - glfwSwapBuffers(window->get_backend()); - GLFWContext::poll_events(); - } - - transformUbo.unmap(); - transformUbo.unbind(); - - vao.destroy(); - vbo.destroy(); - ebo.destroy(); - shaderProgram.destroy(); - - GLFWContext::terminate(); - - return 0; -} diff --git a/examples/gfx/opengl/6_opengl_imgui/vertex.glsl b/examples/gfx/opengl/6_opengl_imgui/vertex.glsl deleted file mode 100644 index e94b6d3a..00000000 --- a/examples/gfx/opengl/6_opengl_imgui/vertex.glsl +++ /dev/null @@ -1,22 +0,0 @@ -#version 450 core - -layout (location = 0) in vec3 aPos; -layout (location = 1) in vec3 aColor; - -layout (location = 0) out vec3 outColor; - -layout(binding = 0) uniform Transform { - mat4 translation; - mat4 scale; - mat4 rotation; -}; - -layout(binding = 1) uniform Camera { - mat4 proj; - mat4 view; -}; - -void main() { - gl_Position = proj * view * translation * rotation * scale * vec4(aPos, 1.0); - outColor = aColor; -} \ No newline at end of file diff --git a/examples/gfx/opengl/7_opengl_bloom/CMakeLists.txt b/examples/gfx/opengl/7_opengl_bloom/CMakeLists.txt new file mode 100644 index 00000000..ea9fb7ca --- /dev/null +++ b/examples/gfx/opengl/7_opengl_bloom/CMakeLists.txt @@ -0,0 +1,7 @@ +file(GLOB_RECURSE BEBONE_EXAMPLE_GFX_OPENGL_7_OPENGL_BLOOM *.cpp) + +include_directories("./") +include_directories(${BEBONE_INCLUDES}) + +add_executable(Bebone_Example_Gfx_7_Opengl_Bloom ${BEBONE_EXAMPLE_GFX_OPENGL_7_OPENGL_BLOOM}) +target_link_libraries(Bebone_Example_Gfx_7_Opengl_Bloom bebone) \ No newline at end of file diff --git a/examples/gfx/opengl/7_opengl_bloom/blur.frag.glsl b/examples/gfx/opengl/7_opengl_bloom/blur.frag.glsl new file mode 100644 index 00000000..7cf07fe9 --- /dev/null +++ b/examples/gfx/opengl/7_opengl_bloom/blur.frag.glsl @@ -0,0 +1,20 @@ +#version 450 core + +layout (location = 0) out vec4 FragColor; + +layout (location = 0) in vec2 texCoord; + +uniform sampler2D image; + +void main() { + vec4 result = vec4(0.0f); + + for(int x = -5; x < 5; ++x) { + for(int y = -5; y < 5; ++y) { + vec2 offset = 5 * vec2(x/800.0, y/600.0); + result += texture(image, texCoord + offset); + } + } + + FragColor = result * (1.0/50.0); +} \ No newline at end of file diff --git a/examples/gfx/opengl/7_opengl_bloom/blur.vert.glsl b/examples/gfx/opengl/7_opengl_bloom/blur.vert.glsl new file mode 100644 index 00000000..c5358add --- /dev/null +++ b/examples/gfx/opengl/7_opengl_bloom/blur.vert.glsl @@ -0,0 +1,12 @@ +#version 450 core + +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec3 aNormal; +layout (location = 2) in vec2 aTexCoord; + +layout (location = 0) out vec2 texCoord; + +void main() { + gl_Position = vec4(aPos, 1.0); + texCoord = aTexCoord; +} \ No newline at end of file diff --git a/examples/gfx/opengl/7_opengl_bloom/main.cpp b/examples/gfx/opengl/7_opengl_bloom/main.cpp new file mode 100644 index 00000000..49681eab --- /dev/null +++ b/examples/gfx/opengl/7_opengl_bloom/main.cpp @@ -0,0 +1,110 @@ +#include +#include "bebone/bebone.h" + +using namespace bebone; +using namespace bebone::gfx; +using namespace bebone::renderer; + +int main() { + glfwInit(); + + auto window = WindowFactory::create_window("7. OpenGL bloom example", 800, 600, GfxAPI::OpenGL); + + GLContext::load_opengl(); + glfwSwapInterval(0); // Todo + GLContext::set_viewport(0, 0, 800, 600); + GLContext::enable(GL_DEPTH_TEST); + + auto transform = renderer::Transform { }; + auto camera = Mat4f::perspective(1, window->get_aspect(), 0.1f, 100.0f) * Mat4f::translation({0.0f, 0.0f, 5.0f}); + + auto cube_generator = std::make_shared(1.0f, 1.0f, 1.0f); + auto quad_generator = std::make_shared(1.0f, 1.0f); + + auto cube_mesh = cube_generator->generate(std::make_shared()); + auto quad_mesh = quad_generator->generate(std::make_shared()); + + // Geometry pass + GLShaderProgram geometry_program( + GLShaderFactory::create_shader("main.vert.glsl", ShaderType::VertexShader, EnableUniforms), + GLShaderFactory::create_shader("main.frag.glsl", ShaderType::FragmentShader, EnableUniforms)); + + auto geometry_fbo = GLFramebuffer(); + auto geometry_texture = GLTexture2D(800, 600); + auto grayscale_texture = GLTexture2D(800, 600); + auto geometry_renderbuffer = GLRenderbuffer(); + geometry_renderbuffer.storage(GL_DEPTH24_STENCIL8, 800, 600); + + geometry_fbo.attach_texture_2d(GL_COLOR_ATTACHMENT0, geometry_texture); + geometry_fbo.attach_texture_2d(GL_COLOR_ATTACHMENT1, grayscale_texture); + geometry_fbo.attach_renderbuffer(GL_DEPTH_STENCIL_ATTACHMENT, geometry_renderbuffer); + + // Blur pass + GLShaderProgram blur_program( + GLShaderFactory::create_shader("blur.vert.glsl", ShaderType::VertexShader, EnableUniforms), + GLShaderFactory::create_shader("blur.frag.glsl", ShaderType::FragmentShader, EnableUniforms)); + + auto blur_fbo = GLFramebuffer(); + auto blur_texture = GLTexture2D(800, 600); + auto blur_renderbuffer = GLRenderbuffer(); + blur_renderbuffer.storage(GL_DEPTH24_STENCIL8, 800, 600); + + blur_fbo.attach_texture_2d(GL_COLOR_ATTACHMENT0, blur_texture); + blur_fbo.attach_renderbuffer(GL_DEPTH_STENCIL_ATTACHMENT, blur_renderbuffer); + + // Final pass + GLShaderProgram post_program( + GLShaderFactory::create_shader("post.vert.glsl", ShaderType::VertexShader, EnableUniforms), + GLShaderFactory::create_shader("post.frag.glsl", ShaderType::FragmentShader, EnableUniforms)); + + while (!window->closing()) { + transform.rotation.x += Time::get_seconds_elapsed(); + transform.rotation.z -= Time::get_seconds_elapsed(); + + // Geometry pass + geometry_fbo.bind(); + GLenum drawBuffers[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 }; + glDrawBuffers(2, drawBuffers); // Todo, this needs to be abstracted + + GLContext::clear_color(0.2f, 0.2f, 0.2f, 1.0f); + GLContext::clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + geometry_program.enable(); + geometry_program.set_uniform("transform", calculate_transform_matrix(transform)); + geometry_program.set_uniform("cam", camera); + + cube_mesh->bind(nullptr); + GLContext::draw_elements(GL_TRIANGLES, static_cast(cube_mesh->get_triangle_count()), GL_UNSIGNED_INT, nullptr); + geometry_fbo.unbind(); + + // Blur pass + blur_fbo.bind(); + GLContext::clear_color(0.2f, 0.2f, 0.2f, 1.0f); + GLContext::clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + blur_program.enable(); + geometry_texture.bind(); + + quad_mesh->bind(nullptr); + GLContext::draw_elements(GL_TRIANGLES, static_cast(quad_mesh->get_triangle_count()), GL_UNSIGNED_INT, nullptr); + blur_fbo.unbind(); + + // Final pass + GLContext::clear_color(0.2f, 0.2f, 0.2f, 1.0f); + GLContext::clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + post_program.enable(); + quad_mesh->bind(nullptr); + + grayscale_texture.bind_texture_unit(0); + blur_texture.bind_texture_unit(1); + GLContext::draw_elements(GL_TRIANGLES, static_cast(quad_mesh->get_triangle_count()), GL_UNSIGNED_INT, nullptr); + + GLFWContext::swap_buffers(*window); + window->pull_events(); + } + + geometry_program.destroy(); + + return 0; +} diff --git a/examples/gfx/opengl/7_opengl_bloom/main.frag.glsl b/examples/gfx/opengl/7_opengl_bloom/main.frag.glsl new file mode 100644 index 00000000..e2251695 --- /dev/null +++ b/examples/gfx/opengl/7_opengl_bloom/main.frag.glsl @@ -0,0 +1,11 @@ +#version 450 core + +layout (location = 0) out vec4 FragColor; +layout (location = 1) out vec4 grayscale_color; + +layout (location = 0) in vec4 outColor; + +void main() { + grayscale_color = vec4(vec3(outColor.x + outColor.y + outColor.z / 3.0), 1.0); + FragColor = outColor; +} \ No newline at end of file diff --git a/examples/gfx/opengl/7_opengl_bloom/main.vert.glsl b/examples/gfx/opengl/7_opengl_bloom/main.vert.glsl new file mode 100644 index 00000000..8b9ed54d --- /dev/null +++ b/examples/gfx/opengl/7_opengl_bloom/main.vert.glsl @@ -0,0 +1,14 @@ +#version 450 core + +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec4 aColor; + +layout (location = 0) out vec4 outColor; + +uniform mat4 transform; +uniform mat4 cam; + +void main() { + gl_Position = cam * transform * vec4(aPos, 1.0); + outColor = aColor; +} \ No newline at end of file diff --git a/examples/gfx/opengl/7_opengl_bloom/post.frag.glsl b/examples/gfx/opengl/7_opengl_bloom/post.frag.glsl new file mode 100644 index 00000000..75d9e494 --- /dev/null +++ b/examples/gfx/opengl/7_opengl_bloom/post.frag.glsl @@ -0,0 +1,22 @@ +#version 450 core + +layout (location = 0) out vec4 FragColor; + +layout (location = 0) in vec2 texCoord; + +layout (binding = 0) uniform sampler2D image; +layout (binding = 1) uniform sampler2D blured; + +void main() { + vec4 fragment = texture(image, texCoord); + vec4 bloom = texture(blured, texCoord); + + vec4 color = fragment + bloom; + + float exposure = 0.8f; + vec4 toneMapped = vec4(1.0) - exp(-color * exposure); + + float gamma = 1.0f; + + FragColor = pow(toneMapped, vec4(1.0f / gamma)); +} \ No newline at end of file diff --git a/examples/gfx/opengl/7_opengl_bloom/post.vert.glsl b/examples/gfx/opengl/7_opengl_bloom/post.vert.glsl new file mode 100644 index 00000000..c5358add --- /dev/null +++ b/examples/gfx/opengl/7_opengl_bloom/post.vert.glsl @@ -0,0 +1,12 @@ +#version 450 core + +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec3 aNormal; +layout (location = 2) in vec2 aTexCoord; + +layout (location = 0) out vec2 texCoord; + +void main() { + gl_Position = vec4(aPos, 1.0); + texCoord = aTexCoord; +} \ No newline at end of file diff --git a/examples/gfx/opengl/CMakeLists.txt b/examples/gfx/opengl/CMakeLists.txt index 63942b05..36f4e9f7 100644 --- a/examples/gfx/opengl/CMakeLists.txt +++ b/examples/gfx/opengl/CMakeLists.txt @@ -4,4 +4,4 @@ add_subdirectory(2_opengl_texture) add_subdirectory(3_opengl_3d_cube) add_subdirectory(4_opengl_bexel) add_subdirectory(5_opengl_flappy_bird) -add_subdirectory(6_opengl_imgui) \ No newline at end of file +# add_subdirectory(7_opengl_bloom) \ No newline at end of file diff --git a/examples/gfx/vulkan/0_vulkan_window/CMakeLists.txt b/examples/gfx/vulkan/0_vulkan_window/CMakeLists.txt index 79bb2ab2..4b6900bc 100644 --- a/examples/gfx/vulkan/0_vulkan_window/CMakeLists.txt +++ b/examples/gfx/vulkan/0_vulkan_window/CMakeLists.txt @@ -1,7 +1,7 @@ file(GLOB_RECURSE BEBONE_EXAMPLE_GFX_VULKAN_0_VULKAN_WINDOW *.cpp) -include_directories("../../src") include_directories("./") +include_directories(${BEBONE_INCLUDES}) add_executable(Bebone_Example_Gfx_0_Vulkan_Window ${BEBONE_EXAMPLE_GFX_VULKAN_0_VULKAN_WINDOW}) target_link_libraries(Bebone_Example_Gfx_0_Vulkan_Window bebone) \ No newline at end of file diff --git a/examples/gfx/vulkan/0_vulkan_window/main.cpp b/examples/gfx/vulkan/0_vulkan_window/main.cpp index 9ba7413e..5bad529d 100644 --- a/examples/gfx/vulkan/0_vulkan_window/main.cpp +++ b/examples/gfx/vulkan/0_vulkan_window/main.cpp @@ -2,18 +2,13 @@ using namespace bebone::core; using namespace bebone::gfx; -using namespace bebone::gfx::vulkan; int main() { - GLFWContext::init(); - - auto window = WindowFactory::create_window("0. Vulkan window example", 800, 600, GfxAPI::VULKAN); + auto window = WindowFactory::create_window("0. Vulkan window example", 800, 600, Vulkan); while (!window->closing()) { - GLFWContext::poll_events(); + window->pull_events(); } - GLFWContext::terminate(); - return 0; } \ No newline at end of file diff --git a/examples/gfx/vulkan/1_vulkan_hello_triangle/CMakeLists.txt b/examples/gfx/vulkan/1_vulkan_hello_triangle/CMakeLists.txt index 90e55f0a..c77b11af 100644 --- a/examples/gfx/vulkan/1_vulkan_hello_triangle/CMakeLists.txt +++ b/examples/gfx/vulkan/1_vulkan_hello_triangle/CMakeLists.txt @@ -1,7 +1,7 @@ file(GLOB_RECURSE BEBONE_EXAMPLE_GFX_VULKAN_1_VULKAN_HELLO_TRIANGLE *.cpp) -include_directories("../../src") include_directories("./") +include_directories(${BEBONE_INCLUDES}) add_executable(Bebone_Example_Gfx_1_Vulkan_Hello_Triangle ${BEBONE_EXAMPLE_GFX_VULKAN_1_VULKAN_HELLO_TRIANGLE}) target_link_libraries(Bebone_Example_Gfx_1_Vulkan_Hello_Triangle bebone) \ No newline at end of file diff --git a/examples/gfx/vulkan/1_vulkan_hello_triangle/frag.glsl b/examples/gfx/vulkan/1_vulkan_hello_triangle/frag.glsl index 2f2ed644..921cbadb 100644 --- a/examples/gfx/vulkan/1_vulkan_hello_triangle/frag.glsl +++ b/examples/gfx/vulkan/1_vulkan_hello_triangle/frag.glsl @@ -1,8 +1,7 @@ #version 450 core -layout (location = 0) in vec3 fragColor; -layout (location = 0) out vec4 outColor; +layout (location = 0) out vec4 out_color; void main() { - outColor = vec4(fragColor, 1.0); + out_color = vec4(0.6f, 0.9f, 0.6f, 1.0f); } \ No newline at end of file diff --git a/examples/gfx/vulkan/1_vulkan_hello_triangle/main.cpp b/examples/gfx/vulkan/1_vulkan_hello_triangle/main.cpp index bbc96c3a..963ca9eb 100644 --- a/examples/gfx/vulkan/1_vulkan_hello_triangle/main.cpp +++ b/examples/gfx/vulkan/1_vulkan_hello_triangle/main.cpp @@ -2,93 +2,60 @@ using namespace bebone::core; using namespace bebone::gfx; -using namespace bebone::gfx::vulkan; - -struct Vertex { - Vec3f pos; - Vec3f color; -}; - -const std::vector vertices = { - {{0.5f, 0.5f, 0.0f}, {1.0f, 0.0f, 0.0f}}, - {{0.0f, -0.5f, 0.0f}, {0.0f, 1.0f, 0.0f}}, - {{-0.5f, 0.5f, 0.0f}, {0.0f, 0.0f, 1.0f}}, -}; // Todo make this nicer -const auto vertexDescriptions = VulkanPipelineVertexInputStateTuple { - .bindingDescriptions = { - { 0, sizeof(Vertex), VK_VERTEX_INPUT_RATE_VERTEX } +const auto vertex_descriptions = VulkanPipelineVertexInputStateTuple { + .binding_descriptions = { + { 0, sizeof(Vec3f), VK_VERTEX_INPUT_RATE_VERTEX } }, - .attributeDescriptions = { - { 0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, pos) }, - { 1, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, color) }, + .attribute_descriptions = { + { 0, 0, VK_FORMAT_R32G32B32_SFLOAT, 0 } } }; -const std::vector indices = { 0, 1, 2 }; - int main() { - GLFWContext::init(); + auto window = WindowFactory::create_window("1. Vulkan hello triangle example", 800, 600, Vulkan); - auto window = WindowFactory::create_window("1. Vulkan hello window example", 800, 600, GfxAPI::VULKAN); + VulkanInstance instance; + VulkanDevice device(instance, window); + VulkanSwapChain swap_chain(device, window); - auto instance = VulkanInstance::create_instance(); - auto device = instance->create_device(window); - auto swapChain = device->create_swap_chain(window); + VulkanPipelineLayout pipeline_layout(device, {}, {}); + VulkanPipeline pipeline(device, swap_chain.render_pass, pipeline_layout, "vert.glsl", "frag.glsl", { .vertex_input_state = { .vertex_descriptions = vertex_descriptions } }); - auto vertShaderModule = device->create_shader_module("vert.glsl", ShaderTypes::VERTEX_SHADER); - auto fragShaderModule = device->create_shader_module("frag.glsl", ShaderTypes::FRAGMENT_SHADER); - auto pipelineLayout = device->create_pipeline_layout({}, {}); - auto pipeline = device->create_pipeline(swapChain, pipelineLayout, { vertShaderModule, fragShaderModule }, { - .pVertexInputState = { .vertexDescriptions = vertexDescriptions } - }); + const std::vector vertices = { {-0.5f, -0.5f, 0.0f}, {0.5f, -0.5f, 0.0f}, {0.0f, 0.5f, 0.0f} }; + const std::vector indices = { 0, 1, 2, }; - auto vertexBuffer = device->create_buffer_memory(sizeof(Vertex) * vertices.size()); - auto indexBuffer = device->create_buffer_memory(sizeof(u32) * indices.size()); - vertexBuffer.memory->upload_data(device, vertices.data(), sizeof(Vertex) * vertices.size()); - indexBuffer.memory->upload_data(device, indices.data(), sizeof(u32) * indices.size()); + VulkanBufferMemory vb(device, vertices); + VulkanBufferMemory eb(device, indices); - auto commandBufferPool = device->create_command_buffer_pool(); - auto commandBuffers = commandBufferPool->create_command_buffers(device, 3); + VulkanCommandBufferPool command_buffer_pool(device); + auto command_buffers = command_buffer_pool.create_command_buffers(3); while (!window->closing()) { - GLFWContext::poll_events(); + window->pull_events(); uint32_t frame; - auto result = swapChain->acquire_next_image(device, &frame); - - if(!result.is_ok()) + if(!swap_chain.acquire_next_image(&frame).is_ok()) continue; - auto& cmd = commandBuffers[frame]; + unique_ptr& cmd = command_buffers[frame]; - cmd->begin_record() - .begin_render_pass(swapChain, frame) - .set_viewport(0, 0, window->get_width(), window->get_height()) - .bind_pipeline(pipeline) - .bind_vertex_buffer(vertexBuffer.buffer) - .bind_index_buffer(indexBuffer.buffer) - .draw_indexed(indices.size()) - .end_render_pass() - .end_record(); + cmd->begin_record(); - result = swapChain->submit_command_buffers(device, cmd, &frame); + cmd->begin_render_pass(swap_chain); + cmd->set_viewport(window); + cmd->bind_pipeline(pipeline); + cmd->bind_vertex_buffer(vb) + .bind_index_buffer(eb) + .draw_indexed(indices.size()); + cmd->end_render_pass(); - if(!result.is_ok()) // Todo check if window is resized + cmd->end_record(); + + if(!swap_chain.submit_present_command_buffers(*cmd, &frame).is_ok()) // Todo check if window is resized continue; } - device->wait_idle(); - - device->destroy_all(commandBuffers); // Todo \/ lets make all tuples also destroyable - device->destroy_all(vertexBuffer.buffer, indexBuffer.buffer, vertexBuffer.memory, indexBuffer.memory,commandBufferPool); - device->destroy_all(vertShaderModule,fragShaderModule,pipelineLayout,pipeline, swapChain); - - device->destroy(); - instance->destroy(); - - GLFWContext::terminate(); - return 0; } diff --git a/examples/gfx/vulkan/1_vulkan_hello_triangle/vert.glsl b/examples/gfx/vulkan/1_vulkan_hello_triangle/vert.glsl index c250da8d..c81e842d 100644 --- a/examples/gfx/vulkan/1_vulkan_hello_triangle/vert.glsl +++ b/examples/gfx/vulkan/1_vulkan_hello_triangle/vert.glsl @@ -2,12 +2,7 @@ #extension GL_EXT_nonuniform_qualifier : enable layout (location = 0) in vec3 position; -layout (location = 1) in vec3 color; - -layout (location = 0) out vec3 fragColor; void main() { gl_Position = vec4(position, 1.0); - - fragColor = color; } diff --git a/examples/gfx/vulkan/2_vulkan_3d_cube/CMakeLists.txt b/examples/gfx/vulkan/2_vulkan_3d_cube/CMakeLists.txt deleted file mode 100644 index f605e848..00000000 --- a/examples/gfx/vulkan/2_vulkan_3d_cube/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -file(GLOB_RECURSE BEBONE_EXAMPLE_GFX_VULKAN_2_VULKAN_3D_CUBE *.cpp) - -include_directories("../../src") -include_directories("./") - -add_executable(Bebone_Example_Gfx_2_Vulkan_3D_Cube ${BEBONE_EXAMPLE_GFX_VULKAN_2_VULKAN_3D_CUBE}) -target_link_libraries(Bebone_Example_Gfx_2_Vulkan_3D_Cube bebone) \ No newline at end of file diff --git a/examples/gfx/vulkan/2_vulkan_3d_cube/frag.glsl b/examples/gfx/vulkan/2_vulkan_3d_cube/frag.glsl deleted file mode 100644 index 2f2ed644..00000000 --- a/examples/gfx/vulkan/2_vulkan_3d_cube/frag.glsl +++ /dev/null @@ -1,8 +0,0 @@ -#version 450 core - -layout (location = 0) in vec3 fragColor; -layout (location = 0) out vec4 outColor; - -void main() { - outColor = vec4(fragColor, 1.0); -} \ No newline at end of file diff --git a/examples/gfx/vulkan/2_vulkan_3d_cube/main.cpp b/examples/gfx/vulkan/2_vulkan_3d_cube/main.cpp deleted file mode 100644 index 66883962..00000000 --- a/examples/gfx/vulkan/2_vulkan_3d_cube/main.cpp +++ /dev/null @@ -1,182 +0,0 @@ -#define OMNI_TYPES_MATRIX_COLLUM_MAJOR_ORDER -#define OMNI_TYPES_MATRIX4X4_PROJECTION_MATRIX_INVERSE_Y_AXIS -#include "bebone/bebone.h" - -using namespace bebone::core; -using namespace bebone::gfx; -using namespace bebone::gfx::vulkan; - -struct Vertex { Vec3f pos, color; }; -struct Handles { u32 cameraHandle, transformHandle; }; -struct CameraTransform { Mat4f view, proj; }; -struct Transform { Mat4f transform, scale, rotation; }; - -const std::vector vertices = { - {{-1.0, -1.0, -1.0}, {0.0f, 1.0f, 1.0f}}, - {{ 1.0, -1.0, -1.0}, {0.0f, 1.0f, 0.0f}}, - {{ 1.0, 1.0, -1.0}, {0.0f, 0.0f, 1.0f}}, - {{-1.0, 1.0, -1.0}, {0.0f, 0.0f, 0.0f}}, - {{-1.0, -1.0, 1.0}, {1.0f, 1.0f, 1.0f}}, - {{ 1.0, -1.0, 1.0}, {1.0f, 1.0f, 0.0f}}, - {{ 1.0, 1.0, 1.0}, {1.0f, 0.0f, 1.0f}}, - {{-1.0, 1.0, 1.0}, {1.0f, 0.0f, 0.0f}}, -}; - -// Todo make this nicer -const auto vertexDescriptions = VulkanPipelineVertexInputStateTuple { - .bindingDescriptions = { - { 0, sizeof(Vertex), VK_VERTEX_INPUT_RATE_VERTEX } - }, - .attributeDescriptions = { - { 0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, pos) }, - { 1, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, color) }, - } -}; - -const std::vector indices = { - 0, 1, 2, 2, 3, 0, - 1, 5, 6, 6, 2, 1, - 7, 6, 5, 5, 4, 7, - 4, 0, 3, 3, 7, 4, - 4, 5, 1, 1, 0, 4, - 3, 2, 6, 6, 7, 3 -}; - -// Todo move view matrix to omni_types -Mat4f get_view_matrix(Vec3f position, Vec3f direction, Vec3f up); - -int main() { - GLFWContext::init(); - - auto window = WindowFactory::create_window("2. Vulkan 3d cube example", 800, 600, GfxAPI::VULKAN); - - auto instance = VulkanInstance::create_instance(); - auto device = instance->create_device(window); - auto swapChain = device->create_swap_chain(window); - - auto descriptorPool = device->create_descriptor_pool(); - auto descriptorSetLayout = device->create_descriptor_set_layouts({ - VulkanDescriptorSetLayoutBinding::bindless_uniform(0), - VulkanDescriptorSetLayoutBinding::bindless_uniform(1) - }); - auto descriptors = descriptorPool->create_descriptors(device, descriptorSetLayout[0], 3); - - auto pipelineLayout = device->create_pipeline_layout(descriptorSetLayout, { - VulkanConstRange::common(sizeof(Handles), 0) - }); - auto vertShaderModule = device->create_shader_module("vert.glsl", ShaderTypes::VERTEX_SHADER); - auto fragShaderModule = device->create_shader_module("frag.glsl", ShaderTypes::FRAGMENT_SHADER); - auto pipeline = device->create_pipeline(swapChain, pipelineLayout, { vertShaderModule, fragShaderModule }, { - .pVertexInputState = { .vertexDescriptions = vertexDescriptions } - }); - - auto vertexBuffer = device->create_buffer_memory(sizeof(Vertex) * vertices.size()); - auto indexBuffer = device->create_buffer_memory(sizeof(u32) * indices.size()); - vertexBuffer.memory->upload_data(device, vertices.data(), sizeof(Vertex) * vertices.size()); - indexBuffer.memory->upload_data(device, indices.data(), sizeof(u32) * indices.size()); - - auto transformUBO = device->create_buffer_memorys(sizeof(Transform), 3); // Todo - auto cameraUBO = device->create_buffer_memorys(sizeof(CameraTransform), 3); - descriptorPool->update_descriptor_sets(device, transformUBO, sizeof(Transform), descriptors, 0, {0, 1, 2}); - descriptorPool->update_descriptor_sets(device, cameraUBO, sizeof(CameraTransform), descriptors, 1, {3, 4, 5}); - - auto commandBufferPool = device->create_command_buffer_pool(); - auto commandBuffers = commandBufferPool->create_command_buffers(device, 3); - - auto cameraTransform = CameraTransform { - get_view_matrix(Vec3f(0.0f, 0.0f, 10.0f), Vec3f::back, Vec3f::down), - Mat4f::perspective(1.0472, window->get_aspect(), 0.1f, 100.0f) - }; - - auto transform = Transform { - Mat4f::translation(Vec3f::zero), - Mat4f::scale(1.0f), - Mat4f::identity() - }; - - f32 t = 0.0f; - - while (!window->closing()) { - ++t; - - GLFWContext::poll_events(); - - uint32_t frame; - auto result = swapChain->acquire_next_image(device, &frame); - - if(!result.is_ok()) - continue; - - transform.rotation = trait_bryan_angle_yxz(Vec3f(t * 0.001f, t * 0.001f, 0.0f)); - cameraTransform.proj = Mat4f::perspective(1.0472, window->get_aspect(), 0.1f, 100.0f); - - transformUBO[frame].memory->upload_data(device, &transform, sizeof(Transform)); - cameraUBO[frame].memory->upload_data(device, &cameraTransform, sizeof(CameraTransform)); - - auto handles = Handles {static_cast(frame + 3), static_cast(frame) }; - - auto& cmd = commandBuffers[frame]; - - cmd->begin_record() - .begin_render_pass(swapChain, frame) - .set_viewport(0, 0, window->get_width(), window->get_height()) - .bind_pipeline(pipeline) - .bind_descriptor_set(pipelineLayout, descriptors, frame) - .bind_vertex_buffer(vertexBuffer.buffer) - .bind_index_buffer(indexBuffer.buffer) - .push_constant(pipelineLayout, sizeof(Handles), 0, &handles) - .draw_indexed(indices.size()) - .end_render_pass() - .end_record(); - - result = swapChain->submit_command_buffers(device, cmd, &frame); - - if(!result.is_ok()) // Todo check if window is resized - continue; - } - - device->wait_idle(); - - device->destroy_all(commandBuffers); - device->destroy_all(vertexBuffer.buffer, indexBuffer.buffer, vertexBuffer.memory, indexBuffer.memory,commandBufferPool); - - for(auto& b : transformUBO) - device->destroy_all(b.buffer, b.memory); - - for(auto& b : cameraUBO) - device->destroy_all(b.buffer, b.memory); - - device->destroy_all(descriptorSetLayout); - device->destroy_all(descriptors); - device->destroy_all(descriptorPool, vertShaderModule,fragShaderModule,pipelineLayout,pipeline, swapChain); - - device->destroy(); - instance->destroy(); - - // Todo move all glfw things to glfw context static class - GLFWContext::terminate(); - - return 0; -} - -Mat4f get_view_matrix(Vec3f position, Vec3f direction, Vec3f up) { - const auto w = direction.normalize(); - const auto u = w.cross(up).normalize(); - const auto v = w.cross(u); - - auto viewMatrix = Mat4f::identity(); - viewMatrix[0 * 4 + 0] = u.x; - viewMatrix[1 * 4 + 0] = u.y; - viewMatrix[2 * 4 + 0] = u.z; - viewMatrix[0 * 4 + 1] = v.x; - viewMatrix[1 * 4 + 1] = v.y; - viewMatrix[2 * 4 + 1] = v.z; - viewMatrix[0 * 4 + 2] = w.x; - viewMatrix[1 * 4 + 2] = w.y; - viewMatrix[2 * 4 + 2] = w.z; - viewMatrix[3 * 4 + 0] = -1.0f * (u).dot(position); - viewMatrix[3 * 4 + 1] = -1.0f * (v).dot(position); - viewMatrix[3 * 4 + 2] = -1.0f * (w).dot(position); - - return viewMatrix; -} diff --git a/examples/gfx/vulkan/2_vulkan_texture/CMakeLists.txt b/examples/gfx/vulkan/2_vulkan_texture/CMakeLists.txt new file mode 100644 index 00000000..af00d4d9 --- /dev/null +++ b/examples/gfx/vulkan/2_vulkan_texture/CMakeLists.txt @@ -0,0 +1,7 @@ +file(GLOB_RECURSE BEBONE_EXAMPLE_GFX_VULKAN_2_VULKAN_TEXTURE *.cpp) + +include_directories("./") +include_directories(${BEBONE_INCLUDES}) + +add_executable(Bebone_Example_Gfx_2_Vulkan_Texture ${BEBONE_EXAMPLE_GFX_VULKAN_2_VULKAN_TEXTURE}) +target_link_libraries(Bebone_Example_Gfx_2_Vulkan_Texture bebone) \ No newline at end of file diff --git a/examples/gfx/vulkan/2_vulkan_texture/frag.glsl b/examples/gfx/vulkan/2_vulkan_texture/frag.glsl new file mode 100644 index 00000000..367d6e16 --- /dev/null +++ b/examples/gfx/vulkan/2_vulkan_texture/frag.glsl @@ -0,0 +1,11 @@ +#version 450 core + +layout (location = 1) in vec2 tex_cord; + +layout (location = 0) out vec4 out_color; + +layout(set = 0, binding = 2) uniform sampler2D textures[]; + +void main() { + out_color = vec4(texture(textures[0], tex_cord).rgb, 1.0); +} \ No newline at end of file diff --git a/examples/gfx/vulkan/2_vulkan_texture/image.png b/examples/gfx/vulkan/2_vulkan_texture/image.png new file mode 100644 index 00000000..dc0e13aa Binary files /dev/null and b/examples/gfx/vulkan/2_vulkan_texture/image.png differ diff --git a/examples/gfx/vulkan/2_vulkan_texture/main.cpp b/examples/gfx/vulkan/2_vulkan_texture/main.cpp new file mode 100644 index 00000000..61795af2 --- /dev/null +++ b/examples/gfx/vulkan/2_vulkan_texture/main.cpp @@ -0,0 +1,87 @@ +#include "bebone/bebone.h" + +using namespace bebone::core; +using namespace bebone::assets; +using namespace bebone::gfx; + +struct Vertex { + Vec3f pos; + Vec2f tex_coords; +}; + +// Todo make this nicer +const auto vertex_descriptions = VulkanPipelineVertexInputStateTuple { + .binding_descriptions = { + { 0, sizeof(Vertex), VK_VERTEX_INPUT_RATE_VERTEX } + }, + .attribute_descriptions = { + { 0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, pos) }, + { 1, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(Vertex, tex_coords) } + } +}; + +int main() { + auto window = WindowFactory::create_window("2. Vulkan texture example", 800, 600, Vulkan); + + VulkanInstance instance; + VulkanDevice device(instance, window); + VulkanSwapChain swap_chain(device, window); + + VulkanPipelineLayout pipeline_layout(device, {}, {}); + VulkanPipeline pipeline(device, swap_chain.render_pass, pipeline_layout, "vert.glsl", "frag.glsl", { .vertex_input_state = { .vertex_descriptions = vertex_descriptions } }); + + const std::vector vertices { + {{0.5f, 0.5f, 0.0f}, {1.0f, 1.0f}}, + {{0.5f, -0.5f, 0.0f}, {1.0f, 0.0f}}, + {{-0.5f, -0.5f, 0.0f}, {0.0f, 0.0f}}, + {{-0.5f, 0.5f, 0.0f}, {0.0f, 1.0f}} + }; + + const std::vector indices { 0, 3, 1, 3, 2, 1 }; + + VulkanBufferMemory vb(device, vertices); + VulkanBufferMemory eb(device, indices); + + VulkanCommandBufferPool command_buffer_pool(device); + auto command_buffers = command_buffer_pool.create_command_buffers(3); + + /* + VulkanTexture texture(device); + + auto texture = device->create_texture("image.png"); + std::ignore = pipeline_manager->bind_texture(device, texture); + + while (!window->closing()) { + window->pull_events(); + + uint32_t frame; + if(!swap_chain->acquire_next_image(device, &frame).is_ok()) + continue; + + auto& cmd = command_buffers[frame]; + + cmd->begin_record(); + cmd->bind_descriptor_set(pipeline_manager->get_pipeline_layout(), pipeline_manager->get_descriptor_set()); + + cmd->begin_render_pass(swap_chain); + // Flipped viewport + cmd->set_viewport(0, window->get_height(), window->get_width(), -window->get_height()); + // cmd->set_viewport(0, 0, window->get_width(), window->get_height()); + + cmd->bind_pipeline(pipeline); + cmd->bind_vertex_buffer(vb); + cmd->bind_index_buffer(eb); + cmd->draw_indexed(indices.size()); + cmd->end_render_pass(); + + cmd->end_record(); + + if(!swap_chain->submit_present_command_buffers(device, cmd, &frame).is_ok()) // Todo check if window is resized + continue; + } + */ + + // instance->destroy(); + + return 0; +} diff --git a/examples/gfx/vulkan/2_vulkan_texture/vert.glsl b/examples/gfx/vulkan/2_vulkan_texture/vert.glsl new file mode 100644 index 00000000..cf8d2267 --- /dev/null +++ b/examples/gfx/vulkan/2_vulkan_texture/vert.glsl @@ -0,0 +1,12 @@ +#version 450 core +#extension GL_EXT_nonuniform_qualifier : enable + +layout (location = 0) in vec3 position; +layout (location = 1) in vec2 tex_cord; + +layout (location = 1) out vec2 otex_cord; + +void main() { + gl_Position = vec4(position, 1.0); + otex_cord = tex_cord; +} diff --git a/examples/gfx/vulkan/3_vulkan_3d_cube/CMakeLists.txt b/examples/gfx/vulkan/3_vulkan_3d_cube/CMakeLists.txt new file mode 100644 index 00000000..30fd1f5a --- /dev/null +++ b/examples/gfx/vulkan/3_vulkan_3d_cube/CMakeLists.txt @@ -0,0 +1,7 @@ +file(GLOB_RECURSE BEBONE_EXAMPLE_GFX_VULKAN_3_VULKAN_3D_CUBE *.cpp) + +include_directories("./") +include_directories(${BEBONE_INCLUDES}) + +add_executable(Bebone_Example_Gfx_3_Vulkan_3D_Cube ${BEBONE_EXAMPLE_GFX_VULKAN_3_VULKAN_3D_CUBE}) +target_link_libraries(Bebone_Example_Gfx_3_Vulkan_3D_Cube bebone) \ No newline at end of file diff --git a/examples/gfx/vulkan/3_vulkan_3d_cube/frag.glsl b/examples/gfx/vulkan/3_vulkan_3d_cube/frag.glsl new file mode 100644 index 00000000..9495778c --- /dev/null +++ b/examples/gfx/vulkan/3_vulkan_3d_cube/frag.glsl @@ -0,0 +1,9 @@ +#version 450 core + +layout (location = 0) in vec3 frag_color; + +layout (location = 0) out vec4 out_color; + +void main() { + out_color = vec4(frag_color, 1.0); +} \ No newline at end of file diff --git a/examples/gfx/vulkan/3_vulkan_3d_cube/main.cpp b/examples/gfx/vulkan/3_vulkan_3d_cube/main.cpp new file mode 100644 index 00000000..04ffaacc --- /dev/null +++ b/examples/gfx/vulkan/3_vulkan_3d_cube/main.cpp @@ -0,0 +1,121 @@ +#include "bebone/bebone.h" + +using namespace bebone::core; +using namespace bebone::gfx; + +struct Vertex { Vec3f pos; ColorRGBA color; }; +struct Handles { VulkanBindlessBufferHandle camera_handle, transform_handle; }; +struct CameraTransform { Mat4f view, proj; }; +struct Transform { Mat4f transform, scale, rotation; }; + +const vector vertices { + {{ -1.0, -1.0, 1.0 }, ColorRGBA::WHITE }, + {{ 1.0, -1.0, 1.0 }, ColorRGBA::YELLOW }, + {{ 1.0, 1.0, 1.0 }, ColorRGBA::MAGENTA}, + {{ -1.0, 1.0, 1.0 }, ColorRGBA::RED }, + {{ -1.0, -1.0, -1.0 }, ColorRGBA::CYAN }, + {{ 1.0, -1.0, -1.0 }, ColorRGBA::GREEN }, + {{ 1.0, 1.0, -1.0 }, ColorRGBA::BLUE }, + {{ -1.0, 1.0, -1.0 }, ColorRGBA::BLACK } +}; + +const vector indices { + 0, 1, 2, 2, 3, 0, 1, 5, 6, 6, 2, 1, 7, 6, 5, 5, 4, 7, 4, 0, 3, 3, 7, 4, 4, 5, 1, 1, 0, 4, 3, 2, 6, 6, 7, 3 +}; + +// Todo make this nicer +const auto vertex_descriptions = VulkanPipelineVertexInputStateTuple { + .binding_descriptions = { + { 0, sizeof(Vertex), VK_VERTEX_INPUT_RATE_VERTEX } + }, + .attribute_descriptions = { + { 0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, pos) }, + { 1, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, color) }, + } +}; + +int main() { + auto window = WindowFactory::create_window("3. Vulkan 3d cube example", 800, 600, GfxAPI::Vulkan); + + VulkanInstance instance; + VulkanDevice device(instance, window); + VulkanSwapChain swapChain + auto swap_chain = device->create_swap_chain(window); + + auto pipeline_manager = device->create_pipeline_manager(); + + auto pipeline = pipeline_manager->create_pipeline( + device, swap_chain->render_pass, "vert.glsl", "frag.glsl", + { .vertex_input_state = { .vertex_descriptions = vertex_descriptions } } + ); + + auto vb = device->create_buffer_memory_from(vertices); + auto eb = device->create_buffer_memory_from(indices); + + auto t_ubo = device->create_buffer_memorys(sizeof(Transform), 3); + auto c_ubo = device->create_buffer_memorys(sizeof(CameraTransform), 3); + + auto t_handles = pipeline_manager->bind_uniform_buffers(device, t_ubo); + auto c_handles = pipeline_manager->bind_uniform_buffers(device, c_ubo); + + auto command_buffer_pool = device->create_command_buffer_pool(); + auto command_buffers = command_buffer_pool->create_command_buffers(device, 3); + + auto c_transform = CameraTransform { + Mat4f::view(Vec3f(0.0f, 0.0f, 0.0f), Vec3f::forward, Vec3f::up), + Mat4f::perspective(1.0472, window->get_aspect(), 0.1f, 100.0f) + }; + + for(auto& ubo : c_ubo) + ubo->upload_data(device, &c_transform, sizeof(CameraTransform)); + + auto transform = Transform { + Mat4f::translation(Vec3f::zero), + Mat4f::scale(1.0f), + Mat4f::identity() + }; + + while (!window->closing()) { + window->pull_events(); + + uint32_t frame; + if(!swap_chain->acquire_next_image(device, &frame).is_ok()) + continue; + + std::cout << Vec3f(0.0f, 2.0f, (sin(Time::get_seconds_elapsed()) + 1.0f) * 5.0f) << "\n"; + transform.transform = Mat4f::translation(Vec3f(0.0f, 2.0f, (sin(Time::get_seconds_elapsed()) + 1.0f) * 5.0f)); + + transform.rotation = trait_bryan_angle_yxz(Vec3f(Time::get_seconds_elapsed(), Time::get_seconds_elapsed(), 0.0f)); + t_ubo[frame]->upload_data(device, &transform, sizeof(Transform)); + + auto& cmd = command_buffers[frame]; + + cmd->begin_record(); + cmd->bind_descriptor_set(pipeline_manager->get_pipeline_layout(), pipeline_manager->get_descriptor_set()); + + cmd->begin_render_pass(swap_chain); + // Flipped viewport + cmd->set_viewport(0, window->get_height(), window->get_width(), -window->get_height()); + // cmd->set_viewport(0, 0, window->get_width(), window->get_height()); + + cmd->bind_pipeline(pipeline); + + auto handles = Handles { c_handles[frame], t_handles[frame] }; + cmd->push_constant(pipeline_manager->get_pipeline_layout(), sizeof(Handles), 0, &handles); + + cmd->bind_vertex_buffer(vb); + cmd->bind_index_buffer(eb); + cmd->draw_indexed(indices.size()); + cmd->end_render_pass(); + + cmd->end_record(); + + if(!swap_chain->submit_present_command_buffers(device, command_buffers[frame], &frame).is_ok()) // Todo check if window is resized + continue; + } + + // Todo + // instance->destroy(); + + return 0; +} diff --git a/examples/gfx/vulkan/2_vulkan_3d_cube/vert.glsl b/examples/gfx/vulkan/3_vulkan_3d_cube/vert.glsl similarity index 81% rename from examples/gfx/vulkan/2_vulkan_3d_cube/vert.glsl rename to examples/gfx/vulkan/3_vulkan_3d_cube/vert.glsl index bd058efb..dfdb055c 100644 --- a/examples/gfx/vulkan/2_vulkan_3d_cube/vert.glsl +++ b/examples/gfx/vulkan/3_vulkan_3d_cube/vert.glsl @@ -4,15 +4,15 @@ layout (location = 0) in vec3 position; layout (location = 1) in vec3 color; -layout (location = 0) out vec3 fragColor; +layout (location = 0) out vec3 frag_color; -layout(binding = 0) uniform TransformUBO { +layout(set = 0, binding = 0) uniform TransformUBO { mat4 translation; mat4 scale; mat4 rotation; } transform[]; -layout(binding = 1) uniform CameraUBO { +layout(set = 0, binding = 0) uniform CameraUBO { mat4 view; mat4 proj; } camera[]; @@ -33,5 +33,5 @@ void main() { mat4 model = translation * rotation * scale; gl_Position = proj * view * model * vec4(position, 1.0); - fragColor = color; + frag_color = color; } diff --git a/examples/gfx/vulkan/4_vulkan_bloom/CMakeLists.txt b/examples/gfx/vulkan/4_vulkan_bloom/CMakeLists.txt new file mode 100644 index 00000000..e30823e6 --- /dev/null +++ b/examples/gfx/vulkan/4_vulkan_bloom/CMakeLists.txt @@ -0,0 +1,7 @@ +file(GLOB_RECURSE BEBONE_EXAMPLE_GFX_VULKAN_4_VULKAN_BLOOM *.cpp) + +include_directories("./") +include_directories(${BEBONE_INCLUDES}) + +add_executable(Bebone_Example_Gfx_4_Vulkan_Bloom ${BEBONE_EXAMPLE_GFX_VULKAN_4_VULKAN_BLOOM}) +target_link_libraries(Bebone_Example_Gfx_4_Vulkan_Bloom bebone) \ No newline at end of file diff --git a/examples/gfx/vulkan/4_vulkan_bloom/blur.frag.glsl b/examples/gfx/vulkan/4_vulkan_bloom/blur.frag.glsl new file mode 100644 index 00000000..abb372e6 --- /dev/null +++ b/examples/gfx/vulkan/4_vulkan_bloom/blur.frag.glsl @@ -0,0 +1,21 @@ +#version 450 core + +layout (location = 0) in vec3 normal; +layout (location = 1) in vec2 texcoord; + +layout (location = 0) out vec4 out_color; + +layout(set = 0, binding = 2) uniform sampler2D textures[]; + +void main() { + vec4 result = vec4(0.0f); + + for(int x = -5; x < 5; ++x) { + for(int y = -5; y < 5; ++y) { + vec2 offset = 5*vec2(x / 800.0, y / 600.0); + result += texture(textures[0], texcoord + offset); + } + } + + out_color = result * (1.0/50.0); +} \ No newline at end of file diff --git a/examples/gfx/vulkan/4_vulkan_bloom/blur.vert.glsl b/examples/gfx/vulkan/4_vulkan_bloom/blur.vert.glsl new file mode 100644 index 00000000..ca4cc944 --- /dev/null +++ b/examples/gfx/vulkan/4_vulkan_bloom/blur.vert.glsl @@ -0,0 +1,16 @@ +#version 450 core +#extension GL_EXT_nonuniform_qualifier : enable + +layout (location = 0) in vec3 position; +layout (location = 1) in vec3 normal; +layout (location = 2) in vec2 texcoord; + +layout (location = 0) out vec3 out_normal; +layout (location = 1) out vec2 out_texcoord; + +void main() { + gl_Position = vec4(position, 1.0); + + out_normal = normal; + out_texcoord = texcoord; +} diff --git a/examples/gfx/vulkan/4_vulkan_bloom/geometry.frag.glsl b/examples/gfx/vulkan/4_vulkan_bloom/geometry.frag.glsl new file mode 100644 index 00000000..9144a978 --- /dev/null +++ b/examples/gfx/vulkan/4_vulkan_bloom/geometry.frag.glsl @@ -0,0 +1,12 @@ +#version 450 core + +layout (location = 0) in vec3 normal; +layout (location = 1) in vec2 texcoord; + +layout (location = 0) out vec4 out_color; +layout (location = 1) out vec4 grayscale_color; + +void main() { + out_color = vec4(normal, 1.0); + grayscale_color = vec4(vec3(out_color.x + out_color.y + out_color.z / 3.0), 1.0); +} \ No newline at end of file diff --git a/examples/gfx/vulkan/4_vulkan_bloom/geometry.vert.glsl b/examples/gfx/vulkan/4_vulkan_bloom/geometry.vert.glsl new file mode 100644 index 00000000..229f1a9d --- /dev/null +++ b/examples/gfx/vulkan/4_vulkan_bloom/geometry.vert.glsl @@ -0,0 +1,29 @@ +#version 450 core +#extension GL_EXT_nonuniform_qualifier : enable + +layout (location = 0) in vec3 position; +layout (location = 1) in vec3 normal; +layout (location = 2) in vec2 texcoord; + +layout (location = 0) out vec3 out_normal; +layout (location = 1) out vec2 out_texcoord; + +layout(set = 0, binding = 0) uniform TransformUBO { + mat4 transform; +} transform[]; + +layout(set = 0, binding = 0) uniform CameraUBO { + mat4 cam; +} camera[]; + +layout( push_constant ) uniform Handles { + int camera; + int transform; +} handles; + +void main() { + gl_Position = camera[handles.camera].cam * transform[handles.transform].transform * vec4(position, 1.0); + + out_normal = normal; + out_texcoord = texcoord; +} diff --git a/examples/gfx/vulkan/4_vulkan_bloom/main.cpp b/examples/gfx/vulkan/4_vulkan_bloom/main.cpp new file mode 100644 index 00000000..c1899109 --- /dev/null +++ b/examples/gfx/vulkan/4_vulkan_bloom/main.cpp @@ -0,0 +1,159 @@ +#include "bebone/bebone.h" + +using namespace bebone::core; +using namespace bebone::gfx; +using namespace bebone::renderer; + +struct GeometryHandles { VulkanBindlessBufferHandle camera_handle, transform_handle; }; +struct PostHandles { VulkanBindlessTextureHandle geometry_texture, blur_texture; }; + +// Todo make this nicer +const auto vertex_descriptions = VulkanPipelineVertexInputStateTuple { + .binding_descriptions = { + { 0, sizeof(Vertex), VK_VERTEX_INPUT_RATE_VERTEX } + }, + .attribute_descriptions = { + { 0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, position) }, + { 1, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, normal) }, + { 2, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(Vertex, texcoord) }, + } +}; + +int main() { + auto window = WindowFactory::create_window("4. Vulkan bloom example", 800, 600, GfxAPI::Vulkan); + + VulkanInstance instance; + auto device = instance.create_device(window); + auto swap_chain = device->create_swap_chain(window); + auto command_buffers = device->create_command_buffers(3); + + auto pipeline_manager = device->create_pipeline_manager(); + + // Geometry pass + auto geometry_render_pass = device->create_render_pass({800, 600}, { + VulkanAttachmentDesc::color2D({ 800,600 }, { .format = VK_FORMAT_R32G32B32A32_SFLOAT }), + VulkanAttachmentDesc::color2D({ 800,600 }, { .format = VK_FORMAT_R32G32B32A32_SFLOAT }), + VulkanAttachmentDesc::depth2D({ 800,600 }, { .format = device->find_depth_format() }), + }); + + auto geometry_render_target = std::unique_ptr(device, geometry_render_pass); + + auto geometry_pipeline = pipeline_manager->create_pipeline( + device, geometry_render_pass, "geometry.vert.glsl", "geometry.frag.glsl", + { .vertex_input_state = { .vertex_descriptions = vertex_descriptions } } + ); + + // Blur render pass + auto blur_render_pass = device->create_render_pass({800, 600}, { + VulkanAttachmentDesc::color2D({800, 600}, {.format = VK_FORMAT_R32G32B32A32_SFLOAT }) + }); + + auto blur_render_target = device->create_render_target(blur_render_pass); + + auto blur_pipeline = pipeline_manager->create_pipeline( + device, blur_render_pass, "blur.vert.glsl", "blur.frag.glsl", + { .vertex_input_state = { .vertex_descriptions = vertex_descriptions } } + ); + + auto blur_texture_handles = pipeline_manager->bind_attachments(device, geometry_render_target->get_color_attachment(0)); + + // Post pipeline + auto post_pipeline = pipeline_manager->create_pipeline( + device, swap_chain->render_pass, "post.vert.glsl", "post.frag.glsl", + { .vertex_input_state = { .vertex_descriptions = vertex_descriptions } } + ); + + auto post_geometry_texture_handles = pipeline_manager->bind_attachments(device, geometry_render_target->get_color_attachment(0)); + auto post_geometry_grayscale_texture_handles = pipeline_manager->bind_attachments(device, geometry_render_target->get_color_attachment(1)); + auto post_blur_texture_handles = pipeline_manager->bind_attachments(device, blur_render_target->get_color_attachment(0)); + + auto cube_generator = std::make_shared(1.0f, 1.0f, 1.0f); + auto quad_generator = std::make_shared(1.0f, 1.0f); + + auto cube_mesh = static_pointer_cast(cube_generator->generate(std::make_shared(*device))->get_impl()); + auto quad_mesh = static_pointer_cast(quad_generator->generate(std::make_shared(*device))->get_impl()); + + auto transform = Transform {}; + auto camera = Mat4f::perspective(1, window->get_aspect(), 0.1f, 100.0f) * Mat4f::translation(Vec3f(0, 0, 5)); + + auto c_ubo = device->create_buffer_memorys(sizeof(Mat4f), 3); + for(auto& ubo : c_ubo) + ubo->upload_data(device, &camera, sizeof(Mat4f)); + auto c_handles = pipeline_manager->bind_uniform_buffers(device, c_ubo); + + auto t_ubo = device->create_buffer_memorys(sizeof(Mat4f), 3); + auto t_handles = pipeline_manager->bind_uniform_buffers(device, t_ubo); + + while (!window->closing()) { + transform.rotation.x += 0.02f; + transform.rotation.z -= 0.02f; + + uint32_t frame; + if(!swap_chain->acquire_next_image(device, &frame).is_ok()) + continue; + + auto mat = calculate_transform_matrix(transform); + t_ubo[frame]->upload_data(device, &mat, sizeof(Mat4f)); + + auto& cmd = command_buffers[frame]; + + cmd->begin_record(); + cmd->bind_descriptor_set(pipeline_manager->get_pipeline_layout(), pipeline_manager->get_descriptor_set()); + + // Render geometry + cmd->begin_render_pass(geometry_render_target, geometry_render_pass, frame); + // Flipped viewport + cmd->set_viewport(0, window->get_height(), window->get_width(), -window->get_height()); + // cmd->set_viewport(0, 0, window->get_width(), window->get_height()); + + cmd->bind_pipeline(geometry_pipeline); + + auto handles = GeometryHandles { c_handles[frame], t_handles[frame] }; + cmd->push_constant(pipeline_manager->get_pipeline_layout(), sizeof(GeometryHandles), 0, &handles); + + cube_mesh->bind(cmd); + cmd->draw_indexed(cube_mesh->get_triangle_count()); + cmd->end_render_pass(); + + // Blur pass + cmd->begin_render_pass(blur_render_target, blur_render_pass, frame); + // Flipped viewport + cmd->set_viewport(0, window->get_height(), window->get_width(), -window->get_height()); + // cmd->set_viewport(0, 0, window->get_width(), window->get_height()); + + cmd->bind_pipeline(blur_pipeline); + + auto blur_handles = blur_texture_handles[frame]; + cmd->push_constant(pipeline_manager->get_pipeline_layout(), sizeof(VulkanBindlessTextureHandle), 0, &blur_handles); + + quad_mesh->bind(cmd); + cmd->draw_indexed(quad_mesh->get_triangle_count()); + cmd->end_render_pass(); + + // Final pass + cmd->begin_render_pass(swap_chain); + // Flipped viewport + cmd->set_viewport(0, window->get_height(), window->get_width(), -window->get_height()); + // cmd->set_viewport(0, 0, window->get_width(), window->get_height()); + + cmd->bind_pipeline(post_pipeline); + + auto post_handle = PostHandles { post_geometry_grayscale_texture_handles[frame], post_blur_texture_handles[frame] }; + cmd->push_constant(pipeline_manager->get_pipeline_layout(), sizeof(PostHandles), 0, &post_handle); + + quad_mesh->bind(cmd); + cmd->draw_indexed(quad_mesh->get_triangle_count()); + cmd->end_render_pass(); + + cmd->end_record(); + if(!swap_chain->submit_present_command_buffers(device, command_buffers[frame], &frame).is_ok()) // Todo check if window is resized + continue; + + window->pull_events(); + } + + // Todo + // instance->destroy(); + + return 0; +} diff --git a/examples/gfx/vulkan/4_vulkan_bloom/post.frag.glsl b/examples/gfx/vulkan/4_vulkan_bloom/post.frag.glsl new file mode 100644 index 00000000..4bc89ab3 --- /dev/null +++ b/examples/gfx/vulkan/4_vulkan_bloom/post.frag.glsl @@ -0,0 +1,28 @@ +#version 450 core +#extension GL_EXT_nonuniform_qualifier : enable + +layout (location = 0) in vec3 normal; +layout (location = 1) in vec2 texcoord; + +layout (location = 0) out vec4 out_color; + +layout( push_constant ) uniform Handles { + int geometry_texture; + int blur_texture; +} handles; + +layout(set = 0, binding = 2) uniform sampler2D textures[]; + +void main() { + vec4 fragment = texture(textures[handles.geometry_texture], texcoord); + vec4 bloom = texture(textures[handles.blur_texture], texcoord); + + vec4 color = fragment + bloom; + + float exposure = 0.8f; + vec4 toneMapped = vec4(1.0) - exp(-color * exposure); + + float gamma = 1.0f; + + out_color = pow(toneMapped, vec4(1.0f / gamma)); +} \ No newline at end of file diff --git a/examples/gfx/vulkan/4_vulkan_bloom/post.vert.glsl b/examples/gfx/vulkan/4_vulkan_bloom/post.vert.glsl new file mode 100644 index 00000000..ca4cc944 --- /dev/null +++ b/examples/gfx/vulkan/4_vulkan_bloom/post.vert.glsl @@ -0,0 +1,16 @@ +#version 450 core +#extension GL_EXT_nonuniform_qualifier : enable + +layout (location = 0) in vec3 position; +layout (location = 1) in vec3 normal; +layout (location = 2) in vec2 texcoord; + +layout (location = 0) out vec3 out_normal; +layout (location = 1) out vec2 out_texcoord; + +void main() { + gl_Position = vec4(position, 1.0); + + out_normal = normal; + out_texcoord = texcoord; +} diff --git a/examples/gfx/vulkan/CMakeLists.txt b/examples/gfx/vulkan/CMakeLists.txt index 49a9cdff..326539f3 100644 --- a/examples/gfx/vulkan/CMakeLists.txt +++ b/examples/gfx/vulkan/CMakeLists.txt @@ -1,3 +1,5 @@ add_subdirectory(0_vulkan_window) add_subdirectory(1_vulkan_hello_triangle) -add_subdirectory(2_vulkan_3d_cube) +# add_subdirectory(2_vulkan_texture) +# add_subdirectory(3_vulkan_3d_cube) +# add_subdirectory(4_vulkan_bloom) diff --git a/examples/renderer/CMakeLists.txt b/examples/renderer/CMakeLists.txt new file mode 100644 index 00000000..526534ba --- /dev/null +++ b/examples/renderer/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(agnostic) \ No newline at end of file diff --git a/examples/renderer/agnostic/0_agnostic_window/CMakeLists.txt b/examples/renderer/agnostic/0_agnostic_window/CMakeLists.txt new file mode 100644 index 00000000..1cc06a23 --- /dev/null +++ b/examples/renderer/agnostic/0_agnostic_window/CMakeLists.txt @@ -0,0 +1,7 @@ +file(GLOB_RECURSE BEBONE_EXAMPLE_RENDERER_AGNOSTIC_0_WINDOW *.cpp) + +include_directories(".") +include_directories(${BEBONE_INCLUDES}) + +add_executable(Bebone_Example_Renderer_Agnostic_0_Agnostic_Window ${BEBONE_EXAMPLE_RENDERER_AGNOSTIC_0_WINDOW}) +target_link_libraries(Bebone_Example_Renderer_Agnostic_0_Agnostic_Window bebone) \ No newline at end of file diff --git a/examples/renderer/agnostic/0_agnostic_window/main.cpp b/examples/renderer/agnostic/0_agnostic_window/main.cpp new file mode 100644 index 00000000..0d4ac2cc --- /dev/null +++ b/examples/renderer/agnostic/0_agnostic_window/main.cpp @@ -0,0 +1,20 @@ +#include "bebone/bebone.h" + +using namespace bebone::renderer; +using namespace bebone::gfx; + +int main() { + /* + auto window = WindowFactory::create_window("0. Renderer window example", 800, 600, GfxAPI::OpenGL); + auto renderer = RendererFactory::create_renderer(window); + + auto sprite = renderer->load_sprite("image.png"); + + while(!window->closing()) { + renderer->render(sprite, Transform{ .position = Vec3f::zero }); + renderer->present(); + } +P*/ + + return 0; +} diff --git a/examples/renderer/agnostic/1_agnostic_hello_triangle/CMakeLists.txt b/examples/renderer/agnostic/1_agnostic_hello_triangle/CMakeLists.txt new file mode 100644 index 00000000..d520737d --- /dev/null +++ b/examples/renderer/agnostic/1_agnostic_hello_triangle/CMakeLists.txt @@ -0,0 +1,7 @@ +file(GLOB_RECURSE BEBONE_EXAMPLE_RENDERER_AGNOSTIC_1_HELLO_TRIANGLE *.cpp) + +include_directories(".") +include_directories(${BEBONE_INCLUDES}) + +add_executable(Bebone_Example_Renderer_Agnostic_1_Agnostic_Hello_Triangle ${BEBONE_EXAMPLE_RENDERER_AGNOSTIC_1_HELLO_TRIANGLE}) +target_link_libraries(Bebone_Example_Renderer_Agnostic_1_Agnostic_Hello_Triangle bebone) \ No newline at end of file diff --git a/examples/renderer/agnostic/1_agnostic_hello_triangle/main.cpp b/examples/renderer/agnostic/1_agnostic_hello_triangle/main.cpp new file mode 100644 index 00000000..0d4ac2cc --- /dev/null +++ b/examples/renderer/agnostic/1_agnostic_hello_triangle/main.cpp @@ -0,0 +1,20 @@ +#include "bebone/bebone.h" + +using namespace bebone::renderer; +using namespace bebone::gfx; + +int main() { + /* + auto window = WindowFactory::create_window("0. Renderer window example", 800, 600, GfxAPI::OpenGL); + auto renderer = RendererFactory::create_renderer(window); + + auto sprite = renderer->load_sprite("image.png"); + + while(!window->closing()) { + renderer->render(sprite, Transform{ .position = Vec3f::zero }); + renderer->present(); + } +P*/ + + return 0; +} diff --git a/examples/renderer/agnostic/2_agnostic_texture/CMakeLists.txt b/examples/renderer/agnostic/2_agnostic_texture/CMakeLists.txt new file mode 100644 index 00000000..1c7a0c1b --- /dev/null +++ b/examples/renderer/agnostic/2_agnostic_texture/CMakeLists.txt @@ -0,0 +1,7 @@ +file(GLOB_RECURSE BEBONE_EXAMPLE_RENDERER_AGNOSTIC_2_TEXTURE *.cpp) + +include_directories(".") +include_directories(${BEBONE_INCLUDES}) + +add_executable(Bebone_Example_Renderer_Agnostic_2_Agnostic_Texture ${BEBONE_EXAMPLE_RENDERER_AGNOSTIC_2_TEXTURE}) +target_link_libraries(Bebone_Example_Renderer_Agnostic_2_Agnostic_Texture bebone) \ No newline at end of file diff --git a/examples/renderer/agnostic/2_agnostic_texture/main.cpp b/examples/renderer/agnostic/2_agnostic_texture/main.cpp new file mode 100644 index 00000000..0d4ac2cc --- /dev/null +++ b/examples/renderer/agnostic/2_agnostic_texture/main.cpp @@ -0,0 +1,20 @@ +#include "bebone/bebone.h" + +using namespace bebone::renderer; +using namespace bebone::gfx; + +int main() { + /* + auto window = WindowFactory::create_window("0. Renderer window example", 800, 600, GfxAPI::OpenGL); + auto renderer = RendererFactory::create_renderer(window); + + auto sprite = renderer->load_sprite("image.png"); + + while(!window->closing()) { + renderer->render(sprite, Transform{ .position = Vec3f::zero }); + renderer->present(); + } +P*/ + + return 0; +} diff --git a/examples/renderer/agnostic/CMakeLists.txt b/examples/renderer/agnostic/CMakeLists.txt new file mode 100644 index 00000000..512a3b29 --- /dev/null +++ b/examples/renderer/agnostic/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(0_agnostic_window) +add_subdirectory(1_agnostic_hello_triangle) +add_subdirectory(2_agnostic_texture) diff --git a/examples/sound/0_playing_sound/CMakeLists.txt b/examples/sound/0_playing_sound/CMakeLists.txt new file mode 100644 index 00000000..3cde39b8 --- /dev/null +++ b/examples/sound/0_playing_sound/CMakeLists.txt @@ -0,0 +1,7 @@ +file(GLOB_RECURSE BEBONE_EXAMPLE_SOUND_0_PLAYING_SOUND *.cpp) + +include_directories("./") +include_directories(${BEBONE_INCLUDES}) + +add_executable(Bebone_Example_Sound_0_Playing_Sound ${BEBONE_EXAMPLE_SOUND_0_PLAYING_SOUND}) +target_link_libraries(Bebone_Example_Sound_0_Playing_Sound bebone) \ No newline at end of file diff --git a/examples/sound/0_playing_sound/coin_sound.mp3 b/examples/sound/0_playing_sound/coin_sound.mp3 new file mode 100644 index 00000000..75fa0b93 Binary files /dev/null and b/examples/sound/0_playing_sound/coin_sound.mp3 differ diff --git a/examples/sound/0_playing_sound/jump.mp3 b/examples/sound/0_playing_sound/jump.mp3 new file mode 100644 index 00000000..51120ea1 Binary files /dev/null and b/examples/sound/0_playing_sound/jump.mp3 differ diff --git a/examples/sound/0_playing_sound/main.cpp b/examples/sound/0_playing_sound/main.cpp new file mode 100644 index 00000000..2e73d8d3 --- /dev/null +++ b/examples/sound/0_playing_sound/main.cpp @@ -0,0 +1,17 @@ +#include "bebone/bebone.h" + +#include + +using namespace bebone::sound_system; + +int main() { + SoundEngine sound_engine; + + auto sound = sound_engine.load_sound("coin_sound.mp3"); + sound->play(); + + std::cout << "Press enter to exit..."; + getchar(); + + return 0; +} diff --git a/examples/sound/1_streaming_sound/CMakeLists.txt b/examples/sound/1_streaming_sound/CMakeLists.txt new file mode 100644 index 00000000..0f649dea --- /dev/null +++ b/examples/sound/1_streaming_sound/CMakeLists.txt @@ -0,0 +1,7 @@ +file(GLOB_RECURSE BEBONE_EXAMPLE_SOUND_1_STREAMING_SOUND *.cpp) + +include_directories("./") +include_directories(${BEBONE_INCLUDES}) + +add_executable(Bebone_Example_Sound_1_Streaming_Sound ${BEBONE_EXAMPLE_SOUND_1_STREAMING_SOUND}) +target_link_libraries(Bebone_Example_Sound_1_Streaming_Sound bebone) \ No newline at end of file diff --git a/examples/sound/1_streaming_sound/Dungeon Master.wav b/examples/sound/1_streaming_sound/Dungeon Master.wav new file mode 100644 index 00000000..8df9160c Binary files /dev/null and b/examples/sound/1_streaming_sound/Dungeon Master.wav differ diff --git a/examples/sound/1_streaming_sound/main.cpp b/examples/sound/1_streaming_sound/main.cpp new file mode 100644 index 00000000..048fde6a --- /dev/null +++ b/examples/sound/1_streaming_sound/main.cpp @@ -0,0 +1,18 @@ +#include "bebone/bebone.h" + +#include + +using namespace bebone::sound_system; + +int main() { + SoundEngine sound_engine; + auto factory = std::make_shared(); + + auto sound = sound_engine.load_sound("Dungeon Master.wav", factory); + sound->play(); + + std::cout << "Press enter to exit..."; + getchar(); + + return 0; +} diff --git a/examples/sound/CMakeLists.txt b/examples/sound/CMakeLists.txt new file mode 100644 index 00000000..34d24e56 --- /dev/null +++ b/examples/sound/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(0_playing_sound) +add_subdirectory(1_streaming_sound) diff --git a/src/bebone/CMakeLists.txt b/src/bebone/CMakeLists.txt index cb5d9fe6..e16e408d 100644 --- a/src/bebone/CMakeLists.txt +++ b/src/bebone/CMakeLists.txt @@ -11,6 +11,14 @@ if(BEBONE_BUILD_GFX) add_subdirectory(gfx) endif() +# if(BEBONE_BUILD_RENDERER) +# add_subdirectory(renderer) +# endif() + +if(BEBONE_BUILD_SOUND) + add_subdirectory(sound) +endif() + # Source files file(GLOB BEBONE_SRC_FILE bebone.cpp) add_library(bebone STATIC ${BEBONE_SRC_FILE}) @@ -26,4 +34,23 @@ endif() if(BEBONE_BUILD_CORE) target_link_libraries(bebone bebone_core) -endif() \ No newline at end of file +endif() + +# if(BEBONE_BUILD_RENDERER) +# target_link_libraries(bebone bebone_renderer) +# endif() + +if(BEBONE_BUILD_SOUND) + target_link_libraries(bebone bebone_sound) +endif() + +set(BEBONE_INCLUDES "${PROJECT_SOURCE_DIR}/src") + +list(APPEND BEBONE_INCLUDES ${BEBONE_ASSETS_INCLUDES}) +list(APPEND BEBONE_INCLUDES ${BEBONE_CORE_INCLUDES}) +list(APPEND BEBONE_INCLUDES ${BEBONE_GFX_INCLUDES}) +# list(APPEND BEBONE_INCLUDES ${BEBONE_RENDERER_INCLUDES}) +list(APPEND BEBONE_INCLUDES ${BEBONE_SOUND_INCLUDES}) + +# Set BEBONE_INCLUDES as global variable +set(BEBONE_INCLUDES "${BEBONE_INCLUDES}" CACHE INTERNAL "") diff --git a/src/bebone/README.md b/src/bebone/README.md new file mode 100644 index 00000000..2364b7d3 --- /dev/null +++ b/src/bebone/README.md @@ -0,0 +1 @@ +# Bebone \ No newline at end of file diff --git a/src/bebone/assets/CMakeLists.txt b/src/bebone/assets/CMakeLists.txt index 2667012e..73a2f5f1 100644 --- a/src/bebone/assets/CMakeLists.txt +++ b/src/bebone/assets/CMakeLists.txt @@ -1,9 +1,11 @@ file(GLOB_RECURSE BEBONE_ASSETS_SRC_FILES "*.cpp") -include_directories("../../../3dparty/stb") -include_directories("../../../3dparty/omni_types/src") +include_directories( + "${PROJECT_SOURCE_DIR}/3dparty/stb" +) add_library(bebone_assets STATIC ${BEBONE_ASSETS_SRC_FILES}) target_link_libraries(bebone_assets stb_image) target_link_libraries(bebone_assets stb_image_write) +target_link_libraries(bebone_assets stb_truetype) diff --git a/src/bebone/assets/README.md b/src/bebone/assets/README.md new file mode 100644 index 00000000..22733546 --- /dev/null +++ b/src/bebone/assets/README.md @@ -0,0 +1 @@ +# bebone_assets module \ No newline at end of file diff --git a/src/bebone/assets/assets.cpp b/src/bebone/assets/assets.cpp deleted file mode 100644 index eebc8348..00000000 --- a/src/bebone/assets/assets.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "assets.h" \ No newline at end of file diff --git a/src/bebone/assets/image/image.cpp b/src/bebone/assets/image/image.cpp index 743e6ed0..ca8797b4 100644 --- a/src/bebone/assets/image/image.cpp +++ b/src/bebone/assets/image/image.cpp @@ -3,106 +3,117 @@ namespace bebone::assets { using namespace bebone::core; - template - Image<_Color>::Image(const std::vector<_Color>& data, const size_t& width, const size_t& height) : color(data), width(width), height(height) { - + template + Image::Image(const std::vector& data, const size_t& width, const size_t& height) : color(data), width(width), height(height) { + LOG_INFORMATION("Created image {}x{}", width, height); } - template - _Color* Image<_Color>::data() { + template + Color* Image::data() { return color.data(); } - template - std::vector<_Color>& Image<_Color>::get_data() { + template + std::vector& Image::get_data() { return color; } - template - _Color& Image<_Color>::at(const size_t& offset) { + template + Color& Image::at(const size_t& offset) { return color[offset]; } - template - _Color& Image<_Color>::at(const size_t& x, const size_t& y) { + template + Color& Image::at(const size_t& x, const size_t& y) { return at(x + y * width); } - template - _Color& Image<_Color>::at(const Vec2i& pos) { + template + Color& Image::at(const Vec2i& pos) { return at(pos.x, pos.y); } - template - const int& Image<_Color>::get_width() const { + template + const int& Image::get_width() const { return width; } - template - const int& Image<_Color>::get_height() const { + template + const int& Image::get_height() const { return height; } - template - size_t Image<_Color>::get_channels() const { - return _Color::get_channels(); + template + size_t Image::get_channels() const { + return Color::get_channels(); } - template - size_t Image<_Color>::get_size() const { - return sizeof(_Color) * color.size(); + template + size_t Image::get_size() const { + return sizeof(Color) * color.size(); } - template - template - std::shared_ptr> Image<_Color>::to() const { - std::vector<_DesiredColor> newColor(width * height); + template + template + std::shared_ptr> Image::to() const { + std::vector newColor(width * height); const auto size = width * height; for(auto i = 0; i < size; ++i) - newColor[i] = color[i].template to<_DesiredColor>(); + newColor[i] = color[i].template to(); - return std::make_shared>(newColor, width, height); + return std::make_shared>(newColor, width, height); } - template - std::shared_ptr> Image<_Color>::clone() const { - return std::make_shared>(color, width, height); + template + std::shared_ptr> Image::clone() const { + return std::make_shared>(color, width, height); } - template - std::shared_ptr> Image<_Color>::from_color(const size_t& width, const size_t& height, const _Color& color) { - return std::make_shared>(std::vector<_Color>(width * height, color), width, height); + template + std::shared_ptr> Image::from_color(const size_t& width, const size_t& height, const Color& color) { + LOG_INFORMATION("Created image from color"); + + return std::make_shared>(std::vector(width * height, color), width, height); } - template - std::shared_ptr> Image<_Color>::from_white_noise(const size_t& width, const size_t & height) { + template + std::shared_ptr> Image::from_white_noise(const size_t& width, const size_t & height) { + LOG_INFORMATION("Created image from white noise"); + const auto size = width * height; - std::vector<_Color> color(size); + std::vector color(size); for(size_t i = 0; i < size; ++i) - color[i] = ColorRGB24::monochrome(rand() % 255).to<_Color>(); + color[i] = ColorRGB24::monochrome(rand() % 255).to(); - return std::make_shared>(color, width, height); + return std::make_shared>(color, width, height); } - template - std::shared_ptr> Image<_Color>::load_from_file(const std::string& filePath, const bool& vFlip) { - stbi_set_flip_vertically_on_load(vFlip); // Todo + template + std::shared_ptr> Image::load_from_file(const std::string& file_path, const bool& v_flip) { + LOG_INFORMATION("Loading image from file {}", file_path); + + stbi_set_flip_vertically_on_load(v_flip); int width, height, channels; - void* bytes = stbi_load(filePath.c_str(), &width, &height, &channels, 0); + void* bytes = stbi_load(file_path.c_str(), &width, &height, &channels, 0); + + if(bytes == nullptr) { + LOG_ERROR("Failed to load image from file {}", file_path); + // throw std::runtime_error("Unsupported color format " + file_path); Todo + } const auto size = width * height; if(channels == 3) { auto* b = static_cast(bytes); - std::vector<_Color> color(size); + std::vector color(size); for(auto i = 0; i < size; ++i) - color[i] = b[i].to<_Color>(); + color[i] = b[i].to(); stbi_image_free(bytes); @@ -110,34 +121,37 @@ namespace bebone::assets { } else if(channels == 4) { auto* b = static_cast(bytes); - std::vector<_Color> color(size); + std::vector color(size); for(auto i = 0; i < size; ++i) - color[i] = b[i].to<_Color>(); + color[i] = b[i].to(); stbi_image_free(bytes); return std::make_shared(color, width, height); } - throw std::runtime_error("Unsupported color format " + filePath); + LOG_ERROR("Unsupported color format {}", file_path); + // throw std::runtime_error("Unsupported color format " + file_path); Todo } - template - void Image<_Color>::export_to_file(const std::string& fileName) { - if(_Color::get_format() & OMNI_TYPES_COLOR_FLOAT) { + template + void Image::export_to_file(const std::string& file_name) { + LOG_INFORMATION("Exporting image into {}", file_name); + + if(Color::get_format() & BEBONE_TYPES_COLOR_FLOAT) { auto image = to(); const auto channels = image->get_channels(); - stbi_write_png(fileName.c_str(), width, height, channels, image->data(), width*channels); + stbi_write_png(file_name.c_str(), width, height, channels, image->data(), width*channels); } else { const auto channels = get_channels(); - stbi_write_png(fileName.c_str(), width, height, channels, data(), width*channels); + stbi_write_png(file_name.c_str(), width, height, channels, data(), width*channels); } } template class Image; template class Image; - template class Image; + template class Image; } diff --git a/src/bebone/assets/image/image.h b/src/bebone/assets/image/image.h index 0d51744a..422cb689 100644 --- a/src/bebone/assets/image/image.h +++ b/src/bebone/assets/image/image.h @@ -6,8 +6,7 @@ #include -#include "../../core/types.h" -#include "../../core/noncopyable.h" +#include "../../core/core.h" #include #include @@ -16,16 +15,16 @@ namespace bebone::assets { using namespace bebone::core; // Pixel data wrapper class - template - class Image : public NonCopyable { + template + class Image : private NonCopyable { private: - std::vector<_Color> color; + std::vector color; int width; int height; public: - template + template friend class ImagePainter; /*! @@ -34,23 +33,23 @@ namespace bebone::assets { * @param width - Image width * @param height - Image height */ - Image(const std::vector<_Color>& data, const size_t& width, const size_t& height); + Image(const std::vector& data, const size_t& width, const size_t& height); /*! * Get a pointer to image pixel data * @return Pointer to pixel data */ - _Color* data(); + Color* data(); // Reference pixel data container - std::vector<_Color>& get_data(); + std::vector& get_data(); /*! * Get a pixel from some linear offset * @param offset - Pixel offset * @return Pixel reference */ - _Color& at(const size_t& offset); + Color& at(const size_t& offset); /*! * Get a pixel at some position @@ -58,14 +57,14 @@ namespace bebone::assets { * @param y - Pixel y position * @return Pixel reference */ - _Color& at(const size_t& x, const size_t& y); + Color& at(const size_t& x, const size_t& y); /*! * Get a pixel at some position * @param pos - Pixel position * @return Pixel reference */ - _Color& at(const Vec2i& pos); + Color& at(const Vec2i& pos); // Image width getter const int& get_width() const; @@ -86,14 +85,14 @@ namespace bebone::assets { * Convert image to desired color format * @return New image */ - template - std::shared_ptr> to() const; + template + std::shared_ptr> to() const; /*! * Clone image, also cloning image pixel data * @return New image */ - std::shared_ptr> clone() const; + std::shared_ptr> clone() const; /*! * Generate image of plain color @@ -102,7 +101,7 @@ namespace bebone::assets { * @param color - Desired image color * @return New image */ - static std::shared_ptr> from_color(const size_t& width, const size_t& height, const _Color& color = _Color::WHITE); + static std::shared_ptr> from_color(const size_t& width, const size_t& height, const Color& color = Color::WHITE); /*! * Generate white noise image @@ -110,21 +109,21 @@ namespace bebone::assets { * @param height - Desired image height * @return New image */ - static std::shared_ptr> from_white_noise(const size_t& width, const size_t & height); + static std::shared_ptr> from_white_noise(const size_t& width, const size_t & height); /*! * Load image from file - * @param filePath - File path to the image file - * @param vFlip - Verticall flip flag + * @param file_path - File path to the image file + * @param v_flip - Verticall flip flag * @return Image */ - static std::shared_ptr> load_from_file(const std::string& filePath, const bool& vFlip = true); + static std::shared_ptr> load_from_file(const std::string& file_path, const bool& v_flip = true); /*! * Export image to file - * @param filePath - Destination path + * @param file_name - file name */ - void export_to_file(const std::string& fileName); + void export_to_file(const std::string& file_name); }; } diff --git a/src/bebone/assets/image/image_painter.cpp b/src/bebone/assets/image/image_painter.cpp index 71b3e1df..4b072617 100644 --- a/src/bebone/assets/image/image_painter.cpp +++ b/src/bebone/assets/image/image_painter.cpp @@ -3,23 +3,31 @@ namespace bebone::assets { using namespace bebone::core; - template - ImagePainter<_Color>::ImagePainter(const std::shared_ptr>& targetImage) : targetImage(targetImage) { + template + ImagePainter::ImagePainter(const std::shared_ptr>& target_image) : target_image(target_image) { + LOG_TRACE("Created image painter"); + } + template + void ImagePainter::paint_pixel(const size_t& x_pos, const size_t& y_pos, const Color& color) { + target_image->at(x_pos, y_pos) = color; } - template - void ImagePainter<_Color>::paint_pixel(const size_t& xPos, const size_t& yPos, const _Color& color) { - const size_t height = targetImage->get_height(); - targetImage->at(xPos, height - yPos) = color; + template + void ImagePainter::paint_pixel(const Vec2i& pos, const Color& color) { + paint_pixel( + static_cast(pos.x), + static_cast(pos.y), + color + ); } - template - void ImagePainter<_Color>::paint_circle(const size_t& xPos, const size_t& yPos, const f32& radius, const _Color& color) { + template + void ImagePainter::paint_circle(const size_t& x_pos, const size_t& y_pos, const f32& radius, const Color& color) { const auto r2 = radius * radius; - const size_t width = targetImage->get_width(); - const size_t height = targetImage->get_height(); + const size_t width = target_image->get_width(); + const size_t height = target_image->get_height(); for(f32 x = -radius; x < radius; ++x) { const f32 x2 = x*x; @@ -27,118 +35,157 @@ namespace bebone::assets { for(f32 y = -radius; y < radius; ++y) { if(x2 + y*y > r2) continue; - const size_t xCord = std::clamp((size_t) (xPos + x), (size_t) 0, width - 1); - const size_t yCord = std::clamp((size_t) (yPos + y), (size_t) 0, height - 1); + const size_t x_cord = std::clamp((size_t) (x_pos + x), (size_t) 0, width - 1); + const size_t y_cord = std::clamp((size_t) (y_pos + y), (size_t) 0, height - 1); - targetImage->at(xCord, height - yCord) = color; + target_image->at(x_cord, height - y_cord) = color; } } } - template - void ImagePainter<_Color>::paint_square(const size_t& xPos, const size_t& yPos, const f32& sqWidth, const f32& sqHeight, const _Color& color) { - const size_t width = targetImage->get_width(); - const size_t height = targetImage->get_height(); + template + void ImagePainter::paint_circle(const Vec2i& pos, const f32& radius, const Color& color) { + paint_circle( + static_cast(pos.x), + static_cast(pos.y), + radius, + color + ); + } + + template + void ImagePainter::paint_square(const size_t& x_pos, const size_t& y_pos, const f32& sq_width, const f32& sq_height, const Color& color) { + const size_t width = target_image->get_width(); + const size_t height = target_image->get_height(); - for(auto x = -sqWidth; x < sqWidth; ++x) { - for(auto y = -sqHeight; y < sqHeight; ++y) { - const size_t xCord = std::clamp((size_t) (static_cast(xPos) + static_cast(x)), (size_t) 0, width - 1); - const size_t yCord = std::clamp((size_t) (static_cast(yPos) + static_cast(y)), (size_t) 0, height - 1); + for(auto x = -sq_width; x < sq_width; ++x) { + for(auto y = -sq_height; y < sq_height; ++y) { + const size_t x_cord = std::clamp((size_t) (static_cast(x_pos) + static_cast(x)), (size_t) 0, width - 1); + const size_t y_cord = std::clamp((size_t) (static_cast(y_pos) + static_cast(y)), (size_t) 0, height - 1); - targetImage->at(xCord, height - yCord) = color; + target_image->at(x_cord, height - y_cord) = color; } } } - template - void ImagePainter<_Color>::flip_vertical() { - const size_t width = targetImage->get_width() - 1; - const size_t height = targetImage->get_height() - 1; + template + void ImagePainter::paint_square(const Vec2i& pos, const Vec2i& size, const Color& color) { + paint_square( + static_cast(pos.x), + static_cast(pos.y), + static_cast(size.x), + static_cast(size.y), + color + ); + } + + template + void ImagePainter::flip_vertical() { + const size_t width = target_image->get_width() - 1; + const size_t height = target_image->get_height() - 1; - const size_t hWidth = width / 2; + const size_t h_width = width / 2; - for(size_t x = 0; x <= hWidth; ++x) { + for(size_t x = 0; x <= h_width; ++x) { for (size_t y = 0; y <= height; ++y) { - auto& pl = targetImage->at(x, y); - auto& pr = targetImage->at(width - x, y); + auto& pl = target_image->at(x, y); + auto& pr = target_image->at(width - x, y); std::swap(pl, pr); } } } - template - void ImagePainter<_Color>::flip_horizontal() { - const size_t width = targetImage->get_width() - 1; - const size_t height = targetImage->get_height() - 1; + template + void ImagePainter::flip_horizontal() { + const size_t width = target_image->get_width() - 1; + const size_t height = target_image->get_height() - 1; - const size_t hHeight = height / 2; + const size_t h_height = height / 2; for(size_t x = 0; x <= width; ++x) { - for (size_t y = 0; y <= hHeight; ++y) { - auto& pl = targetImage->at(x, y); - auto& pr = targetImage->at(x, height - y); + for (size_t y = 0; y <= h_height; ++y) { + auto& pl = target_image->at(x, y); + auto& pr = target_image->at(x, height - y); std::swap(pl, pr); } } } - template - void ImagePainter<_Color>::resize(const size_t& width, const size_t& height) { - std::vector<_Color> color(width * height); + template + void ImagePainter::resize(const size_t& width, const size_t& height) { + std::vector color(width * height); - const size_t startW = targetImage->get_width() - 1; - const size_t startH = targetImage->get_height() - 1; + const size_t start_w = target_image->get_width() - 1; + const size_t start_h = target_image->get_height() - 1; auto index = 0; for(size_t x = 0; x < width; ++x) { for (size_t y = 0; y < height; ++y) { - const auto uvX = static_cast(x) / static_cast(width); - const auto uvY = static_cast(y) / static_cast(height); + const auto uv_x = static_cast(x) / static_cast(width); + const auto uv_y = static_cast(y) / static_cast(height); - const size_t pixelX = round(uvX * startW); - const size_t pixelY = round(uvY * startH); + const size_t pixel_x = round(uv_x * start_w); + const size_t pixel_y = round(uv_y * start_h); - color[index] = targetImage->at(pixelX, pixelY); + color[index] = target_image->at(pixel_x, pixel_y); ++index; } } - targetImage->color = color; - targetImage->width = width; - targetImage->height = height; + target_image->color = color; + target_image->width = width; + target_image->height = height; } - template - void ImagePainter<_Color>::crop(const size_t& startX, const size_t& startY, const size_t& width, const size_t& height) { - const auto endX = startX + width; - const auto endY = startY + height; + template + void ImagePainter::resize(const Vec2i& size) { + resize( + static_cast(size.x), + static_cast(size.y) + ); + } + + template + void ImagePainter::crop(const size_t& start_x, const size_t& start_y, const size_t& width, const size_t& height) { + const auto end_x = start_x + width; + const auto end_y = start_y + height; - std::vector<_Color> color(width * height); + std::vector color(width * height); auto index = 0; - for(size_t x = startX; x < endX; ++x) { - for (size_t y = startY; y < endY; ++y) { - color[index] = targetImage->at(x, y); + for(size_t x = start_x; x < end_x; ++x) { + for (size_t y = start_y; y < end_y; ++y) { + color[index] = target_image->at(x, y); ++index; } } - targetImage->color = color; - targetImage->width = width; - targetImage->height = height; + target_image->color = color; + target_image->width = width; + target_image->height = height; + } + + template + void ImagePainter::crop(const Vec2i& pos, const Vec2i& size) { + crop( + static_cast(pos.x), + static_cast(pos.y), + static_cast(size.x), + static_cast(size.y) + ); } - template - ImagePainter<_Color> ImagePainter<_Color>::from_image(const std::shared_ptr>& targetImage) { - return ImagePainter<_Color>(targetImage); + template + ImagePainter ImagePainter::from_image(const std::shared_ptr>& target_image) { + return ImagePainter(target_image); } template class ImagePainter; template class ImagePainter; - template class ImagePainter; + template class ImagePainter; } diff --git a/src/bebone/assets/image/image_painter.h b/src/bebone/assets/image/image_painter.h index 12024b35..44b34ced 100644 --- a/src/bebone/assets/image/image_painter.h +++ b/src/bebone/assets/image/image_painter.h @@ -3,8 +3,7 @@ #include -#include "../../core/types.h" -#include "../../core/noncopyable.h" +#include "../../core/core.h" #include "image.h" @@ -12,42 +11,63 @@ namespace bebone::assets { using namespace bebone::core; // Image painter class, class used for modification of an image - template + template class ImagePainter { private: - std::shared_ptr> targetImage; + std::shared_ptr> target_image; // Hidden constructor - explicit ImagePainter(const std::shared_ptr>& targetImage); + explicit ImagePainter(const std::shared_ptr>& target_image); public: - // Todo, add Vec2i variants for this functions + /*! + * Sets image pixel color + * @param x_pos - Pixel X position + * @param y_pos - Pixel Y position + * @param color - Color to be set + */ + void paint_pixel(const size_t& x_pos, const size_t& y_pos, const Color& color); /*! * Sets image pixel color - * @param xPos - Pixel X position - * @param yPos - Pixel Y position + * @param pos - Pixel position * @param color - Color to be set */ - void paint_pixel(const size_t& xPos, const size_t& yPos, const _Color& color); + void paint_pixel(const Vec2i& pos, const Color& color); + + /*! + * Draws circle to the image + * @param x_pos - Circle center X position + * @param y_pos - Circle center Y position + * @param radius - Circle radius + * @param color - Circle color + */ + void paint_circle(const size_t& x_pos, const size_t& y_pos, const f32& radius, const Color& color); /*! * Draws circle to the image - * @param xPos - Circle center X position - * @param yPos - Circle center Y position + * @param pos - Circle center position * @param radius - Circle radius * @param color - Circle color */ - void paint_circle(const size_t& xPos, const size_t& yPos, const f32& radius, const _Color& color); + void paint_circle(const Vec2i& pos, const f32& radius, const Color& color); /*! * Draws square to the image - * @param xPos - Square bottom left corner X position - * @param yPos - Square bottom left corner Y position - * @param sqWidth - Square width - * @param sqHeight - Square height + * @param x_pos - Square bottom left corner X position + * @param y_pos - Square bottom left corner Y position + * @param sq_width - Square width + * @param sq_height - Square height * @param color - Square color */ - void paint_square(const size_t& xPos, const size_t& yPos, const f32& sqWidth, const f32& sqHeight, const _Color& color); + void paint_square(const size_t& x_pos, const size_t& y_pos, const f32& sq_width, const f32& sq_height, const Color& color); + + /*! + * Draws square to the image + * @param pos - Square bottom left corner position + * @param size - Square size + * @param color - Square color + */ + void paint_square(const Vec2i& pos, const Vec2i& size, const Color& color); // Flips image vertically void flip_vertical(); @@ -62,21 +82,34 @@ namespace bebone::assets { */ void resize(const size_t& width, const size_t& height); + /*! + * Resizes image + * @param size - New image size + */ + void resize(const Vec2i& size); + /*! * Crops specific image area - * @param startX - Bottom left corner X position - * @param startY - Bottom left corner Y position + * @param start_x - Bottom left corner X position + * @param start_y - Bottom left corner Y position * @param width - Area width * @param height - Area height */ - void crop(const size_t& startX, const size_t& startY, const size_t& width, const size_t& height); + void crop(const size_t& start_x, const size_t& start_y, const size_t& width, const size_t& height); + + /*! + * Crops specific image area + * @param pos - Bottom left corner position + * @param size - Area size + */ + void crop(const Vec2i& pos, const Vec2i& size); /*! * Creates image painter object from an image - * @param targetImage - Image that needs to be modified + * @param target_image - Image that needs to be modified * @return ImagePainter class instance */ - static ImagePainter<_Color> from_image(const std::shared_ptr>& targetImage); + static ImagePainter from_image(const std::shared_ptr>& target_image); }; } diff --git a/src/bebone/bebone.h b/src/bebone/bebone.h index 88f99961..7af43c9e 100644 --- a/src/bebone/bebone.h +++ b/src/bebone/bebone.h @@ -1,9 +1,16 @@ #ifndef _BEBONE_H_ #define _BEBONE_H_ -#define OMNI_GLAD_INTEGRATION +// First API layer #include "core/core.h" #include "assets/assets.h" #include "gfx/gfx.h" +#include "sound/sound_engine.h" + +// Second API layer +// #include "renderer/renderer.h" + +// Third API layer +// Probably app class #endif diff --git a/src/bebone/core/CMakeLists.txt b/src/bebone/core/CMakeLists.txt index cd902b4e..b36058b8 100644 --- a/src/bebone/core/CMakeLists.txt +++ b/src/bebone/core/CMakeLists.txt @@ -1,14 +1,9 @@ -file(GLOB_RECURSE BEBONE_CORE_SRC_FILES "*.cpp") - -# Since we also building gfx module -# lets include glad headers for omni_types library -if(BEBONE_BUILD_GFX) - add_compile_definitions(OMNI_GLAD_INTEGRATION) - include_directories("../../../3dparty/glad/include") -endif() +set(BEBONE_CORE_INCLUDES + "${PROJECT_SOURCE_DIR}/src/bebone/core" +) -include_directories("../../../3dparty/omni_types/src") +set(BEBONE_CORE_INCLUDES "${BEBONE_CORE_INCLUDES}" CACHE INTERNAL "") +include_directories(${BEBONE_CORE_INCLUDES}) +file(GLOB_RECURSE BEBONE_CORE_SRC_FILES "*.cpp") add_library(bebone_core STATIC ${BEBONE_CORE_SRC_FILES}) - -target_link_libraries(bebone_core omni_types) diff --git a/src/bebone/core/README.md b/src/bebone/core/README.md new file mode 100644 index 00000000..9264920a --- /dev/null +++ b/src/bebone/core/README.md @@ -0,0 +1 @@ +# bebone_core module \ No newline at end of file diff --git a/src/bebone/core/arena_allocator.cpp b/src/bebone/core/arena_allocator.cpp deleted file mode 100644 index d851c107..00000000 --- a/src/bebone/core/arena_allocator.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include "arena_allocator.h" - -namespace bebone::core { - ArenaAllocator::ArenaAllocator(const size_t& size) : _capacity(size), _allocated(0) { - _data = malloc(size); - } - - ArenaAllocator::ArenaAllocator(const size_t& size, void* buffer) : _capacity(size), _allocated(0) { - _data = buffer; - } - - ArenaAllocator::~ArenaAllocator() { - free(_data); - } - - void* ArenaAllocator::alloc(const size_t& size) noexcept { - if(_allocated + size > _capacity) { - return nullptr; - } - - const size_t allocated = _allocated; - _allocated += size; - - return static_cast(_data) + allocated; - } - - void* ArenaAllocator::data() noexcept { - return _data; - } - - void ArenaAllocator::clear() noexcept { - _allocated = 0; - } - - [[nodiscard]] const size_t& ArenaAllocator::allocated() const noexcept { - return _allocated; - } - - [[nodiscard]] const size_t& ArenaAllocator::capacity() const noexcept { - return _capacity; - } -} diff --git a/src/bebone/core/core.cpp b/src/bebone/core/core.cpp index e69de29b..5dae506b 100644 --- a/src/bebone/core/core.cpp +++ b/src/bebone/core/core.cpp @@ -0,0 +1,12 @@ +#include "core.h" + +namespace bebone::core { + std::string utils_read_file(const std::string& path) { + std::ifstream file(path); + std::stringstream ss; + + ss << file.rdbuf(); + + return ss.str(); + } +} diff --git a/src/bebone/core/core.h b/src/bebone/core/core.h index 78dd52a9..bf4b919d 100644 --- a/src/bebone/core/core.h +++ b/src/bebone/core/core.h @@ -1,18 +1,35 @@ #ifndef _BEBONE_CORE_CORE_H_ #define _BEBONE_CORE_CORE_H_ -#include "types.h" +#include "types/types.h" -#include "logger.tpp" -#include "profiler.h" +// Debug +#include "debug/ilogger.h" +#include "debug/console_logger.h" +#include "debug/logger.h" -#include "arena_allocator.h" -#include "arena_container.h" +// Memory +#include "memory/arena_allocator.h" +#include "memory/arena_container.h" +// Events #include "events/listeners/event_dispatcher.tpp" #include "events/delegates/action.h" +// Input #include "input/input.h" -#include "input/input_handler.h" +#include "input/input_executor.h" + +// Timestamp +#include "timestamp/watch.h" + +// Todo move this out + +#include +#include + +namespace bebone::core { + std::string utils_read_file(const std::string& path); +} #endif \ No newline at end of file diff --git a/src/bebone/core/debug/console_logger.cpp b/src/bebone/core/debug/console_logger.cpp new file mode 100644 index 00000000..b0ffda03 --- /dev/null +++ b/src/bebone/core/debug/console_logger.cpp @@ -0,0 +1,60 @@ +#include "console_logger.h" + +namespace bebone::core { + ConsoleLogger::ConsoleLogger(std::ostream& st) + : stream(st), log_level(LogLevel::Trace) { + + } + + void ConsoleLogger::log(const LogLevel& level, std::string_view format) { + if(level < log_level) + return; + + auto log_level_str = stringify_log_level(level); + auto log_level_color = unix_log_level_color(level); + + auto t = std::time(nullptr); + auto tm = *std::localtime(&t); + + // Todo add this + // const std::source_location& location = std::source_location::current(); + + std::ostringstream time_stream; + time_stream << std::put_time(&tm, "%H:%M:%S"); + auto formatted_time = time_stream.str(); + + std::stringstream prefix; + prefix << UnixConsoleColors::Gray << "[" << formatted_time << " " << log_level_color << log_level_str << UnixConsoleColors::Gray << "] "; + + stream << prefix.str() << UnixConsoleColors::Default << format << std::endl; + stream.flush(); + } + + void ConsoleLogger::log(const LogLevel& level, std::string_view format, std::format_args&& args) { + if(level < log_level) + return; + + auto log_level_str = stringify_log_level(level); + auto log_level_color = unix_log_level_color(level); + + auto t = std::time(nullptr); + auto tm = *std::localtime(&t); + + // Todo add this + // const std::source_location& location = std::source_location::current(); + + std::ostringstream time_stream; + time_stream << std::put_time(&tm, "%H:%M:%S"); + auto formatted_time = time_stream.str(); + + std::stringstream prefix; + prefix << UnixConsoleColors::Gray << "[" << formatted_time << " " << log_level_color << log_level_str << UnixConsoleColors::Gray << "] "; + + stream << prefix.str() << UnixConsoleColors::Default << std::vformat(format, args) << std::endl; + stream.flush(); + } + + void ConsoleLogger::set_log_level(const LogLevel& level) { + log_level = level; + } +} diff --git a/src/bebone/core/debug/console_logger.h b/src/bebone/core/debug/console_logger.h new file mode 100644 index 00000000..94440c3d --- /dev/null +++ b/src/bebone/core/debug/console_logger.h @@ -0,0 +1,27 @@ +#ifndef _BEBONE_CORE_CONSOLE_LOGGER_H_ +#define _BEBONE_CORE_CONSOLE_LOGGER_H_ + +#include +#include +#include +#include + +#include "ilogger.h" + +namespace bebone::core { + class ConsoleLogger : public ILogger { + private: + std::ostream& stream; + LogLevel log_level; + + public: + explicit ConsoleLogger(std::ostream& st = std::cout); + + void log(const LogLevel& level, std::string_view format) override; + void log(const LogLevel& level, std::string_view format, std::format_args&& args) override; + + void set_log_level(const LogLevel& level) override; + }; +} + +#endif \ No newline at end of file diff --git a/src/bebone/core/debug/ilogger.cpp b/src/bebone/core/debug/ilogger.cpp new file mode 100644 index 00000000..ac8405ed --- /dev/null +++ b/src/bebone/core/debug/ilogger.cpp @@ -0,0 +1,5 @@ +#include "ilogger.h" + +namespace bebone::core { + +} diff --git a/src/bebone/core/debug/ilogger.h b/src/bebone/core/debug/ilogger.h new file mode 100644 index 00000000..490c839b --- /dev/null +++ b/src/bebone/core/debug/ilogger.h @@ -0,0 +1,25 @@ +#ifndef _BEBONE_CORE_ILOGGER_H_ +#define _BEBONE_CORE_ILOGGER_H_ + +#include +#include +#include +#include + +#include "log_level.h" + +namespace bebone::core { + class ILogger { + protected: + + public: + virtual ~ILogger() = default; + + virtual void log(const LogLevel& level, std::string_view format) = 0; + virtual void log(const LogLevel& level, std::string_view format, std::format_args&& args) = 0; + + virtual void set_log_level(const LogLevel& level) = 0; + }; +} + +#endif \ No newline at end of file diff --git a/src/bebone/core/debug/log_level.h b/src/bebone/core/debug/log_level.h new file mode 100644 index 00000000..9144f988 --- /dev/null +++ b/src/bebone/core/debug/log_level.h @@ -0,0 +1,58 @@ +#ifndef _BEBONE_CORE_LOG_LEVEL_H_ +#define _BEBONE_CORE_LOG_LEVEL_H_ + +namespace bebone::core { + enum class LogLevel { + Trace, + Debug, + Information, + Warning, + Error, + Critical + // None + }; + + struct UnixConsoleColors { + constexpr static const char* Default = "\x1B[39m"; + constexpr static const char* Black = "\x1B[30m"; + constexpr static const char* DarkRed = "\x1B[31m"; + constexpr static const char* DarkGreen = "\x1B[32m"; + constexpr static const char* DarkYellow = "\x1B[33m"; + constexpr static const char* DarkBlue = "\x1B[34m"; + constexpr static const char* DarkMagenta = "\x1B[35m"; + constexpr static const char* DarkCyan = "\x1B[36m"; + constexpr static const char* Gray = "\x1B[37m"; + constexpr static const char* DarkGray = "\x1B[90m"; + constexpr static const char* Red = "\x1B[91m"; + constexpr static const char* Green = "\x1B[92m"; + constexpr static const char* Yellow = "\x1B[93m"; + constexpr static const char* Blue = "\x1B[94m"; + constexpr static const char* Magenta = "\x1B[95m"; + constexpr static const char* Cyan = "\x1B[96m"; + constexpr static const char* White = "\x1B[97m"; + }; + + static inline const char* unix_log_level_color(const LogLevel& log_level) { + switch (log_level) { + case LogLevel::Trace: { return UnixConsoleColors::White; } + case LogLevel::Debug: { return UnixConsoleColors::Cyan; } + case LogLevel::Information: { return UnixConsoleColors::Green; } + case LogLevel::Warning: { return UnixConsoleColors::Yellow; } + case LogLevel::Error: { return UnixConsoleColors::Red; } + case LogLevel::Critical: { return UnixConsoleColors::DarkRed; } + } + } + + static inline const char* stringify_log_level(const LogLevel& log_level) { + switch (log_level) { + case LogLevel::Trace: { return "TRC"; } + case LogLevel::Debug: { return "DGB"; } + case LogLevel::Information: { return "INF"; } + case LogLevel::Warning: { return "WAR"; } + case LogLevel::Error: { return "ERR"; } + case LogLevel::Critical: { return "CRI"; } + } + } +} + +#endif \ No newline at end of file diff --git a/src/bebone/core/debug/logger.cpp b/src/bebone/core/debug/logger.cpp new file mode 100644 index 00000000..08a4b83d --- /dev/null +++ b/src/bebone/core/debug/logger.cpp @@ -0,0 +1,12 @@ +#include "logger.h" + +namespace bebone::core { + Logger::Logger() { + logger_instance = std::make_unique(); + } + + std::unique_ptr& Logger::get_instance() { + static Logger logger; + return logger.logger_instance; + } +} diff --git a/src/bebone/core/debug/logger.h b/src/bebone/core/debug/logger.h new file mode 100644 index 00000000..57a7169c --- /dev/null +++ b/src/bebone/core/debug/logger.h @@ -0,0 +1,37 @@ +#ifndef _BEBONE_CORE_LOGGER_H_ +#define _BEBONE_CORE_LOGGER_H_ + +#include + +#include "ilogger.h" + +#include "console_logger.h" + +namespace bebone::core { + // Global logger + class Logger { + private: + std::unique_ptr logger_instance; + + Logger(); + + public: + template + static void log(const LogLevel& log_level, std::string_view format, Args&&... args) { + get_instance()->log(log_level, format, std::make_format_args(args...)); + } + + static std::unique_ptr& get_instance(); + }; +} + +#define LOG(LOG_LEVEL, FORMAT, ...) bebone::core::Logger::log(LOG_LEVEL, FORMAT, ##__VA_ARGS__) + +#define LOG_TRACE(FORMAT, ...) bebone::core::Logger::log(bebone::core::LogLevel::Trace, FORMAT, ##__VA_ARGS__) +#define LOG_DEBUG(FORMAT, ...) bebone::core::Logger::log(bebone::core::LogLevel::Debug, FORMAT, ##__VA_ARGS__) +#define LOG_INFORMATION(FORMAT, ...) bebone::core::Logger::log(bebone::core::LogLevel::Information, FORMAT, ##__VA_ARGS__) +#define LOG_WARNING(FORMAT, ...) bebone::core::Logger::log(bebone::core::LogLevel::Warning, FORMAT, ##__VA_ARGS__) +#define LOG_ERROR(FORMAT, ...) bebone::core::Logger::log(bebone::core::LogLevel::Error, FORMAT, ##__VA_ARGS__) +#define LOG_CRITICAL(FORMAT, ...) bebone::core::Logger::log(bebone::core::LogLevel::Critical, FORMAT, ##__VA_ARGS__) + +#endif \ No newline at end of file diff --git a/src/bebone/core/events/listeners/event.tpp b/src/bebone/core/events/listeners/event.tpp index bf7a4b55..6034edab 100644 --- a/src/bebone/core/events/listeners/event.tpp +++ b/src/bebone/core/events/listeners/event.tpp @@ -1,15 +1,13 @@ #ifndef _BEBONE_CORE_EVENTS_LISTENERS_EVENT_H_ #define _BEBONE_CORE_EVENTS_LISTENERS_EVENT_H_ -#include "../../types.h" - namespace bebone::core { /*! * Base class for all events * @tparam EventCategoryType - enumeration that specifies set of possible events - * @tparam eventType - specific event type + * @tparam event_type - specific event type */ - template + template class Event { private: bool handled = false; @@ -33,8 +31,8 @@ namespace bebone::core { return handled; } - using category = EventCategoryType; - static constexpr const EventCategoryType type = eventType; + using Category = EventCategoryType; + static constexpr const EventCategoryType type = event_type; }; } diff --git a/src/bebone/core/events/listeners/event_dispatcher.tpp b/src/bebone/core/events/listeners/event_dispatcher.tpp index 7c7fc481..13403c93 100644 --- a/src/bebone/core/events/listeners/event_dispatcher.tpp +++ b/src/bebone/core/events/listeners/event_dispatcher.tpp @@ -22,17 +22,17 @@ namespace bebone::core { public: /// Meta function that checks if event is suitable for this event dispatcher template - using is_suitable_event_type = std::enable_if_t::value>; + using IsSuitableEventType = std::enable_if_t::value>; /*! * Function that sends event to desired event listeners * @tparam EventType - type of the event * @param event - event object */ - template> + template> void fire(EventType event) { - const EventCategory eventType = EventType::type; - auto rng = callbacks.equal_range(eventType); + const EventCategory event_type = EventType::type; + auto rng = callbacks.equal_range(event_type); for (auto it = rng.first; it != rng.second; ++it) { void* ptr = it->second.get(); @@ -50,25 +50,25 @@ namespace bebone::core { /// Helper meta function, that extracts type of the first argument of callable type template - using first_arg = typename function_traits::template argument<0>; + using FirstArg = typename FunctionTraits::template Argument<0>; /// Meta function that checks if listener is suitable for this event dispatcher template - using is_suitable_listener = std::enable_if_t>::type::category, EventCategory>::value>; + using IsSuitableListener = std::enable_if_t>::type::Category, EventCategory>::value>; /*! * Function that add listener to dispatcher * @tparam Listener - type of the event listener * @param listener - listener object */ - template> + template> void add_listener(Listener listener) { - using EventType = typename function_traits::template argument<0>; + using EventType = typename FunctionTraits::template Argument<0>; auto ptr = std::make_shared>(listener); - const EventCategory eventType = std::remove_reference::type::type; - callbacks.emplace(eventType, ptr); + const EventCategory event_type = std::remove_reference::type::type; + callbacks.emplace(event_type, ptr); } /*! diff --git a/src/bebone/core/events/listeners/event_listener.tpp b/src/bebone/core/events/listeners/event_listener.tpp index d3448160..266c4e6c 100644 --- a/src/bebone/core/events/listeners/event_listener.tpp +++ b/src/bebone/core/events/listeners/event_listener.tpp @@ -4,7 +4,7 @@ #include "event.tpp" namespace bebone::core { - using namespace std; + // using namespace std; /*! * Base class for all event listeners @@ -15,6 +15,8 @@ namespace bebone::core { private: public: + virtual ~EventListener() = default; + virtual void operator()(EventType&) = 0; }; } diff --git a/src/bebone/core/input/input.cpp b/src/bebone/core/input/input.cpp index cf68975c..9d52e589 100644 --- a/src/bebone/core/input/input.cpp +++ b/src/bebone/core/input/input.cpp @@ -1,44 +1,29 @@ #include "input.h" namespace bebone::core { - Input& Input::get_instance() { - static Input instance; + void Input::register_key_action(const KeyCode& key_code, std::function& action, const InputType& input_type) { + const Key key(key_code, input_type); - return instance; - } - - void Input::register_key_action(const KeyCode& keyCode, std::function& action, const InputType& inputType) { - Key key(keyCode, inputType); - - if (keyActions.find(key) == keyActions.end()) { - keyActions[key] = Action(); + if (key_actions.find(key) == key_actions.end()) { + key_actions[key] = Action(); } - keyActions[key] += action; + key_actions[key] += action; } - void Input::remove_key_action(const KeyCode &keyCode, std::function &action, const InputType &inputType) { - Key key(keyCode, inputType); + void Input::remove_key_action(const KeyCode &key_code, std::function &action, const InputType &input_type) { + const Key key(key_code, input_type); - if (keyActions.find(key) == keyActions.end()) { + if (key_actions.find(key) == key_actions.end()) { return; } - keyActions[key] -= action; + key_actions[key] -= action; } - void Input::queue_key(const KeyCode &keyCode, const InputType &inputType) { - queuedKeys.push(Key(keyCode, inputType)); - } - - void Input::execute_queued_actions() { - while (!queuedKeys.empty()) { - Key key = queuedKeys.front(); - queuedKeys.pop(); - - if (keyActions.find(key) != keyActions.end()) { - keyActions[key](); - } + void Input::apply_action(const Key& key) { + if (key_actions.find(key) != key_actions.end()) { + key_actions[key](); } } } \ No newline at end of file diff --git a/src/bebone/core/input/input.h b/src/bebone/core/input/input.h index 7334107b..a02b0d4d 100644 --- a/src/bebone/core/input/input.h +++ b/src/bebone/core/input/input.h @@ -2,7 +2,6 @@ #define _INPUT_H_ #include -#include #include "../events/delegates/action.h" @@ -13,48 +12,33 @@ namespace bebone::core { using namespace std; - /// Singleton Input System class. Works with Action delegates + /// Input System class. Works with Action delegates class Input { private: using BeboneAction = Action<>; - map keyActions; - queue queuedKeys; - - Input() = default; - - void queue_key(const KeyCode& keyCode, const InputType& inputType); - void execute_queued_actions(); + map key_actions; public: - Input(const Input& obj) = delete; - void operator=(Input const& obj) = delete; - - /// Returns singleton reference to the input system object - /// @return Input system object reference - static Input& get_instance(); - /*! * Registers the key to do specific action * - * @param keyCode - key code + * @param key_code - key code * @param action - function object, which will execute when the key will be pressed/released - * @param inputType - specifies the input type. By default it is set to InputType::PRESS + * @param input_type - specifies the input type. By default it is set to InputType::PRESS */ - void register_key_action(const KeyCode& keyCode, std::function& action, const InputType& inputType = InputType::PRESS); + void register_key_action(const KeyCode& key_code, std::function& action, const InputType& input_type = InputType::Press); /*! * Removes the specific action from the key * - * @param keyCode - key code + * @param key_code - key code * @param action - function object, which will execute when the key will be pressed/released - * @param inputType - specifies the input type. By default it is set to InputType::PRESS + * @param input_type - specifies the input type. By default it is set to InputType::PRESS */ - void remove_key_action(const KeyCode& keyCode, std::function& action, const InputType& inputType = InputType::PRESS); + void remove_key_action(const KeyCode& key_code, std::function& action, const InputType& input_type = InputType::Press); - friend class InputHandler; - friend struct KeyListener; - friend struct MouseListener; + void apply_action(const Key& key); }; } diff --git a/src/bebone/core/input/input_executor.cpp b/src/bebone/core/input/input_executor.cpp new file mode 100644 index 00000000..e9de5de4 --- /dev/null +++ b/src/bebone/core/input/input_executor.cpp @@ -0,0 +1,80 @@ +#include "input_executor.h" + +namespace bebone::core { + InputExecutor::InputExecutor(const std::shared_ptr& input) : input(input) { } + + std::shared_ptr InputExecutor::get_input() const { + return input; + } + + void InputExecutor::queue_key(const KeyCode &key_code, const InputType &input_type) { + queued_keys.emplace(key_code, input_type); + + if (pressed_keys.find(key_code) == pressed_keys.end()) { + pressed_keys[key_code] = false; + } + + if (key_input_types.find(key_code) == key_input_types.end()) { + key_input_types[key_code] = InputType::None; + } + } + + void InputExecutor::execute_input_actions() { + convert_released_keys_to_none(); + + while (!queued_keys.empty()) { + const auto key = queued_keys.front(); + KeyCode key_code = key.key_code; + InputType input_type = key.input_type; + + queued_keys.pop(); + + if (input_type == InputType::Press || input_type == InputType::Repeat) { + pressed_keys[key_code] = true; + } else { + pressed_keys[key_code] = false; + released_keys.push_back(key_code); + } + + key_input_types[key_code] = input_type; + + input->apply_action(key); + } + } + + void InputExecutor::convert_released_keys_to_none() { + for (auto& released_key : released_keys) { + key_input_types[released_key] = InputType::None; + } + + released_keys.clear(); + } + + bool InputExecutor::is_key_down(const KeyCode& key_code) { + if (key_input_types.find(key_code) == key_input_types.end()) { + return false; + } + + return pressed_keys[key_code]; + } + + bool InputExecutor::is_key_up(const KeyCode& key_code) { + return !is_key_down(key_code); + } + + bool InputExecutor::is_key_pressed(const KeyCode& key_code) { + if (key_input_types.find(key_code) == key_input_types.end()) { + return false; + } + + return pressed_keys[key_code] && key_input_types[key_code] == InputType::Press; + } + + bool InputExecutor::is_key_released(const KeyCode& key_code) { + if (key_input_types.find(key_code) == key_input_types.end()) { + return false; + } + + return !pressed_keys[key_code] && key_input_types[key_code] == InputType::Release; + } +} \ No newline at end of file diff --git a/src/bebone/core/input/input_executor.h b/src/bebone/core/input/input_executor.h new file mode 100644 index 00000000..44b20ddf --- /dev/null +++ b/src/bebone/core/input/input_executor.h @@ -0,0 +1,40 @@ +#ifndef _INPUT_HANDLER_H_ +#define _INPUT_HANDLER_H_ + +#include "input.h" + +#include +#include +#include + +namespace bebone::core { + // Queues input provided by the player and executes registered actions + class InputExecutor { + private: + std::shared_ptr input; + std::queue queued_keys; + + std::unordered_map pressed_keys; + std::unordered_map key_input_types; + std::vector released_keys; + + void convert_released_keys_to_none(); + + public: + InputExecutor(const std::shared_ptr& input); + + [[nodiscard]] std::shared_ptr get_input() const; + + void queue_key(const KeyCode& key_code, const InputType& input_type); + + // Executes all queued input actions + void execute_input_actions(); + + bool is_key_down(const KeyCode& key_code); + bool is_key_up(const KeyCode& key_code); + bool is_key_pressed(const KeyCode& key_code); + bool is_key_released(const KeyCode& key_code); + }; +} + +#endif diff --git a/src/bebone/core/input/input_handler.cpp b/src/bebone/core/input/input_handler.cpp deleted file mode 100644 index 13c4c22c..00000000 --- a/src/bebone/core/input/input_handler.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include "input_handler.h" - -namespace bebone::core { - const KeyListener& InputHandler::get_key_listener() const { - return keyListener; - } - - const MouseListener& InputHandler::get_mouse_listener() const { - return mouseListener; - } - - void InputHandler::execute_input_actions() const { - Input::get_instance().execute_queued_actions(); - } -} \ No newline at end of file diff --git a/src/bebone/core/input/input_handler.h b/src/bebone/core/input/input_handler.h deleted file mode 100644 index e9f0b047..00000000 --- a/src/bebone/core/input/input_handler.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef _INPUT_HANDLER_H_ -#define _INPUT_HANDLER_H_ - -#include "input.h" -#include "key_listener.h" -#include "mouse_listener.h" - -namespace bebone::core { - // Input handler class - class InputHandler { - private: - KeyListener keyListener; - MouseListener mouseListener; - - public: - // Getter for key listener - const KeyListener& get_key_listener() const; - - // Getter for mouse listener - const MouseListener& get_mouse_listener() const; - - // Executes all input actions - void execute_input_actions() const; - }; -} - -#endif diff --git a/src/bebone/core/input/input_type.h b/src/bebone/core/input/input_type.h index dda795cc..8a823572 100644 --- a/src/bebone/core/input/input_type.h +++ b/src/bebone/core/input/input_type.h @@ -4,8 +4,10 @@ namespace bebone::core { /// Specifies in which case the action will be executed enum InputType { - PRESS, - RELEASE + Release, + Press, + Repeat, + None }; } diff --git a/src/bebone/core/input/key.cpp b/src/bebone/core/input/key.cpp index c386c036..345ab325 100644 --- a/src/bebone/core/input/key.cpp +++ b/src/bebone/core/input/key.cpp @@ -1,13 +1,13 @@ #include "key.h" namespace bebone::core { - Key::Key(KeyCode keyCode, InputType inputType) : keyCode(keyCode), inputType(inputType) { } + Key::Key(KeyCode key_code, InputType input_type) : key_code(key_code), input_type(input_type) { } bool Key::operator==(const Key& other) const { - return keyCode == other.keyCode && inputType == other.inputType; + return key_code == other.key_code && input_type == other.input_type; } bool Key::operator<(const bebone::core::Key &other) const { - return keyCode < other.keyCode; + return key_code < other.key_code; } } \ No newline at end of file diff --git a/src/bebone/core/input/key.h b/src/bebone/core/input/key.h index 56c57bb5..5683add1 100644 --- a/src/bebone/core/input/key.h +++ b/src/bebone/core/input/key.h @@ -7,10 +7,10 @@ namespace bebone::core { /// Key data type, which holds the key code and input type struct Key { - KeyCode keyCode; - InputType inputType; + KeyCode key_code; + InputType input_type; - Key(KeyCode keyCode, InputType inputType); + Key(KeyCode key_code, InputType input_type); bool operator==(const Key& other) const; bool operator<(const Key& other) const; }; diff --git a/src/bebone/core/input/key_code.h b/src/bebone/core/input/key_code.h index b5c92952..84335567 100644 --- a/src/bebone/core/input/key_code.h +++ b/src/bebone/core/input/key_code.h @@ -4,33 +4,33 @@ namespace bebone::core { /// Specifies the mouse and keyboard buttons. All values are taken from GLFW enum KeyCode { - MOUSE_BUTTON_LEFT, - MOUSE_BUTTON_RIGHT, - MOUSE_BUTTON_MIDDLE, - MOUSE_BUTTON_4, - MOUSE_BUTTON_5, - MOUSE_BUTTON_6, - MOUSE_BUTTON_7, - MOUSE_BUTTON_8, + MouseButtonLeft, + MouseButtonRight, + MouseButtonMiddle, + MouseButton4, + MouseButton5, + MouseButton6, + MouseButton7, + MouseButton8, - SPACE = 32, - APOSTROPHE = 39, + Space = 32, + Apostrophe = 39, - COMMA = 44, - MINUS, - PERIOD, - SLASH, - ONE, - TWO, - THREE, - FIVE, - SIX, - SEVEN, - EIGHT, - NINE, + Comma = 44, + Minus, + Period, + Slash, + One, + Two, + Three, + Five, + Six, + Seven, + Eight, + Nine, - SEMICOLON = 59, - EQUAL = 61, + Semicolon = 59, + Equal = 61, A = 65, B, C, D, E, F, G, @@ -38,33 +38,33 @@ namespace bebone::core { N, O, P, Q, R, S, T, U, V, W, X, Y, Z, - LEFT_BRACKET, - BACKSLASH, - RIGHT_BRACKET, + LeftBracket, + Backslash, + RightBracket, - GRAVE_ACCENT = 96, + GraveAccent = 96, - WORLD_1 = 161, - WORLD_2, + World1 = 161, + World2, - ESCAPE = 256, - ENTER, - TAB, - BACKSPACE, - INSERT, - DELETE, - RIGHT, - LEFT, - DOWN, - UP, - PAGE_UP, - PAGE_DOWN, - HOME, - END, - CAPS_LOCK, - NUM_LOCK, - PRINT_SCREEN, - PAUSE, + Escape = 256, + Enter, + Tab, + Backspace, + Insert, + Delete, + Right, + Left, + Down, + Up, + PageUp, + PageDown, + Home, + End, + CapsLock, + NumLock, + PrintScreen, + Pause, F1 = 290, F2, F3, F4, F5, F6, F7, @@ -72,33 +72,33 @@ namespace bebone::core { F14, F15, F16, F17, F18, F19, F20, F21, F22, F23, F24, F25, - KEYPAD_0 = 320, - KEYPAD_1, - KEYPAD_2, - KEYPAD_3, - KEYPAD_4, - KEYPAD_5, - KEYPAD_6, - KEYPAD_7, - KEYPAD_8, - KEYPAD_9, - KEYPAD_DECIMAL, - KEYPAD_DIVIDE, - KEYPAD_MULTIPLY, - KEYPAD_SUBTRACT, - KEYPAD_ADD, - KEYPAD_ENTER, - KEYPAD_EQUAL, + Keypad0 = 320, + Keypad1, + Keypad2, + Keypad3, + Keypad4, + Keypad5, + Keypad6, + Keypad7, + Keypad8, + Keypad9, + KeypadDecimal, + KeypadDivide, + KeypadMultiply, + KeypadSubtract, + KeypadAdd, + KeypadEnter, + KeypadEqual, - LEFT_SHIFT = 340, - LEFT_CONTROL, - LEFT_ALT, - LEFT_SUPER, - RIGHT_SHIFT, - RIGHT_CONTROL, - RIGHT_ALT, - RIGHT_SUPER, - MENU + LeftShift = 340, + LeftControl, + LeftAlt, + LeftSuper, + RightShift, + RightControl, + RightAlt, + RightSuper, + Menu }; } diff --git a/src/bebone/core/input/key_listener.h b/src/bebone/core/input/key_listener.h deleted file mode 100644 index a8abebd3..00000000 --- a/src/bebone/core/input/key_listener.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef _KEY_LISTENER_H_ -#define _KEY_LISTENER_H_ - -#include "../events/listeners/event_listener.tpp" - -#include "../../gfx/window/events/input_event.h" - -#include "input.h" - -#include - -namespace bebone::core { - using namespace gfx; - - struct KeyListener : EventListener { - void operator()(InputKeyEvent& event) override { - Input& input = Input::get_instance(); - - KeyCode keyCode = static_cast(event.key); - InputType inputType = static_cast(event.action); - input.queue_key(keyCode, inputType); - } - }; -} - -#endif diff --git a/src/bebone/core/input/mouse_listener.h b/src/bebone/core/input/mouse_listener.h deleted file mode 100644 index 1d655f5c..00000000 --- a/src/bebone/core/input/mouse_listener.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef _MOUSE_LISTENER_H_ -#define _MOUSE_LISTENER_H_ - -#include "../events/listeners/event_listener.tpp" - -#include "../../gfx/window/events/input_event.h" - -#include "input.h" - -namespace bebone::core { - using namespace gfx; - - struct MouseListener : EventListener { - void operator()(InputMouseButtonEvent& event) override { - Input& input = Input::get_instance(); - - KeyCode keyCode = static_cast(event.button); - InputType inputType = static_cast(event.action); - input.queue_key(keyCode, inputType); - } - }; -} - -#endif diff --git a/src/bebone/core/logger.tpp b/src/bebone/core/logger.tpp deleted file mode 100644 index 9c7a38fd..00000000 --- a/src/bebone/core/logger.tpp +++ /dev/null @@ -1,113 +0,0 @@ -#ifndef _BEBONE_CORE_LOGGER_TPP_ -#define _BEBONE_CORE_LOGGER_TPP_ - -#include -#include - -#include "noncopyable.h" - -#define BEBONE_LOGGER_DEFAULT_INSTANCE DEFAULT -#define BEBONE_LOGGER_ENABLE_LINE_BREAKS true -#define BEBONE_LOGGER_ENABLE_MESSAGE_TYPE true - -namespace bebone::core { - /// Logger instance specifying enum - enum LOGGER_INSTANCE { - DEFAULT - }; - - /// Logger message type enum - enum LOG_MESSAGE_TYPE { - INFO, - WARNING, - ERROR, - CRITICAL_ERROR - }; - - /// Class that can be used for logging, - template - class Logger : private NonCopyable { - private: - std::ostream& stream; - - Logger() : stream(std::cout) {} - - /*! - * Function that returns singleton instance of logger - * @return Logger instance - */ - static Logger& get_instance() { - static Logger logger; - - return logger; - } - - /*! - * Function that converts LOG_MESSAGE_TYPE enum value into the string - * @param messageType - message type - * @return Message type string - */ - constexpr static const char* get_message_type_string(const LOG_MESSAGE_TYPE& messageType) { - switch (messageType) { - case INFO: return "INFO"; - case WARNING: return "WARNING"; - case ERROR: return "ERROR"; - case CRITICAL_ERROR: return "CRITICAL ERROR"; - default: return "UNNAMED"; - } - - return "UNNAMED"; - } - - public: - /*! - * Function used for setting specific output stream - * @param stream - desired stream - */ - static void set_stream(const std::ostream& stream) { - Logger<__loggerInstance>::get_instance().stream = stream; - } - - /*! - * Function used for logging a message - * @tparam messageType - message type - * @param logMessage - message - */ - template - static void log(const std::string& logMessage) { - auto& stream = Logger<__loggerInstance>::get_instance().stream; - - if constexpr (BEBONE_LOGGER_ENABLE_MESSAGE_TYPE) { - stream << "[" << get_message_type_string(messageType) << "]"; - } - - stream << logMessage; - - if constexpr (BEBONE_LOGGER_ENABLE_LINE_BREAKS) { - stream << "\n"; - } - } - - /*! - * Function used for logging a message - * @tparam messageType - message type - * @param logMessage - message - */ - template - static void log(const char* logMessage) { - auto& stream = Logger<__loggerInstance>::get_instance().stream; - - if constexpr (BEBONE_LOGGER_ENABLE_MESSAGE_TYPE) { - stream << "[" << get_message_type_string(messageType) << "]"; - } - - stream << logMessage; - - if constexpr (BEBONE_LOGGER_ENABLE_LINE_BREAKS) { - stream << "\n"; - } - } - }; -} - -#endif \ No newline at end of file diff --git a/src/bebone/core/memory/arena_allocator.cpp b/src/bebone/core/memory/arena_allocator.cpp new file mode 100644 index 00000000..9ac971c5 --- /dev/null +++ b/src/bebone/core/memory/arena_allocator.cpp @@ -0,0 +1,51 @@ +#include "arena_allocator.h" + +namespace bebone::core { + ArenaAllocator::ArenaAllocator(const size_t& size) : capacity(size), allocated(0) { + data = std::malloc(size); + + if(data == nullptr) // Todo throw error + LOG_ERROR("Failed to allocated {} bytes for arena allocator"); + + LOG_TRACE("Created arena allocator"); + } + + ArenaAllocator::ArenaAllocator(const size_t& size, void* buffer) : capacity(size), allocated(0) { + data = buffer; + + LOG_TRACE("Created arena allocator from memory"); + } + + ArenaAllocator::~ArenaAllocator() { + free(data); + + LOG_TRACE("Freed arena allocator from memory"); + } + + void* ArenaAllocator::alloc(const size_t& size) noexcept { + if(allocated + size > capacity) { + return nullptr; + } + + const size_t tmp_allocated = allocated; + allocated += size; + + return static_cast(data) + tmp_allocated; + } + + void* ArenaAllocator::get_data() noexcept { + return data; + } + + void ArenaAllocator::clear() noexcept { + allocated = 0; + } + + [[nodiscard]] const size_t& ArenaAllocator::get_allocated() const noexcept { + return allocated; + } + + [[nodiscard]] const size_t& ArenaAllocator::get_capacity() const noexcept { + return capacity; + } +} diff --git a/src/bebone/core/arena_allocator.h b/src/bebone/core/memory/arena_allocator.h similarity index 76% rename from src/bebone/core/arena_allocator.h rename to src/bebone/core/memory/arena_allocator.h index 33971bee..9112df00 100644 --- a/src/bebone/core/arena_allocator.h +++ b/src/bebone/core/memory/arena_allocator.h @@ -1,69 +1,70 @@ -#ifndef _BEBONE_CORE_ARENA_ALLOCATOR_H_ -#define _BEBONE_CORE_ARENA_ALLOCATOR_H_ - -#include - -#include "noncopyable.h" - -#define _BEBONE_MEMORY_BYTES_1KB_ 1024 -#define _BEBONE_MEMORY_BYTES_2KB_ 2048 -#define _BEBONE_MEMORY_BYTES_4KB_ 4096 -#define _BEBONE_MEMORY_BYTES_8KB_ 8192 - -namespace bebone::core { - /// Class used for allocating and managing an arena of memory - class ArenaAllocator : private core::NonCopyable { - private: - void *_data; - const size_t _capacity; - size_t _allocated; - - public: - /*! - * Default constructor - * @param size - desired arena size - */ - explicit ArenaAllocator(const size_t& size); - - /*! - * Default constructor - * @param size - desired arena size - * @param buffer - target arena buffer - */ - explicit ArenaAllocator(const size_t& size, void* buffer); - - ~ArenaAllocator(); - - /*! - * Function that is used for allocating memory in arena - * @param size - size of desired memory segment - * @return Pointer to allocated memory segment - */ - void* alloc(const size_t& size) noexcept; - - /*! - * Function that is used for accessing an arena memory - * @return Pointer to arena start - */ - void* data() noexcept; - - /*! - * Clears an arena - */ - void clear() noexcept; - - /*! - * Function that returns how much memory is already allocated in arena - * @return Bytes allocated - */ - [[nodiscard]] const size_t& allocated() const noexcept; - - /*! - * Function that returns a total capacity of arena - * @return Bytes capacity - */ - [[nodiscard]] const size_t& capacity() const noexcept; - }; -} - +#ifndef _BEBONE_CORE_ARENA_ALLOCATOR_H_ +#define _BEBONE_CORE_ARENA_ALLOCATOR_H_ + +#include + +#include "../debug/logger.h" +#include "noncopyable.h" + +#define BEBONE_MEMORY_BYTES_1KB 1024 +#define BEBONE_MEMORY_BYTES_2KB 2048 +#define BEBONE_MEMORY_BYTES_4KB 4096 +#define BEBONE_MEMORY_BYTES_8KB 8192 + +namespace bebone::core { + /// Class used for allocating and managing an arena of memory + class ArenaAllocator : private core::NonCopyable { + private: + void *data; + const size_t capacity; + size_t allocated; + + public: + /*! + * Default constructor + * @param size - desired arena size + */ + explicit ArenaAllocator(const size_t& size); + + /*! + * Default constructor + * @param size - desired arena size + * @param buffer - target arena buffer + */ + explicit ArenaAllocator(const size_t& size, void* buffer); + + ~ArenaAllocator(); + + /*! + * Function that is used for allocating memory in arena + * @param size - size of desired memory segment + * @return Pointer to allocated memory segment + */ + void* alloc(const size_t& size) noexcept; + + /*! + * Function that is used for accessing an arena memory + * @return Pointer to arena start + */ + void* get_data() noexcept; + + /*! + * Clears an arena + */ + void clear() noexcept; + + /*! + * Function that returns how much memory is already allocated in arena + * @return Bytes allocated + */ + [[nodiscard]] const size_t& get_allocated() const noexcept; + + /*! + * Function that returns a total capacity of arena + * @return Bytes capacity + */ + [[nodiscard]] const size_t& get_capacity() const noexcept; + }; +} + #endif \ No newline at end of file diff --git a/src/bebone/core/arena_container.cpp b/src/bebone/core/memory/arena_container.cpp similarity index 63% rename from src/bebone/core/arena_container.cpp rename to src/bebone/core/memory/arena_container.cpp index 7b3bc14c..208452fb 100644 --- a/src/bebone/core/arena_container.cpp +++ b/src/bebone/core/memory/arena_container.cpp @@ -2,20 +2,20 @@ namespace bebone::core { ArenaContainer::ArenaContainer(const size_t& size) : data(size), indices(size) { - + LOG_TRACE("Created arena container"); } void* ArenaContainer::alloc(const size_t& size) noexcept { void* ptr = data.alloc(size); - void** indexPtr = static_cast(indices.alloc(sizeof(void*))); + void** index_ptr = static_cast(indices.alloc(sizeof(void*))); - *indexPtr = ptr; + *index_ptr = ptr; return ptr; } void* ArenaContainer::at(const size_t& index) { - void **ptr = static_cast(indices.data()); + void **ptr = static_cast(indices.get_data()); return ptr[index]; } @@ -25,14 +25,14 @@ namespace bebone::core { } [[nodiscard]] size_t ArenaContainer::size() const noexcept { - return indices.allocated() / sizeof(void*); + return indices.get_allocated() / sizeof(void*); } [[nodiscard]] size_t ArenaContainer::allocated() const noexcept { - return data.allocated() + indices.allocated(); + return data.get_allocated() + indices.get_allocated(); } [[nodiscard]] size_t ArenaContainer::capacity() const noexcept { - return data.allocated() + indices.allocated(); + return data.get_allocated() + indices.get_allocated(); } } diff --git a/src/bebone/core/arena_container.h b/src/bebone/core/memory/arena_container.h similarity index 96% rename from src/bebone/core/arena_container.h rename to src/bebone/core/memory/arena_container.h index 97d806a4..d633978d 100644 --- a/src/bebone/core/arena_container.h +++ b/src/bebone/core/memory/arena_container.h @@ -1,60 +1,60 @@ -#ifndef _BEBONE_CORE_ARENA_CONTAINER_H_ -#define _BEBONE_CORE_ARENA_CONTAINER_H_ - -#include "noncopyable.h" -#include "arena_allocator.h" - -namespace bebone::core { - /// Container class that can store values of different types by their value - class ArenaContainer : private core::NonCopyable { - private: - ArenaAllocator data; - ArenaAllocator indices; - - public: - /*! - * Default constructor - * @param size - desired arena size - */ - explicit ArenaContainer(const size_t& size); - - /*! - * Function that allocated a memory segment of given size - * @param size - size of desired memory segment - * @return Pointer to allocated memory segment - */ - void* alloc(const size_t& size) noexcept; - - /*! - * Function that is used for indexing and specific allocating index - * @param index desired allocation index - * @return Pointer to allocation - */ - void* at(const size_t& index); - - /*! - * Function that clears container - */ - void clear() noexcept; - - /*! - * Function that returns number of allocations in this container - * @return Allocation count - */ - [[nodiscard]] size_t size() const noexcept; - - /*! - * Function that returns how much memory is already allocated in arena - * @return Bytes allocated - */ - [[nodiscard]] size_t allocated() const noexcept; - - /*! - * Function that returns a total capacity of arena - * @return Bytes capacity - */ - [[nodiscard]] size_t capacity() const noexcept; - }; -} - +#ifndef _BEBONE_CORE_ARENA_CONTAINER_H_ +#define _BEBONE_CORE_ARENA_CONTAINER_H_ + +#include "noncopyable.h" +#include "arena_allocator.h" + +namespace bebone::core { + /// Container class that can store values of different types by their value + class ArenaContainer : private core::NonCopyable { + private: + ArenaAllocator data; + ArenaAllocator indices; + + public: + /*! + * Default constructor + * @param size - desired arena size + */ + explicit ArenaContainer(const size_t& size); + + /*! + * Function that allocated a memory segment of given size + * @param size - size of desired memory segment + * @return Pointer to allocated memory segment + */ + void* alloc(const size_t& size) noexcept; + + /*! + * Function that is used for indexing and specific allocating index + * @param index desired allocation index + * @return Pointer to allocation + */ + void* at(const size_t& index); + + /*! + * Function that clears container + */ + void clear() noexcept; + + /*! + * Function that returns number of allocations in this container + * @return Allocation count + */ + [[nodiscard]] size_t size() const noexcept; + + /*! + * Function that returns how much memory is already allocated in arena + * @return Bytes allocated + */ + [[nodiscard]] size_t allocated() const noexcept; + + /*! + * Function that returns a total capacity of arena + * @return Bytes capacity + */ + [[nodiscard]] size_t capacity() const noexcept; + }; +} + #endif \ No newline at end of file diff --git a/src/bebone/core/noncopyable.h b/src/bebone/core/memory/noncopyable.h similarity index 100% rename from src/bebone/core/noncopyable.h rename to src/bebone/core/memory/noncopyable.h diff --git a/src/bebone/core/meta/function_traits.tpp b/src/bebone/core/meta/function_traits.tpp index 86211721..10ea3afd 100644 --- a/src/bebone/core/meta/function_traits.tpp +++ b/src/bebone/core/meta/function_traits.tpp @@ -6,33 +6,33 @@ namespace bebone::core { /// Meta function that is used for accessing function traits such as argument types - template struct function_traits; + template struct FunctionTraits; /// Meta function that is used for accessing function traits such as argument types template - struct function_traits : public function_traits::type::operator())> { + struct FunctionTraits : public FunctionTraits::type::operator())> { }; /// Meta function that is used for accessing function traits such as argument types template - struct function_traits : function_traits { + struct FunctionTraits : FunctionTraits { }; /// Meta function that is used for accessing function traits such as argument types template - struct function_traits : function_traits { + struct FunctionTraits : FunctionTraits { }; /// Meta function that is used for accessing function traits such as argument types template - struct function_traits { + struct FunctionTraits { typedef ReturnType result_type; template - using argument = typename std::tuple_element>::type; + using Argument = typename std::tuple_element>::type; static const std::size_t arity = sizeof...(Arguments); }; diff --git a/src/bebone/core/profiler.cpp b/src/bebone/core/profiler.cpp deleted file mode 100644 index a37e13d3..00000000 --- a/src/bebone/core/profiler.cpp +++ /dev/null @@ -1,145 +0,0 @@ -#include "profiler.h" - -#include - -namespace bebone::core { - Profile::Profile(std::string label) - : label(std::move(label)), - executionCount(0), - totalExecutionTime(0.0), - minExecutionTime(std::numeric_limits::max()), - maxExecutionTime(0.0) - { - Profiler::get_instance().push_profile(this); - } - - Profile::Profile(const char* label) - : label(label), - executionCount(0), - totalExecutionTime(0.0), - minExecutionTime(std::numeric_limits::max()), - maxExecutionTime(0.0) - { - Profiler::get_instance().push_profile(this); - } - - u32 Profile::count_child_profiles() { - return childs.size(); - } - - std::vector& Profile::get_childs() { - return childs; - } - - void Profile::record() { - Profiler::get_instance().bind_top_profile(this); - - ++executionCount; - - recordStartTimestamp = std::chrono::high_resolution_clock::now(); - } - - void Profile::stop() { - Profiler::get_instance().unbind_top_profile(); - - auto record_stop_timestamp = std::chrono::high_resolution_clock::now(); - - f64 duration = std::chrono::duration_cast(record_stop_timestamp - recordStartTimestamp).count(); - - totalExecutionTime += duration; - minExecutionTime = std::min(minExecutionTime, duration); - maxExecutionTime = std::max(maxExecutionTime, duration); - } - - void Profile::push_child_profile(Profile *profile) { - childs.push_back(profile); - } - - Profiler::Profiler() : stack(), stackIndex(0) { - - } - - void Profiler::push_profile(Profile* profile) { - if(stackIndex == 0) - entryPoints.push_back(profile); - else - stack[stackIndex - 1]->push_child_profile(profile); - } - - void Profiler::bind_top_profile(Profile *profile) { - stack[stackIndex] = profile; - ++stackIndex; - } - - void Profiler::unbind_top_profile() { - if(stackIndex <= 0) { - // Todo throw profiler exception - } else { - stack[stackIndex] = nullptr; - --stackIndex; - } - } - - void trace_profiles( - Profile *profile, - Profile *parent, - unsigned long depth, - const std::function& lamda - ) { - std::ignore = parent; - - const auto& childs = profile->get_childs(); - - for(auto& pp : childs) { - lamda(pp, profile, depth + 1); - - trace_profiles(pp, profile, depth + 1, lamda); - } - } - - const unsigned int& Profiler::get_stack_index() const { - return stackIndex; - } - - const std::array& Profiler::get_stack() const { - return stack; - } - - const std::vector& Profiler::get_entry_points() const { - return entryPoints; - } - - std::string Profiler::result() const { - std::stringstream ss; - - for(auto& profile : entryPoints) { - ss << "Profile: '" << profile->label << "' (" - << "times = " << profile->executionCount << ", " - << "total = " << profile->totalExecutionTime / 1000000.0 << " ms, " - << "min = " << profile->minExecutionTime / 1000000.0 << " ms, " - << "max = " << profile->maxExecutionTime / 1000000.0 << " ms, " - << "avg = " << (profile->totalExecutionTime / profile->executionCount) / 1000000.0 << " ms, " - << "perc = 100.0 %) \n"; - - trace_profiles(profile, profile, 1, [&](Profile* pp, Profile* parent, unsigned int depth) { - for(unsigned int i = 0; i < depth; ++i) - ss << " "; - - ss << "Profile :'" << pp->label << "' (" - << "times = " << pp->executionCount << ", " - << "total = " << pp->totalExecutionTime / 1000000.0 << " ms, " - << "min = " << pp->minExecutionTime / 1000000.0 << " ms, " - << "max = " << pp->maxExecutionTime / 1000000.0 << " ms, " - << "avg = " << (pp->totalExecutionTime / pp->executionCount) / 1000000.0 << " ms, " - << "perc = " << (pp->totalExecutionTime / parent->totalExecutionTime) * 100.0 << "%) \n"; - }); - } - - return ss.str(); - } - - Profiler& Profiler::get_instance() { - static Profiler profiler; - return profiler; - } -} diff --git a/src/bebone/core/profiler.h b/src/bebone/core/profiler.h deleted file mode 100644 index 9c8f5d20..00000000 --- a/src/bebone/core/profiler.h +++ /dev/null @@ -1,140 +0,0 @@ -#ifndef _BEBONE_CORE_PROFILER_H_ -#define _BEBONE_CORE_PROFILER_H_ - -#include -#include - -#include - -#include -#include - -#include -#include -#include - -#include - -#include "types.h" - -namespace bebone::core { - // Debug profile class - struct Profile { - private: - std::chrono::high_resolution_clock::time_point recordStartTimestamp; - std::vector childs; - - public: - std::string label; - - u64 executionCount; - - f64 totalExecutionTime; - f64 minExecutionTime; - f64 maxExecutionTime; - - /*! - * Default profile constructor - * @param label - Profile label - */ - explicit Profile(std::string label); - - /*! - * Default profile constructor - * @param label - Profile label - */ - explicit Profile(const char* label); - - // Start profile record - void record(); - - // Stop profile record - void stop(); - - /*! - * Pushes child profile - * @param label - Pointer to child profile - */ - void push_child_profile(Profile *profile); - - // Getter for child profile count - u32 count_child_profiles(); - - /*! - * Reference childs container - * @return childs container - */ - std::vector& get_childs(); - }; - - class Profiler { - private: - // Hidden constructor - Profiler(); - - std::array stack; - unsigned int stackIndex; - - std::vector entryPoints; - - public: - /*! - * Pushes profile to profiler - * @param profile - Pointer to profile - */ - void push_profile(Profile* profile); - - /*! - * Binds top level profile - * @param profile - Pointer to profile - */ - void bind_top_profile(Profile *profile); - - // Unbinds top level profile - void unbind_top_profile(); - - // Getter for current stack index - const unsigned int& get_stack_index() const; - - // Getter for profile stack - const std::array& get_stack() const; - - // Getter for profiler entry points profiles - const std::vector& get_entry_points() const; - - /*! - * Sum ups all profile data, creates single string representation of program performance - * @param profile - Result string - */ - std::string result() const; - - // Returns a reference to a single top instance - static Profiler& get_instance(); - }; - - /*! - * Function that can be used to trace profile tree - * @param profile - Profile - * @param parent - Parent profile - * @param depth - Profile tree depth - * @param lamda - Function lambda, that will be used for every profile in a tree - */ - void trace_profiles( - Profile *profile, - Profile *parent, - unsigned long depth, - const std::function& lamda - ); -} - -#ifdef DEBUG - #define BEBONE_PROFILE_RECORD(LABEL) static bebone::core::Profile LABEL(#LABEL); LABEL.record(); - #define BEBONE_PROFILE_STOP(LABEL) LABEL.stop(); - #define BEBONE_PROFILER_SUM_UP() Profiler::get_instance().result() -#else - #define BEBONE_PROFILE_RECORD(LABEL) - #define BEBONE_PROFILE_STOP(LABEL) - #define BEBONE_PROFILER_SUM_UP() "" -#endif - -#endif \ No newline at end of file diff --git a/src/bebone/core/timestamp/timestamp.cpp b/src/bebone/core/timestamp/timestamp.cpp new file mode 100644 index 00000000..18913f3d --- /dev/null +++ b/src/bebone/core/timestamp/timestamp.cpp @@ -0,0 +1,35 @@ +#include "timestamp.h" + +namespace bebone::core { + const steady_clock::time_point Time::startup_time = steady_clock::now(); + double Time::delta_time = 1.0f / 60; + + void Time::set_delta_time(const double& time) { + if (time <= 0) { + return; + } + + delta_time = time; + } + + double Time::get_delta_time() { + return delta_time; + } + + double Time::get_seconds_elapsed() { + auto now = steady_clock::now(); + return duration_cast(now - startup_time).count() / 1000000.0; + } + + Timestamp::Timestamp() { + time = Time::get_seconds_elapsed(); + } + + double Timestamp::operator-(const Timestamp& timestamp) const { + return time - timestamp.time; + } + + double Timestamp::operator+(const Timestamp& timestamp) const { + return time + timestamp.time; + } +} \ No newline at end of file diff --git a/src/bebone/core/timestamp/timestamp.h b/src/bebone/core/timestamp/timestamp.h new file mode 100644 index 00000000..122ce5ed --- /dev/null +++ b/src/bebone/core/timestamp/timestamp.h @@ -0,0 +1,33 @@ +#ifndef _TIMESTAMP_H +#define _TIMESTAMP_H + +#include + +namespace bebone::core { + using namespace std::chrono; + + class Time { + private: + static double delta_time; + + public: + static const steady_clock::time_point startup_time; + + static double get_delta_time(); + static double get_seconds_elapsed(); + + static void set_delta_time(const double& time); + }; + + struct Timestamp { + public: + double time; + + Timestamp(); + + double operator-(const Timestamp& timestamp) const; + double operator+(const Timestamp& timestamp) const; + }; +} + +#endif diff --git a/src/bebone/core/timestamp/watch.cpp b/src/bebone/core/timestamp/watch.cpp new file mode 100644 index 00000000..815edf6c --- /dev/null +++ b/src/bebone/core/timestamp/watch.cpp @@ -0,0 +1,12 @@ +#include "watch.h" + +namespace bebone::core { + void Watch::update_timestamp() { + current_timestamp = Timestamp(); + } + + double Watch::get_time_difference() { + Timestamp now; + return now - current_timestamp; + } +} \ No newline at end of file diff --git a/src/bebone/core/timestamp/watch.h b/src/bebone/core/timestamp/watch.h new file mode 100644 index 00000000..da06e896 --- /dev/null +++ b/src/bebone/core/timestamp/watch.h @@ -0,0 +1,19 @@ +#ifndef _WATCH_H +#define _WATCH_H + +#include "timestamp.h" + +namespace bebone::core { + class Watch { + private: + Timestamp current_timestamp; + + public: + Watch() = default; + + void update_timestamp(); + double get_time_difference(); + }; +} + +#endif diff --git a/src/bebone/core/types.h b/src/bebone/core/types.h deleted file mode 100644 index b3df3b4f..00000000 --- a/src/bebone/core/types.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef _BEBONE_CORE_TYPES_H_ -#define _BEBONE_CORE_TYPES_H_ - -#include - -namespace bebone::core { - using u8 = omni::types::u8; - using u16 = omni::types::u16; - using u32 = omni::types::u32; - using u64 = omni::types::u64; - - using i8 = omni::types::i8; - using i16 = omni::types::i16; - using i32 = omni::types::i32; - using i64 = omni::types::i64; - - using f32 = omni::types::f32; - using f64 = omni::types::f64; - - using Vec2f = omni::types::Vec2f; - using Vec3f = omni::types::Vec3f; - using Vec4f = omni::types::Vec4f; - - using Vec2i = omni::types::Vec2i; - using Vec3i = omni::types::Vec3i; - using Vec4i = omni::types::Vec4i; - - using Mat4f = omni::types::Mat4f; - using Mat2f = omni::types::Mat2f; - - using ColorFormat = omni::types::ColorFormat; - - template - using Color = omni::types::Color<_Format>; - - using ColorRGB24 = omni::types::ColorRGB24; - using ColorRGBA32 = omni::types::ColorRGBA32; - using ColorRGBA32f = omni::types::ColorRGBA32f; - - // Default color types is R32G32B32A32_FLOAT - using ColorRGBA = ColorRGBA32f; -} - -#endif diff --git a/src/bebone/core/types/color/color.tpp b/src/bebone/core/types/color/color.tpp new file mode 100644 index 00000000..1eb72429 --- /dev/null +++ b/src/bebone/core/types/color/color.tpp @@ -0,0 +1,21 @@ +#ifndef _BEBONE_CORE_TYPES_COLOR_TYPE_H_ +#define _BEBONE_CORE_TYPES_COLOR_TYPE_H_ + +#include +#include "../primitive_types.h" +#include "../vector/vector_types.h" + +#ifndef BEBONE_TYPES_RAND + #define BEBONE_TYPES_RAND rand() +#endif + +#include "color_format.h" + +namespace bebone::core { + template + struct Color { + + }; +} + +#endif diff --git a/src/bebone/core/types/color/color_format.h b/src/bebone/core/types/color/color_format.h new file mode 100644 index 00000000..1a48d4c2 --- /dev/null +++ b/src/bebone/core/types/color/color_format.h @@ -0,0 +1,23 @@ +#ifndef _BEBONE_CORE_TYPES_COLOR_FORMAT_H_ +#define _BEBONE_CORE_TYPES_COLOR_FORMAT_H_ + +#define BEBONE_TYPES_COLOR_UINT 1 +#define BEBONE_TYPES_COLOR_FLOAT 2 + +#define BEBONE_TYPES_COLOR_3_CHANNELS 4 +#define BEBONE_TYPES_COLOR_4_CHANNELS 8 + +namespace bebone::core { + enum ColorFormat { + R8G8B8Uint = BEBONE_TYPES_COLOR_3_CHANNELS | BEBONE_TYPES_COLOR_UINT, + R8G8B8A8Uint = BEBONE_TYPES_COLOR_4_CHANNELS | BEBONE_TYPES_COLOR_UINT, + + R32G32B32A32Float = BEBONE_TYPES_COLOR_4_CHANNELS | BEBONE_TYPES_COLOR_FLOAT, + + RGB24 = R8G8B8Uint, + RGBA32 = R8G8B8A8Uint, + RGBA32F = R32G32B32A32Float + }; +} + +#endif diff --git a/src/bebone/core/types/color/color_r8g8b8.cpp b/src/bebone/core/types/color/color_r8g8b8.cpp new file mode 100644 index 00000000..2b30929b --- /dev/null +++ b/src/bebone/core/types/color/color_r8g8b8.cpp @@ -0,0 +1,35 @@ +#include "color_r8g8b8.tpp" + +#include "color_r8g8b8a8.tpp" +#include "color_rgba32f.tpp" + +namespace bebone::core { + const Color Color::BLACK{0, 0, 0}; + const Color Color::WHITE{255, 255, 255}; + const Color Color::RED{255, 0, 0}; + const Color Color::BLUE{0, 0, 255}; + const Color Color::GREEN{0, 255, 0}; + const Color Color::YELLOW{255, 255, 0}; + const Color Color::MAGENTA{255, 0, 255}; + const Color Color::CYAN{0, 255, 255}; + + template<> + Color Color::to() const { + return *this; + } + + template<> + Color Color::to() const { + return Color{r, g, b, 255}; + } + + template<> + Color Color::to() const { + return Color{ + static_cast(r) / 255.0f, + static_cast(g) / 255.0f, + static_cast(b) / 255.0f, + 1.0f + }; + } +} diff --git a/src/bebone/core/types/color/color_r8g8b8.tpp b/src/bebone/core/types/color/color_r8g8b8.tpp new file mode 100644 index 00000000..737e6152 --- /dev/null +++ b/src/bebone/core/types/color/color_r8g8b8.tpp @@ -0,0 +1,52 @@ +#ifndef _BEBONE_CORE_TYPES_COLOR_R8G8B8_UINT_TPP_ +#define _BEBONE_CORE_TYPES_COLOR_R8G8B8_UINT_TPP_ + +#include "color.tpp" +#include "color_format.h" + +namespace bebone::core { + template<> + struct Color { + u8 r, g, b; + + static const Color BLACK; + static const Color WHITE; + static const Color RED; + static const Color BLUE; + static const Color GREEN; + static const Color YELLOW; + static const Color MAGENTA; + static const Color CYAN; + + explicit operator Vec3() const { return { r, g, b }; } + + template + DesiredColor to() const; + + static inline constexpr ColorFormat get_format() { + return R8G8B8Uint; + } + + static inline constexpr size_t get_channels() { + return 3; + } + + static inline constexpr Color splat(const u8& v) { + return {v, v, v}; + } + + static inline constexpr Color monochrome(const u8& v) { + return splat(v); + } + + static inline Color random() { + return { + static_cast(BEBONE_TYPES_RAND % 255), + static_cast(BEBONE_TYPES_RAND % 255), + static_cast(BEBONE_TYPES_RAND % 255) + }; + } + }; +} + +#endif diff --git a/src/bebone/core/types/color/color_r8g8b8a8.cpp b/src/bebone/core/types/color/color_r8g8b8a8.cpp new file mode 100644 index 00000000..bb0d9d3b --- /dev/null +++ b/src/bebone/core/types/color/color_r8g8b8a8.cpp @@ -0,0 +1,35 @@ +#include "color_r8g8b8a8.tpp" + +#include "color_r8g8b8.tpp" +#include "color_rgba32f.tpp" + +namespace bebone::core { + const Color Color::BLACK{0, 0, 0, 255}; + const Color Color::WHITE{255, 255, 255, 255}; + const Color Color::RED{255, 0, 0, 255}; + const Color Color::BLUE{0, 0, 255, 255}; + const Color Color::GREEN{0, 255, 0, 255}; + const Color Color::YELLOW{255, 255, 0, 255}; + const Color Color::MAGENTA{255, 0, 255, 255}; + const Color Color::CYAN{0, 255, 255, 255}; + + template<> + Color Color::to() const { + return Color{r, g, b}; + } + + template<> + Color Color::to() const { + return *this; + } + + template<> + Color Color::to() const { + return Color{ + static_cast(r) / 255.0f, + static_cast(g) / 255.0f, + static_cast(b) / 255.0f, + static_cast(a) / 255.0f + }; + } +} diff --git a/src/bebone/core/types/color/color_r8g8b8a8.tpp b/src/bebone/core/types/color/color_r8g8b8a8.tpp new file mode 100644 index 00000000..37c5a0ca --- /dev/null +++ b/src/bebone/core/types/color/color_r8g8b8a8.tpp @@ -0,0 +1,53 @@ +#ifndef _BEBONE_CORE_TYPES_COLOR_R8G8B8A8_UINT_TPP_ +#define _BEBONE_CORE_TYPES_COLOR_R8G8B8A8_UINT_TPP_ + +#include "color.tpp" +#include "color_format.h" + +namespace bebone::core { + template<> + struct Color { + u8 r, g, b, a; + + static const Color BLACK; + static const Color WHITE; + static const Color RED; + static const Color BLUE; + static const Color GREEN; + static const Color YELLOW; + static const Color MAGENTA; + static const Color CYAN; + + explicit operator Vec4() const { return { r, g, b, a }; } + + template + DesiredColor to() const; + + static inline constexpr ColorFormat get_format() { + return R8G8B8A8Uint; + } + + static inline constexpr size_t get_channels() { + return 4; + } + + static inline constexpr Color splat(const u8& v) { + return {v, v, v, 255}; + } + + static inline constexpr Color monochrome(const u8& v) { + return splat(v); + } + + static inline Color random() { + return { + static_cast(BEBONE_TYPES_RAND % 255), + static_cast(BEBONE_TYPES_RAND % 255), + static_cast(BEBONE_TYPES_RAND % 255), + 255 + }; + } + }; +} + +#endif diff --git a/src/bebone/core/types/color/color_rgba32f.cpp b/src/bebone/core/types/color/color_rgba32f.cpp new file mode 100644 index 00000000..ae4dab14 --- /dev/null +++ b/src/bebone/core/types/color/color_rgba32f.cpp @@ -0,0 +1,39 @@ +#include "color_rgba32f.tpp" + +#include "color_r8g8b8.tpp" +#include "color_r8g8b8a8.tpp" + +namespace bebone::core { + const Color Color::BLACK{0.0f, 0.0f, 0.0f, 1.0f}; + const Color Color::WHITE{1.0f, 1.0f, 1.0f, 1.0f}; + const Color Color::RED{1.0f, 0.0f, 0.0f, 1.0f}; + const Color Color::BLUE{0.0f, 0.0f, 1.0f, 1.0f}; + const Color Color::GREEN{0.0f, 1.0f, 0.0f, 1.0f}; + const Color Color::YELLOW{1.0f, 1.0f, 0.0f, 1.0f}; + const Color Color::MAGENTA{1.0f, 0.0f, 1.0f, 1.0f}; + const Color Color::CYAN{0.0f, 1.0f, 1.0f, 1.0f}; + + template<> + Color Color::to() const { + return Color{ + static_cast(r * 255), + static_cast(g * 255), + static_cast(b * 255) + }; + } + + template<> + Color Color::to() const { + return Color{ + static_cast(r * 255), + static_cast(g * 255), + static_cast(b * 255), + static_cast(a * 255) + }; + } + + template<> + Color Color::to() const { + return *this; + } +} diff --git a/src/bebone/core/types/color/color_rgba32f.tpp b/src/bebone/core/types/color/color_rgba32f.tpp new file mode 100644 index 00000000..3bc567c7 --- /dev/null +++ b/src/bebone/core/types/color/color_rgba32f.tpp @@ -0,0 +1,53 @@ +#ifndef _BEBONE_CORE_TYPES_COLOR_R32G32B32A32_FLOAT_TPP_ +#define _BEBONE_CORE_TYPES_COLOR_R32G32B32A32_FLOAT_TPP_ + +#include "color.tpp" +#include "color_format.h" + +namespace bebone::core { + template<> + struct Color { + f32 r, g, b, a; + + static const Color BLACK; + static const Color WHITE; + static const Color RED; + static const Color BLUE; + static const Color GREEN; + static const Color YELLOW; + static const Color MAGENTA; + static const Color CYAN; + + explicit operator Vec4() const { return { r, g, b, a }; } + + template + DesiredColor to() const; + + static inline constexpr ColorFormat get_format() { + return R32G32B32A32Float; + } + + static inline constexpr size_t get_channels() { + return 4; + } + + static inline constexpr Color splat(const f32& v) { + return {v, v, v, 1.0f}; + } + + static inline constexpr Color monochrome(const f32& v) { + return splat(v); + } + + static inline Color random() { + return { + static_cast(static_cast(BEBONE_TYPES_RAND % 255)) / 255.0f, + static_cast(static_cast(BEBONE_TYPES_RAND % 255)) / 255.0f, + static_cast(static_cast(BEBONE_TYPES_RAND % 255)) / 255.0f, + 1.0f + }; + } + }; +} + +#endif diff --git a/src/bebone/core/types/color/colors.h b/src/bebone/core/types/color/colors.h new file mode 100644 index 00000000..16e70177 --- /dev/null +++ b/src/bebone/core/types/color/colors.h @@ -0,0 +1,19 @@ +#ifndef _BEBONE_CORE_TYPES_COLORS_H_ +#define _BEBONE_CORE_TYPES_COLORS_H_ + +#include "color.tpp" +#include "color_format.h" + +#include "color_r8g8b8.tpp" +#include "color_r8g8b8a8.tpp" +#include "color_rgba32f.tpp" + +namespace bebone::core { + using ColorRGB24 = Color; + using ColorRGBA32 = Color; + using ColorRGBA32F = Color; + + using ColorRGBA = ColorRGBA32F; +} + +#endif diff --git a/src/bebone/core/types/complex/quaternion.tpp b/src/bebone/core/types/complex/quaternion.tpp new file mode 100644 index 00000000..04d9019a --- /dev/null +++ b/src/bebone/core/types/complex/quaternion.tpp @@ -0,0 +1,84 @@ +#ifndef _BEBONE_CORE_TYPES_QUATERNION_TPP_ +#define _BEBONE_CORE_TYPES_QUATERNION_TPP_ + +#include "../primitive_types.h" + +namespace bebone::core { + struct Quaternion { + f32 a, bi, cj, dk; + + inline Quaternion operator+(const Quaternion& quat) const; + inline Quaternion operator-(const Quaternion& quat) const; + inline Quaternion operator*(const Quaternion& quat) const; + + inline Quaternion& operator+=(const Quaternion& other); + inline Quaternion& operator-=(const Quaternion& other); + inline Quaternion& operator*=(const Quaternion& other); + inline Quaternion& operator/=(const Quaternion& other); + }; +} + +namespace bebone::core { + Quaternion Quaternion::operator+(const Quaternion& quat) const { + return { + this->a + quat.a, + this->bi + quat.bi, + this->cj + quat.cj, + this->dk + quat.dk + }; + } + + Quaternion Quaternion::operator-(const Quaternion& quat) const { + return { + this->a - quat.a, + this->bi - quat.bi, + this->cj - quat.cj, + this->dk - quat.dk + }; + } + + Quaternion Quaternion::operator*(const Quaternion& quat) const { + const auto& w1 = this->a; + const auto& x1 = this->bi; + const auto& y1 = this->cj; + const auto& z1 = this->dk; + + const auto& w2 = quat.a; + const auto& x2 = quat.bi; + const auto& y2 = quat.cj; + const auto& z2 = quat.dk; + + return { + w1*w2 - x1*x2 - y1*y2 - z1*z2, + w1*x2 + x1*w2 + y1*z2 - z1*y2, + w1*y2 - x1*z2 + y1*w2 + z1*x2, + w1*z2 + x1*y2 - y1*x2 + z1*w2 + }; + } + + Quaternion& Quaternion::operator+=(const Quaternion& quat) { + this->a += quat.a; + this->bi += quat.bi; + this->cj += quat.cj; + this->dk += quat.dk; + + return *this; + } + + Quaternion& Quaternion::operator-=(const Quaternion& quat) { + this->a -= quat.a; + this->bi -= quat.bi; + this->cj -= quat.cj; + this->dk -= quat.dk; + + return *this; + } + + Quaternion& Quaternion::operator*=(const Quaternion& quat) { + *this = *this * quat; + + return *this; + } +} + +#endif diff --git a/src/bebone/core/types/matrix/matrix.tpp b/src/bebone/core/types/matrix/matrix.tpp new file mode 100644 index 00000000..d9c6faff --- /dev/null +++ b/src/bebone/core/types/matrix/matrix.tpp @@ -0,0 +1,93 @@ +#ifndef _BEBONE_CORE_TYPES_MATRIX_TPP_ +#define _BEBONE_CORE_TYPES_MATRIX_TPP_ + +#include "../vector/vector_types.h" +#include "../primitive_types.h" + +#include +#include +#include + +namespace bebone::core { + /** + * @brief Type that used as mathematical matrix + * + * @tparam T type of the matrix + * @tparam width width of the matrix + * @tparam height height of the matrix + */ + template + struct Matrix { + private: + /** + * @brief Raw matrix values + */ + T e[width][height]; + public: + T& operator()(const size_t& row, const size_t& col) { + return e[col][row]; + } + + const T& operator()(const size_t& row, const size_t& col) const { + return e[col][row]; + } + + /** + * @brief Method used to get string representation of object instance + * + * @return std::string string representation + */ + std::string to_string() const { + std::stringstream ss; + + for (i32 i = 0; i < width; ++i) { + for (i32 j = 0; j < height; ++j) { + ss << e[i][j] << " "; + } + ss << std::endl; + } + + return ss.str(); + } + }; + + /** + * @brief Puts string representation of the object to the out stream + * + * @param os - reference to the out stream + * @param mat - reference to the object instance + * + * @return std::ostream& reference to the stream instance + */ + template + std::ostream& operator<<(std::ostream& os, const Matrix& mat) { + for (i32 i = 0; i < width; ++i) { + for (i32 j = 0; j < height; ++j) { + os << mat.e[i][j] << " "; + } + } + + return os; + } + + /** + * @brief Constructs object from it string representation + * + * @param os - reference to the in stream + * @param mat - reference to the object instance + * + * @return std::istream& reference to the stream instance + */ + template + std::istream& operator>>(std::istream& os, const Matrix& mat) { + for (i32 i = 0; i < width; ++i) { + for (i32 j = 0; j < height; ++j) { + os >> mat.e[i][j]; + } + } + + return os; + } +} + +#endif diff --git a/src/bebone/core/types/matrix/matrix_2x2.cpp b/src/bebone/core/types/matrix/matrix_2x2.cpp new file mode 100644 index 00000000..e2615057 --- /dev/null +++ b/src/bebone/core/types/matrix/matrix_2x2.cpp @@ -0,0 +1,37 @@ +#include "matrix_2x2.h" + +namespace bebone::core { + Matrix::Matrix(const f32& n00, const f32& n01, + const f32& n10, const f32& n11) { + e[0][0] = n00; e[0][1] = n10; + e[1][0] = n01; e[1][1] = n11; + } + + Matrix::Matrix(const Vec2f& a, const Vec2f& b) { + e[0][0] = a.x; e[0][1] = a.y; + e[1][0] = b.x; e[1][1] = b.y; + } + + Matrix Matrix::get_rotation_matrix(const f32& angle) { + f32 c = std::cos(angle); + f32 s = std::sin(angle); + + return { + c, -s, + s, c + }; + } + + std::string Matrix::to_string() const { + std::stringstream ss; + + for (i32 i = 0; i < 2; ++i) { + for (auto j : e) { + ss << j[i] << " "; + } + ss << std::endl; + } + + return ss.str(); + } +} \ No newline at end of file diff --git a/src/bebone/core/types/matrix/matrix_2x2.h b/src/bebone/core/types/matrix/matrix_2x2.h new file mode 100644 index 00000000..ead34317 --- /dev/null +++ b/src/bebone/core/types/matrix/matrix_2x2.h @@ -0,0 +1,167 @@ +#ifndef _BEBONE_CORE_TYPES_MATRIX_2X2_TPP_ +#define _BEBONE_CORE_TYPES_MATRIX_2X2_TPP_ + +#include "matrix.tpp" + +namespace bebone::core { + template<> + struct Matrix { + private: + f32 e[2][2]; + public: + Matrix() = default; + + Matrix(const f32& n00, const f32& n01, + const f32& n10, const f32& n11); + + Matrix(const Vec2f& a, const Vec2f& b); + + inline Matrix transpose() const; + inline Matrix inverse() const; + + static Matrix get_rotation_matrix(const f32 &angle); + + inline f32& operator()(const size_t& row, const size_t& col); + inline const f32& operator()(const size_t& row, const size_t& col) const; + + inline Vec2f& operator[](const size_t& col); + inline const Vec2f& operator[](const size_t& col) const; + + inline Matrix operator +(const Matrix& other) const; + inline Matrix operator -(const Matrix& other) const; + inline Matrix operator *(const Matrix& other) const; + + inline Vec2f operator *(const Vec2f& v) const; + + inline Matrix operator +(const f32& scalar) const; + inline Matrix operator -(const f32& scalar) const; + inline Matrix operator *(const f32& scalar) const; + inline Matrix operator /(f32 scalar) const; + + inline bool operator ==(const Matrix& other) const; + + std::string to_string() const; + }; + + inline f32& Matrix::operator()(const size_t& row, const size_t& col) { + return e[col][row]; + } + + inline const f32& Matrix::operator()(const size_t& row, const size_t& col) const { + return e[col][row]; + } + + inline Vec2f& Matrix::operator[](const size_t& col) { + return (*reinterpret_cast(e[col])); + } + + inline const Vec2f& Matrix::operator[](const size_t& col) const { + return (*reinterpret_cast(e[col])); + } + + inline Matrix Matrix::operator +(const Matrix& other) const { + const Matrix& m = *this; + + return { + m(0, 0) + other(0, 0), m(0, 1) + other(0, 1), + m(1, 0) + other(1, 0), m (1, 1) + other(1, 1) + }; + } + + inline Matrix Matrix::operator -(const Matrix& other) const { + const Matrix& m = *this; + + return { + m(0, 0) - other(0, 0), m(0, 1) - other(0, 1), + m(1, 0) - other(1, 0), m(1, 1) - other(1, 1) + }; + } + + inline Matrix Matrix::operator *(const Matrix& other) const { + const Matrix& m = *this; + + return { + m(0, 0) * other(0, 0) + m(0, 1) * other(1, 0), + m(0, 0) * other(0, 1) + m(0, 1) * other(1, 1), + m(1, 0) * other(0, 0) + m(1, 1) * other(1, 0), + m(1, 0) * other(0, 1) + m(1, 1) * other(1, 1) + }; + } + + inline Vec2f Matrix::operator *(const Vec2f& v) const { + const Matrix& m = *this; + + return { + m(0, 0) * v.x + m(0, 1) * v.y, + m(1, 0) * v.x + m(1, 1) * v.y + }; + } + + inline Matrix Matrix::operator +(const f32& scalar) const { + const Matrix& m = *this; + + return { + m(0, 0) + scalar, m(0, 1) + scalar, + m(1, 0) + scalar, m(1, 1) + scalar + }; + } + + inline Matrix Matrix::operator -(const f32& scalar) const { + const Matrix& m = *this; + + return { + m(0, 0) - scalar, m(0, 1) - scalar, + m(1, 0) - scalar, m(1, 1) - scalar + }; + } + + inline Matrix Matrix::operator *(const f32& scalar) const { + const Matrix& m = *this; + + return { + m(0, 0) * scalar, m(0, 1) * scalar, + m(1, 0) * scalar, m(1, 1) * scalar + }; + } + + inline Matrix Matrix::operator /(f32 scalar) const { + const Matrix& m = *this; + scalar = 1.0f / scalar; + + return m * scalar; + } + + inline bool Matrix::operator ==(const Matrix& other) const { + const Matrix& m = *this; + + return m(0, 0) == other(0, 0) && m(0, 1) == other(0, 1) && + m(1, 0) == other(1, 0) && m(1, 1) == other(1, 1); + } + + inline Matrix Matrix::transpose() const { + const Matrix& m = *this; + + return { + m(0, 0), m(1, 0), + m(0, 1), m(1, 1) + }; + } + + inline Matrix Matrix::inverse() const { + const Matrix& m = *this; + + const f32& a = m(0, 0); + const f32& b = m(0, 1); + const f32& c = m(1, 0); + const f32& d = m(1, 1); + + f32 inv_det = 1.0f / (a * d - b * c); + + return { + d * inv_det, -b * inv_det, + -c * inv_det, a * inv_det + }; + } +} + +#endif diff --git a/src/bebone/core/types/matrix/matrix_3x3.cpp b/src/bebone/core/types/matrix/matrix_3x3.cpp new file mode 100644 index 00000000..e2f8c809 --- /dev/null +++ b/src/bebone/core/types/matrix/matrix_3x3.cpp @@ -0,0 +1,173 @@ +#include "matrix_3x3.h" + +namespace bebone::core { + Matrix::Matrix(const f32& n00, const f32& n01, const f32& n02, + const f32& n10, const f32& n11, const f32& n12, + const f32& n20, const f32& n21, const f32& n22) { + e[0][0] = n00; e[0][1] = n10; e[0][2] = n20; + e[1][0] = n01; e[1][1] = n11; e[1][2] = n21; + e[2][0] = n02; e[2][1] = n12; e[2][2] = n22; + } + + Matrix::Matrix(const Vec3f &a, const Vec3f &b, const Vec3f &c) { + e[0][0] = a.x; e[0][1] = a.y; e[0][2] = a.z; + e[1][0] = b.x; e[1][1] = b.y; e[1][2] = b.z; + e[2][0] = c.x; e[2][1] = c.y; e[2][2] = c.z; + } + + Matrix Matrix::get_rotation_x(const f32 &angle) { + f32 c = std::cos(angle); + f32 s = std::sin(angle); + + return { + 1.0f, 0.0f, 0.0f, + 0.0f, c, -s, + 0.0f, s, c + }; + } + + Matrix Matrix::get_rotation_y(const f32 &angle) { + f32 c = std::cos(angle); + f32 s = std::sin(angle); + + return { + c, 0.0f, s, + 0.0f, 1.0f, 0.0f, + -s, 0.0f, c + }; + } + + Matrix Matrix::get_rotation_z(const f32 &angle) { + f32 c = std::cos(angle); + f32 s = std::sin(angle); + + return { + c, -s, 0.0f, + s, c, 0.0f, + 0.0f, 0.0f, 1.0f + }; + } + + Matrix Matrix::get_rotation_matrix(const f32 &angle, Vec3f axis) { + axis = axis.normalize(); + + f32 c = std::cos(angle); + f32 s = std::sin(angle); + f32 d = 1.0f - c; + + f32 x = axis.x * d; + f32 y = axis.y * d; + f32 z = axis.z * d; + + f32 axay = x * axis.y; + f32 axaz = x * axis.z; + f32 ayaz = y * axis.z; + + return { + c + x * axis.x, axay - s * axis.z, axaz + s * axis.y, + axay + s * axis.z, c + y * axis.y, ayaz - s * axis.x, + axaz - s * axis.y, ayaz + s * axis.x, c + z * axis.z + }; + } + + Matrix Matrix::get_reflection_matrix(const Vec3f& v) { + f32 x = v.x * -2.0f; + f32 y = v.y * -2.0f; + f32 z = v.z * -2.0f; + f32 vxvy = x * v.y; + f32 vxvz = x * v.z; + f32 vyvz = y * v.z; + + return { + x * v.x + 1.0f, vxvy, vxvz, + vxvy, y * v.y + 1.0f, vyvz, + vxvz, vyvz, z * v.z + 1.0f + }; + } + + Matrix Matrix::get_involution_matrix(const Vec3f& v) { + f32 x = v.x * 2.0f; + f32 y = v.y * 2.0f; + f32 z = v.z * 2.0f; + f32 vxvy = x * v.y; + f32 vxvz = x * v.z; + f32 vyvz = y * v.z; + + return { + x * v.x - 1.0f, vxvy, vxvz, + vxvy, y * v.y - 1.0f, vyvz, + vxvz, vyvz, z * v.z - 1.0f + }; + } + + Matrix Matrix::scale(const f32& s) { + return { + s, 0.0f, 0.0f, + 0.0f, s, 0.0f, + 0.0f, 0.0f, s + }; + } + + Matrix Matrix::scale(const f32& sx, const f32& sy, const f32& sz) { + return { + sx, 0.0f, 0.0f, + 0.0f, sy, 0.0f, + 0.0f, 0.0f, sz + }; + } + + Matrix Matrix::scale(const Vec3f& s) { + return { + s.x, 0.0f, 0.0f, + 0.0f, s.y, 0.0f, + 0.0f, 0.0f, s.z + }; + } + + Matrix Matrix::scale(f32 s, Vec3f v) { + v = v.normalize(); + s -= 1.0f; + + f32 x = v.x * s; + f32 y = v.y * s; + f32 z = v.z * s; + f32 vxvy = x * v.y; + f32 vxvz = x * v.z; + f32 vyvz = y * v.z; + + return { + x * v.x + 1.0f, vxvy, vxvz, + vxvy, y * v.y + 1.0f, vyvz, + vxvz, vyvz, z * v.z + 1.0f + }; + } + + Matrix Matrix::skew(f32 t, Vec3f a, Vec3f b) { + t = std::tan(t); + a = a.normalize(); + b = b.normalize(); + + f32 x = a.x * t; + f32 y = a.y * t; + f32 z = a.z * t; + + return { + x * b.x + 1.0f, x * b.y, x * b.z, + y * b.x, y * b.y + 1.0f, y * b.z, + z * b.x, z * b.y, z * b.z + 1.0f + }; + } + + std::string Matrix::to_string() const { + std::stringstream ss; + + for (i32 i = 0; i < 3; ++i) { + for (i32 j = 0; j < 3; ++j) { + ss << e[j][i] << " "; + } + ss << std::endl; + } + + return ss.str(); + } +} \ No newline at end of file diff --git a/src/bebone/core/types/matrix/matrix_3x3.h b/src/bebone/core/types/matrix/matrix_3x3.h new file mode 100644 index 00000000..43d22fa4 --- /dev/null +++ b/src/bebone/core/types/matrix/matrix_3x3.h @@ -0,0 +1,198 @@ +#ifndef _BEBONE_CORE_TYPES_MATRIX_3X3_TPP_ +#define _BEBONE_CORE_TYPES_MATRIX_3X3_TPP_ + +#include "matrix.tpp" + +namespace bebone::core { + template<> + struct Matrix { + private: + f32 e[3][3]; + public: + Matrix() = default; + + Matrix(const f32& n00, const f32& n01, const f32& n02, + const f32& n10, const f32& n11, const f32& n12, + const f32& n20, const f32& n21, const f32& n22); + + Matrix(const Vec3f& a, const Vec3f& b, const Vec3f& c); + + inline Matrix transpose() const; + inline Matrix inverse() const; + + static Matrix get_rotation_x(const f32& angle); + static Matrix get_rotation_y(const f32& angle); + static Matrix get_rotation_z(const f32& angle); + static Matrix get_rotation_matrix(const f32& angle, Vec3f axis); + static Matrix get_reflection_matrix(const Vec3f& v); + static Matrix get_involution_matrix(const Vec3f& v); + + static Matrix skew(f32 t, Vec3f a, Vec3f b); + + static Matrix scale(const f32& s); + static Matrix scale(const f32& sx, const f32& sy, const f32& sz); + static Matrix scale(const Vec3f& s); + static Matrix scale(f32 s, Vec3f v); + + inline f32& operator()(const size_t& row, const size_t& col); + inline const f32& operator()(const size_t& row, const size_t& col) const; + + inline Vec3f& operator[](const size_t& col); + inline const Vec3f& operator[](const size_t& col) const; + + inline Matrix operator +(const Matrix& other) const; + inline Matrix operator -(const Matrix& other) const; + inline Matrix operator *(const Matrix& other) const; + + inline Vec3f operator *(const Vec3f& v) const; + + inline Matrix operator +(const f32& scalar) const; + inline Matrix operator -(const f32& scalar) const; + inline Matrix operator *(const f32& scalar) const; + inline Matrix operator /(f32 scalar) const; + + inline bool operator ==(const Matrix& other) const; + + std::string to_string() const; + }; + + inline f32& Matrix::operator()(const size_t& row, const size_t& col) { + return e[col][row]; + } + + inline const f32& Matrix::operator()(const size_t& row, const size_t& col) const { + return e[col][row]; + } + + inline Vec3f& Matrix::operator[](const size_t& col) { + return (*reinterpret_cast(e[col])); + } + + inline const Vec3f& Matrix::operator[](const size_t& col) const { + return (*reinterpret_cast(e[col])); + } + + inline Matrix Matrix::operator +(const Matrix& other) const { + const Matrix& m = *this; + + return { + m(0, 0) + other(0, 0), m(0, 1) + other(0, 1), m(0, 2) + other(0, 2), + m(1, 0) + other(1, 0), m(1, 1) + other(1, 1), m(1, 2) + other(1, 2), + m(2, 0) + other(2, 0), m(2, 1) + other(2, 1), m(2, 2) + other(2, 2) + }; + } + + inline Matrix Matrix::operator -(const Matrix& other) const { + const Matrix& m = *this; + + return { + m(0, 0) - other(0, 0), m(0, 1) - other(0, 1), m(0, 2) - other(0, 2), + m(1, 0) - other(1, 0), m(1, 1) - other(1, 1), m(1, 2) - other(1, 2), + m(2, 0) - other(2, 0), m(2, 1) - other(2, 1), m(2, 2) - other(2, 2) + }; + } + + inline Matrix Matrix::operator *(const Matrix& other) const { + const Matrix& m = *this; + + return { + m(0, 0) * other(0, 0) + m(0, 1) * other(1, 0) + m(0, 2) * other(2, 0), + m(0, 0) * other(0, 1) + m(0, 1) * other(1, 1) + m(0, 2) * other(2, 1), + m(0, 0) * other(0, 2) + m(0, 1) * other(1, 2) + m(0, 2) * other(2, 2), + + m(1, 0) * other(0, 0) + m(1, 1) * other(1, 0) + m(1, 2) * other(2, 0), + m(1, 0) * other(0, 1) + m(1, 1) * other(1, 1) + m(1, 2) * other(2, 1), + m(1, 0) * other(0, 2) + m(1, 1) * other(1, 2) + m(1, 2) * other(2, 2), + + m(2, 0) * other(0, 0) + m(2, 1) * other(1, 0) + m(2, 2) * other(2, 0), + m(2, 0) * other(0, 1) + m(2, 1) * other(1, 1) + m(2, 2) * other(2, 1), + m(2, 0) * other(0, 2) + m(2, 1) * other(1, 2) + m(2, 2) * other(2, 2) + }; + } + + inline Vec3f Matrix::operator *(const Vec3f& v) const { + const Matrix& m = *this; + + return { + m(0, 0) * v.x + m(0, 1) * v.y + m(0, 2) * v.z, + m(1, 0) * v.x + m(1, 1) * v.y + m(1, 2) * v.z, + m(2, 0) * v.x + m(2, 1) * v.y + m(2, 2) * v.z + }; + } + + inline Matrix Matrix::operator +(const f32& scalar) const { + const Matrix& m = *this; + + return { + m(0, 0) + scalar, m(0, 1) + scalar, m(0, 2) + scalar, + m(1, 0) + scalar, m(1, 1) + scalar, m(1, 2) + scalar, + m(2, 0) + scalar, m(2, 1) + scalar, m(2, 2) + scalar + }; + } + + inline Matrix Matrix::operator -(const f32& scalar) const { + const Matrix& m = *this; + + return { + m(0, 0) - scalar, m(0, 1) - scalar, m(0, 2) - scalar, + m(1, 0) - scalar, m(1, 1) - scalar, m(1, 2) - scalar, + m(2, 0) - scalar, m(2, 1) - scalar, m(2, 2) - scalar + }; + } + + inline Matrix Matrix::operator *(const f32& scalar) const { + const Matrix& m = *this; + + return { + m(0, 0) * scalar, m(0, 1) * scalar, m(0, 2) * scalar, + m(1, 0) * scalar, m(1, 1) * scalar, m(1, 2) * scalar, + m(2, 0) * scalar, m(2, 1) * scalar, m(2, 2) * scalar + }; + } + + inline Matrix Matrix::operator /(f32 scalar) const { + const Matrix& m = *this; + scalar = 1.0f / scalar; + + return m * scalar; + } + + inline bool Matrix::operator ==(const Matrix& other) const { + const Matrix& m = *this; + + return m(0, 0) == other(0, 0) && m(0, 1) == other(0, 1) && m(0, 2) == other(0, 2) && + m(1, 0) == other(1, 0) && m(1, 1) == other(1, 1) && m(1, 2) == other(1, 2) && + m(2, 0) == other(2, 0) && m(2, 1) == other(2, 1) && m(2, 2) == other(2, 2); + } + + inline Matrix Matrix::transpose() const { + const Matrix& m = *this; + + return { + m(0, 0), m(1, 0), m(2, 0), + m(0, 1), m(1, 1), m(2, 1), + m(0, 2), m(1, 2), m(2, 2) + }; + } + + inline Matrix Matrix::inverse() const { + const Matrix& m = *this; + + const Vec3f& a = m[0]; + const Vec3f& b = m[1]; + const Vec3f& c = m[2]; + + Vec3f r0 = Vec3f::cross(b, c); + Vec3f r1 = Vec3f::cross(c, a); + Vec3f r2 = Vec3f::cross(a, b); + f32 inv_det = 1.0f / Vec3f::dot(r2, c); + + return { + r0.x * inv_det, r0.y * inv_det, r0.z * inv_det, + r1.x * inv_det, r1.y * inv_det, r1.z * inv_det, + r2.x * inv_det, r2.y * inv_det, r2.z * inv_det + }; + } +} + +#endif diff --git a/src/bebone/core/types/matrix/matrix_4x4.cpp b/src/bebone/core/types/matrix/matrix_4x4.cpp new file mode 100644 index 00000000..608f1ac7 --- /dev/null +++ b/src/bebone/core/types/matrix/matrix_4x4.cpp @@ -0,0 +1,299 @@ +#include "matrix_4x4.h" + +namespace bebone::core { + Matrix::Matrix(const f32& n00, const f32& n01, const f32& n02, const f32& n03, + const f32& n10, const f32& n11, const f32& n12, const f32& n13, + const f32& n20, const f32& n21, const f32& n22, const f32& n23, + const f32& n30, const f32& n31, const f32& n32, const f32& n33) { + e[0][0] = n00; e[0][1] = n10; e[0][2] = n20; e[0][3] = n30; + e[1][0] = n01; e[1][1] = n11; e[1][2] = n21; e[1][3] = n31; + e[2][0] = n02; e[2][1] = n12; e[2][2] = n22; e[2][3] = n32; + e[3][0] = n03; e[3][1] = n13; e[3][2] = n23; e[3][3] = n33; + } + + Matrix::Matrix(const Vec4f &a, const Vec4f &b, const Vec4f &c, const Vec4f& d) { + e[0][0] = a.x; e[0][1] = a.y; e[0][2] = a.z; e[0][3] = a.w; + e[1][0] = b.x; e[1][1] = b.y; e[1][2] = b.z; e[1][3] = b.w; + e[2][0] = c.x; e[2][1] = c.y; e[2][2] = c.z; e[2][3] = c.w; + e[3][0] = d.x; e[3][1] = d.y; e[3][2] = d.z; e[3][3] = c.w; + } + + const f32* Matrix::get_raw() const { + return &e[0][0]; + } + + Matrix Matrix::get_rotation_x(const f32& angle) { + f32 c = std::cos(angle); + f32 s = std::sin(angle); + + return { + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, c, -s, 0.0f, + 0.0f, s, c, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }; + } + + Matrix Matrix::get_rotation_y(const f32& angle) { + f32 c = std::cos(angle); + f32 s = std::sin(angle); + + return { + c, 0.0f, s, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + -s, 0.0f, c, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }; + } + + Matrix Matrix::get_rotation_z(const f32& angle) { + f32 c = std::cos(angle); + f32 s = std::sin(angle); + + return { + c, -s, 0.0f, 0.0f, + s, c, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }; + } + + Matrix Matrix::get_rotation_matrix(const f32& angle, Vec3f axis) { + axis = axis.normalize(); + + f32 c = std::cos(angle); + f32 s = std::sin(angle); + f32 d = 1.0f - c; + + f32 x = axis.x * d; + f32 y = axis.y * d; + f32 z = axis.z * d; + + f32 axay = x * axis.y; + f32 axaz = x * axis.z; + f32 ayaz = y * axis.z; + + return { + c + x * axis.x, axay - s * axis.z, axaz + s * axis.y, 0.0f, + axay + s * axis.z, c + y * axis.y, ayaz - s * axis.x, 0.0f, + axaz - s * axis.y, ayaz + s * axis.x, c + z * axis.z, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }; + } + + Matrix Matrix::get_reflection_matrix(const Vec3f& v) { + f32 x = v.x * -2.0f; + f32 y = v.y * -2.0f; + f32 z = v.z * -2.0f; + f32 vxvy = x * v.y; + f32 vxvz = x * v.z; + f32 vyvz = y * v.z; + + return { + x * v.x + 1.0f, vxvy, vxvz, 0.0f, + vxvy, y * v.y + 1.0f, vyvz, 0.0f, + vxvz, vyvz, z * v.z + 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }; + } + + Matrix Matrix::get_involution_matrix(const Vec3f& v) { + f32 x = v.x * -2.0f; + f32 y = v.y * -2.0f; + f32 z = v.z * -2.0f; + f32 vxvy = x * v.y; + f32 vxvz = x * v.z; + f32 vyvz = y * v.z; + + return { + x * v.x - 1.0f, vxvy, vxvz, 0.0f, + vxvy, y * v.y - 1.0f, vyvz, 0.0f, + vxvz, vyvz, z * v.z - 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }; + } + + Matrix Matrix::skew(f32 t, Vec3f a, Vec3f b) { + t = std::tan(t); + a = a.normalize(); + b = b.normalize(); + + f32 x = a.x * t; + f32 y = a.y * t; + f32 z = a.z * t; + + return { + x * b.x + 1.0f, x * b.y, x * b.z, 0.0f, + y * b.x, y * b.y + 1.0f, y * b.z, 0.0f, + z * b.x, z * b.y, z * b.z + 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }; + } + + Matrix Matrix::scale(const f32& s) { + return { + s, 0.0f, 0.0f, 0.0f, + 0.0f, s, 0.0f, 0.0f, + 0.0f, 0.0f, s, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }; + } + + Matrix Matrix::scale(const f32& sx, const f32& sy, const f32& sz) { + return { + sx, 0.0f, 0.0f, 0.0f, + 0.0f, sy, 0.0f, 0.0f, + 0.0f, 0.0f, sz, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }; + } + + Matrix Matrix::scale(const Vec3f& s) { + return { + s.x, 0.0f, 0.0f, 0.0f, + 0.0f, s.y, 0.0f, 0.0f, + 0.0f, 0.0f, s.z, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }; + } + + Matrix Matrix::scale(f32 s, Vec3f v) { + v = v.normalize(); + s -= 1.0f; + + f32 x = v.x * s; + f32 y = v.y * s; + f32 z = v.z * s; + f32 vxvy = x * v.y; + f32 vxvz = x * v.z; + f32 vyvz = y * v.z; + + return { + x * v.x + 1.0f, vxvy, vxvz, 0.0f, + vxvy, y * v.y + 1.0f, vyvz, 0.0f, + vxvz, vyvz, z * v.z + 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }; + } + + std::string Matrix::to_string() const { + std::stringstream ss; + + for (int i = 0; i < 4; ++i) { + for (int j = 0; j < 4; ++j) { + ss << (*this)(i, j) << " "; + } + + ss << std::endl; + } + + return ss.str(); + } + + Matrix Matrix::translation(const f32& tx, const f32& ty, const f32& tz) { + return { + 1.0f, 0.0f, 0.0f, tx, + 0.0f, 1.0f, 0.0f, ty, + 0.0f, 0.0f, 1.0f, tz, + 0.0f, 0.0f, 0.0f, 1.0f + }; + } + + Matrix Matrix::translation(const Vec3f& t) { + return { + 1.0f, 0.0f, 0.0f, t.x, + 0.0f, 1.0f, 0.0f, t.y, + 0.0f, 0.0f, 1.0f, t.z, + 0.0f, 0.0f, 0.0f, 1.0f + }; + } + + Matrix Matrix::orthographic(const f32& right, const f32& left, const f32& bottom, const f32& top, const f32& near, const f32& far) { + return { + 2.0f / (right - left), 0.0f, 0.0f, -(right + left) / (right - left), + 0.0f, 2.0f / (bottom - top), 0.0f, -(bottom + top) / (top - bottom), + 0.0f, 0.0f, 2.0f / (far - near), -(far + near) / (far - near), + 0.0f, 0.0f, 0.0f, 1.0f + }; + } + + /* + Matrix Matrix::perspective(f32 fov, const f32& aspect, const f32& near, const f32& far) { + fov = 1.0f / std::tan(fov / 2.0f); + f32 normalization = far / (far - near); + + return { + 1.0f / aspect * fov, 0.0f, 0.0f, 0.0f, + 0.0f, -fov, 0.0f, 0.0f, + 0.0f, 0.0f, normalization, -normalization * near, + 0.0f, 0.0f, 1.0f, 0.0f + }; + } + */ + + Matrix Matrix::perspective + ( + f32 fovy, + const f32 & aspect, + const f32 & zNear, + const f32 & zFar + ) + { + f32 const rad = fovy; + f32 const tanHalfFovy = tan(rad / static_cast(2)); + + auto Result = Matrix::splat(0); + Result.e[0][0] = static_cast(1) / (aspect * tanHalfFovy); + Result.e[1][1] = static_cast(1) / (tanHalfFovy); + Result.e[2][2] = - (zFar + zNear) / (zFar - zNear); + Result.e[2][3] = - static_cast(1); + Result.e[3][2] = - (static_cast(2) * zFar * zNear) / (zFar - zNear); + return Result; + } + + Matrix Matrix::view(const Vec3f& origin, const Vec3f& direction, const Vec3f& up) { + Vec3f zaxis = direction.normalize(); + Vec3f xaxis = Vec3f::cross(up, zaxis).normalize(); + Vec3f yaxis = Vec3f::cross(zaxis, xaxis); + + return { + xaxis.x, xaxis.y, xaxis.z, -Vec3f::dot(xaxis, origin), + yaxis.x, yaxis.y, yaxis.z, -Vec3f::dot(yaxis, origin), + zaxis.x, zaxis.y, zaxis.z, -Vec3f::dot(zaxis, origin), + 0.0f, 0.0f, 0.0f, 1.0f + }; + } + +#if 1 + Matrix Matrix::look_at + ( + Vec3f const & eye, + Vec3f const & center, + Vec3f const & up + ) +{ + Vec3f const f((center - eye).normalize()); + Vec3f const s(Vec3f::cross(f, up).normalize()); + Vec3f const u(Vec3f::cross(s, f)); + + auto Result = Matrix::identity(); + Result.e[0][0] = s.x; + Result.e[1][0] = s.y; + Result.e[2][0] = s.z; + Result.e[0][1] = u.x; + Result.e[1][1] = u.y; + Result.e[2][1] = u.z; + Result.e[0][2] =-f.x; + Result.e[1][2] =-f.y; + Result.e[2][2] =-f.z; + Result.e[3][0] = - Vec3f::dot(s, eye); + Result.e[3][1] = - Vec3f::dot(u, eye); + Result.e[3][2] = Vec3f::dot(f, eye); + return Result; +} +#else + Matrix Matrix::look_at(const Vec3f& origin, const Vec3f& center, const Vec3f& up) { + return view(origin, center - origin, up); + } +#endif +} \ No newline at end of file diff --git a/src/bebone/core/types/matrix/matrix_4x4.h b/src/bebone/core/types/matrix/matrix_4x4.h new file mode 100644 index 00000000..f62fa324 --- /dev/null +++ b/src/bebone/core/types/matrix/matrix_4x4.h @@ -0,0 +1,268 @@ +#ifndef _BEBONE_CORE_TYPES_MATRIX_4X4_TPP_ +#define _BEBONE_CORE_TYPES_MATRIX_4X4_TPP_ + +#include "matrix.tpp" + +namespace bebone::core { + template<> + struct Matrix { + public: + f32 e[4][4]; + + public: + Matrix() = default; + + Matrix(const f32& n00, const f32& n01, const f32& n02, const f32& n03, + const f32& n10, const f32& n11, const f32& n12, const f32& n13, + const f32& n20, const f32& n21, const f32& n22, const f32& n23, + const f32& n30, const f32& n31, const f32& n32, const f32& n33); + + Matrix(const Vec4f& a, const Vec4f& b, const Vec4f& c, const Vec4f& d); + + inline static Matrix splat(const f32& value); + inline static Matrix identity(); + + static Matrix get_rotation_x(const f32& angle); + static Matrix get_rotation_y(const f32& angle); + static Matrix get_rotation_z(const f32& angle); + static Matrix get_rotation_matrix(const f32& angle, Vec3f axis); + static Matrix get_reflection_matrix(const Vec3f& v); + static Matrix get_involution_matrix(const Vec3f& v); + + static Matrix skew(f32 t, Vec3f a, Vec3f b); + + static Matrix scale(const f32& s); + static Matrix scale(const f32& sx, const f32& sy, const f32& sz); + static Matrix scale(const Vec3f& s); + static Matrix scale(f32 s, Vec3f v); + + static Matrix translation(const f32& tx, const f32& ty, const f32& tz); + static Matrix translation(const Vec3f& t); + + static Matrix orthographic(const f32& right, const f32& left, const f32& bottom, const f32& top, const f32& near, const f32& far); + static Matrix perspective(f32 fov, const f32& aspect, const f32& near, const f32& far); + static Matrix view(const Vec3f& origin, const Vec3f& direction, const Vec3f& up = Vec3f::up); + static Matrix look_at(const Vec3f& origin, const Vec3f& center, const Vec3f& up = Vec3f::up); + + [[nodiscard]] inline Matrix transpose() const; + [[nodiscard]] inline Matrix inverse() const; + + inline f32& operator()(const size_t& row, const size_t& col); + inline const f32& operator()(const size_t& row, const size_t& col) const; + + inline Vec4f& operator[](const size_t& col); + inline const Vec4f& operator[](const size_t& col) const; + + inline Matrix operator +(const Matrix& other) const; + inline Matrix operator -(const Matrix& other) const; + inline Matrix operator *(const Matrix& other) const; + inline Vec4f operator *(const Vec4f& v) const; + + inline Matrix operator+(const f32& scalar) const; + inline Matrix operator-(const f32& scalar) const; + inline Matrix operator*(const f32& scalar) const; + inline Matrix operator/(f32 scalar) const; + + inline bool operator==(const Matrix& other) const; + inline bool operator!=(const Matrix& other) const; + + [[nodiscard]] std::string to_string() const; + [[nodiscard]] const f32* get_raw() const; + }; + + inline Matrix Matrix::splat(const f32& value) { + return { + value, value, value, value, + value, value, value, value, + value, value, value, value, + value, value, value, value + }; + } + + inline Matrix Matrix::identity() { + return { + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }; + } + + inline Matrix Matrix::transpose() const { + const Matrix& m = *this; + + return { + m(0, 0), m(1, 0), m(2, 0), m(3, 0), + m(0, 1), m(1, 1), m(2, 1), m(3, 1), + m(0, 2), m(1, 2), m(2, 2), m(3, 2), + m(0, 3), m(1, 3), m(2, 3), m(3, 3) + }; + } + + inline Matrix Matrix::inverse() const { + const Matrix& m = *this; + + const Vec3f& a = reinterpret_cast(m[0]); + const Vec3f& b = reinterpret_cast(m[1]); + const Vec3f& c = reinterpret_cast(m[2]); + const Vec3f& d = reinterpret_cast(m[3]); + + const f32& x = m(3, 0); + const f32& y = m(3, 1); + const f32& z = m(3, 2); + const f32& w = m(3, 3); + + Vec3f s = Vec3f::cross(a, b); + Vec3f t = Vec3f::cross(c, d); + Vec3f u = a * y - b * x; + Vec3f v = c * w - d * z; + + f32 inv_det = 1.0f / (Vec3f::dot(s, v) + Vec3f::dot(t, u)); + s *= inv_det; + t *= inv_det; + u *= inv_det; + v *= inv_det; + + Vec3f r0 = Vec3f::cross(b, v) + t * y; + Vec3f r1 = Vec3f::cross(v, a) - t * x; + Vec3f r2 = Vec3f::cross(d, u) + s * w; + Vec3f r3 = Vec3f::cross(u, c) - s * z; + + return { + r0.x, r0.y, r0.z, Vec3f::dot(-b, t), + r1.x, r1.y, r1.z, Vec3f::dot(a, t), + r2.x, r2.y, r2.z, Vec3f::dot(-d, s), + r3.x, r3.y, r3.z, Vec3f::dot(c, s) + }; + } + + inline f32& Matrix::operator()(const size_t& row, const size_t& col) { + return e[col][row]; + } + + inline const f32& Matrix::operator()(const size_t& row, const size_t& col) const { + return e[col][row]; + } + + inline Vec4f& Matrix::operator[](const size_t& col) { + return (*reinterpret_cast(e[col])); + } + + inline const Vec4f& Matrix::operator[](const size_t& col) const { + return (*reinterpret_cast(e[col])); + } + + inline Matrix Matrix::operator +(const Matrix& other) const { + const Matrix& m = *this; + + return { + m(0, 0) + other(0, 0), m(0, 1) + other(0, 1), m(0, 2) + other(0, 2), m(0, 3) + other(0, 3), + m(1, 0) + other(1, 0), m(1, 1) + other(1, 1), m(1, 2) + other(1, 2), m(1, 3) + other(1, 3), + m(2, 0) + other(2, 0), m(2, 1) + other(2, 1), m(2, 2) + other(2, 2), m(2, 3) + other(2, 3), + m(3, 0) + other(3, 0), m(3, 1) + other(3, 1), m(3, 2) + other(3, 2), m(3, 3) + other(3, 3) + }; + } + + inline Matrix Matrix::operator -(const Matrix& other) const { + const Matrix& m = *this; + + return { + m(0, 0) - other(0, 0), m(0, 1) - other(0, 1), m(0, 2) - other(0, 2), m(0, 3) - other(0, 3), + m(1, 0) - other(1, 0), m(1, 1) - other(1, 1), m(1, 2) - other(1, 2), m(1, 3) - other(1, 3), + m(2, 0) - other(2, 0), m(2, 1) - other(2, 1), m(2, 2) - other(2, 2), m(2, 3) - other(2, 3), + m(3, 0) - other(3, 0), m(3, 1) - other(3, 1), m(3, 2) - other(3, 2), m(3, 3) - other(3, 3) + }; + } + + inline Matrix Matrix::operator *(const Matrix& other) const { + const Matrix& m = *this; + + return { + m(0, 0) * other(0, 0) + m(0, 1) * other(1, 0) + m(0, 2) * other(2, 0) + m(0, 3) * other(3, 0), + m(0, 0) * other(0, 1) + m(0, 1) * other(1, 1) + m(0, 2) * other(2, 1) + m(0, 3) * other(3, 1), + m(0, 0) * other(0, 2) + m(0, 1) * other(1, 2) + m(0, 2) * other(2, 2) + m(0, 3) * other(3, 2), + m(0, 0) * other(0, 3) + m(0, 1) * other(1, 3) + m(0, 2) * other(2, 3) + m(0, 3) * other(3, 3), + + m(1, 0) * other(0, 0) + m(1, 1) * other(1, 0) + m(1, 2) * other(2, 0) + m(1, 3) * other(3, 0), + m(1, 0) * other(0, 1) + m(1, 1) * other(1, 1) + m(1, 2) * other(2, 1) + m(1, 3) * other(3, 1), + m(1, 0) * other(0, 2) + m(1, 1) * other(1, 2) + m(1, 2) * other(2, 2) + m(1, 3) * other(3, 2), + m(1, 0) * other(0, 3) + m(1, 1) * other(1, 3) + m(1, 2) * other(2, 3) + m(1, 3) * other(3, 3), + + m(2, 0) * other(0, 0) + m(2, 1) * other(1, 0) + m(2, 2) * other(2, 0) + m(2, 3) * other(3, 0), + m(2, 0) * other(0, 1) + m(2, 1) * other(1, 1) + m(2, 2) * other(2, 1) + m(2, 3) * other(3, 1), + m(2, 0) * other(0, 2) + m(2, 1) * other(1, 2) + m(2, 2) * other(2, 2) + m(2, 3) * other(3, 2), + m(2, 0) * other(0, 3) + m(2, 1) * other(1, 3) + m(2, 2) * other(2, 3) + m(2, 3) * other(3, 3), + + m(3, 0) * other(0, 0) + m(3, 1) * other(1, 0) + m(3, 2) * other(2, 0) + m(3, 3) * other(3, 0), + m(3, 0) * other(0, 1) + m(3, 1) * other(1, 1) + m(3, 2) * other(2, 1) + m(3, 3) * other(3, 1), + m(3, 0) * other(0, 2) + m(3, 1) * other(1, 2) + m(3, 2) * other(2, 2) + m(3, 3) * other(3, 2), + m(3, 0) * other(0, 3) + m(3, 1) * other(1, 3) + m(3, 2) * other(2, 3) + m(3, 3) * other(3, 3) + }; + } + + inline Vec4f Matrix::operator *(const Vec4f& v) const { + const Matrix& m = *this; + + return { + m(0, 0) * v.x + m(0, 1) * v.y + m(0, 2) * v.z + m(0, 3) * v.w, + m(1, 0) * v.x + m(1, 1) * v.y + m(1, 2) * v.z + m(1, 3) * v.w, + m(2, 0) * v.x + m(2, 1) * v.y + m(2, 2) * v.z + m(2, 3) * v.w, + m(3, 0) * v.x + m(3, 1) * v.y + m(3, 2) * v.z + m(3, 3) * v.w + }; + } + + inline Matrix Matrix::operator*(const f32& scalar) const { + Matrix m = *this; + + return { + m(0, 0) * scalar, m(0, 1) * scalar, m(0, 2) * scalar, m(0, 3) * scalar, + m(1, 0) * scalar, m(1, 1) * scalar, m(1, 2) * scalar, m(1, 3) * scalar, + m(2, 0) * scalar, m(2, 1) * scalar, m(2, 2) * scalar, m(2, 3) * scalar, + m(3, 0) * scalar, m(3, 1) * scalar, m(3, 2) * scalar, m(3, 3) * scalar + }; + } + + inline Matrix Matrix::operator/(f32 scalar) const { + Matrix m = *this; + scalar = 1.0f / scalar; + + return m * scalar; + } + + inline Matrix Matrix::operator+(const f32& scalar) const { + Matrix m = *this; + + return { + m(0, 0) + scalar, m(0, 1) + scalar, m(0, 2) + scalar, m(0, 3) + scalar, + m(1, 0) + scalar, m(1, 1) + scalar, m(1, 2) + scalar, m(1, 3) + scalar, + m(2, 0) + scalar, m(2, 1) + scalar, m(2, 2) + scalar, m(2, 3) + scalar, + m(3, 0) + scalar, m(3, 1) + scalar, m(3, 2) + scalar, m(3, 3) + scalar + }; + } + + inline Matrix Matrix::operator-(const f32& scalar) const { + Matrix m = *this; + + return { + m(0, 0) - scalar, m(0, 1) - scalar, m(0, 2) - scalar, m(0, 3) - scalar, + m(1, 0) - scalar, m(1, 1) - scalar, m(1, 2) - scalar, m(1, 3) - scalar, + m(2, 0) - scalar, m(2, 1) - scalar, m(2, 2) - scalar, m(2, 3) - scalar, + m(3, 0) - scalar, m(3, 1) - scalar, m(3, 2) - scalar, m(3, 3) - scalar + }; + } + + inline bool Matrix::operator==(const Matrix& other) const { + Matrix m = *this; + + return m(0, 0) == other(0, 0) && m(0, 1) == other(0, 1) && m(0, 2) == other(0, 2) && m(0, 3) == other(0, 3) && + m(1, 0) == other(1, 0) && m(1, 1) == other(1, 1) && m(1, 2) == other(1, 2) && m(1, 3) == other(1, 3) && + m(2, 0) == other(2, 0) && m(2, 1) == other(2, 1) && m(2, 2) == other(2, 2) && m(2, 3) == other(2, 3) && + m(3, 0) == other(3, 0) && m(3, 1) == other(3, 1) && m(3, 2) == other(3, 2) && m(3, 3) == other(3, 3); + } + + inline bool Matrix::operator!=(const Matrix& other) const { + return !(*this == other); + } +} + +#endif diff --git a/src/bebone/core/types/matrix/matrix_types.h b/src/bebone/core/types/matrix/matrix_types.h new file mode 100644 index 00000000..3335bbcf --- /dev/null +++ b/src/bebone/core/types/matrix/matrix_types.h @@ -0,0 +1,21 @@ +#ifndef _BEBONE_CORE_TYPES_MATRIX_TYPES_H_ +#define _BEBONE_CORE_TYPES_MATRIX_TYPES_H_ + +#include "matrix.tpp" + +#include "matrix_2x2.h" +#include "matrix_3x3.h" +#include "matrix_4x4.h" + +namespace bebone::core { + using Matrix2x2f = Matrix; + using Mat2f = Matrix2x2f; + + using Matrix3x3f = Matrix; + using Mat3f = Matrix3x3f; + + using Matrix4x4f = Matrix; + using Mat4f = Matrix4x4f; +} + +#endif diff --git a/src/bebone/core/types/primitive_types.h b/src/bebone/core/types/primitive_types.h new file mode 100644 index 00000000..08e17764 --- /dev/null +++ b/src/bebone/core/types/primitive_types.h @@ -0,0 +1,24 @@ +#ifndef _BEBONE_CORE_TYPES_PRIMITIVE_TYPES_H_ +#define _BEBONE_CORE_TYPES_PRIMITIVE_TYPES_H_ + +#include +#include + +namespace bebone::core { + using u8 = uint8_t; + using u16 = uint16_t; + using u32 = uint32_t; + using u64 = uint64_t; + + using i8 = int8_t; + using i16 = int16_t; + using i32 = int32_t; + using i64 = int64_t; + + using f32 = float; + using f64 = double; +} + +#define BEBONE_PI (f32) 3.14159265359f + +#endif diff --git a/src/bebone/core/types/types.h b/src/bebone/core/types/types.h new file mode 100644 index 00000000..cb56a678 --- /dev/null +++ b/src/bebone/core/types/types.h @@ -0,0 +1,20 @@ +#ifndef _BEBONE_CORE_TYPES_H_ +#define _BEBONE_CORE_TYPES_H_ + +#include "primitive_types.h" + +#include "vector/vector_types.h" +#include "matrix/matrix_types.h" + +#include "uuid/uuid.h" + +#include "complex/quaternion.tpp" + +#include "color/colors.h" + +#include "utils/proper_euler_angles.h" +#include "utils/trait_bryan_angles.h" +#include "utils/interpolation.tpp" +#include "utils/rodrigues_rotation.h" + +#endif diff --git a/src/bebone/core/types/utils/interpolation.tpp b/src/bebone/core/types/utils/interpolation.tpp new file mode 100644 index 00000000..99baa124 --- /dev/null +++ b/src/bebone/core/types/utils/interpolation.tpp @@ -0,0 +1,35 @@ +#ifndef _BEBONE_CORE_TYPES_INTERPOLATION_TPP_ +#define _BEBONE_CORE_TYPES_INTERPOLATION_TPP_ + +#include "../primitive_types.h" + +namespace bebone::core { + template + inline T clamp(const T& value, const T& min_value, const T& max_value) { + if(value < min_value) return min_value; + if(value > max_value) return max_value; + + return value; + } + + template + inline T lerp(const T& start, const T& finish, const f32& t) { + return (finish * t) + start * (1.0f - t); + } + + template + inline T cubic_interpolate(const T& start, const T& finish, const f32& t) { + return (finish - start) * (3.0 - t * 2.0) * t * t + start; + } + + template + inline T smoothstep(const T& start, const T& finish, const f32& t) { + const f32 v1 = t * t; + const f32 v2 = 1.0f - (1.0f - t) * (1.0f - t); + const f32 new_t = lerp(v1, v2, t); + + return lerp(start, finish, new_t); + } +} + +#endif diff --git a/src/bebone/core/types/utils/proper_euler_angles.h b/src/bebone/core/types/utils/proper_euler_angles.h new file mode 100644 index 00000000..73093684 --- /dev/null +++ b/src/bebone/core/types/utils/proper_euler_angles.h @@ -0,0 +1,104 @@ +#ifndef _BEBONE_CORE_TYPES_PROPER_EULER_ANGLES_ +#define _BEBONE_CORE_TYPES_PROPER_EULER_ANGLES_ + +#include "../matrix/matrix_4x4.h" + +namespace bebone::core { + static inline Matrix proper_euler_angle_xzx(const Vec3f& rotation) { + const f32 c3 = std::cos(rotation.z); + const f32 s3 = std::sin(rotation.z); + const f32 c2 = std::cos(rotation.x); + const f32 s2 = std::sin(rotation.x); + const f32 c1 = std::cos(rotation.y); + const f32 s1 = std::sin(rotation.y); + + return { + c2, -c3*s2, s2*s3, 0.0f, + c1*s2, c1*c2*c3 - s1*s3, -c3*s1 - c1*c2*s3, 0.0f, + s1*s2, c1*s3 + c2*c3*s1, c1*c3 - c2*s1*s3, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }; + } + + static inline Matrix proper_euler_angle_xyx(const Vec3f& rotation) { + const f32 c3 = std::cos(rotation.z); + const f32 s3 = std::sin(rotation.z); + const f32 c2 = std::cos(rotation.x); + const f32 s2 = std::sin(rotation.x); + const f32 c1 = std::cos(rotation.y); + const f32 s1 = std::sin(rotation.y); + + return { + c2, s2*s3, c3*s2, 0.0f, + -s1*s2, c1*c3 - c2*s1*s3, -c1*s3 - c2*c3*s1, 0.0f, + -c1*s2, c3*s1 + c1*c2*s3, c1*c2*c3 - s1*s3, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }; + } + + static inline Matrix proper_euler_angle_yxy(const Vec3f& rotation) { + const f32 c3 = std::cos(rotation.z); + const f32 s3 = std::sin(rotation.z); + const f32 c2 = std::cos(rotation.x); + const f32 s2 = std::sin(rotation.x); + const f32 c1 = std::cos(rotation.y); + const f32 s1 = std::sin(rotation.y); + + return { + c1*c3 - c2*s1*s3, s1*s2, c1*s3 + c2*c3*s1, 0.0f, + s2*s3, c2, -c3*s2, 0.0f, + -c3*s1 - c1*c2*s3, c1*s2, c1*c2*c3 - s1*s3, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }; + } + + static inline Matrix proper_euler_angle_yzy(const Vec3f& rotation) { + const f32 c3 = std::cos(rotation.z); + const f32 s3 = std::sin(rotation.z); + const f32 c2 = std::cos(rotation.x); + const f32 s2 = std::sin(rotation.x); + const f32 c1 = std::cos(rotation.y); + const f32 s1 = std::sin(rotation.y); + + return { + c1*c2*c3 - s1*s2, -c1*s3, c3*s1 + c1*c2*s3, 0.0f, + c3*s2, c2, s2*s3, 0.0f, + -c1*s3 - c2*c3*s1, s1*s2, c1*c3 - c2*s1*s3, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }; + } + + static inline Matrix proper_euler_angle_zyz(const Vec3f& rotation) { + const f32 c3 = std::cos(rotation.z); + const f32 s3 = std::sin(rotation.z); + const f32 c2 = std::cos(rotation.x); + const f32 s2 = std::sin(rotation.x); + const f32 c1 = std::cos(rotation.y); + const f32 s1 = std::sin(rotation.y); + + return { + c1*c2*c3 - s1*s3, -c3*s1 - c1*c2*s3, c1*s2, 0.0f, + c1*s3 + c2*c3*s1, c1*c3 - c2*s1*s3, s1*s2, 0.0f, + -c3*s2, s2*s3, c2, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }; + } + + static inline Matrix proper_euler_angle_zxz(const Vec3f& rotation) { + const f32 c3 = std::cos(rotation.z); + const f32 s3 = std::sin(rotation.z); + const f32 c2 = std::cos(rotation.x); + const f32 s2 = std::sin(rotation.x); + const f32 c1 = std::cos(rotation.y); + const f32 s1 = std::sin(rotation.y); + + return { + c1*c3 - c2*s1*s3, -c1*s3 - c2*c3*s1, s1*s2, 0.0f, + c3*s1 + c1*c2*s3, c1*c2*c3 - s1*s3, -c1*s2, 0.0f, + s2*s3, c3*s2, c2, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }; + } +} + +#endif diff --git a/src/bebone/core/types/utils/rodrigues_rotation.h b/src/bebone/core/types/utils/rodrigues_rotation.h new file mode 100644 index 00000000..9f262927 --- /dev/null +++ b/src/bebone/core/types/utils/rodrigues_rotation.h @@ -0,0 +1,40 @@ +#ifndef _BEBONE_CORE_TYPES_RODRIGUES_ROTATION_ +#define _BEBONE_CORE_TYPES_RODRIGUES_ROTATION_ + +#include "interpolation.tpp" +#include "../matrix/matrix_4x4.h" + +namespace bebone::core { + static inline Matrix rodrigues_rotation(const Vec3f& front, const Vec3f& target) { + const auto front_norm = front.normalize(); + const auto target_norm = target.normalize(); + + auto axis = Vec3f::cross(front_norm, target_norm); + const auto dot = Vec3f::dot(front_norm, target_norm); + const auto angle = std::acos(bebone::core::clamp(dot, -1.0f, 1.0f)); + + if (axis.x != 0 || axis.y != 0 || axis.z != 0) { + axis = axis.normalize(); + } else { + if (dot > 0) + return Matrix::identity(); + + axis = {1, 0, 0}; + } + + const auto c = std::cos(angle); + const auto s = std::sin(angle); + const auto t = 1.0f - c; + + const auto x = axis.x, y = axis.y, z = axis.z; + + return { + t * x * x + c, t * x * y - s * z, t * x * z + s * y, 0, + t * x * y + s * z, t * y * y + c, t * y * z - s * x, 0, + t * x * z - s * y, t * y * z + s * x, t * z * z + c, 0, + 0, 0, 0, 1 + }; + } +} + +#endif diff --git a/src/bebone/core/types/utils/trait_bryan_angles.h b/src/bebone/core/types/utils/trait_bryan_angles.h new file mode 100644 index 00000000..fa0f7e91 --- /dev/null +++ b/src/bebone/core/types/utils/trait_bryan_angles.h @@ -0,0 +1,104 @@ +#ifndef _BEBONE_CORE_TYPES_TRAIT_BRYAN_ANGLES_ +#define _BEBONE_CORE_TYPES_TRAIT_BRYAN_ANGLES_ + +#include "../matrix/matrix_4x4.h" + +namespace bebone::core { + static inline Matrix trait_bryan_angle_xzy(const Vec3f& rotation) { + const f32 c3 = std::cos(rotation.z); + const f32 s3 = std::sin(rotation.z); + const f32 c2 = std::cos(rotation.x); + const f32 s2 = std::sin(rotation.x); + const f32 c1 = std::cos(rotation.y); + const f32 s1 = std::sin(rotation.y); + + return { + c2*c3, s1*s3 + c1*c3*s2, c3*s1*s2 - c1*s3, 0.0f, + -s2, c1*c2, c2*s1, 0.0f, + c2*s3, c1*s2*s3 - c3*s1, c1*c3 + s1*s2*s3, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }; + } + + static inline Matrix trait_bryan_angle_xyz(const Vec3f& rotation) { + const f32 c3 = std::cos(rotation.z); + const f32 s3 = std::sin(rotation.z); + const f32 c2 = std::cos(rotation.x); + const f32 s2 = std::sin(rotation.x); + const f32 c1 = std::cos(rotation.y); + const f32 s1 = std::sin(rotation.y); + + return { + c2*c3, c1*s3 + c3*s1*s2, c1*s2*s3 - c3*s1, 0.0f, + -c2*s3, c1*c3 - s1*s2*s3, c3*s1 + c1*s2*s3, 0.0f, + s2, -c2*s1, c1*c2, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }; + } + + static inline Matrix trait_bryan_angle_yxz(const Vec3f& rotation) { + const f32 c3 = std::cos(rotation.z); + const f32 s3 = std::sin(rotation.z); + const f32 c2 = std::cos(rotation.x); + const f32 s2 = std::sin(rotation.x); + const f32 c1 = std::cos(rotation.y); + const f32 s1 = std::sin(rotation.y); + + return { + c1*c3 + s1*s2*s3, c2*s3, c1*s2*s3 - c3*s1, 0.0f, + c3*s1*s2 - c1*s3, c2*c3, c1*c3*s2 + s1*s3, 0.0f, + c2*s1, -s2, c1*c2, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }; + } + + static inline Matrix trait_bryan_angle_yzx(const Vec3f& rotation) { + const f32 c3 = std::cos(rotation.z); + const f32 s3 = std::sin(rotation.z); + const f32 c2 = std::cos(rotation.x); + const f32 s2 = std::sin(rotation.x); + const f32 c1 = std::cos(rotation.y); + const f32 s1 = std::sin(rotation.y); + + return { + c1*c2, s2, -c2*s1, 0.0f, + s1*s3 - c1*c3*c2, c2*c3, c1*s3 + c3*s1*s2, 0.0f, + c3*s1 + c1*s2*s3, -c2*s3, c1*c3 - s1*s2*s3, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }; + } + + static inline Matrix trait_bryan_angle_zyx(const Vec3f& rotation) { + const f32 c3 = std::cos(rotation.z); + const f32 s3 = std::sin(rotation.z); + const f32 c2 = std::cos(rotation.x); + const f32 s2 = std::sin(rotation.x); + const f32 c1 = std::cos(rotation.y); + const f32 s1 = std::sin(rotation.y); + + return { + c1*c2, c2*s1, -s2, 0.0f, + c1*s2*s3 - c3*s1, c1*c3 + s1*s2*s3, c2*s3, 0.0f, + s1*s3 + c1*c3*s2, c3*s1*s2 - c1*s3, c2*c3, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }; + } + + static inline Matrix trait_bryan_angle_zxy(const Vec3f& rotation) { + const f32 c3 = std::cos(rotation.z); + const f32 s3 = std::sin(rotation.z); + const f32 c2 = std::cos(rotation.x); + const f32 s2 = std::sin(rotation.x); + const f32 c1 = std::cos(rotation.y); + const f32 s1 = std::sin(rotation.y); + + return { + c1*c3 - s1*s2*s3, c3*s1 + c1*s2*s3, -c2*s3, 0.0f, + -c2*s1, c1*c2, s2, 0.0f, + c1*s3 + c3*s1*s2, s1*s3 - c1*c3*s2, c2*c3, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }; + } +} + +#endif diff --git a/src/bebone/core/types/uuid/uuid.cpp b/src/bebone/core/types/uuid/uuid.cpp new file mode 100644 index 00000000..fbc5924a --- /dev/null +++ b/src/bebone/core/types/uuid/uuid.cpp @@ -0,0 +1,43 @@ +#include "uuid.h" + +namespace bebone::core { + UUID::UUID(const u64& data1, const u64& data2) { + data[0] = data1; + data[1] = data2; + } + + UUID::UUID() { + *this = UUID(0, 0); + } + + bool UUID::operator==(const UUID& other) const { + return this->data[0] == other.data[0] && this->data[1] == other.data[1]; + } + + bool UUID::operator!=(const UUID& other) const { + return !(*this == other); + } + + std::string UUID::to_string() const { + std::stringstream ss; + ss << std::hex << std::setfill('0') << std::setw(16) << data[0]; + ss << std::hex << std::setfill('0') << std::setw(16) << data[1]; + + std::string tmp = ss.str(); + tmp.insert(8, "-"); + tmp.insert(13, "-"); + tmp.insert(18, "-"); + tmp.insert(23, "-"); + + return tmp; + } + + UUID UUID::gen() { + static std::random_device rd; + static std::mt19937_64 gen(rd()); + + static std::uniform_int_distribution dist(0ULL, std::numeric_limits::max()); + + return UUID(dist(gen), dist(gen)); + } +} diff --git a/src/bebone/core/types/uuid/uuid.h b/src/bebone/core/types/uuid/uuid.h new file mode 100644 index 00000000..099a57a1 --- /dev/null +++ b/src/bebone/core/types/uuid/uuid.h @@ -0,0 +1,31 @@ +#ifndef _BEBONE_CORE_TYPES_UUID_TYPE_H_ +#define _BEBONE_CORE_TYPES_UUID_TYPE_H_ + +#include "../primitive_types.h" + +#include +#include +#include +#include +#include + +namespace bebone::core { + class UUID { + private: + u64 data[2]; + + UUID(const u64& data1, const u64& data2); + + public: + UUID(); + + bool operator==(const UUID& other) const; + bool operator!=(const UUID& other) const; + + std::string to_string() const; + + static UUID gen(); + }; +} + +#endif diff --git a/src/bebone/core/types/vector/vector2_type.tpp b/src/bebone/core/types/vector/vector2_type.tpp new file mode 100644 index 00000000..cae8d46e --- /dev/null +++ b/src/bebone/core/types/vector/vector2_type.tpp @@ -0,0 +1,244 @@ +#ifndef _BEBONE_CORE_TYPES_VECTOR_2_TYPE_TPP_ +#define _BEBONE_CORE_TYPES_VECTOR_2_TYPE_TPP_ + +#include "../primitive_types.h" +#include "../utils/interpolation.tpp" + +#include +#include +#include + +namespace bebone::core { + /** + * @brief Type that used as 2d geometrical vector + * + * @tparam T type of the vector + */ + template + struct Vec2 { + /** @brief Raw vector values */ + T x; + T y; + + using value_type = T; + + constexpr Vec2() = default; + constexpr Vec2(const T& x, const T& y) : x(x), y(y) {} + + static const Vec2 zero; + static const Vec2 one; + + static const Vec2 left; + static const Vec2 right; + static const Vec2 up; + static const Vec2 down; + + inline static Vec2 splat(const T& value); + inline static T dot(const Vec2& a, const Vec2& b); + inline static Vec2 project(const Vec2& a, const Vec2& b); + inline static Vec2 reject(const Vec2& a, const Vec2& b); + + inline Vec2 operator +(const Vec2& v) const; + inline Vec2 operator -(const Vec2& v) const; + inline Vec2 operator *(const Vec2& v) const; + inline Vec2 operator /(const Vec2& v) const; + inline Vec2& operator +=(const Vec2& v); + inline Vec2& operator -=(const Vec2& v); + inline Vec2& operator *=(const Vec2& v); + inline Vec2& operator /=(const Vec2& v); + + inline Vec2 operator +(const T& scalar) const; + inline Vec2 operator -(const T& scalar) const; + inline Vec2 operator *(const T& scalar) const; + inline Vec2 operator /(T scalar) const; + inline Vec2& operator +=(const T& scalar); + inline Vec2& operator -=(const T& scalar); + inline Vec2& operator *=(const T& scalar); + inline Vec2& operator /=(T scalar); + + inline Vec2 operator -() const; + + inline bool operator ==(const Vec2& v) const; + inline bool operator !=(const Vec2& v) const; + + inline std::string to_string() const; + + inline Vec2& clamp(const T& min_value, const T& max_value); + inline Vec2& clamp(const Vec2& min_value, const Vec2& max_value); + + inline Vec2& abs(); + inline T length() const; + inline Vec2 normalize() const; + + inline bool is_normalized() const; + }; +} + +namespace bebone::core { + template + const Vec2 Vec2::zero{ 0.0f, 0.0f }; + + template + const Vec2 Vec2::one{ 1.0f, 1.0f }; + + template + const Vec2 Vec2::left{ -1.0f, 0.0f }; + + template + const Vec2 Vec2::right{ 1.0f, 0.0f }; + + template + const Vec2 Vec2::up{ 0.0f, 1.0f }; + + template + const Vec2 Vec2::down{ 0.0f, -1.0f }; + + template + Vec2 Vec2::operator +(const Vec2& v) const { return Vec2(x + v.x, y + v.y); } + + template + Vec2 Vec2::operator -(const Vec2& v) const { return Vec2(x - v.x, y - v.y); } + + template + Vec2 Vec2::operator *(const Vec2& v) const { return Vec2(x * v.x, y * v.y); } + + template + Vec2 Vec2::operator /(const Vec2& v) const { return Vec2(x / v.x, y / v.y); } + + template + Vec2& Vec2::operator +=(const Vec2& v) { x += v.x; y += v.y; return *this; } + + template + Vec2& Vec2::operator -=(const Vec2& v) { x -= v.x; y -= v.y; return *this; } + + template + Vec2& Vec2::operator *=(const Vec2& v) { x *= v.x; y *= v.y; return *this; } + + template + Vec2& Vec2::operator /=(const Vec2& v) { x /= v.x; y /= v.y; return *this; } + + template + Vec2 Vec2::operator +(const T& scalar) const { return Vec2(x + scalar, y + scalar); } + + template + Vec2 Vec2::operator -(const T& scalar) const { return Vec2(x - scalar, y - scalar); } + + template + Vec2 Vec2::operator *(const T& scalar) const { return Vec2(x * scalar, y * scalar); } + + template + Vec2 Vec2::operator /(T scalar) const { return Vec2(x / scalar, y / scalar); } + + template + Vec2& Vec2::operator +=(const T& scalar) { x += scalar; y += scalar; return *this; } + + template + Vec2& Vec2::operator -=(const T& scalar) { x -= scalar; y -= scalar; return *this; } + + template + Vec2& Vec2::operator *=(const T& scalar) { x *= scalar; y *= scalar; return *this; } + + template + Vec2& Vec2::operator /=(T scalar) { x /= scalar; y /= scalar; return *this; } + + template + Vec2 Vec2::operator -() const { return Vec2(-x, -y); } + + template + bool Vec2::operator ==(const Vec2& other) const { return x == other.x && y == other.y; } + + template + bool Vec2::operator !=(const Vec2& other) const { return !(*this == other); } + + template + std::ostream& operator<<(std::ostream& os, const Vec2& v) { + os << v.x << " " << v.y; + return os; + } + + template + std::istream& operator>>(std::istream& os, const Vec2& v) { + os >> v.x >> v.y; + return os; + } + + template + inline Vec2 Vec2::splat(const T& value) { return Vec2(value, value); } + + template + T Vec2::dot(const Vec2& a, const Vec2& b) { + return a.x * b.x + a.y * b.y; + } + + template + Vec2 Vec2::project(const Vec2& a, const Vec2& b) { + return b * (dot(a, b) / dot(b, b)); + } + + template + Vec2 Vec2::reject(const Vec2& a, const Vec2& b) { + return a - project(a, b); + } + + template + Vec2& Vec2::clamp(const T& min_value, const T& max_value) { + x = bebone::core::clamp(x, min_value, max_value); + y = bebone::core::clamp(y, min_value, max_value); + + return *this; + } + + template + Vec2& Vec2::clamp(const Vec2& min_value, const Vec2& max_value) { + x = bebone::core::clamp(x, min_value.x, max_value.x); + y = bebone::core::clamp(y, min_value.y, max_value.y); + + return *this; + } + + /** + * @brief Method used to get string representation of object instance + * + * @return std::string string representation + */ + template + std::string Vec2::to_string() const { + std::stringstream ss; + ss << x << ' ' << y; + return ss.str(); + } + + /** + * @brief Converts all values of the vector to their absolute values + * + * @return Vec2& reference to vector instance + */ + template + Vec2& Vec2::Vec2::abs() { + if(x < 0) x = -x; + if(y < 0) y = -y; + return *this; + } + + /** + * @brief Calculates length of the vector + * + * @return T length of the vector + */ + template + T Vec2::length() const { + return sqrtf(x * x + y * y); + } + + template + Vec2 Vec2::normalize() const { + return *this / length(); + } + + template + bool Vec2::is_normalized() const { + return std::abs(1.0f - length()) < std::numeric_limits::epsilon(); + } +} + +#endif diff --git a/src/bebone/core/types/vector/vector3_type.tpp b/src/bebone/core/types/vector/vector3_type.tpp new file mode 100644 index 00000000..ee4945b0 --- /dev/null +++ b/src/bebone/core/types/vector/vector3_type.tpp @@ -0,0 +1,291 @@ +#ifndef _BEBONE_CORE_TYPES_VECTOR_3_TYPE_TPP_ +#define _BEBONE_CORE_TYPES_VECTOR_3_TYPE_TPP_ + +#include "vector2_type.tpp" + +namespace bebone::core { + /** + * @brief Type that used as 3d geometrical vector + * + * @tparam T type of the vector + */ + template + struct Vec3 { + /** @brief Raw vector values */ + T x; + T y; + T z; + + using value_type = T; + + constexpr Vec3() = default; + constexpr Vec3(const T& x, const T& y, const T& z) : x(x), y(y), z(z) { } + + static const Vec3 zero; + static const Vec3 one; + + static const Vec3 left; + static const Vec3 right; + static const Vec3 up; + static const Vec3 down; + static const Vec3 back; + static const Vec3 forward; + + inline static Vec3 splat(const T& value); + inline static Vec3 cross(const Vec3& a, const Vec3& b); + inline static T dot(const Vec3& a, const Vec3& b); + inline static Vec3 project(const Vec3& a, const Vec3& b); + inline static Vec3 reject(const Vec3& a, const Vec3& b); + + inline Vec3 operator +(const Vec3& v) const; + inline Vec3 operator -(const Vec3& v) const; + inline Vec3 operator *(const Vec3& v) const; + inline Vec3 operator /(const Vec3& v) const; + inline Vec3& operator +=(const Vec3& v); + inline Vec3& operator -=(const Vec3& v); + inline Vec3& operator *=(const Vec3& v); + inline Vec3& operator /=(const Vec3& v); + + inline Vec3 operator +(const T& scalar) const; + inline Vec3 operator -(const T& scalar) const; + inline Vec3 operator *(const T& scalar) const; + inline Vec3 operator /(T scalar) const; + inline Vec3& operator +=(const T& scalar); + inline Vec3& operator -=(const T& scalar); + inline Vec3& operator *=(const T& scalar); + inline Vec3& operator /=(T scalar); + + inline Vec3 operator -() const; + + inline bool operator ==(const Vec3& v) const; + inline bool operator !=(const Vec3& v) const; + + inline explicit operator Vec2() const; + + inline std::string to_string() const; + + inline Vec3& clamp(const T& min_value, const T& max_value); + inline Vec3& clamp(const Vec3& min_value, const Vec3& max_value); + + inline Vec3& abs(); + inline T length() const; + + inline Vec3 normalize() const; + inline bool is_normalized() const; + }; +} + +namespace bebone::core { + template + const Vec3 Vec3::zero{ 0.0f, 0.0f, 0.0f }; + + template + const Vec3 Vec3::one{ 1.0f, 1.0f, 1.0f }; + + template + const Vec3 Vec3::left{ -1.0f, 0.0f, 0.0f }; + + template + const Vec3 Vec3::right{ 1.0f, 0.0f, 0.0f }; + + template + const Vec3 Vec3::up{ 0.0f, 1.0f, 0.0f }; + + template + const Vec3 Vec3::down{ 0.0f, -1.0f, 0.0f }; + + template + const Vec3 Vec3::back{ 0.0f, 0.0f, -1.0f }; + + template + const Vec3 Vec3::forward{ 0.0f, 0.0f, 1.0f }; + + template + Vec3 Vec3::operator +(const Vec3& v) const { return Vec3(x + v.x, y + v.y, z + v.z); } + + template + Vec3 Vec3::operator -(const Vec3& v) const { return Vec3(x - v.x, y - v.y, z - v.z); } + + template + Vec3 Vec3::operator *(const Vec3& v) const { return Vec3(x * v.x, y * v.y, z * v.z); } + + template + Vec3 Vec3::operator /(const Vec3& v) const { return Vec3(x / v.x, y / v.y, z / v.z); } + + template + Vec3& Vec3::operator +=(const Vec3& v) { x += v.x; y += v.y; z += v.z; return *this; } + + template + Vec3& Vec3::operator -=(const Vec3& v) { x -= v.x; y -= v.y; z -= v.z; return *this; } + + template + Vec3& Vec3::operator *=(const Vec3& v) { x *= v.x; y *= v.y; z *= v.z; return *this; } + + template + Vec3& Vec3::operator /=(const Vec3& v) { x /= v.x; y /= v.y; z /= v.z; return *this; } + + template + Vec3 Vec3::operator +(const T& scalar) const { return Vec3(x + scalar, y + scalar, z + scalar); } + + template + Vec3 Vec3::operator -(const T& scalar) const { return Vec3(x - scalar, y - scalar, z - scalar); } + + template + Vec3 Vec3::operator *(const T& scalar) const { return Vec3(x * scalar, y * scalar, z * scalar); } + + template + Vec3 Vec3::operator /(T scalar) const { + scalar = 1.0f / scalar; + return *this * scalar; + } + + template + Vec3& Vec3::operator +=(const T& scalar) { x += scalar; y += scalar; z += scalar; return *this; } + + template + Vec3& Vec3::operator -=(const T& scalar) { x -= scalar; y -= scalar; z -= scalar; return *this; } + + template + Vec3& Vec3::operator *=(const T& scalar) { x *= scalar; y *= scalar; z *= scalar; return *this; } + + template + Vec3& Vec3::operator /=(T scalar) { + scalar = 1.0f / scalar; + return *this *= scalar; + } + + template + Vec3 Vec3::operator -() const { return Vec3(-x, -y, -z); } + + template + Vec3::operator Vec2() const { return Vec2(x, y); } + + template + bool Vec3::operator ==(const Vec3& v) const { return x == v.x && y == v.y && z == v.z; } + + template + bool Vec3::operator !=(const Vec3& v) const { return !(*this == v); } + + /** + * @brief Puts string representation of the object to the out stream + * + * @param os - reference to the out stream + * @param v - reference to the object instance + * + * @return std::ostream& reference to the stream instance + */ + template + std::ostream& operator <<(std::ostream& os, const Vec3& v) { + os << v.x << " " << v.y << " " << v.z; + return os; + } + + /** + * @brief Constructs object from it string representation + * + * @param os - reference to the in stream + * @param v - reference to the object instance + * + * @return std::istream& reference to the stream instance + */ + template + std::istream& operator >>(std::istream& os, const Vec3& v) { + os >> v.x >> v.y >> v.z; + + return os; + } + + template + Vec3& Vec3::clamp(const T& min_value, const T& max_value) { + x = bebone::core::clamp(x, min_value, max_value); + y = bebone::core::clamp(y, min_value, max_value); + z = bebone::core::clamp(z, min_value, max_value); + + return *this; + } + + template + Vec3& Vec3::clamp(const Vec3& min_value, const Vec3& max_value) { + x = bebone::core::clamp(x, min_value.x, max_value.x); + y = bebone::core::clamp(y, min_value.y, max_value.y); + z = bebone::core::clamp(z, min_value.z, max_value.z); + + return *this; + } + + template + Vec3 Vec3::splat(const T& value) { + return Vec3(value, value, value); + } + + template + Vec3 Vec3::cross(const Vec3& a, const Vec3& b) { + return { + a.y * b.z - a.z * b.y, + a.z * b.x - a.x * b.z, + a.x * b.y - a.y * b.x + }; + } + + template + T Vec3::dot(const Vec3& a, const Vec3& b) { + return a.x * b.x + a.y * b.y + a.z * b.z; + } + + template + Vec3 Vec3::project(const Vec3& a, const Vec3& b) { + return b * (dot(a, b) / dot(b, b)); + } + + template + Vec3 Vec3::reject(const Vec3& a, const Vec3& b) { + return a - project(a, b); + } + + /** + * @brief Method used to get string representation of object instance + * + * @return std::string string representation + */ + template + std::string Vec3::to_string() const { + std::stringstream ss; + ss << x << ' ' << y << ' ' << z; + return ss.str(); + } + + /** + * @brief Converts all values of the vector to their absolute values + * + * @return Vec2& reference to vector instance + */ + template + Vec3& Vec3::abs() { + if(x < 0) x = -x; + if(y < 0) y = -y; + if(z < 0) z = -z; + return *this; + } + + /** + * @brief Calculates length of the vector + * + * @return f32 length of the vector + */ + template + T Vec3::length() const { + return sqrtf(x * x + y * y + z * z); + } + + template + Vec3 Vec3::normalize() const { + return *this / length(); + } + + template + bool Vec3::is_normalized() const { + return std::abs(1.0f - length()) < std::numeric_limits::epsilon(); + } +} + +#endif diff --git a/src/bebone/core/types/vector/vector4_type.tpp b/src/bebone/core/types/vector/vector4_type.tpp new file mode 100644 index 00000000..620c887c --- /dev/null +++ b/src/bebone/core/types/vector/vector4_type.tpp @@ -0,0 +1,275 @@ +#ifndef _BEBONE_CORE_TYPES_VECTOR_4_TYPE_TPP_ +#define _BEBONE_CORE_TYPES_VECTOR_4_TYPE_TPP_ + +#include "vector3_type.tpp" + +namespace bebone::core { + /** + * @brief Type that used as 4d geometrical vector + * + * @tparam T type of the vector + */ + template + struct Vec4 { + /** @brief Raw vector values */ + T x; + T y; + T z; + T w; + + using value_type = T; + + constexpr Vec4() = default; + constexpr Vec4(const T& x, const T& y, const T& z, const T& w) : x(x), y(y), z(z), w(w) {} + + static const Vec4 zero; + static const Vec4 one; + + static Vec4 splat(const T& value); + inline static T dot(const Vec4& a, const Vec4& b); + inline static Vec4 project(const Vec4& a, const Vec4& b); + inline static Vec4 reject(const Vec4& a, const Vec4& b); + + inline Vec4 operator +(const Vec4& v) const; + inline Vec4 operator -(const Vec4& v) const; + inline Vec4 operator *(const Vec4& v) const; + inline Vec4 operator /(const Vec4& v) const; + inline Vec4& operator +=(const Vec4& v); + inline Vec4& operator -=(const Vec4& v); + inline Vec4& operator *=(const Vec4& v); + inline Vec4& operator /=(const Vec4& v); + + inline Vec4 operator +(const T& scalar) const; + inline Vec4 operator -(const T& scalar) const; + inline Vec4 operator *(const T& scalar) const; + inline Vec4 operator /(T scalar) const; + inline Vec4& operator +=(const T& scalar); + inline Vec4& operator -=(const T& scalar); + inline Vec4& operator *=(const T& scalar); + inline Vec4& operator /=(T scalar); + + inline Vec4 operator -() const; + + inline bool operator ==(const Vec4& v) const; + inline bool operator !=(const Vec4& v) const; + + inline explicit operator Vec2() const; + inline explicit operator Vec3() const; + + [[nodiscard]] inline std::string to_string() const; + [[nodiscard]] inline Vec3 to_vec3() const; + [[nodiscard]] inline Vec2 to_vec2() const; + + inline Vec4& clamp(const T& min_value, const T& max_value); + inline Vec4& clamp(const Vec4& min_value, const Vec4& max_value); + + inline Vec4& abs(); + [[nodiscard]] inline f32 length() const; + [[nodiscard]] inline Vec4 normalize() const; + + [[nodiscard]] inline bool is_normalized() const; + }; +} + +namespace bebone::core { + template + const Vec4 Vec4::zero{ 0.0f, 0.0f, 0.0f, 0.0f }; + + template + const Vec4 Vec4::one{ 1.0f, 1.0f, 1.0f, 1.0f }; + + template + Vec4 Vec4::operator +(const Vec4& v) const { return Vec4(x + v.x, y + v.y, z + v.z, w + v.w); } + + template + Vec4 Vec4::operator -(const Vec4& v) const { return Vec4(x - v.x, y - v.y, z - v.z, w - v.w); } + + template + Vec4 Vec4::operator *(const Vec4& v) const { return Vec4(x * v.x, y * v.y, z * v.z, w * v.w); } + + template + Vec4 Vec4::operator /(const Vec4& v) const { return Vec4(x / v.x, y / v.y, z / v.z, w / v.w); } + + template + Vec4& Vec4::operator +=(const Vec4& v) { x += v.x; y += v.y; z += v.z; w += v.w; return *this; } + + template + Vec4& Vec4::operator -=(const Vec4& v) { x -= v.x; y -= v.y; z -= v.z; w -= v.w; return *this; } + + template + Vec4& Vec4::operator *=(const Vec4& v) { x *= v.x; y *= v.y; z *= v.z; w *= v.w; return *this; } + + template + Vec4& Vec4::operator /=(const Vec4& v) { x /= v.x; y /= v.y; z /= v.z; w /= v.w; return *this; } + + template + Vec4 Vec4::operator +(const T& scalar) const { return Vec4(x + scalar, y + scalar, z + scalar, w + scalar); } + + template + Vec4 Vec4::operator -(const T& scalar) const { return Vec4(x - scalar, y - scalar, z - scalar, w - scalar); } + + template + Vec4 Vec4::operator *(const T& scalar) const { return Vec4(x * scalar, y * scalar, z * scalar, w * scalar); } + + template + Vec4 Vec4::operator /(T scalar) const { + scalar = 1.0f / scalar; + return *this * scalar; + } + + template + Vec4& Vec4::operator +=(const T& scalar) { x += scalar; y += scalar; z += scalar; w += scalar; return *this; } + + template + Vec4& Vec4::operator -=(const T& scalar) { x -= scalar; y -= scalar; z -= scalar; w -= scalar; return *this; } + + template + Vec4& Vec4::operator *=(const T& scalar) { x *= scalar; y *= scalar; z *= scalar; w *= scalar; return *this; } + + template + Vec4& Vec4::operator /=(T scalar) { + scalar = 1.0f / scalar; + return *this *= scalar; + } + + template + Vec4 Vec4::operator -() const { return Vec4(-x, -y, -z, -w); } + + template + bool Vec4::operator ==(const Vec4& v) const { return x == v.x && y == v.y && z == v.z && w == v.w; } + + template + bool Vec4::operator !=(const Vec4& v) const { return !(*this == v); } + + template + Vec4::operator Vec2() const { return Vec2(x, y); } + + template + Vec4::operator Vec3() const { return Vec3(x, y, z); } + + template + Vec4 Vec4::splat(const T& value) { return Vec4(value, value, value, value); } + + template + T Vec4::dot(const Vec4& a, const Vec4& b) { + return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; + } + + template + Vec4 Vec4::project(const Vec4& a, const Vec4& b) { + return b * (dot(a, b) / dot(b, b)); + } + + template + Vec4 Vec4::reject(const Vec4& a, const Vec4& b) { + return a - project(a, b); + } + + template + Vec4& Vec4::clamp(const T& min_value, const T& max_value) { + x = bebone::core::clamp(x, min_value, max_value); + y = bebone::core::clamp(y, min_value, max_value); + z = bebone::core::clamp(z, min_value, max_value); + w = bebone::core::clamp(w, min_value, max_value); + + return *this; + } + + template + Vec4& Vec4::clamp(const Vec4& min_value, const Vec4& max_value) { + x = bebone::core::clamp(x, min_value.x, max_value.x); + y = bebone::core::clamp(y, min_value.y, max_value.y); + z = bebone::core::clamp(z, min_value.z, max_value.z); + w = bebone::core::clamp(w, min_value.w, max_value.w); + + return *this; + } + + /** + * @brief Puts string representation of the object to the out stream + * + * @param os - reference to the out stream + * @param v - reference to the object instance + * + * @return std::ostream& reference to the stream instance + */ + template + std::ostream& operator<<(std::ostream& os, const Vec4& v) { + os << v.x << " " << v.y << " " << v.z << " " << v.w; + return os; + } + + /** + * @brief Constructs object from it string representation + * + * @param os - reference to the in stream + * @param v - reference to the object instance + * + * @return std::istream& reference to the stream instance + */ + template + std::istream& operator>>(std::istream& os, const Vec4& v) { + os >> v.x >> v.y >> v.z >> v.w; + + return os; + } + + /** + * @brief Method used to get string representation of object instance + * + * @return std::string string representation + */ + template + std::string Vec4::to_string() const { + std::stringstream ss; + ss << x << ' ' << y << ' ' << z << ' ' << w; + return ss.str(); + } + + template + inline Vec3 Vec4::to_vec3() const { + return Vec3(x, y, z); + } + + template + inline Vec2 Vec4::to_vec2() const { + return Vec2(x, y, z); + } + + /** + * @brief Converts all values of the vector to their absolute values + * + * @return Vec2& reference to vector instance + */ + template + Vec4& Vec4::abs() { + if(x < 0) x = -x; + if(y < 0) y = -y; + if(z < 0) z = -z; + if(w < 0) z = -w; + return *this; + } + + /** + * @brief Calculates length of the vector + * + * @return f32 length of the vector + */ + template + f32 Vec4::length() const { + return sqrtf(x * x + y * y + z * z + w * w); + } + + template + Vec4 Vec4::normalize() const { + return *this / length(); + } + + template + bool Vec4::is_normalized() const { + return std::abs(1.0f - length()) < std::numeric_limits::epsilon(); + } + +} + +#endif diff --git a/src/bebone/core/types/vector/vector_types.h b/src/bebone/core/types/vector/vector_types.h new file mode 100644 index 00000000..cb237269 --- /dev/null +++ b/src/bebone/core/types/vector/vector_types.h @@ -0,0 +1,80 @@ +#ifndef _BEBONE_CORE_TYPES_VECTOR_TYPES_H_ +#define _BEBONE_CORE_TYPES_VECTOR_TYPES_H_ + +#include + +#include "../primitive_types.h" + +#include "vector2_type.tpp" +#include "vector3_type.tpp" +#include "vector4_type.tpp" + +namespace bebone::core { + using Vec2f = Vec2; + using Vec3f = Vec3; + using Vec4f = Vec4; + + using Vec2i = Vec2; + using Vec3i = Vec3; + using Vec4i = Vec4; +} + +namespace std { + template<> + struct hash { + size_t operator()(const bebone::core::Vec2f& key) const { + return std::hash()(key.x) ^ std::hash()(key.y); + } + }; + + template<> + struct hash { + size_t operator()(const bebone::core::Vec3f& key) const { + return + std::hash()(key.x) ^ + std::hash()(key.y) ^ + std::hash()(key.z); + } + }; + + template<> + struct hash { + size_t operator()(const bebone::core::Vec4f& key) const { + return + std::hash()(key.x) ^ + std::hash()(key.y) ^ + std::hash()(key.z) ^ + std::hash()(key.w); + } + }; + + template<> + struct hash { + size_t operator()(const bebone::core::Vec2i& key) const { + return std::hash()(key.x) ^ std::hash()(key.y); + } + }; + + template<> + struct hash { + size_t operator()(const bebone::core::Vec3i& key) const { + return + std::hash()(key.x) ^ + std::hash()(key.y) ^ + std::hash()(key.z); + } + }; + + template<> + struct hash { + size_t operator()(const bebone::core::Vec4i& key) const { + return + std::hash()(key.x) ^ + std::hash()(key.y) ^ + std::hash()(key.z) ^ + std::hash()(key.w); + } + }; +} + +#endif diff --git a/src/bebone/gfx/CMakeLists.txt b/src/bebone/gfx/CMakeLists.txt index f8a75833..8eda9134 100644 --- a/src/bebone/gfx/CMakeLists.txt +++ b/src/bebone/gfx/CMakeLists.txt @@ -1,27 +1,30 @@ file(GLOB_RECURSE BEBONE_GFX_SRC_FILES "*.cpp") -include_directories("../../../3dparty/glad/include") -include_directories("../../../3dparty/glfw/include") -include_directories("../../../3dparty/Vulkan-Headers/include") +set(BEBONE_GFX_INCLUDES "${CMAKE_SOURCE_DIR}/src/bebone/gfx") -add_compile_definitions(OMNI_GLAD_INTEGRATION) -include_directories("../../../3dparty/omni_types/src") +find_package(Vulkan) -include_directories("../../../3dparty/stb") -include_directories("../../../3dparty/glfw/include") -include_directories("../../../3dparty/imgui") +list(APPEND BEBONE_GFX_INCLUDES + "${PROJECT_SOURCE_DIR}/3dparty/glad/include" + "${PROJECT_SOURCE_DIR}/3dparty/stb" + "${PROJECT_SOURCE_DIR}/3dparty/glfw/include" + "${PROJECT_SOURCE_DIR}/3dparty/imgui" + ${Vulkan_INCLUDE_DIRS} +) -include_directories("./") +set(BEBONE_GFX_LIBRARIES + glfw + stb_image + stb_truetype + glad + Vulkan::Vulkan + glslang + SPIRV + glslang-default-resource-limits +) -add_library(bebone_gfx STATIC ${BEBONE_GFX_SRC_FILES}) - -find_package(Vulkan REQUIRED) +set(BEBONE_GFX_INCLUDES "${BEBONE_GFX_INCLUDES}" CACHE INTERNAL "") +include_directories(${BEBONE_GFX_INCLUDES}) -target_link_libraries(bebone_gfx glfw) -target_link_libraries(bebone_gfx stb_image) -target_link_libraries(bebone_gfx glad) -target_link_libraries(bebone_gfx glslang) -target_link_libraries(bebone_gfx SPIRV) -target_link_libraries(bebone_gfx glslang-default-resource-limits) -target_link_libraries(bebone_gfx ${Vulkan_LIBRARIES}) -target_link_libraries(bebone_gfx imgui) +add_library(bebone_gfx STATIC ${BEBONE_GFX_SRC_FILES}) +target_link_libraries(bebone_gfx PUBLIC ${BEBONE_GFX_LIBRARIES}) \ No newline at end of file diff --git a/src/bebone/gfx/README.md b/src/bebone/gfx/README.md new file mode 100644 index 00000000..112eafc5 --- /dev/null +++ b/src/bebone/gfx/README.md @@ -0,0 +1 @@ +# bebone_gfx module \ No newline at end of file diff --git a/src/bebone/gfx/begui/begui.cpp b/src/bebone/gfx/begui/begui.cpp deleted file mode 100644 index 79f57db8..00000000 --- a/src/bebone/gfx/begui/begui.cpp +++ /dev/null @@ -1,77 +0,0 @@ -#include "begui.h" - -namespace bebone::gfx { - void BeGUI::init(const std::shared_ptr& window) { - IMGUI_CHECKVERSION(); - ImGui::CreateContext(); - - ImGuiIO& io = ImGui::GetIO(); - io.ConfigFlags |= ImGuiConfigFlags_None; - - ImGui::CreateContext(); - - //ImGui::StyleColorsDark(); - apply_default_bebone_imgui_theme(); - - ImGui_ImplGlfw_InitForOpenGL(window->get_backend(), true); - ImGui_ImplOpenGL3_Init("#version 330"); - } - - void BeGUI::begin() { - ImGui_ImplOpenGL3_NewFrame(); - ImGui_ImplGlfw_NewFrame(); - ImGui::NewFrame(); - } - - void BeGUI::end() { - ImGui::Render(); - ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); - } - - void BeGUI::profiler_trace_profiles(Profile* parent) { - const auto& childs = parent->get_childs(); - - for(const auto& profile : childs) { - if (ImGui::TreeNode(profile->label.c_str())) { - const f64 totalExecutionTime = profile->totalExecutionTime / 1000000.0; - - const f64 maxExecutionTime = profile->maxExecutionTime / 1000000.0; - const f64 minExecutionTime = profile->minExecutionTime / 1000000.0; - const f64 avgExecutionTime = totalExecutionTime / profile->executionCount; - - f64 parentRationTime = 100.0; - if(parent != nullptr) - parentRationTime = (profile->totalExecutionTime / parent->totalExecutionTime) * 100.0; - - ImGui::Text("executed %llu times, total execution time %f ms", profile->executionCount, totalExecutionTime); - - ImGui::Text("Max execution time %f ms", maxExecutionTime); - ImGui::Text("Min execution time %f ms", minExecutionTime); - ImGui::Text("Avg execution time %f ms", avgExecutionTime); - ImGui::Text("Parent total time ratio %f %%", parentRationTime); - - profiler_trace_profiles(profile); - - ImGui::TreePop(); - } - } - } - - void BeGUI::show_profiler() { - ImGui::Begin("Bebone profiler"); - - const auto& entryPoints = Profiler::get_instance().get_entry_points(); - - for(const auto& profile : entryPoints) { - if (ImGui::TreeNode(profile->label.c_str())) { - ImGui::Text("Execution ratio %f %%", 100.0); - - profiler_trace_profiles(profile); - - ImGui::TreePop(); - } - } - - ImGui::End(); - } -}; diff --git a/src/bebone/gfx/begui/begui.h b/src/bebone/gfx/begui/begui.h deleted file mode 100644 index 19315baa..00000000 --- a/src/bebone/gfx/begui/begui.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef _BEBONE_BEGUI_BEGUI_H_ -#define _BEBONE_BEGUI_BEGUI_H_ - -#include -#include -#include - -#include "../window/window.h" -#include "../../core/core.h" - -#include "theme.h" - -namespace bebone::gfx { - // Dear ImGUI abstraction class - class BeGUI { - public: - /*! - * Initializes Dear ImGUI - * @param window - bebone window - */ - static void init(const std::shared_ptr& window); - - // Begin ImGUI context - static void begin(); - - // Ends ImGUI context - static void end(); - - private: - /*! - * Traces profile tree and renders as ImGUI ui - * @param parent - Pointer to profile - */ - static void profiler_trace_profiles(Profile* parent); - - public: - // Function that renders ImGUI profiler window - static void show_profiler(); - }; -}; - -#endif diff --git a/src/bebone/gfx/begui/theme.cpp b/src/bebone/gfx/begui/theme.cpp deleted file mode 100644 index f5c98d16..00000000 --- a/src/bebone/gfx/begui/theme.cpp +++ /dev/null @@ -1,88 +0,0 @@ -#include "theme.h" - -namespace bebone::gfx { - void apply_default_bebone_imgui_theme() { - /* Source: https://github.com/ocornut/imgui/issues/707#issuecomment-917151020 */ - - ImVec4* colors = ImGui::GetStyle().Colors; - colors[ImGuiCol_Text] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f); - colors[ImGuiCol_TextDisabled] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f); - colors[ImGuiCol_WindowBg] = ImVec4(0.10f, 0.10f, 0.10f, 1.00f); - colors[ImGuiCol_ChildBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); - colors[ImGuiCol_PopupBg] = ImVec4(0.19f, 0.19f, 0.19f, 0.92f); - colors[ImGuiCol_Border] = ImVec4(0.19f, 0.19f, 0.19f, 0.29f); - colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.24f); - colors[ImGuiCol_FrameBg] = ImVec4(0.05f, 0.05f, 0.05f, 0.54f); - colors[ImGuiCol_FrameBgHovered] = ImVec4(0.19f, 0.19f, 0.19f, 0.54f); - colors[ImGuiCol_FrameBgActive] = ImVec4(0.20f, 0.22f, 0.23f, 1.00f); - colors[ImGuiCol_TitleBg] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f); - colors[ImGuiCol_TitleBgActive] = ImVec4(0.06f, 0.06f, 0.06f, 1.00f); - colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f); - colors[ImGuiCol_MenuBarBg] = ImVec4(0.14f, 0.14f, 0.14f, 1.00f); - colors[ImGuiCol_ScrollbarBg] = ImVec4(0.05f, 0.05f, 0.05f, 0.54f); - colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.34f, 0.34f, 0.34f, 0.54f); - colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.40f, 0.40f, 0.40f, 0.54f); - colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.56f, 0.56f, 0.56f, 0.54f); - colors[ImGuiCol_CheckMark] = ImVec4(0.33f, 0.67f, 0.86f, 1.00f); - colors[ImGuiCol_SliderGrab] = ImVec4(0.34f, 0.34f, 0.34f, 0.54f); - colors[ImGuiCol_SliderGrabActive] = ImVec4(0.56f, 0.56f, 0.56f, 0.54f); - colors[ImGuiCol_Button] = ImVec4(0.05f, 0.05f, 0.05f, 0.54f); - colors[ImGuiCol_ButtonHovered] = ImVec4(0.19f, 0.19f, 0.19f, 0.54f); - colors[ImGuiCol_ButtonActive] = ImVec4(0.20f, 0.22f, 0.23f, 1.00f); - colors[ImGuiCol_Header] = ImVec4(0.00f, 0.00f, 0.00f, 0.52f); - colors[ImGuiCol_HeaderHovered] = ImVec4(0.00f, 0.00f, 0.00f, 0.36f); - colors[ImGuiCol_HeaderActive] = ImVec4(0.20f, 0.22f, 0.23f, 0.33f); - colors[ImGuiCol_Separator] = ImVec4(0.28f, 0.28f, 0.28f, 0.29f); - colors[ImGuiCol_SeparatorHovered] = ImVec4(0.44f, 0.44f, 0.44f, 0.29f); - colors[ImGuiCol_SeparatorActive] = ImVec4(0.40f, 0.44f, 0.47f, 1.00f); - colors[ImGuiCol_ResizeGrip] = ImVec4(0.28f, 0.28f, 0.28f, 0.29f); - colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.44f, 0.44f, 0.44f, 0.29f); - colors[ImGuiCol_ResizeGripActive] = ImVec4(0.40f, 0.44f, 0.47f, 1.00f); - colors[ImGuiCol_Tab] = ImVec4(0.00f, 0.00f, 0.00f, 0.52f); - colors[ImGuiCol_TabHovered] = ImVec4(0.14f, 0.14f, 0.14f, 1.00f); - colors[ImGuiCol_TabActive] = ImVec4(0.20f, 0.20f, 0.20f, 0.36f); - colors[ImGuiCol_TabUnfocused] = ImVec4(0.00f, 0.00f, 0.00f, 0.52f); - colors[ImGuiCol_TabUnfocusedActive] = ImVec4(0.14f, 0.14f, 0.14f, 1.00f); - // colors[ImGuiCol_DockingPreview] = ImVec4(0.33f, 0.67f, 0.86f, 1.00f); - // colors[ImGuiCol_DockingEmptyBg] = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); - colors[ImGuiCol_PlotLines] = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); - colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); - colors[ImGuiCol_PlotHistogram] = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); - colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); - colors[ImGuiCol_TableHeaderBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.52f); - colors[ImGuiCol_TableBorderStrong] = ImVec4(0.00f, 0.00f, 0.00f, 0.52f); - colors[ImGuiCol_TableBorderLight] = ImVec4(0.28f, 0.28f, 0.28f, 0.29f); - colors[ImGuiCol_TableRowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); - colors[ImGuiCol_TableRowBgAlt] = ImVec4(1.00f, 1.00f, 1.00f, 0.06f); - colors[ImGuiCol_TextSelectedBg] = ImVec4(0.20f, 0.22f, 0.23f, 1.00f); - colors[ImGuiCol_DragDropTarget] = ImVec4(0.33f, 0.67f, 0.86f, 1.00f); - colors[ImGuiCol_NavHighlight] = ImVec4(1.00f, 0.00f, 0.00f, 1.00f); - colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 0.00f, 0.00f, 0.70f); - colors[ImGuiCol_NavWindowingDimBg] = ImVec4(1.00f, 0.00f, 0.00f, 0.20f); - colors[ImGuiCol_ModalWindowDimBg] = ImVec4(1.00f, 0.00f, 0.00f, 0.35f); - - ImGuiStyle& style = ImGui::GetStyle(); - style.WindowPadding = ImVec2(8.00f, 8.00f); - style.FramePadding = ImVec2(5.00f, 2.00f); - style.CellPadding = ImVec2(6.00f, 6.00f); - style.ItemSpacing = ImVec2(6.00f, 6.00f); - style.ItemInnerSpacing = ImVec2(6.00f, 6.00f); - style.TouchExtraPadding = ImVec2(0.00f, 0.00f); - style.IndentSpacing = 25; - style.ScrollbarSize = 15; - style.GrabMinSize = 10; - style.WindowBorderSize = 1; - style.ChildBorderSize = 1; - style.PopupBorderSize = 1; - style.FrameBorderSize = 1; - style.TabBorderSize = 1; - style.WindowRounding = 7; - style.ChildRounding = 4; - style.FrameRounding = 3; - style.PopupRounding = 4; - style.ScrollbarRounding = 9; - style.GrabRounding = 3; - style.LogSliderDeadzone = 4; - style.TabRounding = 4; - } -}; diff --git a/src/bebone/gfx/begui/theme.h b/src/bebone/gfx/begui/theme.h deleted file mode 100644 index c9ce95f2..00000000 --- a/src/bebone/gfx/begui/theme.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef _BEBONE_BEGUI_THEME_H_ -#define _BEBONE_BEGUI_THEME_H_ - -#include -#include -#include - -#include "../window/window.h" -#include "../../core/core.h" - -namespace bebone::gfx { - // Applies Dear ImGUI bebone default theme - void apply_default_bebone_imgui_theme(); -}; - -#endif diff --git a/src/bebone/gfx/color_extensions.h b/src/bebone/gfx/color_extensions.h new file mode 100644 index 00000000..103afee3 --- /dev/null +++ b/src/bebone/gfx/color_extensions.h @@ -0,0 +1,70 @@ +#ifndef _BEBONE_GFX_COLOR_EXTENSIONS_H_ +#define _BEBONE_GFX_COLOR_EXTENSIONS_H_ + +#include "gfx_backend.h" + +namespace bebone::gfx{ + using namespace bebone::core; + + template + inline constexpr u32 get_gl_format() { + return GL_ZERO; + } + + template + inline constexpr VkFormat get_vulkan_format() { + return VK_FORMAT_UNDEFINED; + } + + template + inline constexpr u32 get_gl_type() { + return GL_ZERO; + } + + template<> + inline constexpr u32 get_gl_format() { + return GL_RGB; + } + + template<> + inline constexpr VkFormat get_vulkan_format() { + return VK_FORMAT_R8G8B8_SRGB; + } + + template<> + inline constexpr u32 get_gl_type() { + return GL_UNSIGNED_BYTE; + } + + template<> + inline constexpr u32 get_gl_format() { + return GL_RGBA; + } + + template<> + inline constexpr VkFormat get_vulkan_format() { + return VK_FORMAT_R8G8B8A8_SRGB; + } + + template<> + inline constexpr u32 get_gl_type() { + return GL_UNSIGNED_BYTE; + } + + template<> + inline constexpr u32 get_gl_format() { + return GL_RGBA; + } + + template<> + inline constexpr VkFormat get_vulkan_format() { + return VK_FORMAT_R32G32B32A32_SFLOAT; + } + + template<> + inline constexpr u32 get_gl_type() { + return GL_FLOAT; + } +} + +#endif diff --git a/src/bebone/gfx/gfx.cpp b/src/bebone/gfx/gfx.cpp deleted file mode 100644 index d3f5a12f..00000000 --- a/src/bebone/gfx/gfx.cpp +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/bebone/gfx/gfx.h b/src/bebone/gfx/gfx.h index 5ef7489e..1ab4d66d 100644 --- a/src/bebone/gfx/gfx.h +++ b/src/bebone/gfx/gfx.h @@ -2,13 +2,14 @@ #define _BEBONE_GFX_GFX_H_ #include "gfx_backend.h" -#include "begui/begui.h" #include "vulkan/vulkan_api.h" #include "opengl/opengl_api.h" #include "window/window.h" #include "window/window_factory.h" +#include "window/events/mouse_listener.h" +#include "window/events/key_listener.h" #include "shaders/shader_code.h" #include "shaders/shader_compiler.h" @@ -17,5 +18,6 @@ #include "shaders/spirv_shader_compiler.h" #include "glfw_context.h" +#include "color_extensions.h" #endif diff --git a/src/bebone/gfx/gfx_api.h b/src/bebone/gfx/gfx_api.h index 49fd864d..cc312b6e 100644 --- a/src/bebone/gfx/gfx_api.h +++ b/src/bebone/gfx/gfx_api.h @@ -3,8 +3,8 @@ /// Specifies the graphics API enum GfxAPI { - OPENGL, - VULKAN + OpenGL, + Vulkan }; #endif diff --git a/src/bebone/gfx/gfx_backend.h b/src/bebone/gfx/gfx_backend.h index cb36df94..aaf0f59f 100644 --- a/src/bebone/gfx/gfx_backend.h +++ b/src/bebone/gfx/gfx_backend.h @@ -4,20 +4,16 @@ #include #include +#include #define GLFW_INCLUDE_VULKAN #include // Shader things -#include +#include #include #include -// Bebone things -#ifndef OMNI_GLAD_INTEGRATION - #define OMNI_GLAD_INTEGRATION -#endif - #include "../core/core.h" #endif diff --git a/src/bebone/gfx/glfw_context.cpp b/src/bebone/gfx/glfw_context.cpp index 99fc6c73..e63b24db 100644 --- a/src/bebone/gfx/glfw_context.cpp +++ b/src/bebone/gfx/glfw_context.cpp @@ -1,4 +1,5 @@ #include "glfw_context.h" +#include "gfx_backend.h" namespace bebone::gfx { void GLFWContext::init() { diff --git a/src/bebone/gfx/glfw_context.h b/src/bebone/gfx/glfw_context.h index bec3fc91..899f5ef7 100644 --- a/src/bebone/gfx/glfw_context.h +++ b/src/bebone/gfx/glfw_context.h @@ -3,33 +3,34 @@ #include -#include "gfx_backend.h" #include "window/window.h" namespace bebone::gfx { + class Window; + /// GLFW library wrapper class GLFWContext { - public: - /// Initializes the GLFW - static void init(); - - /*! - * glfwMakeContextCurrent function - * @param window - window object - */ - static void make_context_current(const Window& window); - - /*! - * glfwSwapBuffers function - * @param window - window object - */ - static void swap_buffers(const Window& window); - - /// glfwPollEvents function - static void poll_events(); - - /// Terminates the GLFW - static void terminate(); + public: + /// Initializes the GLFW + static void init(); + + /*! + * glfwMakeContextCurrent function + * @param window - window object + */ + static void make_context_current(const Window& window); + + /*! + * glfwSwapBuffers function + * @param window - window object + */ + static void swap_buffers(const Window& window); + + /// glfwPollEvents function + static void poll_events(); + + /// Terminates the GLFW + static void terminate(); }; } diff --git a/src/bebone/gfx/opengl/interface/i_opengl_element_buffer_object.h b/src/bebone/gfx/opengl/interface/i_opengl_element_buffer_object.h new file mode 100644 index 00000000..791a12c3 --- /dev/null +++ b/src/bebone/gfx/opengl/interface/i_opengl_element_buffer_object.h @@ -0,0 +1,21 @@ +#ifndef _BEBONE_GFX_I_OPENGL_ELEMENT_BUFFER_OBJECT_H_ +#define _BEBONE_GFX_I_OPENGL_ELEMENT_BUFFER_OBJECT_H_ + +#include "../../gfx_backend.h" + +namespace bebone::gfx { + using namespace bebone::core; + + class IOpenGLElementBufferObject { + public: + virtual ~IOpenGLElementBufferObject() = default; + + virtual void buffer_sub_data(const GLintptr& offset, const GLsizeiptr& size, const void* data) = 0; + + virtual void bind() = 0; + virtual void unbind() = 0; + virtual void destroy() = 0; + }; +} + +#endif diff --git a/src/bebone/gfx/opengl/interface/i_opengl_uniform_buffer_object.h b/src/bebone/gfx/opengl/interface/i_opengl_uniform_buffer_object.h new file mode 100644 index 00000000..891c875d --- /dev/null +++ b/src/bebone/gfx/opengl/interface/i_opengl_uniform_buffer_object.h @@ -0,0 +1,22 @@ +#ifndef _BEBONE_GFX_I_OPENGL_UNIFORM_BUFFER_OBJECT_H_ +#define _BEBONE_GFX_I_OPENGL_UNIFORM_BUFFER_OBJECT_H_ + +#include "../../gfx_backend.h" + +namespace bebone::gfx { + using namespace bebone::core; + + class IOpenGLUniformBufferObject { + public: + virtual ~IOpenGLUniformBufferObject() = default; + + virtual void bind_buffer_base(const i32& binding) const = 0; + virtual void* map() const = 0; + virtual void unmap() const = 0; + virtual void bind() = 0; + virtual void unbind() = 0; + virtual void destroy() = 0; + }; +} + +#endif diff --git a/src/bebone/gfx/opengl/interface/i_opengl_vertex_array_object.h b/src/bebone/gfx/opengl/interface/i_opengl_vertex_array_object.h new file mode 100644 index 00000000..eeded423 --- /dev/null +++ b/src/bebone/gfx/opengl/interface/i_opengl_vertex_array_object.h @@ -0,0 +1,22 @@ +#ifndef _BEBONE_GFX_I_OPENGL_VERTEX_ARRAY_OBJECT_H_ +#define _BEBONE_GFX_I_OPENGL_VERTEX_ARRAY_OBJECT_H_ + +#include "i_opengl_vertex_buffer_object.h" +#include "../../gfx_backend.h" + +namespace bebone::gfx { + using namespace bebone::core; + + class IOpenGLVertexArrayObject { + public: + virtual ~IOpenGLVertexArrayObject() = default; + virtual void link_attributes(IOpenGLVertexBufferObject& vbo, GLuint layout, GLuint num_components, GLenum type, GLsizeiptr stride, const u64& offset) = 0; + virtual void link_attributes(IOpenGLVertexBufferObject& vbo, GLuint layout, GLuint num_components, GLenum type, GLsizeiptr stride, void* offset) = 0; + + virtual void bind() = 0; + virtual void unbind() = 0; + virtual void destroy() = 0; + }; +} + +#endif diff --git a/src/bebone/gfx/opengl/interface/i_opengl_vertex_buffer_object.h b/src/bebone/gfx/opengl/interface/i_opengl_vertex_buffer_object.h new file mode 100644 index 00000000..9990383f --- /dev/null +++ b/src/bebone/gfx/opengl/interface/i_opengl_vertex_buffer_object.h @@ -0,0 +1,21 @@ +#ifndef _BEBONE_GFX_I_OPENGL_VERTEX_BUFFER_OBJECT_H_ +#define _BEBONE_GFX_I_OPENGL_VERTEX_BUFFER_OBJECT_H_ + +#include "../../gfx_backend.h" + +namespace bebone::gfx { + using namespace bebone::core; + + class IOpenGLVertexBufferObject { + public: + virtual ~IOpenGLVertexBufferObject() = default; + + virtual void buffer_sub_data(const GLintptr& offset, const GLsizeiptr& size, const void* data) = 0; + + virtual void bind() = 0; + virtual void unbind() = 0; + virtual void destroy() = 0; + }; +} + +#endif diff --git a/src/bebone/gfx/opengl/opengl_api.h b/src/bebone/gfx/opengl/opengl_api.h index aba418c9..22fe0025 100644 --- a/src/bebone/gfx/opengl/opengl_api.h +++ b/src/bebone/gfx/opengl/opengl_api.h @@ -1,10 +1,9 @@ -#ifndef _BEBONE_GFX_OPENGL_OPENGL_API_H_ -#define _BEBONE_GFX_OPENGL_OPENGL_API_H_ +#ifndef _BEBONE_GFX_OPENGL_API_H_ +#define _BEBONE_GFX_OPENGL_API_H_ #include "opengl_context.h" #include "opengl_gpu_properties.h" -#include "opengl_buffer_object.h" #include "opengl_vertex_array_object.h" #include "opengl_vertex_buffer_object.h" #include "opengl_element_buffer_object.h" @@ -14,6 +13,8 @@ #include "opengl_shader_factory.h" #include "opengl_texture.h" +#include "opengl_framebuffer.h" +#include "opengl_renderbuffer.h" #include "opengl_texture_1d.h" #include "opengl_texture_2d.h" diff --git a/src/bebone/gfx/opengl/opengl_buffer_object.cpp b/src/bebone/gfx/opengl/opengl_buffer_object.cpp deleted file mode 100644 index 355343cd..00000000 --- a/src/bebone/gfx/opengl/opengl_buffer_object.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include "opengl_buffer_object.h" - -namespace bebone::gfx::opengl { - GLBufferObject::GLBufferObject() { - glGenBuffers(1, &id); - } -} \ No newline at end of file diff --git a/src/bebone/gfx/opengl/opengl_buffer_object.h b/src/bebone/gfx/opengl/opengl_buffer_object.h deleted file mode 100644 index 6d4d04cd..00000000 --- a/src/bebone/gfx/opengl/opengl_buffer_object.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef _BEBONE_GFX_OPENGL_OPENGL_BUFFER_OBJECT_H_ -#define _BEBONE_GFX_OPENGL_OPENGL_BUFFER_OBJECT_H_ - -#include "../gfx_backend.h" - -namespace bebone::gfx::opengl { - /// Abstract buffer object which can be initialized, bound, unbound and destroyed - class GLBufferObject : private core::NonCopyable { - protected: - GLuint id; - - public: - /// Generates buffer object and assigns unique ID to it - GLBufferObject(); - - virtual void bind() = 0; - virtual void unbind() = 0; - virtual void destroy() = 0; - }; -} - -#endif diff --git a/src/bebone/gfx/opengl/opengl_context.h b/src/bebone/gfx/opengl/opengl_context.h index 22ee884c..7a87beeb 100644 --- a/src/bebone/gfx/opengl/opengl_context.h +++ b/src/bebone/gfx/opengl/opengl_context.h @@ -1,16 +1,24 @@ -#ifndef _BEBONE_GFX_OPENGL_OPENGL_CONTEXT_H_ -#define _BEBONE_GFX_OPENGL_OPENGL_CONTEXT_H_ +#ifndef _BEBONE_GFX_OPENGL_CONTEXT_H_ +#define _BEBONE_GFX_OPENGL_CONTEXT_H_ #include "../gfx_backend.h" -namespace bebone::gfx::opengl { +namespace bebone::gfx { using namespace bebone::core; /// OpenGL context wrapper struct GLContext { static void inline load_opengl() { - // TODO we need to check if load successful - gladLoadGL(); + if(gladLoadGL() == 0) { + LOG_CRITICAL("Failed to load OpenGL"); + // Todo throw std::runtime_error("Failed to load OpenGL"); + } + + // Setting default opengl settings + enable(GL_CULL_FACE); + enable(GL_DEPTH_TEST); + front_face(GL_CCW); + cull_face(GL_BACK); } static void inline enable(const GLenum& cap) { diff --git a/src/bebone/gfx/opengl/opengl_element_buffer_object.cpp b/src/bebone/gfx/opengl/opengl_element_buffer_object.cpp index 3c3d3442..820142c1 100644 --- a/src/bebone/gfx/opengl/opengl_element_buffer_object.cpp +++ b/src/bebone/gfx/opengl/opengl_element_buffer_object.cpp @@ -1,7 +1,9 @@ #include "opengl_element_buffer_object.h" -namespace bebone::gfx::opengl { - GLElementBufferObject::GLElementBufferObject(const void* indices, const GLsizeiptr& size, const GLenum& usage) : GLBufferObject() { +namespace bebone::gfx { + GLElementBufferObject::GLElementBufferObject(const void* indices, const GLsizeiptr& size, const GLenum& usage) { + glGenBuffers(1, &id); + bind(); glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, indices, usage); } diff --git a/src/bebone/gfx/opengl/opengl_element_buffer_object.h b/src/bebone/gfx/opengl/opengl_element_buffer_object.h index 576b2d73..00639192 100644 --- a/src/bebone/gfx/opengl/opengl_element_buffer_object.h +++ b/src/bebone/gfx/opengl/opengl_element_buffer_object.h @@ -1,11 +1,14 @@ -#ifndef _BEBONE_GFX_OPENGL_OPENGL_ELEMENT_BUFFER_OBJECT_H_ -#define _BEBONE_GFX_OPENGL_OPENGL_ELEMENT_BUFFER_OBJECT_H_ +#ifndef _BEBONE_GFX_OPENGL_ELEMENT_BUFFER_OBJECT_H_ +#define _BEBONE_GFX_OPENGL_ELEMENT_BUFFER_OBJECT_H_ -#include "opengl_buffer_object.h" +#include "interface/i_opengl_element_buffer_object.h" -namespace bebone::gfx::opengl { +namespace bebone::gfx { /// EBO - class GLElementBufferObject final : public GLBufferObject { + class GLElementBufferObject : public IOpenGLElementBufferObject { + private: + u32 id; + public: /*! * Generates EBO and assigns unique ID @@ -15,8 +18,7 @@ namespace bebone::gfx::opengl { */ GLElementBufferObject(const void* indices, const GLsizeiptr& size, const GLenum& usage = GL_STATIC_DRAW); - /// Destroys the EBO - ~GLElementBufferObject(); + ~GLElementBufferObject() override; /*! * Updates a subset of a EBO data store. Automatically binds and unbinds the EBO. To use this method EBO usage must be set to GL_DYNAMIC_DRAW @@ -24,16 +26,16 @@ namespace bebone::gfx::opengl { * @param size - specifies the size in bytes of the data store region being replaced. * @param data - specifies a pointer to the new data that will be copied into the data store */ - void buffer_sub_data(const GLintptr& offset, const GLsizeiptr& size, const void* data); + void buffer_sub_data(const GLintptr& offset, const GLsizeiptr& size, const void* data) override; /// Binds EBO - void bind(); + void bind() override; /// Unbinds EBO - void unbind(); + void unbind() override; /// Destroys EBO. Calls automatically in the destructor - void destroy(); + void destroy() override; }; } diff --git a/src/bebone/gfx/opengl/opengl_extension_checker.cpp b/src/bebone/gfx/opengl/opengl_extension_checker.cpp index e6841b63..b0105e0f 100644 --- a/src/bebone/gfx/opengl/opengl_extension_checker.cpp +++ b/src/bebone/gfx/opengl/opengl_extension_checker.cpp @@ -1,20 +1,20 @@ #include "opengl_extension_checker.h" -namespace bebone::gfx::opengl { +namespace bebone::gfx { GLExtensionChecker::GLExtensionChecker() { update_extension_set(); } void GLExtensionChecker::update_extension_set() { - GLint no_of_extensions = 0; - glGetIntegerv(GL_NUM_EXTENSIONS, &no_of_extensions); + GLint num_of_extensions = 0; + glGetIntegerv(GL_NUM_EXTENSIONS, &num_of_extensions); - for (int i = 0; i < no_of_extensions; ++i) - m_extensions.insert((const char*)glGetStringi(GL_EXTENSIONS, i)); + for (int i = 0; i < num_of_extensions; ++i) + extensions.insert((const char*)glGetStringi(GL_EXTENSIONS, i)); } bool GLExtensionChecker::check(const std::string& extension) const { - return m_extensions.find(extension) != m_extensions.end(); + return extensions.find(extension) != extensions.end(); } bool GLExtensionChecker::available(const std::string& extension) { diff --git a/src/bebone/gfx/opengl/opengl_extension_checker.h b/src/bebone/gfx/opengl/opengl_extension_checker.h index 858cfa15..4103e5a8 100644 --- a/src/bebone/gfx/opengl/opengl_extension_checker.h +++ b/src/bebone/gfx/opengl/opengl_extension_checker.h @@ -1,16 +1,16 @@ -#ifndef _BEBONE_GFX_OPENGL_OPENGL_EXTENSION_CHECKER_H_ -#define _BEBONE_GFX_OPENGL_OPENGL_EXTENSION_CHECKER_H_ +#ifndef _BEBONE_GFX_OPENGL_EXTENSION_CHECKER_H_ +#define _BEBONE_GFX_OPENGL_EXTENSION_CHECKER_H_ #include "../gfx_backend.h" #include #include -namespace bebone::gfx::opengl { +namespace bebone::gfx { /// Class used fort checking if specific opengl gl extension is available on device class GLExtensionChecker : private core::NonCopyable { private: - std::set m_extensions; + std::set extensions; /// Default constructor GLExtensionChecker(); diff --git a/src/bebone/gfx/opengl/opengl_framebuffer.cpp b/src/bebone/gfx/opengl/opengl_framebuffer.cpp new file mode 100644 index 00000000..9ebd0fc2 --- /dev/null +++ b/src/bebone/gfx/opengl/opengl_framebuffer.cpp @@ -0,0 +1,33 @@ +#include "opengl_framebuffer.h" + +namespace bebone::gfx { + using namespace bebone::core; + + GLFramebuffer::GLFramebuffer() { + glGenFramebuffers(1, &id); + } + + void GLFramebuffer::bind() { + glBindFramebuffer(GL_FRAMEBUFFER, id); + } + + void GLFramebuffer::unbind() { + glBindFramebuffer(GL_FRAMEBUFFER, 0); + } + + void GLFramebuffer::attach_texture_2d(const u32& attachment, GLTexture2D& texture) { + bind(); + + glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, texture.get_id(), 0); + + unbind(); + } + + void GLFramebuffer::attach_renderbuffer(const u32& attachment, GLRenderbuffer& renderbuffer) { + bind(); + + glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, renderbuffer.get_id()); + + unbind(); + } +} diff --git a/src/bebone/gfx/opengl/opengl_framebuffer.h b/src/bebone/gfx/opengl/opengl_framebuffer.h new file mode 100644 index 00000000..2095f621 --- /dev/null +++ b/src/bebone/gfx/opengl/opengl_framebuffer.h @@ -0,0 +1,31 @@ +#ifndef _BEBONE_GFX_OPENGL_FRAMEBUFFER_H_ +#define _BEBONE_GFX_OPENGL_FRAMEBUFFER_H_ + +#include "../gfx_backend.h" +#include "../shaders/shader_code.h" + +#include "opengl_shader_properties.h" +#include "opengl_uniform_buffer_object.h" + +#include "opengl_texture_2d.h" +#include "opengl_renderbuffer.h" + +namespace bebone::gfx { + using namespace bebone::core; + + class GLFramebuffer : private core::NonCopyable { + private: + GLuint id; + + public: + GLFramebuffer(); + + void bind(); + void unbind(); + + void attach_texture_2d(const u32& attachment, GLTexture2D& texture); + void attach_renderbuffer(const u32& attachment, GLRenderbuffer& renderbuffer); + }; +} + +#endif diff --git a/src/bebone/gfx/opengl/opengl_gpu_properties.cpp b/src/bebone/gfx/opengl/opengl_gpu_properties.cpp index 9414f295..1e051191 100644 --- a/src/bebone/gfx/opengl/opengl_gpu_properties.cpp +++ b/src/bebone/gfx/opengl/opengl_gpu_properties.cpp @@ -1,10 +1,10 @@ #include "opengl_gpu_properties.h" -namespace bebone::gfx::opengl { +namespace bebone::gfx { int GLGpuProperties::texture_unit_capacity() { - int textureUnitCapacity = 0; - glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &textureUnitCapacity); + int texture_unit_capacity = 0; + glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &texture_unit_capacity); - return textureUnitCapacity; + return texture_unit_capacity; } } \ No newline at end of file diff --git a/src/bebone/gfx/opengl/opengl_gpu_properties.h b/src/bebone/gfx/opengl/opengl_gpu_properties.h index a6e25949..4aa1a093 100644 --- a/src/bebone/gfx/opengl/opengl_gpu_properties.h +++ b/src/bebone/gfx/opengl/opengl_gpu_properties.h @@ -1,9 +1,9 @@ -#ifndef _BEBONE_GFX_OPENGL_OPENGL_GPU_PROPERTIES_H_ -#define _BEBONE_GFX_OPENGL_OPENGL_GPU_PROPERTIES_H_ +#ifndef _BEBONE_GFX_OPENGL_GPU_PROPERTIES_H_ +#define _BEBONE_GFX_OPENGL_GPU_PROPERTIES_H_ #include "../gfx_backend.h" -namespace bebone::gfx::opengl { +namespace bebone::gfx { class GLGpuProperties : private core::NonCopyable { public: static int texture_unit_capacity(); diff --git a/src/bebone/gfx/opengl/opengl_renderbuffer.cpp b/src/bebone/gfx/opengl/opengl_renderbuffer.cpp new file mode 100644 index 00000000..94c0e928 --- /dev/null +++ b/src/bebone/gfx/opengl/opengl_renderbuffer.cpp @@ -0,0 +1,27 @@ +#include "opengl_renderbuffer.h" + +namespace bebone::gfx { + GLRenderbuffer::GLRenderbuffer() { + glGenRenderbuffers(1, &id); + } + + void GLRenderbuffer::storage(const u32& type, const u32& width, const u32& height) { + bind(); + + glRenderbufferStorage(GL_RENDERBUFFER, type, width, height); + + unbind(); + } + + void GLRenderbuffer::bind() { + glBindRenderbuffer(GL_RENDERBUFFER, id); + } + + void GLRenderbuffer::unbind() { + glBindRenderbuffer(GL_RENDERBUFFER, 0); + } + + GLuint GLRenderbuffer::get_id() const { + return id; + } +} diff --git a/src/bebone/gfx/opengl/opengl_renderbuffer.h b/src/bebone/gfx/opengl/opengl_renderbuffer.h new file mode 100644 index 00000000..e79ccdc4 --- /dev/null +++ b/src/bebone/gfx/opengl/opengl_renderbuffer.h @@ -0,0 +1,32 @@ +#ifndef _BEBONE_GFX_OPENGL_RENDERBUFFER_H_ +#define _BEBONE_GFX_OPENGL_RENDERBUFFER_H_ + +#include "../gfx_backend.h" +#include "../shaders/shader_code.h" + +#include "opengl_shader_properties.h" +#include "opengl_uniform_buffer_object.h" + +#include "opengl_texture_2d.h" + +namespace bebone::gfx { + using namespace bebone::core; + + class GLRenderbuffer : private core::NonCopyable { + private: + GLuint id; + + public: + GLRenderbuffer(); + + // Todo + void storage(const u32& type, const u32& width, const u32& height); + + void bind(); + void unbind(); + + GLuint get_id() const; + }; +} + +#endif diff --git a/src/bebone/gfx/opengl/opengl_shader.cpp b/src/bebone/gfx/opengl/opengl_shader.cpp index 33946c45..defb5d9b 100644 --- a/src/bebone/gfx/opengl/opengl_shader.cpp +++ b/src/bebone/gfx/opengl/opengl_shader.cpp @@ -1,62 +1,60 @@ #include "opengl_shader.h" -namespace bebone::gfx::opengl { - GLShader::GLShader(const ShaderCode& code, const ShaderType& shaderType, const GLShaderProperties& properties) - : m_properties(properties) { +namespace bebone::gfx { + GLShader::GLShader(const ShaderCode& code, const ShaderType& shader_type, const GLShaderProperties& properties) + : properties(properties) { - m_shader = glCreateShader(shaderType.to_opengl()); + shader = glCreateShader(to_opengl(shader_type)); const auto& source = code.get_byte_code(); // **_ARB things can be used only with specific glad extensions, see all-extensions glad branch // This should always work, since we now check if device can use SPIRV shader binary code. // If no, then factory will try to use second constructor - glShaderBinary(1, &m_shader, GL_SHADER_BINARY_FORMAT_SPIR_V_ARB, source.data(), source.size() * sizeof(unsigned int)); - glSpecializeShaderARB(m_shader, "main", 0, nullptr, nullptr); + glShaderBinary(1, &shader, GL_SHADER_BINARY_FORMAT_SPIR_V_ARB, source.data(), source.size() * sizeof(unsigned int)); + glSpecializeShaderARB(shader, "main", 0, nullptr, nullptr); } GLShader::~GLShader() { destroy(); } - GLShader::GLShader(const std::string& code, const ShaderType& shaderType, const GLShaderProperties& properties) - : m_properties(properties) { + GLShader::GLShader(const std::string& code, const ShaderType& shader_type, const GLShaderProperties& properties) + : properties(properties) { - m_shader = glCreateShader(shaderType.to_opengl()); + shader = glCreateShader(to_opengl(shader_type)); const auto str = code.c_str(); - glShaderSource(m_shader, 1, &str, nullptr); - glCompileShader(m_shader); + glShaderSource(shader, 1, &str, nullptr); + glCompileShader(shader); - check_shader_compilation(m_shader); + check_shader_compilation(shader); } void GLShader::check_shader_compilation(const GLuint& shader) { - char infoLog[512]; + char info_log[512]; i32 success; glGetShaderiv(shader, GL_COMPILE_STATUS, &success); if(!success) { - glGetShaderInfoLog(shader, 512, nullptr, infoLog); + glGetShaderInfoLog(shader, 512, nullptr, info_log); - // Todo resolve this - std::cout << infoLog << "\n"; - - throw std::runtime_error("Failed to compile shader, with error: " + std::string(infoLog)); + LOG_ERROR("Failed to compile shader, with error: {}", std::string(info_log)); + // throw std::runtime_error("Failed to compile shader, with error: " + ); Todo } } GLuint GLShader::get_shader() const { - return m_shader; + return shader; } const GLShaderProperties& GLShader::get_properties() const { - return m_properties; + return properties; } void GLShader::destroy() { - glDeleteShader(m_shader); + glDeleteShader(shader); } } diff --git a/src/bebone/gfx/opengl/opengl_shader.h b/src/bebone/gfx/opengl/opengl_shader.h index 3373bb49..45b62e9c 100644 --- a/src/bebone/gfx/opengl/opengl_shader.h +++ b/src/bebone/gfx/opengl/opengl_shader.h @@ -1,5 +1,5 @@ -#ifndef _BEBONE_GFX_OPENGL_OPENGL_SHADER_H_ -#define _BEBONE_GFX_OPENGL_OPENGL_SHADER_H_ +#ifndef _BEBONE_GFX_OPENGL_SHADER_H_ +#define _BEBONE_GFX_OPENGL_SHADER_H_ #include "../gfx_backend.h" #include "../shaders/shader_code.h" @@ -7,14 +7,14 @@ #include "opengl_shader_properties.h" #include "opengl_uniform_buffer_object.h" -namespace bebone::gfx::opengl { +namespace bebone::gfx { using namespace bebone::core; /// Opengl shader wrapper class GLShader : private core::NonCopyable { private: - GLuint m_shader; - GLShaderProperties m_properties; + GLuint shader; + GLShaderProperties properties; /*! * Checks if opengl shader is compiled successfully @@ -26,18 +26,18 @@ namespace bebone::gfx::opengl { /*! * Default constructor * @param code - Shader code object - * @param shaderType - Shader type + * @param shader_type - Shader type * @param properties - Shader properties object */ - GLShader(const ShaderCode& code, const ShaderType& shaderType, const GLShaderProperties& properties = NONE); + GLShader(const ShaderCode& code, const ShaderType& shader_type, const GLShaderProperties& properties = None); /*! * Default constructor * @param code - Shader string code - * @param shaderType - Shader type + * @param shader_type - Shader type * @param properties - Shader properties object */ - GLShader(const std::string& code, const ShaderType& shaderType, const GLShaderProperties& properties = NONE); + GLShader(const std::string& code, const ShaderType& shader_type, const GLShaderProperties& properties = None); ~GLShader(); /*! diff --git a/src/bebone/gfx/opengl/opengl_shader_factory.cpp b/src/bebone/gfx/opengl/opengl_shader_factory.cpp index 31439fe9..ff256a8f 100644 --- a/src/bebone/gfx/opengl/opengl_shader_factory.cpp +++ b/src/bebone/gfx/opengl/opengl_shader_factory.cpp @@ -1,15 +1,8 @@ #include "opengl_shader_factory.h" -namespace bebone::gfx::opengl { - std::string GLShaderFactory::read_file(const std::string& path) { - std::ifstream file(path); - std::stringstream ss; - ss << file.rdbuf(); - return ss.str(); - } - +namespace bebone::gfx { bool GLShaderFactory::is_use_legacy_compiler(const GLShaderProperties& properties) { - if (properties & GLShaderProperties::ENABLE_UNIFORMS) + if (properties & GLShaderProperties::EnableUniforms) return true; // There we check if device supports SPIR-V binary shaders @@ -19,17 +12,17 @@ namespace bebone::gfx::opengl { return false; } - GLShader GLShaderFactory::create_shader(const std::string& path, const ShaderType& shaderType, const GLShaderProperties& properties) { - const auto source = read_file(path); + GLShader GLShaderFactory::create_shader(const std::string& path, const ShaderType& shader_type, const GLShaderProperties& properties) { + const auto source = utils_read_file(path); if (is_use_legacy_compiler(properties)) - return GLShader(source, shaderType, properties); + return GLShader(source, shader_type, properties); - SpirVShaderCompiler shaderCompiler; + SpirVShaderCompiler shader_compiler; - shaderCompiler.add_shader_source(ShaderSource(source, shaderType)); - const auto code = shaderCompiler.compile(shaderType); + shader_compiler.add_shader_source(ShaderSource(source, shader_type)); + const auto code = shader_compiler.compile(shader_type); - return GLShader(code, shaderType, properties); + return GLShader(code, shader_type, properties); } } diff --git a/src/bebone/gfx/opengl/opengl_shader_factory.h b/src/bebone/gfx/opengl/opengl_shader_factory.h index 9d793c5d..033febbe 100644 --- a/src/bebone/gfx/opengl/opengl_shader_factory.h +++ b/src/bebone/gfx/opengl/opengl_shader_factory.h @@ -1,5 +1,5 @@ -#ifndef _BEBONE_GFX_OPENGL_OPENGL_SHADER_FACTORY_H_ -#define _BEBONE_GFX_OPENGL_OPENGL_SHADER_FACTORY_H_ +#ifndef _BEBONE_GFX_OPENGL_SHADER_FACTORY_H_ +#define _BEBONE_GFX_OPENGL_SHADER_FACTORY_H_ #include "../shaders/shader_type.h" @@ -9,11 +9,10 @@ #include "opengl_extension_checker.h" #include "opengl_shader.h" -namespace bebone::gfx::opengl { +namespace bebone::gfx { /// This class is used to create shaders class GLShaderFactory { private: - static std::string read_file(const std::string& path); static bool is_use_legacy_compiler(const GLShaderProperties& properties); public: @@ -22,11 +21,11 @@ namespace bebone::gfx::opengl { /*! * Creates shader object from the specified file and parameters * @param path - path to the glsl shader file - * @param shaderType - specifies the shader type (vertex or fragment) + * @param shader_type - specifies the shader type (vertex or fragment) * @param properties - specifies other shader properties, like enabling uniforms * @return shader object */ - static GLShader create_shader(const std::string& path, const ShaderType& shaderType, const GLShaderProperties& properties = NONE); + static GLShader create_shader(const std::string& path, const ShaderType& shader_type, const GLShaderProperties& properties = None); }; } diff --git a/src/bebone/gfx/opengl/opengl_shader_program.cpp b/src/bebone/gfx/opengl/opengl_shader_program.cpp index bb973664..6597c47f 100644 --- a/src/bebone/gfx/opengl/opengl_shader_program.cpp +++ b/src/bebone/gfx/opengl/opengl_shader_program.cpp @@ -1,16 +1,17 @@ #include "opengl_shader_program.h" -namespace bebone::gfx::opengl { +namespace bebone::gfx { GLShaderProgram::GLShaderProgram(const GLShader& vertex, const GLShader& fragment) { create_shader_program(vertex, fragment); if(vertex.get_properties() != fragment.get_properties()) { // Todo, we need to have some sort of policy for compatibility of shader properties - throw std::runtime_error("Provided opengl shaders have different properties, therefore they can not be use for shader program creation"); + LOG_ERROR("Provided OpenGL shaders have different properties, therefore they can not be use for shader program creation"); + // throw std::runtime_error("Provided OpenGL shaders have different properties, therefore they can not be use for shader program creation"); Todo } // Todo also look there - m_properties = vertex.get_properties() | fragment.get_properties(); + properties = vertex.get_properties() | fragment.get_properties(); } GLShaderProgram::~GLShaderProgram() { @@ -28,84 +29,82 @@ namespace bebone::gfx::opengl { void GLShaderProgram::check_program_linking(const GLuint& program) { i32 success; - char infoLog[512]; + char info_log[512]; glGetProgramiv(program, GL_LINK_STATUS, &success); if (!success) { - glGetProgramInfoLog(program, 512, nullptr, infoLog); + glGetProgramInfoLog(program, 512, nullptr, info_log); - // Todo resolve this - std::cout << infoLog << "\n"; - - throw std::runtime_error("Failed to link shader program, with error: " + std::string(infoLog)); + // throw std::runtime_error("Failed to link shader program, with error: " + std::string(info_log)); Todo + LOG_ERROR("Failed to link shader program, with error: {}", std::string(info_log)); } } - GLint GLShaderProgram::get_uniform_location(const char* uniformName) const { - return glGetUniformLocation(id, uniformName); + GLint GLShaderProgram::get_uniform_location(const char* uniform_name) const { + return glGetUniformLocation(id, uniform_name); } - void GLShaderProgram::set_uniform(const char* uniformName, const i32& value) const { - if(m_properties & ENABLE_UNIFORMS) { - const auto uniform = get_uniform_location(uniformName); + void GLShaderProgram::set_uniform(const char* uniform_name, const i32& value) const { + if(properties & EnableUniforms) { + const auto uniform = get_uniform_location(uniform_name); glUniform1i(uniform, value); } } - void GLShaderProgram::set_uniform(const char* uniformName, const GLsizei& size, const i32* value) const { - if(m_properties & ENABLE_UNIFORMS) { - const auto uniform = get_uniform_location(uniformName); + void GLShaderProgram::set_uniform(const char* uniform_name, const GLsizei& size, const i32* value) const { + if(properties & EnableUniforms) { + const auto uniform = get_uniform_location(uniform_name); glUniform1iv(uniform, size, value); } } - void GLShaderProgram::set_uniform(const char* uniformName, const u32& value) const { - if(m_properties & ENABLE_UNIFORMS) { - const auto uniform = get_uniform_location(uniformName); + void GLShaderProgram::set_uniform(const char* uniform_name, const u32& value) const { + if(properties & EnableUniforms) { + const auto uniform = get_uniform_location(uniform_name); glUniform1ui(uniform, value); } } - void GLShaderProgram::set_uniform(const char* uniformName, const f32& value) const { - if(m_properties & ENABLE_UNIFORMS) { - const auto uniform = get_uniform_location(uniformName); + void GLShaderProgram::set_uniform(const char* uniform_name, const f32& value) const { + if(properties & EnableUniforms) { + const auto uniform = get_uniform_location(uniform_name); glUniform1f(uniform, value); } } - void GLShaderProgram::set_uniform(const char* uniformName, const Vec2f& value) const { - if(m_properties & ENABLE_UNIFORMS) { - const auto uniform = get_uniform_location(uniformName); + void GLShaderProgram::set_uniform(const char* uniform_name, const Vec2f& value) const { + if(properties & EnableUniforms) { + const auto uniform = get_uniform_location(uniform_name); glUniform2f(uniform, value.x, value.y); } } - void GLShaderProgram::set_uniform(const char* uniformName, const Vec3f& value) const { - if(m_properties & ENABLE_UNIFORMS) { - const auto uniform = get_uniform_location(uniformName); + void GLShaderProgram::set_uniform(const char* uniform_name, const Vec3f& value) const { + if(properties & EnableUniforms) { + const auto uniform = get_uniform_location(uniform_name); glUniform3f(uniform, value.x, value.y, value.z); } } - void GLShaderProgram::set_uniform(const char* uniformName, const Vec4f& value) const { - if(m_properties & ENABLE_UNIFORMS) { - const auto uniform = get_uniform_location(uniformName); + void GLShaderProgram::set_uniform(const char* uniform_name, const Vec4f& value) const { + if(properties & EnableUniforms) { + const auto uniform = get_uniform_location(uniform_name); glUniform4f(uniform, value.x, value.y, value.z, value.w); } } - void GLShaderProgram::set_uniform(const char* uniformName, const Mat4f& value) const { - if(m_properties & ENABLE_UNIFORMS) { - const auto uniform = get_uniform_location(uniformName); - glUniformMatrix4fv(uniform, 1, GL_FALSE, value.e); + void GLShaderProgram::set_uniform(const char* uniform_name, const Mat4f& value) const { + if(properties & EnableUniforms) { + const auto uniform = get_uniform_location(uniform_name); + glUniformMatrix4fv(uniform, 1, GL_FALSE, value.get_raw()); } } - void GLShaderProgram::bind_buffer(const char* uniformBufferName, const i32& binding, const GLUniformBufferObject& buffer) const { + void GLShaderProgram::bind_buffer(const char* uniform_buffer_name, const i32& binding, const GLUniformBufferObject& buffer) const { buffer.bind_buffer_base(binding); - const auto uboIndex = glGetUniformBlockIndex(id, uniformBufferName); - glUniformBlockBinding(id, uboIndex, binding); + const auto ubo_index = glGetUniformBlockIndex(id, uniform_buffer_name); + glUniformBlockBinding(id, ubo_index, binding); } void GLShaderProgram::enable() { diff --git a/src/bebone/gfx/opengl/opengl_shader_program.h b/src/bebone/gfx/opengl/opengl_shader_program.h index 9a1ebcf3..3c040784 100644 --- a/src/bebone/gfx/opengl/opengl_shader_program.h +++ b/src/bebone/gfx/opengl/opengl_shader_program.h @@ -1,21 +1,21 @@ -#ifndef _BEBONE_GFX_OPENGL_OPENGL_SHADER_PROGRAM_H_ -#define _BEBONE_GFX_OPENGL_OPENGL_SHADER_PROGRAM_H_ +#ifndef _BEBONE_GFX_OPENGL_SHADER_PROGRAM_H_ +#define _BEBONE_GFX_OPENGL_SHADER_PROGRAM_H_ #include "../gfx_backend.h" #include "opengl_shader_properties.h" #include "opengl_shader.h" -namespace bebone::gfx::opengl { +namespace bebone::gfx { using namespace bebone::core; /// Shader Program class GLShaderProgram : private NonCopyable { private: GLuint id; - GLShaderProperties m_properties; + GLShaderProperties properties; void create_shader_program(const GLShader& vertex, const GLShader& fragment); - GLint get_uniform_location(const char* uniformName) const; + GLint get_uniform_location(const char* uniform_name) const; static void check_program_linking(const GLuint& program); @@ -30,68 +30,68 @@ namespace bebone::gfx::opengl { /*! * glUniform1i - * @param uniformName - uniform name from the shader + * @param uniform_name - uniform name from the shader * @param value - the value to be assigned to the uniform */ - void set_uniform(const char* uniformName, const i32& value) const; + void set_uniform(const char* uniform_name, const i32& value) const; /*! * glUniform1iv - * @param uniformName - uniform name from the shader + * @param uniform_name - uniform name from the shader * @param size - array size (not in bytes) * @param value - the value to be assigned to the uniform */ - void set_uniform(const char* uniformName, const GLsizei& size, const i32* value) const; + void set_uniform(const char* uniform_name, const GLsizei& size, const i32* value) const; /*! * glUniform1ui - * @param uniformName - uniform name from the shader + * @param uniform_name - uniform name from the shader * @param value - the value to be assigned to the uniform */ - void set_uniform(const char* uniformName, const u32& value) const; + void set_uniform(const char* uniform_name, const u32& value) const; /*! * glUniform1f - * @param uniformName - uniform name from the shader + * @param uniform_name - uniform name from the shader * @param value - the value to be assigned to the uniform */ - void set_uniform(const char* uniformName, const f32& value) const; + void set_uniform(const char* uniform_name, const f32& value) const; /*! * glUniform2f - * @param uniformName - uniform name from the shader + * @param uniform_name - uniform name from the shader * @param value - the value to be assigned to the uniform */ - void set_uniform(const char* uniformName, const Vec2f& value) const; + void set_uniform(const char* uniform_name, const Vec2f& value) const; /*! * glUniform3f - * @param uniformName - uniform name from the shader + * @param uniform_name - uniform name from the shader * @param value - the value to be assigned to the uniform */ - void set_uniform(const char* uniformName, const Vec3f& value) const; + void set_uniform(const char* uniform_name, const Vec3f& value) const; /*! * glUniform4f - * @param uniformName - uniform name from the shader + * @param uniform_name - uniform name from the shader * @param value - the value to be assigned to the uniform */ - void set_uniform(const char* uniformName, const Vec4f& value) const; + void set_uniform(const char* uniform_name, const Vec4f& value) const; /*! * glUniformMatrix4fv - * @param uniformName - uniform name from the shader + * @param uniform_name - uniform name from the shader * @param value - the value to be assigned to the uniform */ - void set_uniform(const char* uniformName, const Mat4f& value) const; + void set_uniform(const char* uniform_name, const Mat4f& value) const; /*! * Binds uniform buffer object to shader program - * @param uniformBufferName - uniform buffer name + * @param uniform_buffer_name - uniform buffer name * @param binding - uniform buffer binding * @param buffer - GLUniformBufferObject object */ - void bind_buffer(const char* uniformBufferName, const i32& binding, const GLUniformBufferObject& buffer) const; + void bind_buffer(const char* uniform_buffer_name, const i32& binding, const GLUniformBufferObject& buffer) const; /// Enables shader program void enable(); diff --git a/src/bebone/gfx/opengl/opengl_shader_properties.h b/src/bebone/gfx/opengl/opengl_shader_properties.h index bd412d3b..99057c11 100644 --- a/src/bebone/gfx/opengl/opengl_shader_properties.h +++ b/src/bebone/gfx/opengl/opengl_shader_properties.h @@ -1,10 +1,10 @@ -#ifndef _BEBONE_GFX_OPENGL_OPENGL_SHADER_PROPERTIES_H_ -#define _BEBONE_GFX_OPENGL_OPENGL_SHADER_PROPERTIES_H_ +#ifndef _BEBONE_GFX_OPENGL_SHADER_PROPERTIES_H_ +#define _BEBONE_GFX_OPENGL_SHADER_PROPERTIES_H_ -namespace bebone::gfx::opengl { +namespace bebone::gfx { enum GLShaderProperties { - NONE = (1 << 0), - ENABLE_UNIFORMS = (1 << 1), + None = (1 << 0), + EnableUniforms = (1 << 1), }; inline GLShaderProperties operator|(GLShaderProperties first, GLShaderProperties second) { diff --git a/src/bebone/gfx/opengl/opengl_texture.cpp b/src/bebone/gfx/opengl/opengl_texture.cpp index d743b3bb..d59ddd56 100644 --- a/src/bebone/gfx/opengl/opengl_texture.cpp +++ b/src/bebone/gfx/opengl/opengl_texture.cpp @@ -1,7 +1,7 @@ #include "opengl_texture.h" -namespace bebone::gfx::opengl { - GLTexture::GLTexture(const GLenum& textureType) : textureType(textureType) { +namespace bebone::gfx { + GLTexture::GLTexture(const GLenum& texture_type) : texture_type(texture_type) { glGenTextures(1, &id); } @@ -11,11 +11,11 @@ namespace bebone::gfx::opengl { void GLTexture::configure_gl_texture(const GLTextureParameters& parameters) { for(auto& param : parameters.parameters) - glTexParameteri(textureType, param.first, param.second); + glTexParameteri(texture_type, param.first, param.second); }; void GLTexture::generate_mipmap() { - glGenerateMipmap(textureType); + glGenerateMipmap(texture_type); } const GLuint& GLTexture::get_id() const { @@ -23,19 +23,19 @@ namespace bebone::gfx::opengl { } const GLenum& GLTexture::get_texture_type() const { - return textureType; + return texture_type; } - void GLTexture::bind_texture_unit(const GLuint& textureUnit) { - glBindTextureUnit(textureUnit, id); + void GLTexture::bind_texture_unit(const GLuint& texture_unit) { + glBindTextureUnit(texture_unit, id); } void GLTexture::bind() { - glBindTexture(textureType, id); + glBindTexture(texture_type, id); } void GLTexture::unbind() { - glBindTexture(textureType, 0); + glBindTexture(texture_type, 0); } void GLTexture::destroy() { diff --git a/src/bebone/gfx/opengl/opengl_texture.h b/src/bebone/gfx/opengl/opengl_texture.h index c7d41180..93269287 100644 --- a/src/bebone/gfx/opengl/opengl_texture.h +++ b/src/bebone/gfx/opengl/opengl_texture.h @@ -1,10 +1,10 @@ -#ifndef _BEBONE_GFX_OPENGL_OPENGL_TEXTURE_H_ -#define _BEBONE_GFX_OPENGL_OPENGL_TEXTURE_H_ +#ifndef _BEBONE_GFX_OPENGL_TEXTURE_H_ +#define _BEBONE_GFX_OPENGL_TEXTURE_H_ #include "../../assets/image/image.h" #include "../gfx_backend.h" -namespace bebone::gfx::opengl { +namespace bebone::gfx { using namespace bebone::assets; struct GLTextureParameters { @@ -19,7 +19,7 @@ namespace bebone::gfx::opengl { class GLTexture : private core::NonCopyable { private: GLuint id; - GLenum textureType; + GLenum texture_type; protected: void configure_gl_texture(const GLTextureParameters& parameters); @@ -28,9 +28,9 @@ namespace bebone::gfx::opengl { public: /*! * Default GLTexture constructor - * @param textureType - opengl texture type + * @param texture_type - opengl texture type */ - GLTexture(const GLenum& textureType); + GLTexture(const GLenum& texture_type); ~GLTexture(); // Getter for opengl texture handle @@ -41,9 +41,9 @@ namespace bebone::gfx::opengl { /*! * Binds texture to the specified texture unit - * @param textureUnit - texture unit, to which texture should be bound to + * @param texture_unit - texture unit, to which texture should be bound to */ - void bind_texture_unit(const GLuint& textureUnit); + void bind_texture_unit(const GLuint& texture_unit); /// Binds texture void bind(); diff --git a/src/bebone/gfx/opengl/opengl_texture_1d.cpp b/src/bebone/gfx/opengl/opengl_texture_1d.cpp index 91540419..4849804b 100644 --- a/src/bebone/gfx/opengl/opengl_texture_1d.cpp +++ b/src/bebone/gfx/opengl/opengl_texture_1d.cpp @@ -1,6 +1,6 @@ #include "opengl_texture_1d.h" -namespace bebone::gfx::opengl { +namespace bebone::gfx { GLTexture1D::GLTexture1D(const int& w, void* data) : GLTexture(GL_TEXTURE_1D), width(w) diff --git a/src/bebone/gfx/opengl/opengl_texture_1d.h b/src/bebone/gfx/opengl/opengl_texture_1d.h index 151e34f7..fbe70e91 100644 --- a/src/bebone/gfx/opengl/opengl_texture_1d.h +++ b/src/bebone/gfx/opengl/opengl_texture_1d.h @@ -1,5 +1,5 @@ -#ifndef _BEBONE_GFX_OPENGL_OPENGL_TEXTURE_1D_H_ -#define _BEBONE_GFX_OPENGL_OPENGL_TEXTURE_1D_H_ +#ifndef _BEBONE_GFX_OPENGL_TEXTURE_1D_H_ +#define _BEBONE_GFX_OPENGL_TEXTURE_1D_H_ #include "../../assets/image/image.h" @@ -7,7 +7,7 @@ #include "opengl_texture.h" -namespace bebone::gfx::opengl { +namespace bebone::gfx { using namespace bebone::assets; // Todo need testing diff --git a/src/bebone/gfx/opengl/opengl_texture_2d.cpp b/src/bebone/gfx/opengl/opengl_texture_2d.cpp index 266faba2..5dc6faa7 100644 --- a/src/bebone/gfx/opengl/opengl_texture_2d.cpp +++ b/src/bebone/gfx/opengl/opengl_texture_2d.cpp @@ -1,15 +1,15 @@ #include "opengl_texture_2d.h" -namespace bebone::gfx::opengl { +namespace bebone::gfx { void GLTexture2D::create_gl_texture() { - const auto format = ColorRGBA::get_gl_format(); - const auto type = ColorRGBA::get_gl_type(); + const auto format = get_gl_format(); + const auto type = get_gl_type(); bind(); glTexImage2D( - get_texture_type(), - 0, format, width, height, 0, - format, type, nullptr); + get_texture_type(), + 0, format, width, height, 0, + format, type, nullptr); const GLTextureParameters parameters; configure_gl_texture(parameters); @@ -17,19 +17,32 @@ namespace bebone::gfx::opengl { unbind(); } - template - void GLTexture2D::create_gl_texture(const std::shared_ptr>& image) { + void GLTexture2D::create_gl_texture(void* buffer, u32 format, u32 type) { + bind(); + glTexImage2D( + get_texture_type(), + 0, format, width, height, 0, + format, type, buffer); + + const GLTextureParameters parameters; + configure_gl_texture(parameters); + generate_mipmap(); + unbind(); + } + + template + void GLTexture2D::create_gl_texture(const std::shared_ptr>& image) { width = image->get_width(); height = image->get_height(); - const auto format = ColorRGBA::get_gl_format(); - const auto type = ColorRGBA::get_gl_type(); + const auto format = get_gl_format(); + const auto type = get_gl_type(); bind(); glTexImage2D( - get_texture_type(), - 0, format, width, height, 0, - format, type, image->data()); + get_texture_type(), + 0, format, width, height, 0, + format, type, image->data()); const GLTextureParameters parameters; configure_gl_texture(parameters); @@ -39,7 +52,7 @@ namespace bebone::gfx::opengl { template void GLTexture2D::create_gl_texture(const std::shared_ptr>& image); template void GLTexture2D::create_gl_texture(const std::shared_ptr>& image); - template void GLTexture2D::create_gl_texture(const std::shared_ptr>& image); + template void GLTexture2D::create_gl_texture(const std::shared_ptr>& image); GLTexture2D::GLTexture2D(const int& width, const int& height) : GLTexture(GL_TEXTURE_2D), @@ -49,27 +62,35 @@ namespace bebone::gfx::opengl { create_gl_texture(); } - GLTexture2D::GLTexture2D(const std::string& filePath) + GLTexture2D::GLTexture2D(const int& width, const int& height, void* buffer, u32 format, u32 type) + : GLTexture(GL_TEXTURE_2D), + width(width), + height(height) + { + create_gl_texture(buffer, format, type); + } + + GLTexture2D::GLTexture2D(const std::string& file_path) : GLTexture(GL_TEXTURE_2D), width(0), height(0) { - auto image = Image::load_from_file(filePath); + auto image = Image::load_from_file(file_path); create_gl_texture(image); } - template - GLTexture2D::GLTexture2D(const std::shared_ptr>& image) + template + GLTexture2D::GLTexture2D(const std::shared_ptr>& image) : GLTexture(GL_TEXTURE_2D), width(0), height(0) { - create_gl_texture<_Color>(image); + create_gl_texture(image); } template GLTexture2D::GLTexture2D(const std::shared_ptr>& image); template GLTexture2D::GLTexture2D(const std::shared_ptr>& image); - template GLTexture2D::GLTexture2D(const std::shared_ptr>& image); + template GLTexture2D::GLTexture2D(const std::shared_ptr>& image); const int& GLTexture2D::get_width() const { return width; diff --git a/src/bebone/gfx/opengl/opengl_texture_2d.h b/src/bebone/gfx/opengl/opengl_texture_2d.h index 5453aae4..63224b29 100644 --- a/src/bebone/gfx/opengl/opengl_texture_2d.h +++ b/src/bebone/gfx/opengl/opengl_texture_2d.h @@ -1,13 +1,14 @@ -#ifndef _BEBONE_GFX_OPENGL_OPENGL_TEXTURE_2D_H_ -#define _BEBONE_GFX_OPENGL_OPENGL_TEXTURE_2D_H_ +#ifndef _BEBONE_GFX_OPENGL_TEXTURE_2D_H_ +#define _BEBONE_GFX_OPENGL_TEXTURE_2D_H_ #include "../../assets/image/image.h" #include "../gfx_backend.h" +#include "../color_extensions.h" #include "opengl_texture.h" -namespace bebone::gfx::opengl { +namespace bebone::gfx { using namespace bebone::assets; class GLTexture2D : public GLTexture { @@ -17,8 +18,10 @@ namespace bebone::gfx::opengl { void create_gl_texture(); - template - void create_gl_texture(const std::shared_ptr>& image); + void create_gl_texture(void* buffer, u32 format, u32 type); + + template + void create_gl_texture(const std::shared_ptr>& image); public: /*! @@ -28,18 +31,20 @@ namespace bebone::gfx::opengl { */ GLTexture2D(const int& width, const int& height); + GLTexture2D(const int& width, const int& height, void* buffer, u32 format, u32 type); + /*! * Constructor, loads image from a file - * @param filePath - Image file path + * @param file_path - Image file path */ - GLTexture2D(const std::string& filePath); + GLTexture2D(const std::string& file_path); /*! * Constructor, creates GLTexture2D from already loaded image * @param image - Image */ - template - GLTexture2D(const std::shared_ptr>& image); + template + GLTexture2D(const std::shared_ptr>& image); // Getter for image width const int& get_width() const; diff --git a/src/bebone/gfx/opengl/opengl_texture_3d.cpp b/src/bebone/gfx/opengl/opengl_texture_3d.cpp index 8f03aa6e..4d648060 100644 --- a/src/bebone/gfx/opengl/opengl_texture_3d.cpp +++ b/src/bebone/gfx/opengl/opengl_texture_3d.cpp @@ -1,6 +1,6 @@ #include "opengl_texture_3d.h" -namespace bebone::gfx::opengl { +namespace bebone::gfx { GLTexture3D::GLTexture3D(const int& w, const int& h, const int& d, void* data) : GLTexture(GL_TEXTURE_3D), width(w), diff --git a/src/bebone/gfx/opengl/opengl_texture_3d.h b/src/bebone/gfx/opengl/opengl_texture_3d.h index a2ac05be..55ff747a 100644 --- a/src/bebone/gfx/opengl/opengl_texture_3d.h +++ b/src/bebone/gfx/opengl/opengl_texture_3d.h @@ -1,5 +1,5 @@ -#ifndef _BEBONE_GFX_OPENGL_OPENGL_TEXTURE_3D_H_ -#define _BEBONE_GFX_OPENGL_OPENGL_TEXTURE_3D_H_ +#ifndef _BEBONE_GFX_OPENGL_TEXTURE_3D_H_ +#define _BEBONE_GFX_OPENGL_TEXTURE_3D_H_ #include "../../assets/image/image.h" @@ -7,7 +7,7 @@ #include "opengl_texture.h" -namespace bebone::gfx::opengl { +namespace bebone::gfx { using namespace bebone::assets; // Todo need testing diff --git a/src/bebone/gfx/opengl/opengl_texture_cube_map.cpp b/src/bebone/gfx/opengl/opengl_texture_cube_map.cpp index a5987b47..5073c7e1 100644 --- a/src/bebone/gfx/opengl/opengl_texture_cube_map.cpp +++ b/src/bebone/gfx/opengl/opengl_texture_cube_map.cpp @@ -1,21 +1,21 @@ #include "opengl_texture_cube_map.h" -namespace bebone::gfx::opengl { - template - void GLTextureCubeMap::create_cube_map_texture(const std::array>, 6>& images) { +namespace bebone::gfx { + template + void GLTextureCubeMap::create_cube_map_texture(const std::array>, 6>& images) { bind(); for(auto i = 0; i < 6; ++i) { const auto width = images[i]->get_width(); const auto height = images[i]->get_height(); - const auto format = ColorRGBA::get_gl_format(); - const auto type = ColorRGBA::get_gl_type(); + const auto format = get_gl_format(); + const auto type = get_gl_type(); glTexImage2D( - GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, - 0, format, width, height, 0, - format, type, images[i]->data()); + GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, + 0, format, width, height, 0, + format, type, images[i]->data()); } const GLTextureParameters parameters; @@ -27,27 +27,27 @@ namespace bebone::gfx::opengl { template void GLTextureCubeMap::create_cube_map_texture(const std::array>, 6>& images); template void GLTextureCubeMap::create_cube_map_texture(const std::array>, 6>& images); - template void GLTextureCubeMap::create_cube_map_texture(const std::array>, 6>& images); + template void GLTextureCubeMap::create_cube_map_texture(const std::array>, 6>& images); - GLTextureCubeMap::GLTextureCubeMap(const std::vector& filePaths) : GLTexture(GL_TEXTURE_CUBE_MAP) { + GLTextureCubeMap::GLTextureCubeMap(const std::vector& file_paths) : GLTexture(GL_TEXTURE_CUBE_MAP) { std::array>, 6> images = { - Image::load_from_file(filePaths[0], false), // Todo - Image::load_from_file(filePaths[1], false), - Image::load_from_file(filePaths[2], false), - Image::load_from_file(filePaths[3], false), - Image::load_from_file(filePaths[4], false), - Image::load_from_file(filePaths[5], false) + Image::load_from_file(file_paths[0], false), // Todo + Image::load_from_file(file_paths[1], false), + Image::load_from_file(file_paths[2], false), + Image::load_from_file(file_paths[3], false), + Image::load_from_file(file_paths[4], false), + Image::load_from_file(file_paths[5], false) }; create_cube_map_texture(images); } - template - GLTextureCubeMap::GLTextureCubeMap(const std::array>, 6>& images) : GLTexture(GL_TEXTURE_CUBE_MAP) { - create_cube_map_texture<_Color>(images); + template + GLTextureCubeMap::GLTextureCubeMap(const std::array>, 6>& images) : GLTexture(GL_TEXTURE_CUBE_MAP) { + create_cube_map_texture(images); } template GLTextureCubeMap::GLTextureCubeMap(const std::array>, 6>& images); template GLTextureCubeMap::GLTextureCubeMap(const std::array>, 6>& images); - template GLTextureCubeMap::GLTextureCubeMap(const std::array>, 6>& images); + template GLTextureCubeMap::GLTextureCubeMap(const std::array>, 6>& images); } diff --git a/src/bebone/gfx/opengl/opengl_texture_cube_map.h b/src/bebone/gfx/opengl/opengl_texture_cube_map.h index cea0cc9f..d88305a8 100644 --- a/src/bebone/gfx/opengl/opengl_texture_cube_map.h +++ b/src/bebone/gfx/opengl/opengl_texture_cube_map.h @@ -1,34 +1,36 @@ -#ifndef _BEBONE_GFX_OPENGL_OPENGL_TEXTURE_CUBE_MAP_H_ -#define _BEBONE_GFX_OPENGL_OPENGL_TEXTURE_CUBE_MAP_H_ +#ifndef _BEBONE_GFX_OPENGL_TEXTURE_CUBE_MAP_H_ +#define _BEBONE_GFX_OPENGL_TEXTURE_CUBE_MAP_H_ +#include #include "../../assets/image/image.h" #include "../gfx_backend.h" +#include "../color_extensions.h" #include "opengl_texture.h" -namespace bebone::gfx::opengl { +namespace bebone::gfx { using namespace bebone::assets; class GLTextureCubeMap : public GLTexture { private: // Function that creates cube map from image array - template - void create_cube_map_texture(const std::array>, 6>& images); + template + void create_cube_map_texture(const std::array>, 6>& images); public: /*! * Constructor - * @param filePaths - container with file paths for cube map texture, 6 textures required + * @param file_paths - container with file paths for cube map texture, 6 textures required */ - GLTextureCubeMap(const std::vector& filePaths); + GLTextureCubeMap(const std::vector& file_paths); /*! * Constructor * @param images - 6 element array, with image for each cube side */ - template - GLTextureCubeMap(const std::array>, 6>& images); + template + GLTextureCubeMap(const std::array>, 6>& images); }; } diff --git a/src/bebone/gfx/opengl/opengl_uniform_buffer_object.cpp b/src/bebone/gfx/opengl/opengl_uniform_buffer_object.cpp index 23446b3a..a2439753 100644 --- a/src/bebone/gfx/opengl/opengl_uniform_buffer_object.cpp +++ b/src/bebone/gfx/opengl/opengl_uniform_buffer_object.cpp @@ -1,9 +1,10 @@ #include "opengl_uniform_buffer_object.h" -namespace bebone::gfx::opengl { - GLUniformBufferObject::GLUniformBufferObject(const u64& _size) : GLBufferObject(), size(_size) { +namespace bebone::gfx { + GLUniformBufferObject::GLUniformBufferObject(const u64& size) : size(size) { + glGenBuffers(1, &id); + bind(); - glBufferData(GL_UNIFORM_BUFFER, size, nullptr, GL_DYNAMIC_DRAW); } diff --git a/src/bebone/gfx/opengl/opengl_uniform_buffer_object.h b/src/bebone/gfx/opengl/opengl_uniform_buffer_object.h index 25743166..db5be407 100644 --- a/src/bebone/gfx/opengl/opengl_uniform_buffer_object.h +++ b/src/bebone/gfx/opengl/opengl_uniform_buffer_object.h @@ -1,49 +1,49 @@ -#ifndef _BEBONE_GFX_OPENGL_OPENGL_UNIFORM_BUFFER_OBJECT_H_ -#define _BEBONE_GFX_OPENGL_OPENGL_UNIFORM_BUFFER_OBJECT_H_ +#ifndef _BEBONE_GFX_OPENGL_UNIFORM_BUFFER_OBJECT_H_ +#define _BEBONE_GFX_OPENGL_UNIFORM_BUFFER_OBJECT_H_ -#include "opengl_buffer_object.h" -#include +#include "interface/i_opengl_uniform_buffer_object.h" -namespace bebone::gfx::opengl { +namespace bebone::gfx { using namespace bebone::core; /// UBO - class GLUniformBufferObject final : public GLBufferObject { + class GLUniformBufferObject : public IOpenGLUniformBufferObject { private: + u32 id; u64 size; public: /*! * Default constructor - * @param _size - desired buffer size + * @param size - desired buffer size */ - GLUniformBufferObject(const u64& _size); + GLUniformBufferObject(const u64& size); - ~GLUniformBufferObject(); + ~GLUniformBufferObject() override; /*! * Binds buffer to specific binding * @param binding - binding index */ - void bind_buffer_base(const i32& binding) const; + void bind_buffer_base(const i32& binding) const override; /*! * Maps buffer to accessible memory region * @return - pointer to mapped memory region */ - void* map() const; + void* map() const override; /// Unmaps uniform buffer - void unmap() const; + void unmap() const override; /// Binds UBO - void bind(); + void bind() override; /// Unbinds UBO - void unbind(); + void unbind() override; /// Destroys UBO. Calls automatically in the destructor - void destroy(); + void destroy() override; }; } diff --git a/src/bebone/gfx/opengl/opengl_vertex_array_object.cpp b/src/bebone/gfx/opengl/opengl_vertex_array_object.cpp index 4182223e..7da01730 100644 --- a/src/bebone/gfx/opengl/opengl_vertex_array_object.cpp +++ b/src/bebone/gfx/opengl/opengl_vertex_array_object.cpp @@ -1,6 +1,6 @@ #include "opengl_vertex_array_object.h" -namespace bebone::gfx::opengl { +namespace bebone::gfx { GLVertexArrayObject::GLVertexArrayObject() { glGenVertexArrays(1, &id); } @@ -9,19 +9,19 @@ namespace bebone::gfx::opengl { destroy(); } - void GLVertexArrayObject::link_attributes(GLVertexBufferObject& vbo, GLuint layout, GLuint numComponents, GLenum type, GLsizeiptr stride, const u64& offset) { + void GLVertexArrayObject::link_attributes(IOpenGLVertexBufferObject& vbo, GLuint layout, GLuint num_components, GLenum type, GLsizeiptr stride, const u64& offset) { vbo.bind(); - glVertexAttribPointer(layout, numComponents, type, GL_FALSE, stride, (void*)(offset)); + glVertexAttribPointer(layout, num_components, type, GL_FALSE, stride, (void*)(offset)); glEnableVertexAttribArray(layout); vbo.unbind(); } - void GLVertexArrayObject::link_attributes(GLVertexBufferObject& vbo, GLuint layout, GLuint numComponents, GLenum type, GLsizeiptr stride, void* offset) { + void GLVertexArrayObject::link_attributes(IOpenGLVertexBufferObject& vbo, GLuint layout, GLuint num_components, GLenum type, GLsizeiptr stride, void* offset) { vbo.bind(); - glVertexAttribPointer(layout, numComponents, type, GL_FALSE, stride, offset); + glVertexAttribPointer(layout, num_components, type, GL_FALSE, stride, offset); glEnableVertexAttribArray(layout); vbo.unbind(); diff --git a/src/bebone/gfx/opengl/opengl_vertex_array_object.h b/src/bebone/gfx/opengl/opengl_vertex_array_object.h index 4db83b3e..fd9e5baa 100644 --- a/src/bebone/gfx/opengl/opengl_vertex_array_object.h +++ b/src/bebone/gfx/opengl/opengl_vertex_array_object.h @@ -1,51 +1,53 @@ -#ifndef _BEBONE_GFX_OPENGL_OPENGL_VERTEX_ARRAY_OBJECT_H_ -#define _BEBONE_GFX_OPENGL_OPENGL_VERTEX_ARRAY_OBJECT_H_ +#ifndef _BEBONE_GFX_OPENGL_VERTEX_ARRAY_OBJECT_H_ +#define _BEBONE_GFX_OPENGL_VERTEX_ARRAY_OBJECT_H_ -#include "opengl_buffer_object.h" -#include "opengl_vertex_buffer_object.h" +#include "interface/i_opengl_vertex_array_object.h" -namespace bebone::gfx::opengl { +namespace bebone::gfx { using namespace bebone::core; /// VAO - class GLVertexArrayObject final : public GLBufferObject { + class GLVertexArrayObject : public IOpenGLVertexArrayObject { + private: + u32 id; + public: /// Generates VAO and assigns unique ID GLVertexArrayObject(); /// Destroys VAO - ~GLVertexArrayObject(); + ~GLVertexArrayObject() override; /*! * Interpret the vertex buffer data * @param vbo - vertex buffer object * @param layout - vertex shader layout - * @param numComponents - number of components + * @param num_components - number of components * @param type - data type * @param stride - byte offset between consecutive vertex attributes * @param offset - an offset of the first component of the first vertex attribute in the array */ - void link_attributes(GLVertexBufferObject& vbo, GLuint layout, GLuint numComponents, GLenum type, GLsizeiptr stride, const u64& offset); + void link_attributes(IOpenGLVertexBufferObject& vbo, GLuint layout, GLuint num_components, GLenum type, GLsizeiptr stride, const u64& offset) override; /*! * Interpret the vertex buffer data * @param vbo - vertex buffer object * @param layout - vertex shader layout - * @param numComponents - number of components + * @param num_components - number of components * @param type - data type * @param stride - byte offset between consecutive vertex attributes * @param offset - an offset of the first component of the first vertex attribute in the array */ - void link_attributes(GLVertexBufferObject& vbo, GLuint layout, GLuint numComponents, GLenum type, GLsizeiptr stride, void* offset); + void link_attributes(IOpenGLVertexBufferObject& vbo, GLuint layout, GLuint num_components, GLenum type, GLsizeiptr stride, void* offset) override; /// Binds VAO - void bind(); + void bind() override; /// Unbinds VAO - void unbind(); + void unbind() override; /// Destroys VAO. Calls automatically in the destructor - void destroy(); + void destroy() override; }; } diff --git a/src/bebone/gfx/opengl/opengl_vertex_buffer_object.cpp b/src/bebone/gfx/opengl/opengl_vertex_buffer_object.cpp index a1169b03..f8d3a2cb 100644 --- a/src/bebone/gfx/opengl/opengl_vertex_buffer_object.cpp +++ b/src/bebone/gfx/opengl/opengl_vertex_buffer_object.cpp @@ -1,7 +1,9 @@ #include "opengl_vertex_buffer_object.h" -namespace bebone::gfx::opengl { - GLVertexBufferObject::GLVertexBufferObject(const void* vertices, const GLsizeiptr& size, const GLenum& usage) : GLBufferObject() { +namespace bebone::gfx { + GLVertexBufferObject::GLVertexBufferObject(const void* vertices, const GLsizeiptr& size, const GLenum& usage) { + glGenBuffers(1, &id); + bind(); glBufferData(GL_ARRAY_BUFFER, size, vertices, usage); } @@ -9,12 +11,6 @@ namespace bebone::gfx::opengl { GLVertexBufferObject::~GLVertexBufferObject() { destroy(); } - - void GLVertexBufferObject::buffer_sub_data(const GLintptr& offset, const GLsizeiptr& size, const void* data) { - bind(); - glBufferSubData(GL_ARRAY_BUFFER, offset, size, data); - unbind(); - } void GLVertexBufferObject::bind() { glBindBuffer(GL_ARRAY_BUFFER, id); @@ -27,4 +23,10 @@ namespace bebone::gfx::opengl { void GLVertexBufferObject::destroy() { glDeleteBuffers(1, &id); } + + void GLVertexBufferObject::buffer_sub_data(const GLintptr& offset, const GLsizeiptr& size, const void* data) { + bind(); + glBufferSubData(GL_ARRAY_BUFFER, offset, size, data); + unbind(); + } } diff --git a/src/bebone/gfx/opengl/opengl_vertex_buffer_object.h b/src/bebone/gfx/opengl/opengl_vertex_buffer_object.h index 89a728ca..dc17d2e1 100644 --- a/src/bebone/gfx/opengl/opengl_vertex_buffer_object.h +++ b/src/bebone/gfx/opengl/opengl_vertex_buffer_object.h @@ -1,12 +1,16 @@ -#ifndef _BEBONE_GFX_OPENGL_OPENGL_VERTEX_BUFFER_OBJECT_H_ -#define _BEBONE_GFX_OPENGL_OPENGL_VERTEX_BUFFER_OBJECT_H_ +#ifndef _BEBONE_GFX_OPENGL_VERTEX_BUFFER_OBJECT_H_ +#define _BEBONE_GFX_OPENGL_VERTEX_BUFFER_OBJECT_H_ -#include "opengl_buffer_object.h" -#include +#include "interface/i_opengl_vertex_buffer_object.h" + +namespace bebone::gfx { + using namespace bebone::core; -namespace bebone::gfx::opengl { /// VBO - class GLVertexBufferObject final : public GLBufferObject { + class GLVertexBufferObject : public IOpenGLVertexBufferObject { + private: + u32 id; + public: /*! * Initializes VBO. GL_STATIC_DRAW usage is set by default. Automatically binds it @@ -17,7 +21,16 @@ namespace bebone::gfx::opengl { GLVertexBufferObject(const void* vertices, const GLsizeiptr& size, const GLenum& usage = GL_STATIC_DRAW); /// Destroys VBO - ~GLVertexBufferObject(); + ~GLVertexBufferObject() override; + + /// Binds VBO + void bind() override; + + /// Unbinds VBO + void unbind() override; + + /// Destroys VBO. Calls automatically in the destructor + void destroy() override; /*! * Updates a subset of a VBO data store. Automatically binds and unbinds the VBO. To use this method VBO usage must be set to GL_DYNAMIC_DRAW @@ -25,16 +38,7 @@ namespace bebone::gfx::opengl { * @param size - specifies the size in bytes of the data store region being replaced. * @param data - specifies a pointer to the new data that will be copied into the data store */ - void buffer_sub_data(const GLintptr& offset, const GLsizeiptr& size, const void* data); - - /// Binds VBO - void bind(); - - /// Unbinds VBO - void unbind(); - - /// Destroys VBO. Calls automatically in the destructor - void destroy(); + void buffer_sub_data(const GLintptr& offset, const GLsizeiptr& size, const void* data) override; }; } diff --git a/src/bebone/gfx/shaders/shader_code.cpp b/src/bebone/gfx/shaders/shader_code.cpp index 1aeb869c..7eaa4c77 100644 --- a/src/bebone/gfx/shaders/shader_code.cpp +++ b/src/bebone/gfx/shaders/shader_code.cpp @@ -1,22 +1,22 @@ #include "shader_code.h" namespace bebone::gfx { - ShaderCode::ShaderCode(const ShaderType& p_shaderType) - : m_shaderType(p_shaderType) { + ShaderCode::ShaderCode(const ShaderType& shader_type) + : shader_type(shader_type) { } - ShaderCode::ShaderCode(const RawSpirVByteCode& p_spirVByteCode, const ShaderType& p_shaderType) - : m_spirVCode(p_spirVByteCode), - m_shaderType(p_shaderType) { + ShaderCode::ShaderCode(const RawSpirVByteCode& spirv_byte_code, const ShaderType& shader_type) + : spirv_code(spirv_byte_code), + shader_type(shader_type) { } const ShaderType& ShaderCode::get_shader_type() const { - return m_shaderType; + return shader_type; } const RawSpirVByteCode& ShaderCode::get_byte_code() const { - return m_spirVCode; + return spirv_code; } } diff --git a/src/bebone/gfx/shaders/shader_code.h b/src/bebone/gfx/shaders/shader_code.h index 9f7c701e..a68b4998 100644 --- a/src/bebone/gfx/shaders/shader_code.h +++ b/src/bebone/gfx/shaders/shader_code.h @@ -16,22 +16,22 @@ namespace bebone::gfx { /// Class used for storing shader code class ShaderCode { private: - RawSpirVByteCode m_spirVCode; - ShaderType m_shaderType; + RawSpirVByteCode spirv_code; + ShaderType shader_type; public: /*! * Default constructor - * @param p_shaderType - shader type + * @param shader_type - shader type */ - ShaderCode(const ShaderType& p_shaderType); + ShaderCode(const ShaderType& shader_type); /*! * Standart constructor - * @param p_spirVByteCode - shader byte code vector - * @param p_shaderType - shader type + * @param spirv_byte_code - shader byte code vector + * @param shader_type - shader type */ - ShaderCode(const RawSpirVByteCode& p_spirVByteCode, const ShaderType& p_shaderType) ; + ShaderCode(const RawSpirVByteCode& spirv_byte_code, const ShaderType& shader_type) ; /*! * Returns shader type diff --git a/src/bebone/gfx/shaders/shader_compiler.cpp b/src/bebone/gfx/shaders/shader_compiler.cpp index 629f1195..c8ad420c 100644 --- a/src/bebone/gfx/shaders/shader_compiler.cpp +++ b/src/bebone/gfx/shaders/shader_compiler.cpp @@ -2,19 +2,19 @@ namespace bebone::gfx { ShaderCompiler::ShaderCompiler() - : m_defaultEntryPoint("main") { + : default_entry_point("main") { } - void ShaderCompiler::set_entry_point(const std::string& p_entryPoint) { - m_defaultEntryPoint = p_entryPoint; + void ShaderCompiler::set_entry_point(const std::string& entry_point) { + default_entry_point = entry_point; } - void ShaderCompiler::add_shader_source(const ShaderSource& p_shaderSource) { - m_shaderSources.push_back(p_shaderSource); + void ShaderCompiler::add_shader_source(const ShaderSource& shader_source) { + shader_sources.push_back(shader_source); } void ShaderCompiler::clear_shader_source() { - m_shaderSources.clear(); + shader_sources.clear(); } } diff --git a/src/bebone/gfx/shaders/shader_compiler.h b/src/bebone/gfx/shaders/shader_compiler.h index 490887d0..98f45a2e 100644 --- a/src/bebone/gfx/shaders/shader_compiler.h +++ b/src/bebone/gfx/shaders/shader_compiler.h @@ -11,8 +11,8 @@ namespace bebone::gfx { /// Class used for compiling shaders class ShaderCompiler { protected: - std::string m_defaultEntryPoint; - std::vector m_shaderSources; + std::string default_entry_point; + std::vector shader_sources; public: /// Default constructor @@ -20,21 +20,21 @@ namespace bebone::gfx { /*! * Function sets an entry point for target shader - * @param p_entryPoint - desired entry point name + * @param entry_point - desired entry point name */ - void set_entry_point(const std::string& p_entryPoint); + void set_entry_point(const std::string& entry_point); /*! * Adds source file to shader compiler - * @param p_shaderSource - shader source object + * @param shader_source - shader source object */ - void add_shader_source(const ShaderSource& p_shaderSource); + void add_shader_source(const ShaderSource& shader_source); /// Cleans shader compiler, all shader sources void clear_shader_source(); /// Abstract method that compiles all shader sources to shader byte code with desired shader type - virtual ShaderCode compile(const ShaderType& p_shaderType) = 0; + virtual ShaderCode compile(const ShaderType& shader_type) = 0; }; } diff --git a/src/bebone/gfx/shaders/shader_source.cpp b/src/bebone/gfx/shaders/shader_source.cpp index 4dcab52d..a898f7bb 100644 --- a/src/bebone/gfx/shaders/shader_source.cpp +++ b/src/bebone/gfx/shaders/shader_source.cpp @@ -1,17 +1,17 @@ #include "shader_source.h" namespace bebone::gfx { - ShaderSource::ShaderSource(const std::string& p_shaderSource, const ShaderType& p_shaderType) - : m_shaderSource(p_shaderSource), - m_shaderType(p_shaderType) { + ShaderSource::ShaderSource(const std::string& shader_source, const ShaderType& shader_type) + : shader_source(shader_source), + shader_type(shader_type) { } const ShaderType& ShaderSource::get_type() const { - return m_shaderType; + return shader_type; } const std::string& ShaderSource::get_shader_source() const { - return m_shaderSource; + return shader_source; } } diff --git a/src/bebone/gfx/shaders/shader_source.h b/src/bebone/gfx/shaders/shader_source.h index 659d34cb..b9e05fe0 100644 --- a/src/bebone/gfx/shaders/shader_source.h +++ b/src/bebone/gfx/shaders/shader_source.h @@ -10,16 +10,16 @@ namespace bebone::gfx { /// Class used for storing shader source class ShaderSource { private: - std::string m_shaderSource; - ShaderType m_shaderType; + std::string shader_source; + ShaderType shader_type; public: /*! * Default constructor - * @param p_shaderSource - shader source string - * @param p_shaderType - shader type + * @param shader_source - shader source string + * @param shader_type - shader type */ - ShaderSource(const std::string& p_shaderSource, const ShaderType& p_shaderType); + ShaderSource(const std::string& shader_source, const ShaderType& shader_type); /// Function that returns shader type const ShaderType& get_type() const; diff --git a/src/bebone/gfx/shaders/shader_type.cpp b/src/bebone/gfx/shaders/shader_type.cpp index f7b67350..a7a28c78 100644 --- a/src/bebone/gfx/shaders/shader_type.cpp +++ b/src/bebone/gfx/shaders/shader_type.cpp @@ -1,60 +1,30 @@ #include "shader_type.h" namespace bebone::gfx { - const ShaderType ShaderTypes::FRAGMENT_SHADER = ShaderType(0); - const ShaderType ShaderTypes::VERTEX_SHADER = ShaderType(1); - - ShaderType::ShaderType(const u32 &p_value) - : m_value(p_value) { - - } - - bool ShaderType::operator==(const ShaderType &p_another) const { - return m_value == p_another.m_value; - } - - bool ShaderType::operator!=(const ShaderType &p_another) const { - return m_value != p_another.m_value; - } - - std::string ShaderType::to_string() const { - switch (m_value) { - case 0: - return "FRAGMENT_SHADER"; - case 1: - return "VERTEX_SHADER"; - default: - throw std::runtime_error("undefined shader type"); + std::string to_string(const ShaderType& type) { + switch (type) { + case ShaderType::FragmentShader: + return "FragmentShader"; + case ShaderType::VertexShader: + return "VertexShader"; } - - // Just do not want to have any warnings - return ""; } - EShLanguage ShaderType::to_glslang() const { - switch (m_value) { - case 0: + EShLanguage to_glslang(const ShaderType& shader_type) { + switch (shader_type) { + case ShaderType::FragmentShader: return EShLanguage::EShLangFragment; - case 1: + case ShaderType::VertexShader: return EShLanguage::EShLangVertex; - default: - throw std::runtime_error("undefined shader type, cannot be converted to glslang enum"); } - - // Just do not want to have any warnings - return EShLanguage::EShLangVertex; } - GLuint ShaderType::to_opengl() const { - switch (m_value) { - case 0: + GLuint to_opengl(const ShaderType& type) { + switch (type) { + case ShaderType::FragmentShader: return GL_FRAGMENT_SHADER; - case 1: + case ShaderType::VertexShader: return GL_VERTEX_SHADER; - default: - throw std::runtime_error("undefined shader type, cannot be converted to opengl gluint"); } - - return GL_VERTEX_SHADER; } } diff --git a/src/bebone/gfx/shaders/shader_type.h b/src/bebone/gfx/shaders/shader_type.h index ae8004b4..accded9c 100644 --- a/src/bebone/gfx/shaders/shader_type.h +++ b/src/bebone/gfx/shaders/shader_type.h @@ -6,39 +6,15 @@ namespace bebone::gfx { using namespace bebone::core; - struct ShaderTypes; - - // Class used for specifying a shader type - struct ShaderType { - private: - u32 m_value; - - ShaderType(const u32& p_value); - - public: - friend struct ShaderTypes; - - /// Overloaded shader type comparison operator - bool operator==(const ShaderType& p_another) const; - - /// Overloaded shader type comparison operator - bool operator!=(const ShaderType& p_another) const; - - /// Function that return string representation of shader type - std::string to_string() const; - - /// Function that return glslang representation of shader type - EShLanguage to_glslang() const; - - /// Function that return opengl representation of shader type - GLuint to_opengl() const; + enum class ShaderType { + FragmentShader, + VertexShader }; - /// Class that is used for enumerating different shader types - struct ShaderTypes { - static const ShaderType FRAGMENT_SHADER; - static const ShaderType VERTEX_SHADER; - }; + std::string to_string(const ShaderType& type); + + EShLanguage to_glslang(const ShaderType& type); + GLuint to_opengl(const ShaderType& type); } #endif diff --git a/src/bebone/gfx/shaders/spirv_shader_compiler.cpp b/src/bebone/gfx/shaders/spirv_shader_compiler.cpp index 288ff93f..b24f488a 100644 --- a/src/bebone/gfx/shaders/spirv_shader_compiler.cpp +++ b/src/bebone/gfx/shaders/spirv_shader_compiler.cpp @@ -1,47 +1,49 @@ #include "spirv_shader_compiler.h" namespace bebone::gfx { - ShaderCode SpirVShaderCompiler::compile(const ShaderType& p_shaderType) { - const auto targetShaderType = p_shaderType.to_glslang(); + ShaderCode SpirVShaderCompiler::compile(const ShaderType& shader_type) { + const auto target_shader_type = to_glslang(shader_type); // First we check if all shader source type match - for(auto& shaderSource : m_shaderSources) - if(p_shaderType != shaderSource.get_type()) - throw std::runtime_error("shader source type do not match with desired shader code target type"); + for(auto& shader_source : shader_sources) + if(shader_type != shader_source.get_type()) { + LOG_ERROR("Shader source type do not match with desired shader code target type"); + // throw std::runtime_error("shader source type do not match with desired shader code target type"); Todo + } - std::vector rawShaderSources; + std::vector raw_shader_sources; - for(const auto& source : m_shaderSources) - rawShaderSources.push_back(source.get_shader_source().c_str()); + for(const auto& source : shader_sources) + raw_shader_sources.push_back(source.get_shader_source().c_str()); glslang::InitializeProcess(); - glslang::TShader shader(targetShaderType); + glslang::TShader shader(target_shader_type); - shader.setStrings(rawShaderSources.data(), rawShaderSources.size()); - shader.setEntryPoint(m_defaultEntryPoint.c_str()); + shader.setStrings(raw_shader_sources.data(), raw_shader_sources.size()); + shader.setEntryPoint(default_entry_point.c_str()); #if 0 // Set environment input for Vulkan - shader.setEnvInput(glslang::EShSource::EShSourceGlsl, targetShaderType, glslang::EShClient::EShClientVulkan, 100); + shader.setEnvInput(glslang::EShSource::EShSourceGlsl, target_shader_type, glslang::EShClient::EShClientVulkan, 100); // Set environment target for Vulkan SPIR-V shader.setEnvClient(glslang::EShClient::EShClientVulkan, glslang::EShTargetClientVersion::EShTargetVulkan_1_2); shader.setEnvTarget(glslang::EShTargetLanguage::EShTargetSpv, glslang::EShTargetLanguageVersion::EShTargetSpv_1_0); #else - shader.setEnvInput(glslang::EShSource::EShSourceGlsl, targetShaderType, glslang::EShClient::EShClientOpenGL, 450); + shader.setEnvInput(glslang::EShSource::EShSourceGlsl, target_shader_type, glslang::EShClient::EShClientOpenGL, 450); shader.setEnvClient(glslang::EShClient::EShClientOpenGL, glslang::EShTargetClientVersion::EShTargetOpenGL_450); shader.setEnvTarget(glslang::EShTargetLanguage::EShTargetSpv, glslang::EShTargetLanguageVersion::EShTargetSpv_1_0); #endif - const int defaultVersion = 100; + const int default_version = 100; EShMessages messages = (EShMessages)(EShMsgSpvRules | EShMsgVulkanRules); // EShMessages messages = (EShMessages)(EShMsgSpvRules); - if (!shader.parse(GetDefaultResources(), defaultVersion, false, messages)) { - std::cerr << "Error in shader compilation:\n" << shader.getInfoLog() << std::endl; - // std::cerr << "Error in shader source:\n" << shaderSource << std::endl; + if (!shader.parse(GetDefaultResources(), default_version, false, messages)) { + LOG_ERROR("Error in shader compilation: {}", shader.getInfoLog()); + glslang::FinalizeProcess(); - throw std::runtime_error("Error in shader source"); + // throw std::runtime_error("Error in shader source"); Todo } glslang::TProgram program; @@ -51,27 +53,27 @@ namespace bebone::gfx { // program.getReflectionIndex if (!program.link(messages)) { - std::cerr << "Error while linking shaders:\n" << program.getInfoLog() << std::endl; + LOG_ERROR("Error while linking shaders: {}", program.getInfoLog()); glslang::FinalizeProcess(); - throw std::runtime_error("Error while linking shaders"); + // throw std::runtime_error("Error while linking shaders"); Todo } - glslang::TIntermediate *intermediate = program.getIntermediate(targetShaderType); + glslang::TIntermediate *intermediate = program.getIntermediate(target_shader_type); if (!intermediate) { - std::cerr << "Failed to get SPIR-V intermediate code." << std::endl; + LOG_ERROR("Failed to get SPIR-V intermediate code."); glslang::FinalizeProcess(); - throw std::runtime_error("Failed to get SPIR-V intermediate code"); + // throw std::runtime_error("Failed to get SPIR-V intermediate code"); Todo } // SpirV to be returned - RawSpirVByteCode spirVCode; + RawSpirVByteCode spirv_code; spv::SpvBuildLogger logger; - glslang::SpvOptions spvOptions; - glslang::GlslangToSpv(*intermediate, spirVCode, &logger, &spvOptions); + glslang::SpvOptions spv_options; + glslang::GlslangToSpv(*intermediate, spirv_code, &logger, &spv_options); glslang::FinalizeProcess(); - return ShaderCode(spirVCode, p_shaderType); + return ShaderCode(spirv_code, shader_type); } } diff --git a/src/bebone/gfx/shaders/spirv_shader_compiler.h b/src/bebone/gfx/shaders/spirv_shader_compiler.h index 60d701a0..a53f5bfb 100644 --- a/src/bebone/gfx/shaders/spirv_shader_compiler.h +++ b/src/bebone/gfx/shaders/spirv_shader_compiler.h @@ -12,10 +12,10 @@ namespace bebone::gfx { /*! * Function that compiles shader source codes with desired shader type - * @param p_shaderType - desired shader type + * @param shader_type - desired shader type * @return Shader code object */ - ShaderCode compile(const ShaderType& p_shaderType); + ShaderCode compile(const ShaderType& shader_type); }; } diff --git a/src/bebone/gfx/vulkan/interface/i_vulkan_buffer.h b/src/bebone/gfx/vulkan/interface/i_vulkan_buffer.h new file mode 100644 index 00000000..199e9f33 --- /dev/null +++ b/src/bebone/gfx/vulkan/interface/i_vulkan_buffer.h @@ -0,0 +1,22 @@ +#ifndef _BEBONE_GFX_I_VULKAN_BUFFER_H_ +#define _BEBONE_GFX_I_VULKAN_BUFFER_H_ + +#include "../../gfx_backend.h" + +#include "i_vulkan_image.h" + +namespace bebone::gfx { + using namespace bebone::core; + + class IVulkanBuffer { + public: + virtual ~IVulkanBuffer() = default; + + [[nodiscard]] virtual VkBuffer get_vk_buffer() const = 0; + [[nodiscard]] virtual VkMemoryRequirements get_memory_requirements() const = 0; + [[nodiscard]] virtual size_t get_size() const = 0; + virtual void copy_to_image(IVulkanImage& image) = 0; + }; +} + +#endif diff --git a/src/bebone/gfx/vulkan/interface/i_vulkan_command_buffer.h b/src/bebone/gfx/vulkan/interface/i_vulkan_command_buffer.h new file mode 100644 index 00000000..dbc8d1c5 --- /dev/null +++ b/src/bebone/gfx/vulkan/interface/i_vulkan_command_buffer.h @@ -0,0 +1,15 @@ +#ifndef _BEBONE_GFX_I_VULKAN_COMMAND_BUFFER_H_ +#define _BEBONE_GFX_I_VULKAN_COMMAND_BUFFER_H_ + +#include "../../gfx_backend.h" + +namespace bebone::gfx { + using namespace bebone::core; + + class IVulkanCommandBuffer { + public: + virtual ~IVulkanCommandBuffer() = default; + }; +} + +#endif diff --git a/src/bebone/gfx/vulkan/interface/i_vulkan_command_buffer_pool.h b/src/bebone/gfx/vulkan/interface/i_vulkan_command_buffer_pool.h new file mode 100644 index 00000000..f69097b0 --- /dev/null +++ b/src/bebone/gfx/vulkan/interface/i_vulkan_command_buffer_pool.h @@ -0,0 +1,19 @@ +#ifndef _BEBONE_GFX_I_VULKAN_COMMAND_BUFFER_POOL_H_ +#define _BEBONE_GFX_I_VULKAN_COMMAND_BUFFER_POOL_H_ + +#include "../../gfx_backend.h" + +namespace bebone::gfx { + using namespace bebone::core; + + class IVulkanCommandBufferPool { + public: + virtual ~IVulkanCommandBufferPool() = default; + + [[nodiscard]] virtual VkCommandPool get_vk_command_buffer_pool() const = 0; + virtual VkCommandBuffer begin_single_time_commands() = 0; + virtual void end_single_time_commands(VkCommandBuffer command_buffer) = 0; + }; +} + +#endif diff --git a/src/bebone/gfx/vulkan/interface/i_vulkan_device.h b/src/bebone/gfx/vulkan/interface/i_vulkan_device.h new file mode 100644 index 00000000..d6b4277b --- /dev/null +++ b/src/bebone/gfx/vulkan/interface/i_vulkan_device.h @@ -0,0 +1,48 @@ +#ifndef _BEBONE_GFX_I_VULKAN_DEVICE_H_ +#define _BEBONE_GFX_I_VULKAN_DEVICE_H_ + +#include "../../gfx_backend.h" + +#include "i_vulkan_command_buffer.h" + +namespace bebone::gfx { + using namespace bebone::core; + + struct VulkanSwapChainSupportDetails { + VkSurfaceCapabilitiesKHR capabilities; + std::vector formats; + std::vector present_modes; + }; + + struct VulkanQueueFamilyIndices { + uint32_t graphics_family; + uint32_t present_family; + bool graphics_family_has_value = false; + bool present_family_has_value = false; + + bool is_complete(); + }; + + class IVulkanDevice { + public: + virtual ~IVulkanDevice() = default; + + virtual uint32_t find_memory_type(uint32_t type_filter, VkMemoryPropertyFlags properties) = 0; + virtual VkFormat find_supported_format(const std::vector &candidates, VkImageTiling tiling, VkFormatFeatureFlags features) = 0; + virtual VkFormat find_depth_format() = 0; + + // virtual std::unique_ptr begin_single_time_commands() = 0; + // virtual void end_single_time_commands(std::unique_ptr& command_buffer) = 0; + + virtual VulkanQueueFamilyIndices find_physical_queue_families() = 0; + virtual VulkanSwapChainSupportDetails get_swap_chain_support() = 0; + + [[nodiscard]] virtual VkDevice get_vk_device() const = 0; + [[nodiscard]] virtual VkSurfaceKHR get_surface() const = 0; + [[nodiscard]] virtual VkQueue get_graphics_queue() const = 0; + [[nodiscard]] virtual VkQueue get_present_queue() const = 0; + virtual void wait_idle() const = 0; + }; +} + +#endif diff --git a/src/bebone/gfx/vulkan/interface/i_vulkan_device_memory.h b/src/bebone/gfx/vulkan/interface/i_vulkan_device_memory.h new file mode 100644 index 00000000..485ea06f --- /dev/null +++ b/src/bebone/gfx/vulkan/interface/i_vulkan_device_memory.h @@ -0,0 +1,26 @@ +#ifndef _BEBONE_GFX_I_VULKAN_DEVICE_MEMORY_H_ +#define _BEBONE_GFX_I_VULKAN_DEVICE_MEMORY_H_ + +#include "../../gfx_backend.h" + +#include "i_vulkan_buffer.h" +#include "i_vulkan_image.h" + +namespace bebone::gfx { + using namespace bebone::core; + + class IVulkanDeviceMemory { + public: + virtual ~IVulkanDeviceMemory() = default; + + [[nodiscard]] virtual VkDeviceMemory get_vk_device_memory() const = 0; + virtual void bind_buffer_memory(IVulkanBuffer& buffer) = 0; + virtual void bind_image_memory(IVulkanImage& image) = 0; + virtual void map(const size_t& size, void** data) = 0; + virtual void unmap() = 0; + virtual void upload_data(const void* src, const size_t& size) = 0; + + }; +} + +#endif diff --git a/src/bebone/gfx/vulkan/interface/i_vulkan_image.h b/src/bebone/gfx/vulkan/interface/i_vulkan_image.h new file mode 100644 index 00000000..0a8778e5 --- /dev/null +++ b/src/bebone/gfx/vulkan/interface/i_vulkan_image.h @@ -0,0 +1,19 @@ +#ifndef _BEBONE_GFX_I_VULKAN_IMAGE_H_ +#define _BEBONE_GFX_I_VULKAN_IMAGE_H_ + +#include "../../gfx_backend.h" + +namespace bebone::gfx { + using namespace bebone::core; + + class IVulkanImage { + public: + virtual ~IVulkanImage() = default; + + [[nodiscard]] virtual VkImage get_vk_image() const = 0; + [[nodiscard]] virtual VkMemoryRequirements get_memory_requirements() const = 0; + [[nodiscard]] virtual VkExtent3D get_extent() const = 0; + }; +} + +#endif diff --git a/src/bebone/gfx/vulkan/interface/i_vulkan_image_view.h b/src/bebone/gfx/vulkan/interface/i_vulkan_image_view.h new file mode 100644 index 00000000..62aef7ca --- /dev/null +++ b/src/bebone/gfx/vulkan/interface/i_vulkan_image_view.h @@ -0,0 +1,17 @@ +#ifndef _BEBONE_GFX_I_VULKAN_IMAGE_VIEW_H_ +#define _BEBONE_GFX_I_VULKAN_IMAGE_VIEW_H_ + +#include "../../gfx_backend.h" + +namespace bebone::gfx { + using namespace bebone::core; + + class IVulkanImageView { + public: + virtual ~IVulkanImageView() = default; + + [[nodiscard]] virtual VkImageView get_vk_image_view() const = 0; + }; +} + +#endif diff --git a/src/bebone/gfx/vulkan/interface/i_vulkan_instance.h b/src/bebone/gfx/vulkan/interface/i_vulkan_instance.h new file mode 100644 index 00000000..01ea7196 --- /dev/null +++ b/src/bebone/gfx/vulkan/interface/i_vulkan_instance.h @@ -0,0 +1,17 @@ +#ifndef _BEBONE_GFX_I_VULKAN_INSTANCE_H_ +#define _BEBONE_GFX_I_VULKAN_INSTANCE_H_ + +#include "../../gfx_backend.h" + +namespace bebone::gfx { + using namespace bebone::core; + + class IVulkanInstance { + public: + virtual ~IVulkanInstance() = default; + + [[nodiscard]] virtual VkInstance get_vk_instance() const = 0; + }; +} + +#endif diff --git a/src/bebone/gfx/vulkan/interface/i_vulkan_sampler.h b/src/bebone/gfx/vulkan/interface/i_vulkan_sampler.h new file mode 100644 index 00000000..210d56d8 --- /dev/null +++ b/src/bebone/gfx/vulkan/interface/i_vulkan_sampler.h @@ -0,0 +1,17 @@ +#ifndef _BEBONE_GFX_I_VULKAN_SAMPLER_H_ +#define _BEBONE_GFX_I_VULKAN_SAMPLER_H_ + +#include "../../gfx_backend.h" + +namespace bebone::gfx { + using namespace bebone::core; + + class IVulkanSampler { + public: + virtual ~IVulkanSampler() = default; + + [[nodiscard]] virtual VkSampler get_vk_image_sampler() const = 0; + }; +} + +#endif diff --git a/src/bebone/gfx/vulkan/vulkan_api.h b/src/bebone/gfx/vulkan/vulkan_api.h index c6411132..d863e795 100644 --- a/src/bebone/gfx/vulkan/vulkan_api.h +++ b/src/bebone/gfx/vulkan/vulkan_api.h @@ -1,9 +1,10 @@ -#ifndef _BEBONE_GFX_VULKAN_VULKAN_API_H_ -#define _BEBONE_GFX_VULKAN_VULKAN_API_H_ +#ifndef _BEBONE_GFX_VULKAN_API_H_ +#define _BEBONE_GFX_VULKAN_API_H_ #include "vulkan_buffer.h" #include "vulkan_image.h" #include "vulkan_image_view.h" +#include "vulkan_sampler.h" #include "vulkan_device_memory.h" #include "vulkan_framebuffer.h" @@ -33,8 +34,18 @@ #include "vulkan_swap_chain.h" #include "vulkan_render_target.h" +#include "vulkan_attachment.h" +#include "vulkan_render_pass.h" + #include "vulkan_const_range.h" -#include "vulkan_wrapper.tpp" +// Utils class +#include "vulkan_pipeline_manager.h" +#include "vulkan_texture.h" + +#include "vulkan_buffer_memory.h" + +#include "vulkan_depth_image.h" +#include "vulkan_swap_chain_image.h" #endif diff --git a/src/bebone/gfx/vulkan/vulkan_attachment.cpp b/src/bebone/gfx/vulkan/vulkan_attachment.cpp new file mode 100644 index 00000000..9d941594 --- /dev/null +++ b/src/bebone/gfx/vulkan/vulkan_attachment.cpp @@ -0,0 +1,49 @@ +#include "vulkan_attachment.h" + +namespace bebone::gfx { + VulkanAttachmentDesc VulkanAttachmentDesc::depth3D(VkExtent3D extent, VulkanDepthAttachmentDescription description) { + return VulkanAttachmentDesc { + .description { + .flags = description.flags, + .format = description.format, + .samples = description.samples, + .loadOp = description.loadOp, + .storeOp = description.storeOp, + .stencilLoadOp = description.stencilLoadOp, + .stencilStoreOp = description.stencilStoreOp, + .initialLayout = description.initialLayout, + .finalLayout = description.finalLayout, + }, + .type = Depth, + .layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, + .extent = extent + }; + } + + VulkanAttachmentDesc VulkanAttachmentDesc::depth2D(VkExtent2D extent, VulkanDepthAttachmentDescription description) { + return VulkanAttachmentDesc::depth3D({ extent.width, extent.height, 1 }, description); + } + + VulkanAttachmentDesc VulkanAttachmentDesc::color3D(VkExtent3D extent, VulkanColorAttachmentDescription description) { + return VulkanAttachmentDesc { + .description { + .flags = description.flags, + .format = description.format, + .samples = description.samples, + .loadOp = description.loadOp, + .storeOp = description.storeOp, + .stencilLoadOp = description.stencilLoadOp, + .stencilStoreOp = description.stencilStoreOp, + .initialLayout = description.initialLayout, + .finalLayout = description.finalLayout, + }, + .type = Color, + .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + .extent = extent + }; + } + + VulkanAttachmentDesc VulkanAttachmentDesc::color2D(VkExtent2D extent, VulkanColorAttachmentDescription description) { + return VulkanAttachmentDesc::color3D({ extent.width, extent.height, 1 }, description); + } +} diff --git a/src/bebone/gfx/vulkan/vulkan_attachment.h b/src/bebone/gfx/vulkan/vulkan_attachment.h new file mode 100644 index 00000000..196df87c --- /dev/null +++ b/src/bebone/gfx/vulkan/vulkan_attachment.h @@ -0,0 +1,54 @@ +#ifndef _BEBONE_GFX_VULKAN_ATTACHMENT_H_ +#define _BEBONE_GFX_VULKAN_ATTACHMENT_H_ + +#include + +#include "../gfx_backend.h" + +namespace bebone::gfx { + using namespace bebone::core; + + struct VulkanDepthAttachmentDescription { + VkAttachmentDescriptionFlags flags = 0; + VkFormat format = VK_FORMAT_UNDEFINED; + VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT; + VkAttachmentLoadOp loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + VkAttachmentStoreOp storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + VkAttachmentLoadOp stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + VkAttachmentStoreOp stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + VkImageLayout initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + VkImageLayout finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + }; + + struct VulkanColorAttachmentDescription { + VkAttachmentDescriptionFlags flags = 0; + VkFormat format = VK_FORMAT_UNDEFINED; + VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT; + VkAttachmentLoadOp loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + VkAttachmentStoreOp storeOp = VK_ATTACHMENT_STORE_OP_STORE; + VkAttachmentLoadOp stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + VkAttachmentStoreOp stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + VkImageLayout initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + VkImageLayout finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + }; + + enum VulkanAttachmentType { + Depth, + Color + }; + + struct VulkanAttachmentDesc { + VkAttachmentDescription description; + VulkanAttachmentType type; + VkImageLayout layout; + VkExtent3D extent; + + static VulkanAttachmentDesc depth3D(VkExtent3D extent, VulkanDepthAttachmentDescription description = {}); + static VulkanAttachmentDesc depth2D(VkExtent2D extent, VulkanDepthAttachmentDescription description = {}); + + static VulkanAttachmentDesc color3D(VkExtent3D extent, VulkanColorAttachmentDescription description = {}); + static VulkanAttachmentDesc color2D(VkExtent2D extent, VulkanColorAttachmentDescription description = {}); + }; +} + +#endif diff --git a/src/bebone/gfx/vulkan/vulkan_buffer.cpp b/src/bebone/gfx/vulkan/vulkan_buffer.cpp index 60d9e1d3..c04c9e18 100644 --- a/src/bebone/gfx/vulkan/vulkan_buffer.cpp +++ b/src/bebone/gfx/vulkan/vulkan_buffer.cpp @@ -1,34 +1,78 @@ #include "vulkan_buffer.h" -#include "vulkan_device.h" +#include "vulkan_command_buffer.h" -namespace bebone::gfx::vulkan { +namespace bebone::gfx { using namespace bebone::core; - VulkanBuffer::VulkanBuffer(VulkanDevice& device, VkDeviceSize size, VulkanBufferInfo bufferInfo) {//VkMemoryPropertyFlags properties) { - VkBufferCreateInfo createInfo{}; + VulkanBuffer::VulkanBuffer( + IVulkanDevice& device, + const size_t& size, + VulkanBufferInfo buffer_info + ) : device_owner(device), size(size) { + VkBufferCreateInfo create_info{}; - createInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - createInfo.pNext = nullptr; - createInfo.flags = bufferInfo.flags; - createInfo.size = size; - createInfo.usage = bufferInfo.usage; - createInfo.sharingMode = bufferInfo.sharingMode; - createInfo.queueFamilyIndexCount = bufferInfo.queueFamilyIndexCount; - createInfo.pQueueFamilyIndices = bufferInfo.pQueueFamilyIndices; + create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + create_info.pNext = nullptr; + create_info.flags = buffer_info.flags; + create_info.size = size; + create_info.usage = buffer_info.usage; + create_info.sharingMode = buffer_info.sharing_mode; + create_info.queueFamilyIndexCount = buffer_info.queue_family_index_count; + create_info.pQueueFamilyIndices = buffer_info.ptr_queue_family_indices; - if (vkCreateBuffer(device.device(), &createInfo, nullptr, &backend) != VK_SUCCESS) { - throw std::runtime_error("failed to create vulkan buffer!"); + if(vkCreateBuffer(device_owner.get_vk_device(), &create_info, nullptr, &buffer) != VK_SUCCESS) { + LOG_ERROR("Failed to create Vulkan buffer"); + // throw std::runtime_error("failed to create vulkan buffer!"); Todo } + + LOG_TRACE("Created Vulkan buffer with size {}", size); + } + + VulkanBuffer::~VulkanBuffer() { + vkDestroyBuffer(device_owner.get_vk_device(), buffer, nullptr); + + LOG_TRACE("Destroyed Vulkan buffer"); + } + + void VulkanBuffer::copy_to_image(IVulkanImage& image) { + LOG_CRITICAL("VulkanBuffer::copy_to_image is not implemented"); + /* + auto command_buffer = device_owner.begin_single_time_commands(); + + VkBufferImageCopy region{}; + region.bufferOffset = 0; + region.bufferRowLength = 0; + region.bufferImageHeight = 0; + + region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region.imageSubresource.mipLevel = 0; + region.imageSubresource.baseArrayLayer = 0; + region.imageSubresource.layerCount = 1; // Todo + + region.imageOffset = { 0, 0, 0 }; + region.imageExtent = image.get_extent(); + + auto vk_image = image.get_vk_image(); + vkCmdCopyBufferToImage(command_buffer->buffer, buffer, vk_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); + + device_owner.end_single_time_commands(command_buffer); + */ + } + + VkMemoryRequirements VulkanBuffer::get_memory_requirements() const { + VkMemoryRequirements requirements; + + vkGetBufferMemoryRequirements(device_owner.get_vk_device(), buffer, &requirements); + + return requirements; } - VkMemoryRequirements VulkanBuffer::get_memory_requirements(VulkanDevice& device) { - VkMemoryRequirements memRequirements; - vkGetBufferMemoryRequirements(device.device(), backend, &memRequirements); - return memRequirements; + VkBuffer VulkanBuffer::get_vk_buffer() const { + return buffer; } - void VulkanBuffer::destroy(VulkanDevice &device) { - vkDestroyBuffer(device.device(), backend, nullptr); + size_t VulkanBuffer::get_size() const { + return size; } } diff --git a/src/bebone/gfx/vulkan/vulkan_buffer.h b/src/bebone/gfx/vulkan/vulkan_buffer.h index a3f7f194..e492da99 100644 --- a/src/bebone/gfx/vulkan/vulkan_buffer.h +++ b/src/bebone/gfx/vulkan/vulkan_buffer.h @@ -1,22 +1,18 @@ -#ifndef _BEBONE_GFX_VULKAN_VULKAN_BUFFER_IMPLEMENTATION_H_ -#define _BEBONE_GFX_VULKAN_VULKAN_BUFFER_IMPLEMENTATION_H_ +#ifndef _BEBONE_GFX_VULKAN_BUFFER_IMPLEMENTATION_H_ +#define _BEBONE_GFX_VULKAN_BUFFER_IMPLEMENTATION_H_ #include #include "../gfx_backend.h" -#include "vulkan_wrapper.tpp" +#include "interface/i_vulkan_buffer.h" + #include "vulkan_device_memory.h" -namespace bebone::gfx::vulkan { +namespace bebone::gfx { using namespace bebone::core; - class VulkanDevice; - - class VulkanBuffer; - class VulkanDeviceMemory; - - const static VkBufferUsageFlags VULKAN_BUFFER_ANY_USE_FLAG = + const static VkBufferUsageFlags vulkan_buffer_any_use_flag = VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | @@ -35,28 +31,34 @@ namespace bebone::gfx::vulkan { VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR; struct VulkanBufferInfo { - // VkStructureType sType; - // const void* pNext; + // VkStructureType type; + // const void* ptr_next; VkBufferCreateFlags flags = 0; // VkDeviceSize size; - VkBufferUsageFlags usage = VULKAN_BUFFER_ANY_USE_FLAG; - VkSharingMode sharingMode = VK_SHARING_MODE_EXCLUSIVE; - uint32_t queueFamilyIndexCount = 0; - uint32_t* pQueueFamilyIndices = nullptr; + VkBufferUsageFlags usage = vulkan_buffer_any_use_flag; + VkSharingMode sharing_mode = VK_SHARING_MODE_EXCLUSIVE; + uint32_t queue_family_index_count = 0; + uint32_t* ptr_queue_family_indices = nullptr; }; - struct VulkanBufferMemoryTuple { - std::shared_ptr buffer; - std::shared_ptr memory; - }; + class VulkanBuffer : public IVulkanBuffer, private core::NonCopyable { + private: + IVulkanDevice& device_owner; - class VulkanBuffer : public VulkanWrapper, private core::NonCopyable { - public: - VulkanBuffer(VulkanDevice& device, VkDeviceSize size, VulkanBufferInfo bufferInfo); + VkBuffer buffer; + + private: + size_t size; // Todo, Do we really need to store buffer size there ? - VkMemoryRequirements get_memory_requirements(VulkanDevice& device); + public: + VulkanBuffer(IVulkanDevice& device, const size_t& size, VulkanBufferInfo buffer_info); + ~VulkanBuffer() override; - void destroy(VulkanDevice &device) override; + // Vulkan Buffer + [[nodiscard]] VkBuffer get_vk_buffer() const override; + [[nodiscard]] VkMemoryRequirements get_memory_requirements() const override; + [[nodiscard]] size_t get_size() const override; + void copy_to_image(IVulkanImage& image) override; }; } diff --git a/src/bebone/gfx/vulkan/vulkan_buffer_memory.cpp b/src/bebone/gfx/vulkan/vulkan_buffer_memory.cpp new file mode 100644 index 00000000..894e7d38 --- /dev/null +++ b/src/bebone/gfx/vulkan/vulkan_buffer_memory.cpp @@ -0,0 +1,55 @@ +#include "vulkan_buffer_memory.h" + +namespace bebone::gfx { + VulkanBufferMemory::VulkanBufferMemory( + IVulkanDevice& device, + const size_t& size, + VulkanBufferInfo buffer_info + ) { + buffer = std::make_unique(device, size, buffer_info); + auto requirements = buffer->get_memory_requirements(); + + memory = std::make_unique(device, requirements, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); + memory->bind_buffer_memory(*buffer); + } + + VulkanBufferMemory::~VulkanBufferMemory() = default; + + VkBuffer VulkanBufferMemory::get_vk_buffer() const { + return buffer->get_vk_buffer(); + } + + VkMemoryRequirements VulkanBufferMemory::get_memory_requirements() const { + return buffer->get_memory_requirements(); + } + + size_t VulkanBufferMemory::get_size() const { + return buffer->get_size(); + } + + void VulkanBufferMemory::copy_to_image(IVulkanImage& image) { + return buffer->copy_to_image(image); + } + + VkDeviceMemory VulkanBufferMemory::get_vk_device_memory() const { + return memory->get_vk_device_memory(); + } + + void VulkanBufferMemory::bind_buffer_memory(IVulkanBuffer& bind_buffer) { + memory->bind_buffer_memory(bind_buffer); + } + + void VulkanBufferMemory::bind_image_memory(IVulkanImage& image) { + memory->bind_image_memory(image); + } + void VulkanBufferMemory::map(const size_t& size, void** data) { + memory->map(size, data); + } + void VulkanBufferMemory::unmap() { + memory->unmap(); + } + + void VulkanBufferMemory::upload_data(const void* src, const size_t& size) { + memory->upload_data(src, size); + } +} diff --git a/src/bebone/gfx/vulkan/vulkan_buffer_memory.h b/src/bebone/gfx/vulkan/vulkan_buffer_memory.h new file mode 100644 index 00000000..0b022908 --- /dev/null +++ b/src/bebone/gfx/vulkan/vulkan_buffer_memory.h @@ -0,0 +1,58 @@ +#ifndef _BEBONE_GFX_VULKAN_BUFFER_TUPLES_H_ +#define _BEBONE_GFX_VULKAN_BUFFER_TUPLES_H_ + +#include + +#include "../gfx_backend.h" + +#include "vulkan_buffer.h" +#include "vulkan_device_memory.h" + +namespace bebone::gfx { + using namespace bebone::core; + + struct VulkanBufferMemory : public IVulkanBuffer, public IVulkanDeviceMemory { + private: + std::unique_ptr buffer; + std::unique_ptr memory; + + public: + VulkanBufferMemory(IVulkanDevice& device, const size_t& size, VulkanBufferInfo buffer_info = {}); + + template + VulkanBufferMemory( + IVulkanDevice& device, + const std::vector& data, + VulkanBufferInfo buffer_info = {} + ) { + const auto size = sizeof(T) * data.size(); + + buffer = std::make_unique(device, size, buffer_info); + + auto requirements = buffer->get_memory_requirements(); + + memory = std::make_unique(device, requirements, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); // Todo this should be configurable + memory->bind_buffer_memory(*buffer); + + memory->upload_data(data.data(), size); + } + + ~VulkanBufferMemory() override; + + // Vulkan Buffer + [[nodiscard]] VkBuffer get_vk_buffer() const override; + [[nodiscard]] VkMemoryRequirements get_memory_requirements() const override; + [[nodiscard]] size_t get_size() const override; + void copy_to_image(IVulkanImage& image) override; + + // Vulkan Device Memory + [[nodiscard]] VkDeviceMemory get_vk_device_memory() const override; + void bind_buffer_memory(IVulkanBuffer& buffer) override; + void bind_image_memory(IVulkanImage& image) override; + void map(const size_t& size, void** data) override; + void unmap() override; + void upload_data(const void* src, const size_t& size) override; + }; +} + +#endif diff --git a/src/bebone/gfx/vulkan/vulkan_command_buffer.cpp b/src/bebone/gfx/vulkan/vulkan_command_buffer.cpp index 87d9e475..2117d4a5 100644 --- a/src/bebone/gfx/vulkan/vulkan_command_buffer.cpp +++ b/src/bebone/gfx/vulkan/vulkan_command_buffer.cpp @@ -1,28 +1,32 @@ #include "vulkan_command_buffer.h" -#include "vulkan_device.h" #include "vulkan_pipeline_layout.h" -#include "vulkan_command_buffer_pool.h" #include "vulkan_descriptor_set.h" -namespace bebone::gfx::vulkan { - VulkanCommandBuffer::VulkanCommandBuffer(std::shared_ptr& device, VulkanCommandBufferPool& commandBufferPool) { - VkCommandBufferAllocateInfo allocInfo{}; - allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - allocInfo.commandPool = commandBufferPool.backend; - allocInfo.commandBufferCount = static_cast(1); +namespace bebone::gfx { + VulkanCommandBuffer::VulkanCommandBuffer(IVulkanDevice& device, IVulkanCommandBufferPool& command_buffer_pool) : device_owner(device) { + VkCommandBufferAllocateInfo alloc_info{}; - if(vkAllocateCommandBuffers(device->device(), &allocInfo, &backend) != VK_SUCCESS) { + alloc_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + alloc_info.commandPool = command_buffer_pool.get_vk_command_buffer_pool(); + alloc_info.commandBufferCount = static_cast(1); // Todo + + if(vkAllocateCommandBuffers(device_owner.get_vk_device(), &alloc_info, &command_buffer) != VK_SUCCESS) { + LOG_ERROR("Failed to allocate command buffers"); throw std::runtime_error("Failed to allocate command buffers !"); } + + LOG_TRACE("Allocated 1 command buffer"); } VulkanCommandBuffer& VulkanCommandBuffer::begin_record() { - VkCommandBufferBeginInfo beginInfo{}; - beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + VkCommandBufferBeginInfo begin_info{}; - if(vkBeginCommandBuffer(backend, &beginInfo) != VK_SUCCESS) { + begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + + if(vkBeginCommandBuffer(command_buffer, &begin_info) != VK_SUCCESS) { + LOG_ERROR("Failed to being recording command buffer"); throw std::runtime_error("failed to being recording command buffer"); } @@ -30,135 +34,216 @@ namespace bebone::gfx::vulkan { } VulkanCommandBuffer& VulkanCommandBuffer::end_record() { - if (vkEndCommandBuffer(backend) != VK_SUCCESS) { + if(vkEndCommandBuffer(command_buffer) != VK_SUCCESS) { + LOG_ERROR("Failed to end command buffer"); throw std::runtime_error("failed to end command buffer"); } return *this; } - VulkanCommandBuffer& VulkanCommandBuffer::begin_render_pass(std::shared_ptr& swapChain, const u32& frameBuffer) { - VkRenderPassBeginInfo renderPassInfo{}; - renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; - renderPassInfo.renderPass = swapChain->renderTarget->renderPass->backend; - renderPassInfo.framebuffer = swapChain->renderTarget->swapChainFramebuffers[frameBuffer]->backend; - - renderPassInfo.renderArea.offset = {0, 0}; - renderPassInfo.renderArea.extent = swapChain->extent; // Todo not sure is extent is right, maybe there should be extent of render target + VulkanCommandBuffer& VulkanCommandBuffer::begin_render_pass(const VulkanSwapChain& swap_chain) { + const auto& frame = swap_chain.get_current_frame(); - std::array clearValues{}; - clearValues[0].color = {{ 0.2f, 0.2f, 0.2f, 1.0f }}; - clearValues[1].depthStencil = { 1.0f, 0 }; + begin_render_pass( + swap_chain.render_target->framebuffers[frame], + swap_chain.render_pass); - renderPassInfo.clearValueCount = static_cast(clearValues.size()); - renderPassInfo.pClearValues = clearValues.data(); + return *this; + } - vkCmdBeginRenderPass(backend, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE); + VulkanCommandBuffer& VulkanCommandBuffer::begin_render_pass( + const std::unique_ptr& render_target, + const std::unique_ptr& render_pass, + const size_t& frame + ) { + begin_render_pass( + render_target->framebuffers[frame], + render_pass); return *this; } - VulkanCommandBuffer& VulkanCommandBuffer::set_viewport(const i32& x, const i32& y, const u32& width, const u32& height) { - VkViewport viewport; + // This function should have multiple variants, with swap chain or just with custom render target + VulkanCommandBuffer& VulkanCommandBuffer::begin_render_pass( + const std::unique_ptr& framebuffer, + const std::unique_ptr& render_pass + ) { + VkRenderPassBeginInfo render_pass_info{}; + render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; + render_pass_info.renderPass = render_pass->render_pass; + render_pass_info.framebuffer = framebuffer->framebuffer; + render_pass_info.renderArea.offset = {0, 0}; + render_pass_info.renderArea.extent = render_pass->get_extent(); // Todo not sure is extent is right, maybe there should be extent of render target - viewport.x = static_cast(x); - viewport.y = static_cast(y); - viewport.width = static_cast(width); - viewport.height = static_cast(height); + // Collect all clear values + auto clear_values = std::vector {}; + clear_values.reserve(render_pass->get_attachments().size()); - viewport.minDepth = 0.0f; - viewport.maxDepth = 1.0f; // Todo for now this set as default + for(const auto& attachment : render_pass->get_attachments()) { + if(attachment.type == Color) + clear_values.push_back({ .color = { { 0.2f, 0.2f, 0.2f, 1.0f } } }); // Todo clear values should be allowed to be changet + else if(attachment.type == Depth) + clear_values.push_back({ .depthStencil = { 1.0f, 0 }}); // Todo clear values should be allowed to be changet + } - VkRect2D scissor = {{x, y}, {width, height}}; + render_pass_info.clearValueCount = static_cast(clear_values.size()); + render_pass_info.pClearValues = clear_values.data(); - vkCmdSetViewport(backend, 0, 1, &viewport); - vkCmdSetScissor(backend, 0, 1, &scissor); + vkCmdBeginRenderPass(command_buffer, &render_pass_info, VK_SUBPASS_CONTENTS_INLINE); return *this; } - VulkanCommandBuffer& VulkanCommandBuffer::end_render_pass() { - vkCmdEndRenderPass(backend); + VulkanCommandBuffer& VulkanCommandBuffer::set_viewport(std::unique_ptr& window) { + // Flipped viewport + return set_viewport(0, window->get_height(), window->get_width(), -window->get_height()); + } - return *this; + VulkanCommandBuffer& VulkanCommandBuffer::set_viewport(const Vec2i& viewport, const f32& min_depth, const f32& max_depth) { + return set_viewport(0, 0, static_cast(viewport.x), static_cast(viewport.y), min_depth, max_depth); } - VulkanCommandBuffer& VulkanCommandBuffer::bind_pipeline(VulkanPipeline& pipeline) { - vkCmdBindPipeline(backend, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.backend); + VulkanCommandBuffer& VulkanCommandBuffer::set_viewport( + const f32& x, + const f32& y, + const f32& width, + const f32& height, + const f32& min_depth, + const f32& max_depth + ) { + VkViewport viewport; + + viewport.x = x; + viewport.y = y; + viewport.width = width; + viewport.height = height; + viewport.minDepth = min_depth; + viewport.maxDepth = max_depth; + + vkCmdSetViewport(command_buffer, 0, 1, &viewport); return *this; } - VulkanCommandBuffer& VulkanCommandBuffer::bind_pipeline(std::shared_ptr& pipeline) { - vkCmdBindPipeline(backend, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->backend); + VulkanCommandBuffer& VulkanCommandBuffer::set_scissors( + const i32& x, + const i32& y, + const u32& width, + const u32& height + ) { + + VkRect2D scissor = { { x, y }, { width, height } }; + + vkCmdSetScissor(command_buffer, 0, 1, &scissor); return *this; } - VulkanCommandBuffer& VulkanCommandBuffer::bind_vertex_buffer(std::shared_ptr& buffer) { - VkBuffer buffers[] = {buffer->backend}; - VkDeviceSize offset[] = {0}; - vkCmdBindVertexBuffers(backend, 0, 1, buffers, offset); + VulkanCommandBuffer& VulkanCommandBuffer::end_render_pass() { + vkCmdEndRenderPass(command_buffer); return *this; } - VulkanCommandBuffer& VulkanCommandBuffer::bind_index_buffer(std::shared_ptr& indexBuffer) { - // Todo, note that VK_INDEX_TYPE_UINT32 should match index size, akka for int should be used VK_INDEX_TYPE_UINT32 - vkCmdBindIndexBuffer(backend, indexBuffer->backend, 0, VK_INDEX_TYPE_UINT32); + // Todo VK_PIPELINE_BIND_POINT_GRAPHICS should be configured + VulkanCommandBuffer& VulkanCommandBuffer::bind_pipeline(const VulkanPipeline& pipeline) { + vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.pipeline); return *this; } - VulkanCommandBuffer& VulkanCommandBuffer::draw(const size_t& vertexCount) { - vkCmdDraw(backend, vertexCount, 1, 0, 0); + // Todo VK_PIPELINE_BIND_POINT_GRAPHICS should be configured + VulkanCommandBuffer& VulkanCommandBuffer::bind_pipeline(const std::unique_ptr& pipeline) { + vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->pipeline); return *this; } - VulkanCommandBuffer& VulkanCommandBuffer::draw_indexed(const size_t& indexCount) { - vkCmdDrawIndexed(backend, static_cast(indexCount), 1, 0, 0, 0); + VulkanCommandBuffer& VulkanCommandBuffer::bind_vertex_buffer(IVulkanBuffer& buffer) { + VkBuffer buffers[] = { buffer.get_vk_buffer() }; + VkDeviceSize offset[] = { 0 }; // Todo + + vkCmdBindVertexBuffers(command_buffer, 0, 1, buffers, offset); return *this; } + VulkanCommandBuffer& VulkanCommandBuffer::bind_index_buffer(IVulkanBuffer& buffer) { + vkCmdBindIndexBuffer(command_buffer, buffer.get_vk_buffer(), 0, VK_INDEX_TYPE_UINT32); - VulkanCommandBuffer& VulkanCommandBuffer::bind_descriptor_set(std::shared_ptr& pipelineLayout, std::shared_ptr& descriptorSet) { - vkCmdBindDescriptorSets(backend, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout->get_layout(), 0, 1, &descriptorSet->backend, 0, nullptr); + return *this; + } + + VulkanCommandBuffer& VulkanCommandBuffer::draw(const size_t& vertex_count) { + vkCmdDraw(command_buffer, vertex_count, 1, 0, 0); return *this; } - VulkanCommandBuffer& VulkanCommandBuffer::bind_descriptor_set(std::shared_ptr& pipelineLayout, std::vector>& descriptorSets, const size_t& frame) { - vkCmdBindDescriptorSets(backend, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout->get_layout(), 0, 1, &descriptorSets[frame]->backend, 0, nullptr); + VulkanCommandBuffer& VulkanCommandBuffer::draw_indexed(const size_t& index_count) { + vkCmdDrawIndexed(command_buffer, static_cast(index_count), 1, 0, 0, 0); return *this; } - VulkanCommandBuffer& VulkanCommandBuffer::bind_descriptor_sets(std::shared_ptr& pipelineLayout, std::vector>& descriptorSets) { - std::vector sets; + // Todo VK_PIPELINE_BIND_POINT_GRAPHICS should be configured + VulkanCommandBuffer& VulkanCommandBuffer::bind_descriptor_set( + const std::unique_ptr& pipeline_layout, + const std::unique_ptr& descriptor_set + ) { + vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout->pipeline_layout, 0, 1, &descriptor_set->descriptor_set, 0, nullptr); - for(const auto& descriptor : descriptorSets) - sets.push_back(descriptor->backend); + return *this; + } - vkCmdBindDescriptorSets(backend, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout->get_layout(), 0, sets.size(), sets.data(), 0, nullptr); + // Todo VK_PIPELINE_BIND_POINT_GRAPHICS should be configured + VulkanCommandBuffer& VulkanCommandBuffer::bind_descriptor_set( + const std::unique_ptr& pipeline_layout, + const std::vector>& descriptor_sets, + const size_t& frame + ) { + vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout->pipeline_layout, 0, 1, &descriptor_sets[frame]->descriptor_set, 0, nullptr); return *this; } - VulkanCommandBuffer& VulkanCommandBuffer::push_constant(std::shared_ptr& pipelineLayout, const uint32_t& size, const void* constantPtr) { - vkCmdPushConstants(backend, pipelineLayout->get_layout(), VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, size, constantPtr); + // Todo VK_PIPELINE_BIND_POINT_GRAPHICS should be configured + VulkanCommandBuffer& VulkanCommandBuffer::bind_descriptor_sets( + const std::unique_ptr& pipeline_layout, + const std::vector>& descriptor_sets + ) { + auto sets = std::vector { }; + sets.reserve(descriptor_sets.size()); + + for(const auto& descriptor : descriptor_sets) + sets.push_back(descriptor->descriptor_set); + + vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout->pipeline_layout, 0, sets.size(), sets.data(), 0, nullptr); return *this; } - VulkanCommandBuffer& VulkanCommandBuffer::push_constant(std::shared_ptr& pipelineLayout, const uint32_t& size, const size_t& offset, const void* constantPtr) { - vkCmdPushConstants(backend, pipelineLayout->get_layout(), VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, offset, size, constantPtr); + // Todo VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT should be configured + VulkanCommandBuffer& VulkanCommandBuffer::push_constant( + const std::unique_ptr& pipeline_layout, + const u32& size, + const void* ptr + ) { + vkCmdPushConstants(command_buffer, pipeline_layout->pipeline_layout, VK_SHADER_STAGE_ALL, 0, size, ptr); // Todo, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT return *this; } - void VulkanCommandBuffer::destroy(VulkanDevice&) { + // Todo VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT should be configured + VulkanCommandBuffer& VulkanCommandBuffer::push_constant( + const std::unique_ptr& pipeline_layout, + const uint32_t& size, + const size_t& offset, + const void* ptr + ) { + vkCmdPushConstants(command_buffer, pipeline_layout->pipeline_layout, VK_SHADER_STAGE_ALL, offset, size, ptr); // Todo, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT + return *this; } } diff --git a/src/bebone/gfx/vulkan/vulkan_command_buffer.h b/src/bebone/gfx/vulkan/vulkan_command_buffer.h index c30309ff..d5b6e0a1 100644 --- a/src/bebone/gfx/vulkan/vulkan_command_buffer.h +++ b/src/bebone/gfx/vulkan/vulkan_command_buffer.h @@ -1,77 +1,88 @@ -#ifndef _BEBONE_GFX_VULKAN_VULKAN_COMMAND_BUFFER_H_ -#define _BEBONE_GFX_VULKAN_VULKAN_COMMAND_BUFFER_H_ +#ifndef _BEBONE_GFX_VULKAN_COMMAND_BUFFER_H_ +#define _BEBONE_GFX_VULKAN_COMMAND_BUFFER_H_ #include #include #include "../gfx_backend.h" -#include "vulkan_wrapper.tpp" #include "vulkan_swap_chain.h" #include "vulkan_pipeline.h" -namespace bebone::gfx::vulkan { +#include "interface/i_vulkan_buffer.h" +#include "interface/i_vulkan_command_buffer_pool.h" + +namespace bebone::gfx { using namespace bebone::core; - class VulkanDevice; - class VulkanCommandBufferPool; class VulkanDescriptorSet; - class VulkanCommandBuffer : public VulkanWrapper, private core::NonCopyable { + class VulkanCommandBuffer : private core::NonCopyable { public: - VulkanCommandBuffer( - std::shared_ptr& device, - VulkanCommandBufferPool& commandBufferPool); + VkCommandBuffer command_buffer; + + private: + IVulkanDevice& device_owner; + + public: + using Self = VulkanCommandBuffer; + + VulkanCommandBuffer(IVulkanDevice& device, IVulkanCommandBufferPool& command_buffer_pool); - VulkanCommandBuffer& begin_record(); - VulkanCommandBuffer& end_record(); + Self& begin_record(); + Self& end_record(); - VulkanCommandBuffer& begin_render_pass( - std::shared_ptr& swapChain, - const u32& frameBuffer); + // Swap chain specific begin render pass + Self& begin_render_pass(const VulkanSwapChain& swap_chain); - VulkanCommandBuffer& end_render_pass(); + Self& begin_render_pass( + const std::unique_ptr& render_target, + const std::unique_ptr& render_pass, + const size_t& frame); + + Self& begin_render_pass( + const std::unique_ptr& framebuffer, + const std::unique_ptr& render_pass); + + Self& end_render_pass(); - VulkanCommandBuffer& set_viewport( - const i32& x, - const i32& y, - const u32& width, - const u32& height); + Self& set_viewport(std::unique_ptr& window); + Self& set_viewport(const Vec2i& viewport, const f32& min_depth = 0.0f, const f32& max_depth = 1.0f); + Self& set_viewport(const f32& x, const f32& y, const f32& width, const f32& height, const f32& min_depth = 0.0f, const f32& max_depth = 1.0f); + Self& set_scissors(const i32& x, const i32& y, const u32& width, const u32& height); - VulkanCommandBuffer& bind_pipeline(VulkanPipeline& pipeline); - VulkanCommandBuffer& bind_pipeline(std::shared_ptr& pipeline); + Self& bind_pipeline(const VulkanPipeline& pipeline); + Self& bind_pipeline(const std::unique_ptr& pipeline); - VulkanCommandBuffer& bind_vertex_buffer(std::shared_ptr& buffer); - VulkanCommandBuffer& bind_index_buffer(std::shared_ptr& indexBuffer); + Self& bind_vertex_buffer(IVulkanBuffer& buffer); + Self& bind_index_buffer(IVulkanBuffer& buffer); - VulkanCommandBuffer& bind_descriptor_set( - std::shared_ptr& pipelineLayout, - std::shared_ptr& descriptorSet); + Self& bind_descriptor_set( + const std::unique_ptr& pipeline_layout, + const std::unique_ptr& descriptor_set); - VulkanCommandBuffer& bind_descriptor_set( - std::shared_ptr& pipelineLayout, - std::vector>& descriptorSets, + Self& bind_descriptor_set( + const std::unique_ptr& pipeline_layout, + const std::vector>& descriptor_sets, const size_t& frame); - VulkanCommandBuffer& bind_descriptor_sets( - std::shared_ptr& pipelineLayout, - std::vector>& descriptorSets); + Self& bind_descriptor_sets( + const std::unique_ptr& pipeline_layout, + const std::vector>& descriptor_sets); - VulkanCommandBuffer& push_constant( - std::shared_ptr& pipelineLayout, - const uint32_t& size, + Self& push_constant( + const std::unique_ptr& pipeline_layout, + const u32& size, const void* ptr); - VulkanCommandBuffer& push_constant( - std::shared_ptr& pipelineLayout, + Self& push_constant( + const std::unique_ptr& pipeline_layout, const uint32_t& size, const size_t& offset, const void* ptr); - VulkanCommandBuffer& draw(const size_t& vertexCount); - VulkanCommandBuffer& draw_indexed(const size_t& vertexCount); - - void destroy(VulkanDevice& device) override; + Self& draw(const size_t& vertex_count); + Self& draw_indexed(const size_t& vertex_count); }; } diff --git a/src/bebone/gfx/vulkan/vulkan_command_buffer_pool.cpp b/src/bebone/gfx/vulkan/vulkan_command_buffer_pool.cpp index 536df711..6d26ac53 100644 --- a/src/bebone/gfx/vulkan/vulkan_command_buffer_pool.cpp +++ b/src/bebone/gfx/vulkan/vulkan_command_buffer_pool.cpp @@ -1,94 +1,95 @@ #include "vulkan_command_buffer_pool.h" -namespace bebone::gfx::vulkan { - VulkanCommandBufferPool::VulkanCommandBufferPool(VulkanDevice& device) { - QueueFamilyIndices queueFamilyIndices = device.find_physical_queue_families(); +namespace bebone::gfx { + VulkanCommandBufferPool::VulkanCommandBufferPool(IVulkanDevice& device) : device_owner(device) { + VulkanQueueFamilyIndices queue_family_indices = device.find_physical_queue_families(); - VkCommandPoolCreateInfo poolInfo = {}; - poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - poolInfo.queueFamilyIndex = queueFamilyIndices.graphicsFamily; - poolInfo.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; + VkCommandPoolCreateInfo pool_info = {}; + pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + pool_info.queueFamilyIndex = queue_family_indices.graphics_family; + pool_info.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - if (vkCreateCommandPool(device.device(), &poolInfo, nullptr, &backend) != VK_SUCCESS) { + if (vkCreateCommandPool(device_owner.get_vk_device(), &pool_info, nullptr, &command_buffer_pool) != VK_SUCCESS) { + LOG_ERROR("Failed to create command pool"); throw std::runtime_error("failed to create command pool!"); } + + LOG_TRACE("Created command buffer pool"); } - std::vector> VulkanCommandBufferPool::create_command_buffers(std::shared_ptr& device, const size_t& commandBufferCount) { - std::vector> commandBuffersVector; + VulkanCommandBufferPool::~VulkanCommandBufferPool() { + device_owner.wait_idle(); - for(size_t i = 0; i < commandBufferCount; ++i) - commandBuffersVector.push_back(std::make_shared(device, *this)); + vkDestroyCommandPool(device_owner.get_vk_device(), command_buffer_pool, nullptr); - return commandBuffersVector; + LOG_TRACE("Destroyed command buffer pool"); } - VkCommandBuffer VulkanCommandBufferPool::begin_single_time_commands(VulkanDevice& device) { - VkCommandBufferAllocateInfo allocInfo{}; - allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - allocInfo.commandPool = backend; - allocInfo.commandBufferCount = 1; + std::unique_ptr VulkanCommandBufferPool::create_command_buffer() { + return std::make_unique(device_owner, *this); + } - VkCommandBuffer commandBuffer; - vkAllocateCommandBuffers(device.device(), &allocInfo, &commandBuffer); + std::vector> VulkanCommandBufferPool::create_command_buffers( + const size_t& count + ) { + auto command_buffers = std::vector> {}; + command_buffers.reserve(count); - VkCommandBufferBeginInfo beginInfo{}; - beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; + for(size_t i = 0; i < count; ++i) + command_buffers.push_back(create_command_buffer()); - vkBeginCommandBuffer(commandBuffer, &beginInfo); - return commandBuffer; + return command_buffers; } - void VulkanCommandBufferPool::end_single_time_commands(VulkanDevice& device, VkCommandBuffer commandBuffer) { - vkEndCommandBuffer(commandBuffer); + VkCommandPool VulkanCommandBufferPool::get_vk_command_buffer_pool() const { + return command_buffer_pool; + } - VkSubmitInfo submitInfo{}; - submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &commandBuffer; + // Todo, rethink single time commands + VkCommandBuffer VulkanCommandBufferPool::begin_single_time_commands() { + VkCommandBufferAllocateInfo alloc_info{}; - vkQueueSubmit(device.graphicsQueue(), 1, &submitInfo, VK_NULL_HANDLE); - vkQueueWaitIdle(device.graphicsQueue()); + alloc_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + alloc_info.commandPool = command_buffer_pool; + alloc_info.commandBufferCount = 1; - vkFreeCommandBuffers(device.device(), backend, 1, &commandBuffer); - } + VkCommandBuffer command_buffer; + vkAllocateCommandBuffers(device_owner.get_vk_device(), &alloc_info, &command_buffer); - void VulkanCommandBufferPool::destroy(VulkanDevice& device) { - vkDestroyCommandPool(device.device(), backend, nullptr); + VkCommandBufferBeginInfo begin_info{}; + begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; + + vkBeginCommandBuffer(command_buffer, &begin_info); + + return command_buffer; } + // Todo, rethink single time commands + void VulkanCommandBufferPool::end_single_time_commands(VkCommandBuffer command_buffer) { + vkEndCommandBuffer(command_buffer); + + VkSubmitInfo submit_info{}; + submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submit_info.commandBufferCount = 1; + submit_info.pCommandBuffers = &command_buffer; + + vkQueueSubmit(device_owner.get_graphics_queue(), 1, &submit_info, VK_NULL_HANDLE); + vkQueueWaitIdle(device_owner.get_graphics_queue()); + + vkFreeCommandBuffers(device_owner.get_vk_device(), command_buffer_pool, 1, &command_buffer); + } // void copy_buffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size) { - // VkCommandBuffer commandBuffer = begin_single_time_commands(); + // VkCommandBuffer command_buffer = begin_single_time_commands(); // // VkBufferCopy copyRegion{}; // copyRegion.srcOffset = 0; // Optional // copyRegion.dstOffset = 0; // Optional // copyRegion.size = size; - // vkCmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, 1, ©Region); -// - // end_single_time_commands(commandBuffer); - // } - - // void copy_buffe_to_image(VkBuffer buffer, VkImage image, uint32_t width, uint32_t height, uint32_t layerCount) { - // VkCommandBuffer commandBuffer = begin_single_time_commands(); -// - // VkBufferImageCopy region{}; - // region.bufferOffset = 0; - // region.bufferRowLength = 0; - // region.bufferImageHeight = 0; -// - // region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - // region.imageSubresource.mipLevel = 0; - // region.imageSubresource.baseArrayLayer = 0; - // region.imageSubresource.layerCount = layerCount; -// - // region.imageOffset = {0, 0, 0}; - // region.imageExtent = {width, height, 1}; + // vkCmdCopyBuffer(command_buffer, srcBuffer, dstBuffer, 1, ©Region); // - // vkCmdCopyBufferToImage(commandBuffer, buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); - // end_single_time_commands(commandBuffer); + // end_single_time_commands(command_buffer); // } } diff --git a/src/bebone/gfx/vulkan/vulkan_command_buffer_pool.h b/src/bebone/gfx/vulkan/vulkan_command_buffer_pool.h index d5277e3d..16fd1951 100644 --- a/src/bebone/gfx/vulkan/vulkan_command_buffer_pool.h +++ b/src/bebone/gfx/vulkan/vulkan_command_buffer_pool.h @@ -1,25 +1,33 @@ -#ifndef _BEBONE_GFX_VULKAN_VULKAN_COMMAND_BUFFER_POOL_H_ -#define _BEBONE_GFX_VULKAN_VULKAN_COMMAND_BUFFER_POOL_H_ +#ifndef _BEBONE_GFX_VULKAN_COMMAND_BUFFER_POOL_H_ +#define _BEBONE_GFX_VULKAN_COMMAND_BUFFER_POOL_H_ #include #include "../gfx_backend.h" -#include "vulkan_device.h" +#include "interface/i_vulkan_command_buffer_pool.h" #include "vulkan_command_buffer.h" -namespace bebone::gfx::vulkan { - class VulkanCommandBufferPool : public VulkanWrapper, private core::NonCopyable { +namespace bebone::gfx { + class VulkanCommandBufferPool : public IVulkanCommandBufferPool, private core::NonCopyable { public: - VulkanCommandBufferPool(VulkanDevice& device); + VkCommandPool command_buffer_pool; - std::vector> create_command_buffers(std::shared_ptr& device, const size_t& commandBufferCount); + private: + IVulkanDevice& device_owner; - VkCommandBuffer begin_single_time_commands(VulkanDevice& device); - void end_single_time_commands(VulkanDevice& device, VkCommandBuffer commandBuffer); + public: + VulkanCommandBufferPool(IVulkanDevice& device); + ~VulkanCommandBufferPool() override; + + std::unique_ptr create_command_buffer(); + std::vector> create_command_buffers(const size_t& count); - void destroy(VulkanDevice& device) override; + // Vulkan Command Buffer Pool + [[nodiscard]] VkCommandPool get_vk_command_buffer_pool() const override; + VkCommandBuffer begin_single_time_commands() override; + void end_single_time_commands(VkCommandBuffer command_buffer) override; }; } diff --git a/src/bebone/gfx/vulkan/vulkan_const_range.cpp b/src/bebone/gfx/vulkan/vulkan_const_range.cpp index 15e4c9fe..53a4686f 100644 --- a/src/bebone/gfx/vulkan/vulkan_const_range.cpp +++ b/src/bebone/gfx/vulkan/vulkan_const_range.cpp @@ -1,17 +1,13 @@ #include "vulkan_const_range.h" -namespace bebone::gfx::vulkan { +namespace bebone::gfx { using namespace bebone::core; - VulkanConstRange::VulkanConstRange(const VkPushConstantRange& range) : range(range) { - - } - - VulkanConstRange VulkanConstRange::common(const size_t& size, const u32& offset) { - return VulkanConstRange({ - .stageFlags = (VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT), + VulkanConstRange::VulkanConstRange(const size_t& size, const u32& offset, const VkShaderStageFlags& stage_flags) { + const_range = VkPushConstantRange{ + .stageFlags = stage_flags, .offset = offset, - .size = sizeof(size) - }); + .size = static_cast(size) + }; } } diff --git a/src/bebone/gfx/vulkan/vulkan_const_range.h b/src/bebone/gfx/vulkan/vulkan_const_range.h index d2af60c3..cfa11070 100644 --- a/src/bebone/gfx/vulkan/vulkan_const_range.h +++ b/src/bebone/gfx/vulkan/vulkan_const_range.h @@ -1,18 +1,17 @@ -#ifndef _BEBONE_GFX_VULKAN_VULKAN_CONST_RANGE_H_ -#define _BEBONE_GFX_VULKAN_VULKAN_CONST_RANGE_H_ +#ifndef _BEBONE_GFX_VULKAN_CONST_RANGE_H_ +#define _BEBONE_GFX_VULKAN_CONST_RANGE_H_ #include "../gfx_backend.h" -namespace bebone::gfx::vulkan { +namespace bebone::gfx { using namespace bebone::core; + // Todo simplify this class class VulkanConstRange { public: - VkPushConstantRange range; + VkPushConstantRange const_range; - VulkanConstRange(const VkPushConstantRange& range); - - static VulkanConstRange common(const size_t& size, const u32& offset); + VulkanConstRange(const size_t& size, const u32& offset, const VkShaderStageFlags& stage_flags = VK_SHADER_STAGE_ALL); }; } diff --git a/src/bebone/gfx/vulkan/vulkan_debug_messenger.cpp b/src/bebone/gfx/vulkan/vulkan_debug_messenger.cpp index 9c29ed9b..c249d7fd 100644 --- a/src/bebone/gfx/vulkan/vulkan_debug_messenger.cpp +++ b/src/bebone/gfx/vulkan/vulkan_debug_messenger.cpp @@ -1,56 +1,69 @@ #include "vulkan_debug_messenger.h" #include "vulkan_instance.h" -namespace bebone::gfx::vulkan { - static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData, void *pUserData) { - std::ignore = messageSeverity; - std::ignore = messageType; - std::ignore = pUserData; +namespace bebone::gfx { + static VKAPI_ATTR VkBool32 VKAPI_CALL debug_callback( + VkDebugUtilsMessageSeverityFlagBitsEXT message_severity, + VkDebugUtilsMessageTypeFlagsEXT message_type, + const VkDebugUtilsMessengerCallbackDataEXT *callback, + void *user_ptr + ) { + std::ignore = message_severity; + std::ignore = message_type; + std::ignore = user_ptr; - std::cerr << "validation layer: " << pCallbackData->pMessage << std::endl; + LOG_WARNING("Validation layer: {}", callback->pMessage); return VK_FALSE; } - VkResult CreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDebugUtilsMessengerEXT *pDebugMessenger) { + VkResult CreateDebugUtilsMessengerEXT( + VkInstance instance, + const VkDebugUtilsMessengerCreateInfoEXT *create_info, + const VkAllocationCallbacks *allocator, + VkDebugUtilsMessengerEXT *debug_messenger + ) { auto func = (PFN_vkCreateDebugUtilsMessengerEXT) vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT"); - if (func != nullptr) { - return func(instance, pCreateInfo, pAllocator, pDebugMessenger); - } - + if(func != nullptr) + return func(instance, create_info, allocator, debug_messenger); return VK_ERROR_EXTENSION_NOT_PRESENT; } - void DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT debugMessenger, const VkAllocationCallbacks *pAllocator) { - auto func = (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT"); + void DestroyDebugUtilsMessengerEXT( + VkInstance instance, + VkDebugUtilsMessengerEXT debug_messenger, + const VkAllocationCallbacks *allocator + ) { + auto func = (PFN_vkDestroyDebugUtilsMessengerEXT) vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT"); - if (func != nullptr) { - func(instance, debugMessenger, pAllocator); - } + if(func != nullptr) + func(instance, debug_messenger, allocator); } - void VulkanDebugMessenger::populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT &createInfo) { - createInfo = {}; - createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; - createInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT; - createInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT; - createInfo.pfnUserCallback = debugCallback; - createInfo.pUserData = nullptr; // Optional + void VulkanDebugMessenger::populate_debug_messenger_create_info(VkDebugUtilsMessengerCreateInfoEXT &create_info) { + create_info = {}; + create_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; + create_info.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT; + create_info.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT; + create_info.pfnUserCallback = debug_callback; + create_info.pUserData = nullptr; // Optional } - VulkanDebugMessenger::VulkanDebugMessenger(VulkanInstance& _vulkanInstance) : vulkanInstance(_vulkanInstance) { - VkDebugUtilsMessengerCreateInfoEXT createInfo; - populateDebugMessengerCreateInfo(createInfo); + VulkanDebugMessenger::VulkanDebugMessenger(IVulkanInstance& instance) : instance_owner(instance) { + VkDebugUtilsMessengerCreateInfoEXT create_info; + + populate_debug_messenger_create_info(create_info); - if (CreateDebugUtilsMessengerEXT(vulkanInstance.get_instance(), &createInfo, nullptr, &debugMessenger) != VK_SUCCESS) { + if(CreateDebugUtilsMessengerEXT(instance_owner.get_vk_instance(), &create_info, nullptr, &debug_messenger) != VK_SUCCESS) { + LOG_ERROR("Failed to set up debug messenger"); throw std::runtime_error("failed to set up debug messenger!"); } } VulkanDebugMessenger::~VulkanDebugMessenger() { - DestroyDebugUtilsMessengerEXT(vulkanInstance.get_instance(), debugMessenger, nullptr); + DestroyDebugUtilsMessengerEXT(instance_owner.get_vk_instance(), debug_messenger, nullptr); } } diff --git a/src/bebone/gfx/vulkan/vulkan_debug_messenger.h b/src/bebone/gfx/vulkan/vulkan_debug_messenger.h index 9d5add2e..be3fa576 100644 --- a/src/bebone/gfx/vulkan/vulkan_debug_messenger.h +++ b/src/bebone/gfx/vulkan/vulkan_debug_messenger.h @@ -1,22 +1,24 @@ -#ifndef _BEBONE_GFX_VULKAN_VULKAN_DEBUG_MESSENGER_H_ -#define _BEBONE_GFX_VULKAN_VULKAN_DEBUG_MESSENGER_H_ +#ifndef _BEBONE_GFX_VULKAN_DEBUG_MESSENGER_H_ +#define _BEBONE_GFX_VULKAN_DEBUG_MESSENGER_H_ #include "../gfx_backend.h" +#include "interface/i_vulkan_instance.h" -namespace bebone::gfx::vulkan { - class VulkanInstance; +namespace bebone::gfx { + class IVulkanInstance; class VulkanDebugMessenger : private core::NonCopyable { private: - VulkanInstance& vulkanInstance; + IVulkanInstance& instance_owner; - VkDebugUtilsMessengerEXT debugMessenger; + private: + VkDebugUtilsMessengerEXT debug_messenger; public: - static void populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT &createInfo); - - VulkanDebugMessenger(VulkanInstance& vulkanInstance); + VulkanDebugMessenger(IVulkanInstance& instance); ~VulkanDebugMessenger(); + + static void populate_debug_messenger_create_info(VkDebugUtilsMessengerCreateInfoEXT &create_info); }; } diff --git a/src/bebone/gfx/vulkan/vulkan_depth_image.cpp b/src/bebone/gfx/vulkan/vulkan_depth_image.cpp new file mode 100644 index 00000000..f411516a --- /dev/null +++ b/src/bebone/gfx/vulkan/vulkan_depth_image.cpp @@ -0,0 +1,40 @@ +#include "vulkan_depth_image.h" + +#include "vulkan_image.h" + +namespace bebone::gfx { + VulkanDepthImage::VulkanDepthImage(IVulkanDevice& device, VkExtent3D extent) { + auto format = device.find_depth_format(); + + VulkanImageInfo image_info{}; + image_info.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + image = std::make_unique(device, format, extent, image_info); + + auto req = image->get_memory_requirements(); + + memory = std::make_unique(device, req, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + memory->bind_image_memory(*image); + + VulkanImageViewInfo image_view_info{}; + image_view_info.subresource_range = { .aspect_mask = VK_IMAGE_ASPECT_DEPTH_BIT }; + view = std::make_unique(device, *image, format, image_view_info); + } + + VulkanDepthImage::~VulkanDepthImage() = default; + + VkImage VulkanDepthImage::get_vk_image() const { + return image->get_vk_image(); + } + + VkMemoryRequirements VulkanDepthImage::get_memory_requirements() const { + return image->get_memory_requirements(); + } + + VkExtent3D VulkanDepthImage::get_extent() const { + return image->get_extent(); + } + + VkImageView VulkanDepthImage::get_vk_image_view() const { + return view->get_vk_image_view(); + } +} diff --git a/src/bebone/gfx/vulkan/vulkan_depth_image.h b/src/bebone/gfx/vulkan/vulkan_depth_image.h new file mode 100644 index 00000000..0ad22314 --- /dev/null +++ b/src/bebone/gfx/vulkan/vulkan_depth_image.h @@ -0,0 +1,39 @@ +#ifndef _BEBONE_GFX_VULKAN_DEPTH_IMAGE_H_ +#define _BEBONE_GFX_VULKAN_DEPTH_IMAGE_H_ + +#include + +#include "../gfx_backend.h" + +#include "vulkan_image.h" +#include "vulkan_sampler.h" +#include "vulkan_image_view.h" + +#include "interface/i_vulkan_image.h" +#include "interface/i_vulkan_image_view.h" +#include "interface/i_vulkan_sampler.h" + +namespace bebone::gfx { + using namespace bebone::core; + + class VulkanDepthImage : public IVulkanImage, public IVulkanImageView, private core::NonCopyable{ + private: + std::unique_ptr image; + std::unique_ptr view; + std::unique_ptr memory; + + public: + VulkanDepthImage(IVulkanDevice& device, VkExtent3D extent); + ~VulkanDepthImage() override; + + // Vulkan Image + [[nodiscard]] VkImage get_vk_image() const override; + [[nodiscard]] VkMemoryRequirements get_memory_requirements() const override; + [[nodiscard]] VkExtent3D get_extent() const override; + + // Vulkan Image View + [[nodiscard]] VkImageView get_vk_image_view() const override; + }; +} + +#endif diff --git a/src/bebone/gfx/vulkan/vulkan_descriptor_pool.cpp b/src/bebone/gfx/vulkan/vulkan_descriptor_pool.cpp index 5a96aa3f..260c155e 100644 --- a/src/bebone/gfx/vulkan/vulkan_descriptor_pool.cpp +++ b/src/bebone/gfx/vulkan/vulkan_descriptor_pool.cpp @@ -1,129 +1,55 @@ #include "vulkan_descriptor_pool.h" -#include "vulkan_device.h" +#include "vulkan_texture.h" #include "vulkan_descriptor_set.h" -namespace bebone::gfx::vulkan { - VulkanDescriptorPool::VulkanDescriptorPool(VulkanDevice& device) { +namespace bebone::gfx { + VulkanDescriptorPool::VulkanDescriptorPool(IVulkanDevice& device) : device_owner(device) { // Todo Why do we need to set type to specific, i wanned to use this also for ssbo - std::vector poolSizes = { + auto pool_sizes = std::vector { { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 65536 }, - // { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, maxBindlessResources }, + { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 65536 }, + { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 65536 } }; - VkDescriptorPoolCreateInfo poolInfo{}; - poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - poolInfo.poolSizeCount = poolSizes.size(); - poolInfo.pPoolSizes = poolSizes.data(); - poolInfo.maxSets = static_cast(65536 * poolSizes.size()); - poolInfo.flags = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT; + VkDescriptorPoolCreateInfo pool_info{}; - if (vkCreateDescriptorPool(device.device(), &poolInfo, nullptr, &backend) != VK_SUCCESS) { + pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + pool_info.poolSizeCount = pool_sizes.size(); + pool_info.pPoolSizes = pool_sizes.data(); + pool_info.maxSets = static_cast(65536 * pool_sizes.size()); + pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT; + + if(vkCreateDescriptorPool(device_owner.get_vk_device(), &pool_info, nullptr, &descriptor_pool) != VK_SUCCESS) { + LOG_ERROR("Failed to create descriptor pool"); throw std::runtime_error("failed to create descriptor pool!"); } - } - - // VulkanDescriptorPool::~VulkanDescriptorPool() { - // // for(const auto& layouts : descriptorSetLayouts) { - // // vkDestroyDescriptorSetLayout(_device.device(), layouts, nullptr); - // // } - // } - - void VulkanDescriptorPool::update_descriptor_set( - std::shared_ptr& device, - std::shared_ptr& buffer, - const size_t& size, - std::shared_ptr& descriptorSet, - const size_t& binding, - const size_t& dstArrayElement - ) { - VkDescriptorBufferInfo bufferInfo{}; - bufferInfo.buffer = buffer->backend; - bufferInfo.offset = 0; - bufferInfo.range = size; - - VkWriteDescriptorSet descriptorWrite{}; - descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptorWrite.dstSet = descriptorSet->backend; - descriptorWrite.dstBinding = binding; - descriptorWrite.dstArrayElement = dstArrayElement; // Todo THIS IS A HANDLE, and handle counter should work per shader binding, not a cpu binding thing - - descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - descriptorWrite.descriptorCount = 1; - descriptorWrite.pBufferInfo = &bufferInfo; - - descriptorWrite.pImageInfo = nullptr; // Optional - descriptorWrite.pTexelBufferView = nullptr; // Optional - - vkUpdateDescriptorSets(device->device(), 1, &descriptorWrite, 0, nullptr); + LOG_TRACE("Created Descriptor pool"); } - void VulkanDescriptorPool::update_descriptor_set( - std::shared_ptr& device, - VulkanBufferMemoryTuple& tuple, - const size_t& size, - std::shared_ptr& descriptorSet, - const size_t& binding, - const size_t& dstArrayElement - ) { - update_descriptor_set(device, tuple.buffer, size, descriptorSet, binding, dstArrayElement); - } + VulkanDescriptorPool::~VulkanDescriptorPool() { + vkDestroyDescriptorPool(device_owner.get_vk_device(), descriptor_pool, nullptr); - void VulkanDescriptorPool::update_descriptor_sets( - std::shared_ptr& device, - std::vector>& buffers, - const size_t& size, - std::vector>& descriptorSets, - const size_t& binding, - const std::vector& dstArrayElements - ) { - if(buffers.size() != dstArrayElements.size()) - throw std::runtime_error("buffer an dstArrayElements count is not matching"); - - for(size_t i = 0; i < dstArrayElements.size(); ++i) { - auto& buffer = buffers[i]; - auto& dstArrayElement = dstArrayElements[i]; - auto& descriptorSet = descriptorSets[i]; - - update_descriptor_set(device, buffer, size, descriptorSet, binding, dstArrayElement); - } + LOG_TRACE("Destroyed Descriptor pool"); } - void VulkanDescriptorPool::update_descriptor_sets( - std::shared_ptr& device, - std::vector& tuples, - const size_t& size, - std::vector>& descriptorSets, - const size_t& binding, - const std::vector& dstArrayElements + std::unique_ptr VulkanDescriptorPool::create_descriptor( + const std::unique_ptr& descriptor_set_layout ) { - if(tuples.size() != dstArrayElements.size()) - throw std::runtime_error("buffer an dstArrayElements count is not matching"); - - for(size_t i = 0; i < dstArrayElements.size(); ++i) { - auto& buffer = tuples[i].buffer; - auto& dstArrayElement = dstArrayElements[i]; - auto& descriptorSet = descriptorSets[i]; - - update_descriptor_set(device, buffer, size, descriptorSet, binding, dstArrayElement); - } + return std::make_unique(device_owner, *this, descriptor_set_layout); } - std::shared_ptr VulkanDescriptorPool::create_descriptor(std::shared_ptr& device, std::shared_ptr& descriptorSetLayout) { - return std::make_shared(device, *this, descriptorSetLayout); - } - - std::vector> VulkanDescriptorPool::create_descriptors(std::shared_ptr& device, std::shared_ptr& descriptorSetLayout, const size_t& descriptorCount) { - std::vector> descriptors; + std::vector> VulkanDescriptorPool::create_descriptors( + const std::unique_ptr& descriptor_set_layout, + const size_t& count + ) { + auto descriptors = std::vector>{}; + descriptors.reserve(count); - for(size_t i = 0; i < descriptorCount; ++i) - descriptors.push_back(std::make_shared(device, *this, descriptorSetLayout)); + for(size_t i = 0; i < count; ++i) + descriptors.push_back(std::make_unique(device_owner, *this, descriptor_set_layout)); return descriptors; } - - void VulkanDescriptorPool::destroy(VulkanDevice& device) { - vkDestroyDescriptorPool(device.device(), backend, nullptr); - } } diff --git a/src/bebone/gfx/vulkan/vulkan_descriptor_pool.h b/src/bebone/gfx/vulkan/vulkan_descriptor_pool.h index f6f0a8c3..f5f10576 100644 --- a/src/bebone/gfx/vulkan/vulkan_descriptor_pool.h +++ b/src/bebone/gfx/vulkan/vulkan_descriptor_pool.h @@ -1,5 +1,5 @@ -#ifndef _BEBONE_GFX_VULKAN_VULKAN_DESCRIPTOR_POOL_H_ -#define _BEBONE_GFX_VULKAN_VULKAN_DESCRIPTOR_POOL_H_ +#ifndef _BEBONE_GFX_VULKAN_DESCRIPTOR_POOL_H_ +#define _BEBONE_GFX_VULKAN_DESCRIPTOR_POOL_H_ #include @@ -7,61 +7,24 @@ #include "vulkan_command_buffer.h" -namespace bebone::gfx::vulkan { +namespace bebone::gfx { class VulkanDescriptorSet; class VulkanDescriptorSetLayout; - class VulkanDescriptorPool : public VulkanWrapper, private core::NonCopyable { + class VulkanDescriptorPool : private core::NonCopyable { public: - VulkanDescriptorPool(VulkanDevice& device); + VkDescriptorPool descriptor_pool; - std::shared_ptr create_descriptor( - std::shared_ptr& device, - std::shared_ptr& descriptorSetLayout); + private: + IVulkanDevice& device_owner; - std::vector> create_descriptors( - std::shared_ptr& device, - std::shared_ptr& descriptorSetLayout, - const size_t& descriptorCount); - - void update_descriptor_set( - std::shared_ptr& device, - std::shared_ptr& buffer, - const size_t& size, - std::shared_ptr& descriptorSet, - const size_t& binding, - const size_t& dstArrayElement - ); - - void update_descriptor_set( - std::shared_ptr& device, - VulkanBufferMemoryTuple& tuple, - const size_t& size, - std::shared_ptr& descriptorSet, - const size_t& binding, - const size_t& dstArrayElement - ); - - void update_descriptor_sets( - std::shared_ptr& device, - std::vector>& buffers, - const size_t& size, - std::vector>& descriptorSets, - const size_t& binding, - const std::vector& dstArrayElements - ); - - void update_descriptor_sets( - std::shared_ptr& device, - std::vector& tuples, - const size_t& size, - std::vector>& descriptorSets, - const size_t& binding, - const std::vector& dstArrayElements - ); + public: + VulkanDescriptorPool(IVulkanDevice& device); + ~VulkanDescriptorPool(); - void destroy(VulkanDevice& device) override; - }; + std::unique_ptr create_descriptor(const std::unique_ptr& descriptor_set_layout); + std::vector> create_descriptors(const std::unique_ptr& descriptor_set_layout, const size_t& count); + }; } #endif diff --git a/src/bebone/gfx/vulkan/vulkan_descriptor_set.cpp b/src/bebone/gfx/vulkan/vulkan_descriptor_set.cpp index fbc8dc71..45324c50 100644 --- a/src/bebone/gfx/vulkan/vulkan_descriptor_set.cpp +++ b/src/bebone/gfx/vulkan/vulkan_descriptor_set.cpp @@ -1,39 +1,95 @@ #include "vulkan_descriptor_set.h" -#include "vulkan_device.h" #include "vulkan_descriptor_pool.h" #include "vulkan_descriptor_set_layout.h" -namespace bebone::gfx::vulkan { +namespace bebone::gfx { VulkanDescriptorSet::VulkanDescriptorSet( - std::shared_ptr& device, - VulkanDescriptorPool& descriptorPool, - std::shared_ptr& descriptorSetLayout - ) { - VkDescriptorSetAllocateInfo allocInfo{}; - allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; - allocInfo.descriptorPool = descriptorPool.backend; - allocInfo.descriptorSetCount = 1; - allocInfo.pSetLayouts = &descriptorSetLayout->backend; - - VkDescriptorSetVariableDescriptorCountAllocateInfoEXT countInfo; - countInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO_EXT; - countInfo.pNext = nullptr; + IVulkanDevice& device, + VulkanDescriptorPool& descriptor_pool, + const std::unique_ptr& descriptor_set_layout + ) : device_owner(device) { + VkDescriptorSetAllocateInfo alloc_info{}; + alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + alloc_info.descriptorPool = descriptor_pool.descriptor_pool; + alloc_info.descriptorSetCount = 1; + alloc_info.pSetLayouts = &descriptor_set_layout->descriptor_set_layout; - unsigned int maxBinding = 65536 - 1; - countInfo.descriptorSetCount = 1; + VkDescriptorSetVariableDescriptorCountAllocateInfoEXT count_info; + count_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO_EXT; + count_info.pNext = nullptr; - countInfo.pDescriptorCounts = &maxBinding; - allocInfo.pNext = &countInfo; // Todo + // Todo + static unsigned int max_binding = 65536 - 1; + count_info.descriptorSetCount = 1; - // auto& descriptorSet = descriptorSets[descriptorSets.size() - 1]; + count_info.pDescriptorCounts = &max_binding; + alloc_info.pNext = &count_info; // Todo - if (vkAllocateDescriptorSets(device->device(), &allocInfo, &backend) != VK_SUCCESS) { + if (vkAllocateDescriptorSets(device_owner.get_vk_device(), &alloc_info, &descriptor_set) != VK_SUCCESS) { + LOG_ERROR("Failed to allocate descriptor sets"); throw std::runtime_error("failed to allocate descriptor sets!"); } + + LOG_TRACE("Allocated Descriptor set"); + } + + // Todo add buffer_info offset there +void VulkanDescriptorSet::update_descriptor_set( + IVulkanBuffer& buffer, + const size_t& binding, + const size_t& dst_array_element + ) { + VkDescriptorBufferInfo buffer_info{}; + buffer_info.buffer = buffer.get_vk_buffer(); + buffer_info.offset = 0; + buffer_info.range = buffer.get_size(); + + VkWriteDescriptorSet descriptor_write{}; + descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + + descriptor_write.dstSet = descriptor_set; + descriptor_write.dstBinding = binding; + descriptor_write.dstArrayElement = dst_array_element; + // Todo, remember that this mean \/ + // Todo THIS IS A HANDLE, and handle counter should work per shader binding, not a cpu binding thing + + descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + descriptor_write.descriptorCount = 1; + descriptor_write.pBufferInfo = &buffer_info; + + descriptor_write.pImageInfo = nullptr; // Optional + descriptor_write.pTexelBufferView = nullptr; // Optional + + vkUpdateDescriptorSets(device_owner.get_vk_device(), 1, &descriptor_write, 0, nullptr); } - void VulkanDescriptorSet::destroy(VulkanDevice&) { + void VulkanDescriptorSet::update_descriptor_set( + IVulkanSampler& sampler, + IVulkanImageView& view, + const size_t& binding, + const size_t& dst_array_element + ) { + VkDescriptorImageInfo image_info{}; + image_info.sampler = sampler.get_vk_image_sampler(); + image_info.imageView = view.get_vk_image_view(); + image_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; // Todo, remove this hard coded cringe + + VkWriteDescriptorSet descriptor_write{}; + descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + + descriptor_write.dstSet = descriptor_set; + descriptor_write.dstBinding = binding; + descriptor_write.dstArrayElement = dst_array_element; // Todo THIS IS A HANDLE, and handle counter should work per shader binding, not a cpu binding thing + + descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + descriptor_write.descriptorCount = 1; + // descriptorWrite.pBufferInfo = &buffer_info; + descriptor_write.pImageInfo = &image_info; + + // descriptorWrite.pImageInfo = nullptr; // Optional + descriptor_write.pTexelBufferView = nullptr; // Optional + vkUpdateDescriptorSets(device_owner.get_vk_device(), 1, &descriptor_write, 0, nullptr); } } diff --git a/src/bebone/gfx/vulkan/vulkan_descriptor_set.h b/src/bebone/gfx/vulkan/vulkan_descriptor_set.h index 667f3aac..b527501b 100644 --- a/src/bebone/gfx/vulkan/vulkan_descriptor_set.h +++ b/src/bebone/gfx/vulkan/vulkan_descriptor_set.h @@ -1,25 +1,32 @@ -#ifndef _BEBONE_GFX_VULKAN_VULKAN_DESCRIPTOR_SET_H_ -#define _BEBONE_GFX_VULKAN_VULKAN_DESCRIPTOR_SET_H_ +#ifndef _BEBONE_GFX_VULKAN_DESCRIPTOR_SET_H_ +#define _BEBONE_GFX_VULKAN_DESCRIPTOR_SET_H_ #include #include "../gfx_backend.h" -#include "vulkan_wrapper.tpp" +#include "interface/i_vulkan_buffer.h" +#include "interface/i_vulkan_sampler.h" +#include "interface/i_vulkan_image_view.h" +#include "interface/i_vulkan_device.h" -namespace bebone::gfx::vulkan { - class VulkanDevice; +namespace bebone::gfx { class VulkanDescriptorPool; class VulkanDescriptorSetLayout; - class VulkanDescriptorSet : public VulkanWrapper, private core::NonCopyable { + class VulkanDescriptorSet : private core::NonCopyable { + public: + IVulkanDevice& device_owner; + VkDescriptorSet descriptor_set; + public: VulkanDescriptorSet( - std::shared_ptr& device, - VulkanDescriptorPool& descriptorPool, - std::shared_ptr& descriptorSetLayout); + IVulkanDevice& device, + VulkanDescriptorPool& descriptor_pool, + const std::unique_ptr& descriptor_set_layout); - void destroy(VulkanDevice& device) override; + void update_descriptor_set(IVulkanBuffer& buffer, const size_t& binding, const size_t& dst_array_element); + void update_descriptor_set(IVulkanSampler& sampler, IVulkanImageView& view, const size_t& binding, const size_t& dst_array_element); }; } diff --git a/src/bebone/gfx/vulkan/vulkan_descriptor_set_layout.cpp b/src/bebone/gfx/vulkan/vulkan_descriptor_set_layout.cpp index 6e61d5d8..6a52af6e 100644 --- a/src/bebone/gfx/vulkan/vulkan_descriptor_set_layout.cpp +++ b/src/bebone/gfx/vulkan/vulkan_descriptor_set_layout.cpp @@ -1,58 +1,67 @@ #include "vulkan_descriptor_set_layout.h" #include "vulkan_descriptor_set_layout_binding.h" -#include "vulkan_device.h" +namespace bebone::gfx { + VulkanDescriptorSetLayout::VulkanDescriptorSetLayout( + IVulkanDevice& device, + const std::vector& all_bindings + ) : device_owner(device) { + auto binding_flags = std::vector {}; + binding_flags.reserve(all_bindings.size()); -namespace bebone::gfx::vulkan { - VulkanDescriptorSetLayout::VulkanDescriptorSetLayout(VulkanDevice& device, const std::vector& allBindings) { - std::vector bindingFlags; - std::vector bindings; + auto bindings = std::vector {}; + bindings.reserve(all_bindings.size()); - for(const auto& b : allBindings) - bindings.push_back(b.binding); + for(const auto& b : all_bindings) + bindings.push_back(b.descriptor_set_layout_binding); for(size_t i = 0; i < bindings.size(); ++i) { - VkDescriptorBindingFlags bindlessFlags; + VkDescriptorBindingFlags flags; if(i == bindings.size() - 1) { - bindlessFlags = - VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT | - // VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT | - VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT; + flags = + VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT | + // VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT | + VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT; } else { - bindlessFlags = - VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT | - VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT; + flags = + VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT | + VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT; } - bindingFlags.push_back(bindlessFlags); + binding_flags.push_back(flags); } // Descriptor set - VkDescriptorSetLayoutCreateInfo layoutInfo{}; - layoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; - layoutInfo.bindingCount = bindings.size(); - layoutInfo.pBindings = bindings.data(); - layoutInfo.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT; + VkDescriptorSetLayoutCreateInfo layout_info{}; + layout_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + layout_info.bindingCount = bindings.size(); + layout_info.pBindings = bindings.data(); + layout_info.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT; - VkDescriptorSetLayoutBindingFlagsCreateInfoEXT extendedInfo; - extendedInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO_EXT; - extendedInfo.pNext = nullptr; - extendedInfo.bindingCount = bindingFlags.size(); + VkDescriptorSetLayoutBindingFlagsCreateInfoEXT extended_info; + extended_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO_EXT; + extended_info.pNext = nullptr; + extended_info.bindingCount = binding_flags.size(); - if(bindingFlags.size() == 0) { - extendedInfo.pBindingFlags = nullptr; - } else - extendedInfo.pBindingFlags = bindingFlags.data(); + if(binding_flags.empty()) + extended_info.pBindingFlags = nullptr; + else + extended_info.pBindingFlags = binding_flags.data(); - layoutInfo.pNext = &extendedInfo; + layout_info.pNext = &extended_info; - if (vkCreateDescriptorSetLayout(device.device(), &layoutInfo, nullptr, &backend) != VK_SUCCESS) { + if(vkCreateDescriptorSetLayout(device_owner.get_vk_device(), &layout_info, nullptr, &descriptor_set_layout) != VK_SUCCESS) { + LOG_ERROR("Failed to create descriptor set layout"); throw std::runtime_error("failed to create descriptor set layout!"); } + + LOG_TRACE("Created Descriptor set layout"); } - void VulkanDescriptorSetLayout::destroy(VulkanDevice& device) { - vkDestroyDescriptorSetLayout(device.device(), backend, nullptr); + VulkanDescriptorSetLayout::~VulkanDescriptorSetLayout() { + vkDestroyDescriptorSetLayout(device_owner.get_vk_device(), descriptor_set_layout, nullptr); + + LOG_TRACE("Destroyed Descriptor set layout"); } } \ No newline at end of file diff --git a/src/bebone/gfx/vulkan/vulkan_descriptor_set_layout.h b/src/bebone/gfx/vulkan/vulkan_descriptor_set_layout.h index 1bff2870..9d9621fb 100644 --- a/src/bebone/gfx/vulkan/vulkan_descriptor_set_layout.h +++ b/src/bebone/gfx/vulkan/vulkan_descriptor_set_layout.h @@ -1,21 +1,26 @@ -#ifndef _BEBONE_GFX_VULKAN_VULKAN_DESCRIPTOR_SET_LAYOUT_H_ -#define _BEBONE_GFX_VULKAN_VULKAN_DESCRIPTOR_SET_LAYOUT_H_ +#ifndef _BEBONE_GFX_VULKAN_DESCRIPTOR_SET_LAYOUT_H_ +#define _BEBONE_GFX_VULKAN_DESCRIPTOR_SET_LAYOUT_H_ #include "../gfx_backend.h" #include "vulkan_descriptor_pool.h" -namespace bebone::gfx::vulkan { - class VulkanDevice; +namespace bebone::gfx { class VulkanDescriptorSetLayoutBinding; - class VulkanDescriptorSetLayout : public VulkanWrapper, private core::NonCopyable { + class VulkanDescriptorSetLayout : private core::NonCopyable { public: - VulkanDescriptorSetLayout( - VulkanDevice& device, - const std::vector& bindings); + VkDescriptorSetLayout descriptor_set_layout; - void destroy(VulkanDevice& device) override; + private: + IVulkanDevice& device_owner; + + public: + VulkanDescriptorSetLayout( // Todo move to private + IVulkanDevice& device, + const std::vector& all_bindings); + + ~VulkanDescriptorSetLayout(); }; } diff --git a/src/bebone/gfx/vulkan/vulkan_descriptor_set_layout_binding.cpp b/src/bebone/gfx/vulkan/vulkan_descriptor_set_layout_binding.cpp index 4bb8d28c..9c914bcf 100644 --- a/src/bebone/gfx/vulkan/vulkan_descriptor_set_layout_binding.cpp +++ b/src/bebone/gfx/vulkan/vulkan_descriptor_set_layout_binding.cpp @@ -1,17 +1,33 @@ #include "vulkan_descriptor_set_layout_binding.h" -namespace bebone::gfx::vulkan { +namespace bebone::gfx { using namespace bebone::core; - VulkanDescriptorSetLayoutBinding VulkanDescriptorSetLayoutBinding::bindless_uniform(const u32& binding) { - return { - .binding = { + VulkanDescriptorSetLayoutBinding::VulkanDescriptorSetLayoutBinding(const VulkanDescriptorSetLayoutBindingType& type, const u32& binding) { + if(type == Uniform) { + descriptor_set_layout_binding = { .binding = binding, .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, .descriptorCount = 65536, .stageFlags = VK_SHADER_STAGE_ALL, .pImmutableSamplers = nullptr - } - }; + }; + } else if(type == Storage) { + descriptor_set_layout_binding = { + .binding = binding, + .descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, + .descriptorCount = 65536, + .stageFlags = VK_SHADER_STAGE_ALL, + .pImmutableSamplers = nullptr + }; + } else if(type == Sampler) { + descriptor_set_layout_binding = { + .binding = binding, + .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .descriptorCount = 65536, + .stageFlags = VK_SHADER_STAGE_ALL, + .pImmutableSamplers = nullptr + }; + } } } diff --git a/src/bebone/gfx/vulkan/vulkan_descriptor_set_layout_binding.h b/src/bebone/gfx/vulkan/vulkan_descriptor_set_layout_binding.h index 8ae6f928..053c62fd 100644 --- a/src/bebone/gfx/vulkan/vulkan_descriptor_set_layout_binding.h +++ b/src/bebone/gfx/vulkan/vulkan_descriptor_set_layout_binding.h @@ -1,18 +1,23 @@ -#ifndef _BEBONE_GFX_VULKAN_VULKAN_DESCRIPTOR_SET_LAYOUT_BINDING_H_ -#define _BEBONE_GFX_VULKAN_VULKAN_DESCRIPTOR_SET_LAYOUT_BINDING_H_ +#ifndef _BEBONE_GFX_VULKAN_DESCRIPTOR_SET_LAYOUT_BINDING_H_ +#define _BEBONE_GFX_VULKAN_DESCRIPTOR_SET_LAYOUT_BINDING_H_ #include "../gfx_backend.h" -namespace bebone::gfx::vulkan { +namespace bebone::gfx { using namespace bebone::core; - class VulkanDescriptorSetLayoutBinding { - private: + enum VulkanDescriptorSetLayoutBindingType { + Uniform, + Storage, + Sampler + }; + class VulkanDescriptorSetLayoutBinding { public: - VkDescriptorSetLayoutBinding binding; + VkDescriptorSetLayoutBinding descriptor_set_layout_binding; - static VulkanDescriptorSetLayoutBinding bindless_uniform(const u32& binding); + public: + VulkanDescriptorSetLayoutBinding(const VulkanDescriptorSetLayoutBindingType& type, const u32& binding); }; } diff --git a/src/bebone/gfx/vulkan/vulkan_device.cpp b/src/bebone/gfx/vulkan/vulkan_device.cpp index 53e54c8e..4677bc40 100644 --- a/src/bebone/gfx/vulkan/vulkan_device.cpp +++ b/src/bebone/gfx/vulkan/vulkan_device.cpp @@ -1,234 +1,175 @@ #include "vulkan_device.h" +#include "vulkan_sampler.h" + #include "vulkan_swap_chain.h" + #include "vulkan_descriptor_pool.h" +#include "vulkan_descriptor_set.h" #include "vulkan_descriptor_set_layout.h" + #include "vulkan_command_buffer_pool.h" #include "vulkan_pipeline_layout.h" #include "vulkan_pipeline.h" #include "vulkan_shader_module.h" #include "vulkan_descriptor_set_layout_binding.h" #include "vulkan_const_range.h" +#include "vulkan_pipeline_manager.h" +#include "vulkan_render_pass.h" +#include "vulkan_framebuffer.h" -#include "../shaders/spirv_shader_compiler.h" - -namespace bebone::gfx::vulkan { - std::string vulkan_device_read_file(const std::string& path) { - std::ifstream file(path); - std::stringstream ss; - ss << file.rdbuf(); - return ss.str(); - } - - VulkanDevice::VulkanDevice(VulkanInstance& _vulkanInstance, VulkanWindow &window) : vulkanInstance(_vulkanInstance) { - window.create_window_surface(vulkanInstance.get_instance(), &surface_); +namespace bebone::gfx { + VulkanDevice::VulkanDevice(IVulkanInstance& instance, std::unique_ptr& window) : instance_owner(instance) { + auto& vulkan_window = *static_cast(window.get()); + vulkan_window.create_window_surface(instance.get_vk_instance(), &surface); - pick_physical_device(_vulkanInstance); + pick_physical_device(instance); create_logical_device(); - } - - void VulkanDevice::pick_physical_device(VulkanInstance& vulkanInstance) { - VulkanDeviceChooser chooser; - physicalDevice = chooser.get_physical_device(vulkanInstance, surface_); + command_buffer_pool = std::make_unique(*this); - vkGetPhysicalDeviceProperties(physicalDevice, &properties); - std::cout << "physical device: " << properties.deviceName << std::endl; + LOG_TRACE("Created Vulkan device"); } - std::shared_ptr VulkanDevice::create_descriptor_pool() { - return std::make_shared(*this); - } + VulkanDevice::~VulkanDevice() { + wait_idle(); - std::vector> VulkanDevice::create_descriptor_set_layouts(const std::vector& bindings) { - return { std::make_shared(*this, bindings) }; - } + command_buffer_pool.reset(); - std::shared_ptr VulkanDevice::create_swap_chain(std::shared_ptr &window) { - return std::make_shared(*this, VkExtent2D { static_cast(window->get_width()), static_cast(window->get_height()) }); - } + vkDestroyDevice(device, nullptr); - std::shared_ptr VulkanDevice::create_pipeline_layout(const std::vector>& layouts, const std::vector& constantRanges) { - return std::make_shared(*this, layouts, constantRanges); - } + LOG_DEBUG("TODO, destroy surface KHR"); + vkDestroySurfaceKHR(instance_owner.get_vk_instance(), surface, nullptr); - std::shared_ptr VulkanDevice::create_command_buffer_pool() { - return std::make_shared(*this); + LOG_TRACE("Destroyed Vulkan device"); } - std::shared_ptr VulkanDevice::create_device_memory(VkMemoryRequirements memRequirements, VkMemoryPropertyFlags properties) { - return std::make_shared(*this, memRequirements, properties); - } - - std::shared_ptr VulkanDevice::create_buffer(const size_t& size, VulkanBufferInfo bufferInfo) { - return std::make_shared(*this, size, bufferInfo); - } + void VulkanDevice::pick_physical_device(IVulkanInstance& instance) { + auto chooser = VulkanDeviceChooser(); - VulkanBufferMemoryTuple VulkanDevice::create_buffer_memory(const size_t& size, VulkanBufferInfo bufferInfo) { - auto buffer = create_buffer(size, bufferInfo); + physical_device = chooser.get_physical_device(instance, surface); - auto memRequirements = buffer->get_memory_requirements(*this); + vkGetPhysicalDeviceProperties(physical_device, &properties); - auto memory = create_device_memory(memRequirements, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); - memory->bind_buffer_memory(*this, buffer); - - return { buffer, memory }; + LOG_INFORMATION("Physical device: {}", properties.deviceName); } - std::vector> VulkanDevice::create_buffers(const size_t& size, const size_t& bufferCount, VulkanBufferInfo bufferInfo) { - std::vector> buffers; + /* + std::unique_ptr VulkanDevice::begin_single_time_commands() { + auto command_buffer = command_buffer_pool->create_command_buffer(); - for(size_t i = 0; i < bufferCount; ++i) - buffers.push_back(std::make_shared(*this, size, bufferInfo)); + command_buffer->begin_record(); - return buffers; + return command_buffer; } - std::vector VulkanDevice::create_buffer_memorys(const size_t& size, const size_t& bufferCount, VulkanBufferInfo bufferInfo) { - std::vector tuples; + void VulkanDevice::end_single_time_commands(std::unique_ptr& command_buffer) { + command_buffer->end_record(); - for(size_t i = 0; i < bufferCount; ++i) - tuples.emplace_back(create_buffer_memory(size, bufferInfo)); + VkSubmitInfo submit_info{}; + submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submit_info.commandBufferCount = 1; + submit_info.pCommandBuffers = &command_buffer->backend; - return tuples; - } + vkQueueSubmit(graphics_queue, 1, &submit_info, VK_NULL_HANDLE); + vkQueueWaitIdle(graphics_queue); - std::shared_ptr VulkanDevice::create_image(VkFormat format, VkExtent3D extent, VulkanImageInfo imageInfo) { - return std::make_shared(*this, format, extent, imageInfo); - } - - std::shared_ptr VulkanDevice::create_image(VkImage& image) { - return std::make_shared(image); - } - - std::shared_ptr VulkanDevice::create_image_view(VulkanImage& image, VkFormat& imageFormat, VulkanImageViewInfo imageViewInfo) { - return std::make_shared(*this, image, imageFormat, imageViewInfo); - } - - std::shared_ptr VulkanDevice::create_pipeline( - std::shared_ptr& swapChain, - std::shared_ptr& pipelineLayout, - std::vector> shaderModules, - VulkanPipelineConfig configInfo - ) { - - return std::make_shared(*this, swapChain, pipelineLayout, shaderModules, configInfo); - } - - std::shared_ptr VulkanDevice::create_shader_module(const std::string& shaderCodePath, const ShaderType& type) { - SpirVShaderCompiler shaderCompiler; - - shaderCompiler.add_shader_source(ShaderSource( - vulkan_device_read_file(shaderCodePath), - type - )); - - gfx::ShaderCode shadeCode = shaderCompiler.compile(type); - - return std::make_shared(*this, shadeCode); + vkFreeCommandBuffers(device, command_buffer_pool->backend, 1, &command_buffer->backend); } + */ void VulkanDevice::create_logical_device() { - QueueFamilyIndices indices = VulkanDeviceChooser::find_queue_families(physicalDevice, surface_); - - std::vector queueCreateInfos; - std::set uniqueQueueFamilies = {indices.graphicsFamily, indices.presentFamily}; - - float queuePriority = 1.0f; - for (uint32_t queueFamily : uniqueQueueFamilies) { - VkDeviceQueueCreateInfo queueCreateInfo = {}; - queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; - queueCreateInfo.queueFamilyIndex = queueFamily; - queueCreateInfo.queueCount = 1; - queueCreateInfo.pQueuePriorities = &queuePriority; - queueCreateInfos.push_back(queueCreateInfo); - } - - // VkPhysicalDeviceFeatures deviceFeatures = {}; - // deviceFeatures.samplerAnisotropy = VK_TRUE; - - VkDeviceCreateInfo createInfo = {}; - createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; + auto indices = VulkanDeviceChooser::find_queue_families(physical_device, surface); - createInfo.queueCreateInfoCount = static_cast(queueCreateInfos.size()); - createInfo.pQueueCreateInfos = queueCreateInfos.data(); + auto unique_queue_families = std::set { indices.graphics_family, indices.present_family }; - // createInfo.pEnabledFeatures = &deviceFeatures; - createInfo.pEnabledFeatures = nullptr; - createInfo.enabledExtensionCount = static_cast(VulkanDeviceChooser::deviceExtensions.size()); - createInfo.ppEnabledExtensionNames = VulkanDeviceChooser::deviceExtensions.data(); + auto queue_create_infos = std::vector {}; + queue_create_infos.reserve(unique_queue_families.size()); - VkPhysicalDeviceDescriptorIndexingFeatures descriptorIndexingFeatures{}; - descriptorIndexingFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT; - descriptorIndexingFeatures.pNext = nullptr; - descriptorIndexingFeatures.descriptorBindingSampledImageUpdateAfterBind = VK_TRUE; - descriptorIndexingFeatures.descriptorBindingPartiallyBound = VK_TRUE; - descriptorIndexingFeatures.descriptorBindingVariableDescriptorCount = VK_TRUE; - descriptorIndexingFeatures.descriptorBindingUniformBufferUpdateAfterBind = VK_TRUE; - descriptorIndexingFeatures.shaderUniformBufferArrayNonUniformIndexing = VK_TRUE; - descriptorIndexingFeatures.runtimeDescriptorArray = VK_TRUE; + float queue_priority = 1.0f; - VkPhysicalDeviceFeatures2 deviceFeatures2{}; - deviceFeatures2.features.samplerAnisotropy = VK_TRUE; + for(const auto& queue_family : unique_queue_families) { + VkDeviceQueueCreateInfo queue_create_info = {}; - deviceFeatures2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; - deviceFeatures2.pNext = &descriptorIndexingFeatures; + queue_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + queue_create_info.queueFamilyIndex = queue_family; + queue_create_info.queueCount = 1; + queue_create_info.pQueuePriorities = &queue_priority; - createInfo.pNext = &deviceFeatures2; - - // might not really be necessary anymore because device specific validation layers - // have been deprecated - // if (enableValidationLayers) { - // createInfo.enabledLayerCount = static_cast(validationLayers.size()); - // createInfo.ppEnabledLayerNames = validationLayers.data(); - // } else { - createInfo.enabledLayerCount = 0; - // } + queue_create_infos.push_back(queue_create_info); + } - if (vkCreateDevice(physicalDevice, &createInfo, nullptr, &device_) != VK_SUCCESS) { + VkDeviceCreateInfo create_info = {}; + create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; + + create_info.queueCreateInfoCount = static_cast(queue_create_infos.size()); + create_info.pQueueCreateInfos = queue_create_infos.data(); + create_info.pEnabledFeatures = nullptr; + create_info.enabledExtensionCount = static_cast(VulkanDeviceChooser::device_extensions.size()); + create_info.ppEnabledExtensionNames = VulkanDeviceChooser::device_extensions.data(); + + VkPhysicalDeviceDescriptorIndexingFeatures descriptor_indexing_features{}; + descriptor_indexing_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT; + descriptor_indexing_features.pNext = nullptr; + descriptor_indexing_features.descriptorBindingSampledImageUpdateAfterBind = VK_TRUE; + descriptor_indexing_features.descriptorBindingPartiallyBound = VK_TRUE; + descriptor_indexing_features.descriptorBindingVariableDescriptorCount = VK_TRUE; + descriptor_indexing_features.descriptorBindingUniformBufferUpdateAfterBind = VK_TRUE; + descriptor_indexing_features.shaderUniformBufferArrayNonUniformIndexing = VK_TRUE; + descriptor_indexing_features.runtimeDescriptorArray = VK_TRUE; + + VkPhysicalDeviceFeatures2 device_features_2{}; + device_features_2.features.samplerAnisotropy = VK_TRUE; + device_features_2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; + device_features_2.pNext = &descriptor_indexing_features; + + create_info.pNext = &device_features_2; + create_info.enabledLayerCount = 0; + + if(vkCreateDevice(physical_device, &create_info, nullptr, &device) != VK_SUCCESS) { + LOG_ERROR("Failed to create logical device"); throw std::runtime_error("failed to create logical device!"); } - vkGetDeviceQueue(device_, indices.graphicsFamily, 0, &graphicsQueue_); - vkGetDeviceQueue(device_, indices.presentFamily, 0, &presentQueue_); + vkGetDeviceQueue(device, indices.graphics_family, 0, &graphics_queue); + vkGetDeviceQueue(device, indices.present_family, 0, &present_queue); } - VkFormat VulkanDevice::find_supported_format(const std::vector &candidates, VkImageTiling tiling, VkFormatFeatureFlags features) { - for (VkFormat format : candidates) { + VkFormat VulkanDevice::find_supported_format( + const std::vector &candidates, + VkImageTiling tiling, + VkFormatFeatureFlags features + ) { + for(const auto& format : candidates) { VkFormatProperties props; - vkGetPhysicalDeviceFormatProperties(physicalDevice, format, &props); - if (tiling == VK_IMAGE_TILING_LINEAR && (props.linearTilingFeatures & features) == features) { + vkGetPhysicalDeviceFormatProperties(physical_device, format, &props); + + if(tiling == VK_IMAGE_TILING_LINEAR && (props.linearTilingFeatures & features) == features) return format; - } else if ( - tiling == VK_IMAGE_TILING_OPTIMAL && (props.optimalTilingFeatures & features) == features) { + else if(tiling == VK_IMAGE_TILING_OPTIMAL && (props.optimalTilingFeatures & features) == features) return format; - } } + LOG_ERROR("Failed to find supported format"); throw std::runtime_error("failed to find supported format!"); } - uint32_t VulkanDevice::find_memory_type(uint32_t typeFilter, VkMemoryPropertyFlags properties) { - VkPhysicalDeviceMemoryProperties memProperties; - vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memProperties); + uint32_t VulkanDevice::find_memory_type(uint32_t type_filter, VkMemoryPropertyFlags mem_properties) { + VkPhysicalDeviceMemoryProperties physical_properties; + vkGetPhysicalDeviceMemoryProperties(physical_device, &physical_properties); - for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++) { - if ((typeFilter & (1 << i)) && (memProperties.memoryTypes[i].propertyFlags & properties) == properties) { + for(uint32_t i = 0; i < physical_properties.memoryTypeCount; i++) { + if((type_filter & (1 << i)) && (physical_properties.memoryTypes[i].propertyFlags & mem_properties) == mem_properties) return i; - } } + LOG_ERROR("Failed to find suitable memory type"); throw std::runtime_error("failed to find suitable memory type!"); } - void VulkanDevice::wait_idle() { - vkDeviceWaitIdle(device_); - } - - void VulkanDevice::destroy() { - vkDestroyDevice(device_, nullptr); - vkDestroySurfaceKHR(vulkanInstance.get_instance(), surface_, nullptr); + void VulkanDevice::wait_idle() const { + vkDeviceWaitIdle(device); } VkFormat VulkanDevice::find_depth_format() { @@ -237,4 +178,20 @@ namespace bebone::gfx::vulkan { VK_IMAGE_TILING_OPTIMAL, VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT); } + + VkDevice VulkanDevice::get_vk_device() const { + return device; + } + + VkSurfaceKHR VulkanDevice::get_surface() const { + return surface; + } + + VkQueue VulkanDevice::get_graphics_queue() const { + return graphics_queue; + } + + VkQueue VulkanDevice::get_present_queue() const { + return present_queue; + } } diff --git a/src/bebone/gfx/vulkan/vulkan_device.h b/src/bebone/gfx/vulkan/vulkan_device.h index 44b13021..1173fed2 100644 --- a/src/bebone/gfx/vulkan/vulkan_device.h +++ b/src/bebone/gfx/vulkan/vulkan_device.h @@ -1,5 +1,5 @@ -#ifndef _BEBONE_GFX_VULKAN_VULKAN_DEVICE_H_ -#define _BEBONE_GFX_VULKAN_VULKAN_DEVICE_H_ +#ifndef _BEBONE_GFX_VULKAN_DEVICE_H_ +#define _BEBONE_GFX_VULKAN_DEVICE_H_ #include #include @@ -11,135 +11,76 @@ #include "../shaders/shader_type.h" #include "../shaders/shader_code.h" -#include "vulkan_wrapper.tpp" #include "vulkan_instance.h" #include "vulkan_device_chooser.h" -#include "vulkan_buffer.h" -#include "vulkan_image.h" +#include "vulkan_sampler.h" #include "vulkan_image_view.h" #include "vulkan_pipeline.h" +#include "vulkan_texture.h" +#include "vulkan_descriptor_set.h" +#include "vulkan_descriptor_set_layout_binding.h" +#include "vulkan_attachment.h" +#include "vulkan_swap_chain_image.h" -namespace bebone::gfx::vulkan { +#include "interface/i_vulkan_device.h" + +namespace bebone::gfx { class VulkanSwapChain; class VulkanPipeline; class VulkanDescriptorPool; class VulkanCommandBufferPool; + class VulkanCommandBuffer; class VulkanShaderModule; class VulkanPipelineLayout; class VulkanDescriptorSetLayout; - class VulkanDescriptorSetLayoutBinding; class VulkanConstRange; + class VulkanPipelineManager; + class VulkanRenderTarget; + class VulkanRenderPass; + class VulkanFramebuffer; - class VulkanDevice : private core::NonCopyable { + class VulkanDevice : public IVulkanDevice, private core::NonCopyable { private: - VkPhysicalDevice physicalDevice = VK_NULL_HANDLE; - - VkDevice device_; - VkSurfaceKHR surface_; - - VkQueue graphicsQueue_; - VkQueue presentQueue_; - - VulkanInstance &vulkanInstance; + IVulkanInstance& instance_owner; - void pick_physical_device(VulkanInstance &vulkanInstance); - void create_logical_device(); + VkDevice device; + VkSurfaceKHR surface; + VkQueue graphics_queue; + VkQueue present_queue; - public: VkPhysicalDeviceProperties properties; - VulkanDevice( - VulkanInstance& _vulkanInstance, - VulkanWindow &window); - - std::shared_ptr create_device_memory( - VkMemoryRequirements memRequirements, - VkMemoryPropertyFlags properties); - - std::shared_ptr create_buffer( - const size_t& size, - VulkanBufferInfo bufferInfo = {}); - - VulkanBufferMemoryTuple create_buffer_memory( - const size_t& size, - VulkanBufferInfo bufferInfo = {}); - - std::vector> create_buffers( - const size_t& size, - const size_t& bufferCount, - VulkanBufferInfo bufferInfo = {}); - - std::vector create_buffer_memorys( - const size_t& size, - const size_t& bufferCount, - VulkanBufferInfo bufferInfo = {}); - - std::shared_ptr create_image( - VkFormat format, - VkExtent3D extent, - VulkanImageInfo imageInfo = {}); - - std::shared_ptr create_image( - VkImage& image); - - std::shared_ptr create_image_view( - VulkanImage& image, - VkFormat& imageFormat, - VulkanImageViewInfo imageViewInfo = {}); - - std::shared_ptr create_descriptor_pool(); + // Todo, abstract all things below + VkPhysicalDevice physical_device = VK_NULL_HANDLE; - std::vector> create_descriptor_set_layouts( - const std::vector& bindings); - - std::shared_ptr create_pipeline_layout( - const std::vector>& layouts, - const std::vector& constantRanges); - - std::shared_ptr create_pipeline( - std::shared_ptr& swapChain, - std::shared_ptr& pipelineLayout, - std::vector> shaderModules, - VulkanPipelineConfig configInfo = {}); - - std::shared_ptr create_command_buffer_pool(); - - std::shared_ptr create_shader_module( - const std::string& shaderCodePath, - const ShaderType& type); - - std::shared_ptr create_swap_chain(std::shared_ptr& window); - - void wait_idle(); - - VkDevice device() { return device_; } - VkSurfaceKHR surface() { return surface_; } - VkQueue graphicsQueue() { return graphicsQueue_; } - VkQueue presentQueue() { return presentQueue_; } - - uint32_t find_memory_type(uint32_t typeFilter, VkMemoryPropertyFlags properties); - - QueueFamilyIndices find_physical_queue_families() { return VulkanDeviceChooser::find_queue_families(physicalDevice, surface_); } - SwapChainSupportDetails get_swap_chain_support() { return VulkanDeviceChooser::query_swap_chain_support(physicalDevice, surface_); } - - VkFormat find_supported_format(const std::vector &candidates, VkImageTiling tiling, VkFormatFeatureFlags features); - - template - void destroy_all(std::shared_ptr... args) { - (args->destroy(*this), ...); - } - - template - void destroy_all(std::vector>... args) { - for(auto& arg : (args, ...)) { - arg->destroy(*this); - } - } + void pick_physical_device(IVulkanInstance &instance); + void create_logical_device(); - void destroy(); + // Todo, maybe this can be optimized + std::unique_ptr command_buffer_pool; - VkFormat find_depth_format(); + public: + VulkanDevice(IVulkanInstance& instance, std::unique_ptr& window); + ~VulkanDevice() override; + + // Todo make this a ICommandBufferPool interface + // std::unique_ptr begin_single_time_commands() override; + // void end_single_time_commands(std::unique_ptr& command_buffer) override; + + VulkanQueueFamilyIndices find_physical_queue_families() override { return VulkanDeviceChooser::find_queue_families(physical_device, surface); } + VulkanSwapChainSupportDetails get_swap_chain_support() override { return VulkanDeviceChooser::query_swap_chain_support(physical_device, surface); } + + uint32_t find_memory_type(uint32_t type_filter, VkMemoryPropertyFlags properties) override; + VkFormat find_supported_format(const std::vector &candidates, VkImageTiling tiling, VkFormatFeatureFlags features) override; + VkFormat find_depth_format() override; + + // Vulkan Device + [[nodiscard]] VkDevice get_vk_device() const override; + [[nodiscard]] VkSurfaceKHR get_surface() const override; + [[nodiscard]] VkQueue get_graphics_queue() const override; + [[nodiscard]] VkQueue get_present_queue() const override; + void wait_idle() const override; }; } diff --git a/src/bebone/gfx/vulkan/vulkan_device_chooser.cpp b/src/bebone/gfx/vulkan/vulkan_device_chooser.cpp index caa419da..802047ae 100644 --- a/src/bebone/gfx/vulkan/vulkan_device_chooser.cpp +++ b/src/bebone/gfx/vulkan/vulkan_device_chooser.cpp @@ -1,126 +1,132 @@ #include "vulkan_device_chooser.h" -namespace bebone::gfx::vulkan { - const std::vector VulkanDeviceChooser::deviceExtensions = { - VK_KHR_SWAPCHAIN_EXTENSION_NAME, - VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME +namespace bebone::gfx { + bool VulkanQueueFamilyIndices::is_complete() { + return graphics_family_has_value && present_family_has_value ; + } + + const std::vector VulkanDeviceChooser::device_extensions = { + VK_KHR_SWAPCHAIN_EXTENSION_NAME, + VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME }; bool VulkanDeviceChooser::check_device_extension_support(VkPhysicalDevice device) { - uint32_t extensionCount; - vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, nullptr); + uint32_t count; + vkEnumerateDeviceExtensionProperties(device, nullptr, &count, nullptr); - std::vector availableExtensions(extensionCount); - vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, availableExtensions.data()); + auto available_extensions = std::vector(count); + vkEnumerateDeviceExtensionProperties(device, nullptr, &count, available_extensions.data()); - std::set requiredExtensions(deviceExtensions.begin(), deviceExtensions.end()); + auto required_extensions = std::set(device_extensions.begin(), device_extensions.end()); - for (const auto &extension : availableExtensions) { - requiredExtensions.erase(extension.extensionName); - } + for(const auto &extension : available_extensions) + required_extensions.erase(extension.extensionName); - return requiredExtensions.empty(); + return required_extensions.empty(); } bool VulkanDeviceChooser::is_device_suitable(VkPhysicalDevice device, VkSurfaceKHR& surface) { - QueueFamilyIndices indices = find_queue_families(device, surface); + VulkanQueueFamilyIndices indices = find_queue_families(device, surface); - bool extensionsSupported = check_device_extension_support(device); + bool extensions_supported = check_device_extension_support(device); + bool swap_chain_adequate = false; - bool swapChainAdequate = false; - if (extensionsSupported) { - SwapChainSupportDetails swapChainSupport = query_swap_chain_support(device, surface); - swapChainAdequate = !swapChainSupport.formats.empty() && !swapChainSupport.presentModes.empty(); + if(extensions_supported) { + auto swap_chain_support = query_swap_chain_support(device, surface); + + swap_chain_adequate = !swap_chain_support.formats.empty() && !swap_chain_support.present_modes.empty(); } - VkPhysicalDeviceFeatures supportedFeatures; - vkGetPhysicalDeviceFeatures(device, &supportedFeatures); + VkPhysicalDeviceFeatures supported_features; + vkGetPhysicalDeviceFeatures(device, &supported_features); - return indices.is_complete() && extensionsSupported && swapChainAdequate && supportedFeatures.samplerAnisotropy; + return indices.is_complete() && extensions_supported && swap_chain_adequate && supported_features.samplerAnisotropy; } - SwapChainSupportDetails VulkanDeviceChooser::query_swap_chain_support(VkPhysicalDevice device, VkSurfaceKHR& surface) { - SwapChainSupportDetails details; + VulkanSwapChainSupportDetails VulkanDeviceChooser::query_swap_chain_support(VkPhysicalDevice device, VkSurfaceKHR& surface) { + VulkanSwapChainSupportDetails details; vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface, &details.capabilities); - uint32_t formatCount; - vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, nullptr); + uint32_t format_count; + vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &format_count, nullptr); - if (formatCount != 0) { - details.formats.resize(formatCount); - vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, details.formats.data()); + if(format_count != 0) { + details.formats.resize(format_count); + vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &format_count, details.formats.data()); } - uint32_t presentModeCount; - vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, nullptr); + uint32_t present_mode_count; + vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &present_mode_count, nullptr); - if (presentModeCount != 0) { - details.presentModes.resize(presentModeCount); - vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, details.presentModes.data()); + if(present_mode_count != 0) { + details.present_modes.resize(present_mode_count); + vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &present_mode_count, details.present_modes.data()); } return details; } - QueueFamilyIndices VulkanDeviceChooser::find_queue_families(VkPhysicalDevice device, VkSurfaceKHR& surface) { - QueueFamilyIndices indices; + VulkanQueueFamilyIndices VulkanDeviceChooser::find_queue_families(VkPhysicalDevice device, VkSurfaceKHR& surface) { + uint32_t queue_family_count = 0; + vkGetPhysicalDeviceQueueFamilyProperties(device, &queue_family_count, nullptr); - uint32_t queueFamilyCount = 0; - vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr); + auto queue_families = std::vector(queue_family_count); + vkGetPhysicalDeviceQueueFamilyProperties(device, &queue_family_count, queue_families.data()); - std::vector queueFamilies(queueFamilyCount); - vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data()); + VulkanQueueFamilyIndices indices; int i = 0; - for (const auto &queueFamily : queueFamilies) { - if (queueFamily.queueCount > 0 && queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) { - indices.graphicsFamily = i; - indices.graphicsFamilyHasValue = true; + for(const auto &queue_family : queue_families) { + if(queue_family.queueCount > 0 && queue_family.queueFlags & VK_QUEUE_GRAPHICS_BIT) { + indices.graphics_family = i; + indices.graphics_family_has_value = true; } - VkBool32 presentSupport = false; - vkGetPhysicalDeviceSurfaceSupportKHR(device, i, surface, &presentSupport); + VkBool32 present_support = false; + vkGetPhysicalDeviceSurfaceSupportKHR(device, i, surface, &present_support); - if (queueFamily.queueCount > 0 && presentSupport) { - indices.presentFamily = i; - indices.presentFamilyHasValue = true; + if(queue_family.queueCount > 0 && present_support) { + indices.present_family = i; + indices.present_family_has_value = true; } - if (indices.is_complete()) { + if(indices.is_complete()) break; - } - i++; + ++i; } return indices; } - VkPhysicalDevice VulkanDeviceChooser::get_physical_device(VulkanInstance& vulkanInstance, VkSurfaceKHR& surface) { - VkPhysicalDevice physicalDevice = VK_NULL_HANDLE; + VkPhysicalDevice VulkanDeviceChooser::get_physical_device(IVulkanInstance& instance, VkSurfaceKHR& surface) { + VkPhysicalDevice physical_device = VK_NULL_HANDLE; - uint32_t deviceCount = 0; - vkEnumeratePhysicalDevices(vulkanInstance.get_instance(), &deviceCount, nullptr); - if (deviceCount == 0) { + uint32_t device_count = 0; + vkEnumeratePhysicalDevices(instance.get_vk_instance(), &device_count, nullptr); + if (device_count == 0) { + LOG_ERROR("Failed to find GPUs with Vulkan support"); throw std::runtime_error("failed to find GPUs with Vulkan support!"); } - std::cout << "Device count: " << deviceCount << std::endl; - std::vector devices(deviceCount); - vkEnumeratePhysicalDevices(vulkanInstance.get_instance(), &deviceCount, devices.data()); + LOG_INFORMATION("Device count: {}", device_count); + + auto devices = std::vector(device_count); + vkEnumeratePhysicalDevices(instance.get_vk_instance(), &device_count, devices.data()); - for (const auto &device : devices) { - if (is_device_suitable(device, surface)) { - physicalDevice = device; + for(const auto &device : devices) { + if(is_device_suitable(device, surface)) { + physical_device = device; break; } } - if (physicalDevice == VK_NULL_HANDLE) { + if (physical_device == VK_NULL_HANDLE) { + LOG_ERROR("Failed to find a suitable GPU"); throw std::runtime_error("failed to find a suitable GPU!"); } - return physicalDevice; + return physical_device; } } diff --git a/src/bebone/gfx/vulkan/vulkan_device_chooser.h b/src/bebone/gfx/vulkan/vulkan_device_chooser.h index f7ed1310..8acb1ea1 100644 --- a/src/bebone/gfx/vulkan/vulkan_device_chooser.h +++ b/src/bebone/gfx/vulkan/vulkan_device_chooser.h @@ -1,38 +1,25 @@ -#ifndef _BEBONE_GFX_VULKAN_VULKAN_DEVICE_CHOOSER_H_ -#define _BEBONE_GFX_VULKAN_VULKAN_DEVICE_CHOOSER_H_ +#ifndef _BEBONE_GFX_VULKAN_DEVICE_CHOOSER_H_ +#define _BEBONE_GFX_VULKAN_DEVICE_CHOOSER_H_ #include #include "vulkan_instance.h" -namespace bebone::gfx::vulkan { - struct SwapChainSupportDetails { - VkSurfaceCapabilitiesKHR capabilities; - std::vector formats; - std::vector presentModes; - }; - - struct QueueFamilyIndices { - uint32_t graphicsFamily; - uint32_t presentFamily; - bool graphicsFamilyHasValue = false; - bool presentFamilyHasValue = false; - bool is_complete() { return graphicsFamilyHasValue && presentFamilyHasValue; } - }; +#include "interface/i_vulkan_device.h" +namespace bebone::gfx { class VulkanDeviceChooser { private: bool check_device_extension_support(VkPhysicalDevice device); bool is_device_suitable(VkPhysicalDevice device, VkSurfaceKHR& surface); public: - static const std::vector deviceExtensions; - - static SwapChainSupportDetails query_swap_chain_support(VkPhysicalDevice device, VkSurfaceKHR& surface); + static const std::vector device_extensions; - static QueueFamilyIndices find_queue_families(VkPhysicalDevice device, VkSurfaceKHR& surface); + static VulkanSwapChainSupportDetails query_swap_chain_support(VkPhysicalDevice device, VkSurfaceKHR& surface); + static VulkanQueueFamilyIndices find_queue_families(VkPhysicalDevice device, VkSurfaceKHR& surface); - VkPhysicalDevice get_physical_device(VulkanInstance& vulkanInstance, VkSurfaceKHR& surface); + VkPhysicalDevice get_physical_device(IVulkanInstance& instance, VkSurfaceKHR& surface); }; } diff --git a/src/bebone/gfx/vulkan/vulkan_device_memory.cpp b/src/bebone/gfx/vulkan/vulkan_device_memory.cpp index ee64dff2..54eeff1b 100644 --- a/src/bebone/gfx/vulkan/vulkan_device_memory.cpp +++ b/src/bebone/gfx/vulkan/vulkan_device_memory.cpp @@ -1,55 +1,61 @@ #include "vulkan_device_memory.h" -#include "vulkan_device.h" - #include "vulkan_buffer.h" #include "vulkan_image.h" -namespace bebone::gfx::vulkan { - VulkanDeviceMemory::VulkanDeviceMemory(VulkanDevice& device, VkMemoryRequirements memRequirements, VkMemoryPropertyFlags properties) { - VkMemoryAllocateInfo allocInfo{}; - allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - allocInfo.allocationSize = memRequirements.size; - allocInfo.memoryTypeIndex = device.find_memory_type(memRequirements.memoryTypeBits, properties); +namespace bebone::gfx { + VulkanDeviceMemory::VulkanDeviceMemory( + IVulkanDevice& device, + VkMemoryRequirements requirements, + VkMemoryPropertyFlags properties + ) : device_owner(device) { + VkMemoryAllocateInfo alloc_info{}; + + alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + alloc_info.allocationSize = requirements.size; + alloc_info.memoryTypeIndex = device.find_memory_type(requirements.memoryTypeBits, properties); - if (vkAllocateMemory(device.device(), &allocInfo, nullptr, &backend) != VK_SUCCESS) { + if (vkAllocateMemory(device_owner.get_vk_device(), &alloc_info, nullptr, &device_memory) != VK_SUCCESS) { + LOG_ERROR("Failed to allocate vulkan buffer memory"); throw std::runtime_error("failed to allocate vulkan buffer memory!"); } - } - void VulkanDeviceMemory::bind_buffer_memory(VulkanDevice& device, VulkanBuffer& buffer) { - vkBindBufferMemory(device.device(), buffer.backend, backend, 0); + LOG_TRACE("Allocated Vulkan device memory"); } - void VulkanDeviceMemory::bind_buffer_memory(VulkanDevice& device, std::shared_ptr& buffer) { - bind_buffer_memory(device, *buffer); - } + VulkanDeviceMemory::~VulkanDeviceMemory() { + vkFreeMemory(device_owner.get_vk_device(), device_memory, nullptr); - void VulkanDeviceMemory::bind_image_memory(VulkanDevice& device, VulkanImage& image) { - vkBindImageMemory(device.device(), image.backend, backend, 0); + LOG_TRACE("Freed Vulkan device memory"); } - void VulkanDeviceMemory::bind_image_memory(VulkanDevice& device, std::shared_ptr& image) { - bind_image_memory(device, *image); + void VulkanDeviceMemory::bind_buffer_memory(IVulkanBuffer& buffer) { + auto vk_buffer = buffer.get_vk_buffer(); + vkBindBufferMemory(device_owner.get_vk_device(), vk_buffer, device_memory, 0); } - void VulkanDeviceMemory::map(std::shared_ptr& device, const size_t& size, void** data) { - vkMapMemory(device->device(), backend, 0, size, 0, data); + void VulkanDeviceMemory::bind_image_memory(IVulkanImage& image) { + auto vk_image = image.get_vk_image(); + vkBindImageMemory(device_owner.get_vk_device(), vk_image, device_memory, 0); } - void VulkanDeviceMemory::unmap(std::shared_ptr& device) { - vkUnmapMemory(device->device(), backend); + void VulkanDeviceMemory::map(const size_t& size, void** data) { + vkMapMemory(device_owner.get_vk_device(), device_memory, 0, size, 0, data); } - void VulkanDeviceMemory::destroy(VulkanDevice &device) { - vkFreeMemory(device.device(), backend, nullptr); + void VulkanDeviceMemory::unmap() { + vkUnmapMemory(device_owner.get_vk_device(), device_memory); } - void VulkanDeviceMemory::upload_data(std::shared_ptr& device, const void* src, const size_t& size) { + void VulkanDeviceMemory::upload_data(const void* src, const size_t& size) { void* data; - map(device, size, &data); + map(size, &data); memcpy(data, src, size); - unmap(device); + unmap(); + } + + VkDeviceMemory VulkanDeviceMemory::get_vk_device_memory() const { + return device_memory; } } diff --git a/src/bebone/gfx/vulkan/vulkan_device_memory.h b/src/bebone/gfx/vulkan/vulkan_device_memory.h index 6538dfdf..9cabe584 100644 --- a/src/bebone/gfx/vulkan/vulkan_device_memory.h +++ b/src/bebone/gfx/vulkan/vulkan_device_memory.h @@ -1,49 +1,37 @@ -#ifndef _BEBONE_GFX_VULKAN_VULKAN_BUFFER_DEVICE_MEMORY_H_ -#define _BEBONE_GFX_VULKAN_VULKAN_BUFFER_DEVICE_MEMORY_H_ +#ifndef _BEBONE_GFX_VULKAN_BUFFER_DEVICE_MEMORY_H_ +#define _BEBONE_GFX_VULKAN_BUFFER_DEVICE_MEMORY_H_ #include #include "../gfx_backend.h" -#include "vulkan_wrapper.tpp" +#include "interface/i_vulkan_device_memory.h" +#include "interface/i_vulkan_device.h" +#include "interface/i_vulkan_buffer.h" -namespace bebone::gfx::vulkan { +namespace bebone::gfx { using namespace bebone::core; - class VulkanDevice; - class VulkanBuffer; class VulkanImage; - class VulkanDeviceMemory : public VulkanWrapper, private core::NonCopyable { - public: - VulkanDeviceMemory(VulkanDevice& device, VkMemoryRequirements memRequirements, VkMemoryPropertyFlags properties); - - void bind_buffer_memory( - VulkanDevice& device, - VulkanBuffer& buffer); - - void bind_buffer_memory( - VulkanDevice& device, - std::shared_ptr& buffer); + class VulkanDeviceMemory : public IVulkanDeviceMemory, private core::NonCopyable { + private: + IVulkanDevice& device_owner; - void bind_image_memory( - VulkanDevice& device, - VulkanImage& image); + VkDeviceMemory device_memory; - void bind_image_memory( - VulkanDevice& device, - std::shared_ptr& image); - - void map(std::shared_ptr& device, const size_t& size, void** data); - void unmap(std::shared_ptr& device); - - void upload_data( - std::shared_ptr& device, - const void* src, - const size_t& size); - - void destroy(VulkanDevice &device) override; + public: + VulkanDeviceMemory(IVulkanDevice& device, VkMemoryRequirements requirements, VkMemoryPropertyFlags properties); + ~VulkanDeviceMemory() override; + + // Vulkan Device Memory + VkDeviceMemory get_vk_device_memory() const override; + void bind_buffer_memory(IVulkanBuffer& buffer) override; + void bind_image_memory(IVulkanImage& image) override; + void map(const size_t& size, void** data) override; + void unmap() override; + void upload_data(const void* src, const size_t& size) override; }; } diff --git a/src/bebone/gfx/vulkan/vulkan_framebuffer.cpp b/src/bebone/gfx/vulkan/vulkan_framebuffer.cpp index a7334d64..1b29056d 100644 --- a/src/bebone/gfx/vulkan/vulkan_framebuffer.cpp +++ b/src/bebone/gfx/vulkan/vulkan_framebuffer.cpp @@ -1,32 +1,43 @@ #include "vulkan_framebuffer.h" -#include "vulkan_device.h" #include "vulkan_image_view.h" #include "vulkan_render_pass.h" -namespace bebone::gfx::vulkan { +namespace bebone::gfx { using namespace bebone::core; - VulkanFramebuffer::VulkanFramebuffer(VulkanDevice& device, std::vector>& attachmentViews, std::shared_ptr& renderPass, VkExtent2D extent) { - std::vector attachments; - for(auto& view : attachmentViews) - attachments.push_back(view->backend); - - VkFramebufferCreateInfo framebufferInfo = {}; - framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; - framebufferInfo.renderPass = renderPass->backend; - framebufferInfo.attachmentCount = static_cast(attachments.size()); - framebufferInfo.pAttachments = attachments.data(); - framebufferInfo.width = extent.width; - framebufferInfo.height = extent.height; - framebufferInfo.layers = 1; - - if (vkCreateFramebuffer(device.device(), &framebufferInfo, nullptr, &backend) != VK_SUCCESS) { + VulkanFramebuffer::VulkanFramebuffer( + IVulkanDevice& device, + std::vector>& attachment_views, + std::unique_ptr& render_pass, + VkExtent2D extent + ) : device_owner(device) { + auto attachments = std::vector {}; + attachments.reserve(attachment_views.size()); + + for(auto& view : attachment_views) + attachments.push_back(view->get_vk_image_view()); + + VkFramebufferCreateInfo create_info = {}; + create_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; + create_info.renderPass = render_pass->render_pass; + create_info.attachmentCount = static_cast(attachments.size()); + create_info.pAttachments = attachments.data(); + create_info.width = extent.width; + create_info.height = extent.height; + create_info.layers = 1; + + if(vkCreateFramebuffer(device_owner.get_vk_device(), &create_info, nullptr, &framebuffer) != VK_SUCCESS) { + LOG_ERROR("Failed to create framebuffer"); throw std::runtime_error("failed to create framebuffer!"); } + + LOG_TRACE("Created Vulkan framebuffer"); } - void VulkanFramebuffer::destroy(VulkanDevice &device) { - vkDestroyFramebuffer(device.device(), backend, nullptr); + VulkanFramebuffer::~VulkanFramebuffer() { + vkDestroyFramebuffer(device_owner.get_vk_device(), framebuffer, nullptr); + + LOG_TRACE("Destroyed Vulkan framebuffer"); } } diff --git a/src/bebone/gfx/vulkan/vulkan_framebuffer.h b/src/bebone/gfx/vulkan/vulkan_framebuffer.h index de8b1e09..ecc53c30 100644 --- a/src/bebone/gfx/vulkan/vulkan_framebuffer.h +++ b/src/bebone/gfx/vulkan/vulkan_framebuffer.h @@ -1,29 +1,33 @@ -#ifndef _BEBONE_GFX_VULKAN_VULKAN_FRAMEBUFFER_H_ -#define _BEBONE_GFX_VULKAN_VULKAN_FRAMEBUFFER_H_ +#ifndef _BEBONE_GFX_VULKAN_FRAMEBUFFER_H_ +#define _BEBONE_GFX_VULKAN_FRAMEBUFFER_H_ #include #include "../gfx_backend.h" -#include "vulkan_wrapper.tpp" +#include "interface/i_vulkan_device.h" +#include "interface/i_vulkan_image_view.h" -namespace bebone::gfx::vulkan { +namespace bebone::gfx { using namespace bebone::core; - class VulkanDevice; - - class VulkanImageView; class VulkanRenderPass; - class VulkanFramebuffer : public VulkanWrapper, private core::NonCopyable { + class VulkanFramebuffer : private core::NonCopyable { + public: + VkFramebuffer framebuffer; + + private: + IVulkanDevice& device_owner; + public: VulkanFramebuffer( - VulkanDevice& device, - std::vector>& attachmentViews, - std::shared_ptr& renderPass, + IVulkanDevice& device, + std::vector>& attachment_views, + std::unique_ptr& render_pass, VkExtent2D extent); - void destroy(VulkanDevice &device) override; + ~VulkanFramebuffer(); }; } diff --git a/src/bebone/gfx/vulkan/vulkan_image.cpp b/src/bebone/gfx/vulkan/vulkan_image.cpp index 38b301de..967bbfd3 100644 --- a/src/bebone/gfx/vulkan/vulkan_image.cpp +++ b/src/bebone/gfx/vulkan/vulkan_image.cpp @@ -1,46 +1,109 @@ #include "vulkan_image.h" -#include "vulkan_device.h" -#include "vulkan_image_view.h" +#include "vulkan_command_buffer_pool.h" -namespace bebone::gfx::vulkan { +namespace bebone::gfx { using namespace bebone::core; - VulkanImage::VulkanImage(const VkImage& image) { - backend = image; - } + VulkanImage::VulkanImage( + IVulkanDevice& device, + VkFormat format, + VkExtent3D extent, + VulkanImageInfo image_info + ) : device_owner(device), extent(extent) { + VkImageCreateInfo create_info{}; + + create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + create_info.pNext = nullptr; + create_info.flags = image_info.flags; + create_info.imageType = image_info.image_type; + create_info.format = format; + create_info.extent = extent; + create_info.mipLevels = image_info.mip_levels; + create_info.arrayLayers = image_info.array_layers; + create_info.samples = image_info.samples; + create_info.tiling = image_info.tiling; + create_info.usage = image_info.usage; + create_info.sharingMode = image_info.sharing_mode; + create_info.queueFamilyIndexCount = image_info.queue_family_index_count; + create_info.pQueueFamilyIndices = image_info.ptr_queue_family_indices; + create_info.initialLayout = image_info.initial_layout; - VulkanImage::VulkanImage(VulkanDevice& device, VkFormat format, VkExtent3D extent, VulkanImageInfo imageInfo) { - VkImageCreateInfo createInfo{}; - - createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - createInfo.pNext = nullptr; - createInfo.flags = imageInfo.flags; - createInfo.imageType = imageInfo.imageType; - createInfo.format = format; - createInfo.extent = extent; - createInfo.mipLevels = imageInfo.mipLevels; - createInfo.arrayLayers = imageInfo.arrayLayers; - createInfo.samples = imageInfo.samples; - createInfo.tiling = imageInfo.tiling; - createInfo.usage = imageInfo.usage; - createInfo.sharingMode = imageInfo.sharingMode; - createInfo.queueFamilyIndexCount = imageInfo.queueFamilyIndexCount; - createInfo.pQueueFamilyIndices = imageInfo.pQueueFamilyIndices; - createInfo.initialLayout = imageInfo.initialLayout; - - if (vkCreateImage(device.device(), &createInfo, nullptr, &backend) != VK_SUCCESS) { + if(vkCreateImage(device_owner.get_vk_device(), &create_info, nullptr, &image) != VK_SUCCESS) { + LOG_ERROR("Failed to create image"); throw std::runtime_error("failed to create image!"); } + + LOG_TRACE("Created Vulkan image"); } - VkMemoryRequirements VulkanImage::get_memory_requirements(VulkanDevice& device) { - VkMemoryRequirements memRequirements; - vkGetImageMemoryRequirements(device.device(), backend, &memRequirements); - return memRequirements; + VulkanImage::~VulkanImage() { + vkDestroyImage(device_owner.get_vk_device(), image, nullptr); + LOG_DEBUG("Destroyed Vulkan image"); + }; + + // Todo, clear out this + void VulkanImage::transition_layout( + VkImageLayout old_layout, + VkImageLayout new_layout + ) { + LOG_CRITICAL("VulkanImage::transition_layout is not implemented"); + /* + auto command_buffer = device_owner.begin_single_time_commands(); + + VkImageMemoryBarrier barrier{}; + + barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barrier.oldLayout = old_layout; + barrier.newLayout = new_layout; + barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.image = image; + barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + barrier.subresourceRange.baseMipLevel = 0; + barrier.subresourceRange.levelCount = 1; + barrier.subresourceRange.baseArrayLayer = 0; + barrier.subresourceRange.layerCount = 1; + + VkPipelineStageFlags source_stage; + VkPipelineStageFlags destination_stage; + + if(old_layout == VK_IMAGE_LAYOUT_UNDEFINED && new_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) { + barrier.srcAccessMask = 0; + barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + + source_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + destination_stage = VK_PIPELINE_STAGE_TRANSFER_BIT; + } else if (old_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && new_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { + barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + + source_stage = VK_PIPELINE_STAGE_TRANSFER_BIT; + destination_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + } else { + LOG_ERROR("Unsupported image layout transition"); + throw std::runtime_error("unsupported layout transition!"); + } + + vkCmdPipelineBarrier(command_buffer->backend, source_stage, destination_stage, 0, 0, nullptr, 0, nullptr, 1, &barrier); + + device_owner.end_single_time_commands(command_buffer); + */ + } + + VkImage VulkanImage::get_vk_image() const { + return image; + } + + VkMemoryRequirements VulkanImage::get_memory_requirements() const { + VkMemoryRequirements requirements; + + vkGetImageMemoryRequirements(device_owner.get_vk_device(), image, &requirements); + + return requirements; } - void VulkanImage::destroy(VulkanDevice &device) { - vkDestroyImage(device.device(), backend, nullptr); + VkExtent3D VulkanImage::get_extent() const { + return extent; } } diff --git a/src/bebone/gfx/vulkan/vulkan_image.h b/src/bebone/gfx/vulkan/vulkan_image.h index 7de33a5b..c4fbec4b 100644 --- a/src/bebone/gfx/vulkan/vulkan_image.h +++ b/src/bebone/gfx/vulkan/vulkan_image.h @@ -1,64 +1,51 @@ -#ifndef _BEBONE_GFX_VULKAN_VULKAN_IMAGE_H_ -#define _BEBONE_GFX_VULKAN_VULKAN_IMAGE_H_ +#ifndef _BEBONE_GFX_VULKAN_IMAGE_H_ +#define _BEBONE_GFX_VULKAN_IMAGE_H_ #include #include "../gfx_backend.h" -#include "vulkan_wrapper.tpp" -#include "vulkan_device_memory.h" +#include "interface/i_vulkan_image.h" +#include "interface/i_vulkan_device.h" -namespace bebone::gfx::vulkan { +namespace bebone::gfx { using namespace bebone::core; - class VulkanDevice; - - class VulkanImage; - class VulkanImageView; - class VulkanDeviceMemory; - - struct VulkanSwapChainImageTuple { - std::shared_ptr image; - std::shared_ptr view; - }; - - struct VulkanDepthImageTuple { - std::shared_ptr image; - std::shared_ptr view; - std::shared_ptr memory; - }; - struct VulkanImageInfo { - // VkStructureType sType; - // const void* pNext; + // VkStructureType type; + // const void* ptr_next; VkImageCreateFlags flags = 0; - VkImageType imageType = VK_IMAGE_TYPE_2D; + VkImageType image_type = VK_IMAGE_TYPE_2D; // VkFormat format = VK_FORMAT_UNDEFINED; // VkExtent3D extent = {0, 0, 0}; - uint32_t mipLevels = 1; - uint32_t arrayLayers = 1; + uint32_t mip_levels = 1; + uint32_t array_layers = 1; VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT; VkImageTiling tiling = VK_IMAGE_TILING_OPTIMAL; VkImageUsageFlags usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - VkSharingMode sharingMode = VK_SHARING_MODE_EXCLUSIVE; - uint32_t queueFamilyIndexCount = 0; - const uint32_t* pQueueFamilyIndices = nullptr; - VkImageLayout initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + VkSharingMode sharing_mode = VK_SHARING_MODE_EXCLUSIVE; + uint32_t queue_family_index_count = 0; + const uint32_t* ptr_queue_family_indices = nullptr; + VkImageLayout initial_layout = VK_IMAGE_LAYOUT_UNDEFINED; }; - class VulkanImage : public VulkanWrapper, private core::NonCopyable { - public: - VulkanImage(const VkImage& image); + class VulkanImage : public IVulkanImage, private core::NonCopyable { + private: + IVulkanDevice& device_owner; - VulkanImage( - VulkanDevice& device, - VkFormat format, - VkExtent3D extent, - VulkanImageInfo imageInfo = {}); + VkImage image; + VkExtent3D extent; + + public: + VulkanImage(IVulkanDevice& device, VkFormat format, VkExtent3D extent, VulkanImageInfo image_info = {}); + ~VulkanImage() override; - VkMemoryRequirements get_memory_requirements(VulkanDevice& device); + void transition_layout(VkImageLayout old_layout, VkImageLayout new_layout); - void destroy(VulkanDevice &device) override; + // Vulkan Image + [[nodiscard]] VkImage get_vk_image() const override; + [[nodiscard]] VkMemoryRequirements get_memory_requirements() const override; + [[nodiscard]] VkExtent3D get_extent() const override; }; } diff --git a/src/bebone/gfx/vulkan/vulkan_image_view.cpp b/src/bebone/gfx/vulkan/vulkan_image_view.cpp index b0dacade..9a54f9f0 100644 --- a/src/bebone/gfx/vulkan/vulkan_image_view.cpp +++ b/src/bebone/gfx/vulkan/vulkan_image_view.cpp @@ -1,36 +1,70 @@ #include "vulkan_image_view.h" -#include "vulkan_device.h" #include "vulkan_image.h" -namespace bebone::gfx::vulkan { +namespace bebone::gfx { using namespace bebone::core; - VulkanImageView::VulkanImageView(VulkanDevice& device, VulkanImage& image, VkFormat& imageFormat, VulkanImageViewInfo imageViewInfo) { - VkImageViewCreateInfo createInfo{}; - - createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - createInfo.pNext = nullptr; - createInfo.flags = imageViewInfo.flags; - createInfo.image = image.backend; - createInfo.viewType = imageViewInfo.viewType; - createInfo.format = imageFormat; - createInfo.components = imageViewInfo.components; - - createInfo.subresourceRange = { - .aspectMask = imageViewInfo.subresourceRange.aspectMask, - .baseMipLevel = imageViewInfo.subresourceRange.baseMipLevel, - .levelCount = imageViewInfo.subresourceRange.levelCount, - .baseArrayLayer = imageViewInfo.subresourceRange.baseArrayLayer, - .layerCount = imageViewInfo.subresourceRange.layerCount + VulkanImageView::VulkanImageView(IVulkanDevice& device, VulkanImage& image, const VkFormat& image_format, VulkanImageViewInfo image_view_info) : device_owner(device) { + VkImageViewCreateInfo create_info{}; + + create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + create_info.pNext = nullptr; + create_info.flags = image_view_info.flags; + create_info.image = image.get_vk_image(); + create_info.viewType = image_view_info.view_type; + create_info.format = image_format; + create_info.components = image_view_info.components; + + create_info.subresourceRange = { + .aspectMask = image_view_info.subresource_range.aspect_mask, + .baseMipLevel = image_view_info.subresource_range.base_mip_level, + .levelCount = image_view_info.subresource_range.level_count, + .baseArrayLayer = image_view_info.subresource_range.base_array_layer, + .layerCount = image_view_info.subresource_range.layer_count + }; + + if(vkCreateImageView(device_owner.get_vk_device(), &create_info, nullptr, &image_view) != VK_SUCCESS) { + LOG_ERROR("Failed to create texture image view"); + throw std::runtime_error("failed to create texture image view!"); + } + + LOG_TRACE("Created Vulkan image view"); + } + + VulkanImageView::VulkanImageView(IVulkanDevice& device, VkImage image, const VkFormat& image_format, VulkanImageViewInfo image_view_info) : device_owner(device) { + VkImageViewCreateInfo create_info{}; + + create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + create_info.pNext = nullptr; + create_info.flags = image_view_info.flags; + create_info.image = image; + create_info.viewType = image_view_info.view_type; + create_info.format = image_format; + create_info.components = image_view_info.components; + + create_info.subresourceRange = { + .aspectMask = image_view_info.subresource_range.aspect_mask, + .baseMipLevel = image_view_info.subresource_range.base_mip_level, + .levelCount = image_view_info.subresource_range.level_count, + .baseArrayLayer = image_view_info.subresource_range.base_array_layer, + .layerCount = image_view_info.subresource_range.layer_count }; - if (vkCreateImageView(device.device(), &createInfo, nullptr, &backend) != VK_SUCCESS) { + if(vkCreateImageView(device_owner.get_vk_device(), &create_info, nullptr, &image_view) != VK_SUCCESS) { + LOG_ERROR("Failed to create texture image view"); throw std::runtime_error("failed to create texture image view!"); } + + LOG_TRACE("Created Vulkan image view"); + } + + VulkanImageView::~VulkanImageView() { + vkDestroyImageView(device_owner.get_vk_device(), image_view, nullptr); + LOG_DEBUG("Destroyed Vulkan image view"); } - void VulkanImageView::destroy(VulkanDevice &device) { - vkDestroyImageView(device.device(), backend, nullptr); + VkImageView VulkanImageView::get_vk_image_view() const { + return image_view; } } diff --git a/src/bebone/gfx/vulkan/vulkan_image_view.h b/src/bebone/gfx/vulkan/vulkan_image_view.h index b039e961..521c8ea4 100644 --- a/src/bebone/gfx/vulkan/vulkan_image_view.h +++ b/src/bebone/gfx/vulkan/vulkan_image_view.h @@ -1,46 +1,50 @@ -#ifndef _BEBONE_GFX_VULKAN_VULKAN_IMAGE_VIEW_H_ -#define _BEBONE_GFX_VULKAN_VULKAN_IMAGE_VIEW_H_ +#ifndef _BEBONE_GFX_VULKAN_IMAGE_VIEW_H_ +#define _BEBONE_GFX_VULKAN_IMAGE_VIEW_H_ #include #include "../gfx_backend.h" -#include "vulkan_wrapper.tpp" +#include "interface/i_vulkan_image_view.h" +#include "interface/i_vulkan_device.h" -namespace bebone::gfx::vulkan { +namespace bebone::gfx { using namespace bebone::core; - class VulkanDevice; class VulkanImage; struct VulkanImageSubresourceRange { - VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - uint32_t baseMipLevel = 0; - uint32_t levelCount = 1; - uint32_t baseArrayLayer = 0; - uint32_t layerCount = 1; + VkImageAspectFlags aspect_mask = VK_IMAGE_ASPECT_COLOR_BIT; + uint32_t base_mip_level = 0; + uint32_t level_count = 1; + uint32_t base_array_layer = 0; + uint32_t layer_count = 1; }; struct VulkanImageViewInfo { - // VkStructureType sType; - // const void* pNext; + // VkStructureType type; + // const void* ptr_next; VkImageViewCreateFlags flags = 0; // VkImage image; - VkImageViewType viewType = VK_IMAGE_VIEW_TYPE_2D; + VkImageViewType view_type = VK_IMAGE_VIEW_TYPE_2D; // VkFormat format; VkComponentMapping components = {}; - VulkanImageSubresourceRange subresourceRange = {}; + VulkanImageSubresourceRange subresource_range = {}; }; - class VulkanImageView : public VulkanWrapper, private core::NonCopyable { + class VulkanImageView : public IVulkanImageView, private core::NonCopyable { + private: + IVulkanDevice& device_owner; + + VkImageView image_view; + public: - VulkanImageView( - VulkanDevice& device, - VulkanImage& image, - VkFormat& imageFormat, - VulkanImageViewInfo imageViewInfo = {}); + VulkanImageView(IVulkanDevice& device, VulkanImage& image, const VkFormat& image_format, VulkanImageViewInfo image_view_info = {}); + VulkanImageView(IVulkanDevice& device, VkImage image, const VkFormat& image_format, VulkanImageViewInfo image_view_info = {}); + + ~VulkanImageView() override; - void destroy(VulkanDevice &device) override; + VkImageView get_vk_image_view() const override; }; } diff --git a/src/bebone/gfx/vulkan/vulkan_instance.cpp b/src/bebone/gfx/vulkan/vulkan_instance.cpp index ec644476..a2327999 100644 --- a/src/bebone/gfx/vulkan/vulkan_instance.cpp +++ b/src/bebone/gfx/vulkan/vulkan_instance.cpp @@ -1,124 +1,126 @@ #include "vulkan_instance.h" -#include "vulkan_device.h" - -namespace bebone::gfx::vulkan { - VkInstance& VulkanInstance::get_instance() { - return instance; - } +namespace bebone::gfx { VulkanInstance::VulkanInstance() { - createInstance(); + if (enable_validation_layers && !check_validation_layer_support()) { + LOG_ERROR("Validation layers requested, but not available"); + throw std::runtime_error("validation layers requested, but not available!"); + } - if(enableValidationLayers) - debugMessenger = std::make_unique(*this); - } + VkApplicationInfo app_info = {}; + app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; + app_info.pApplicationName = "Bebone"; + app_info.applicationVersion = VK_MAKE_VERSION(1, 0, 0); + app_info.pEngineName = "Bebone"; + app_info.engineVersion = VK_MAKE_VERSION(1, 0, 0); + app_info.apiVersion = VK_API_VERSION_1_2; - bool VulkanInstance::checkValidationLayerSupport() { - uint32_t layerCount; - vkEnumerateInstanceLayerProperties(&layerCount, nullptr); + VkInstanceCreateInfo create_info = {}; + create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; + create_info.pApplicationInfo = &app_info; - std::vector availableLayers(layerCount); - vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data()); + auto extensions = get_required_extensions(); + create_info.enabledExtensionCount = static_cast(extensions.size()); + create_info.ppEnabledExtensionNames = extensions.data(); - for (const char *layerName : validationLayers) { - bool layerFound = false; + if (enable_validation_layers) { + VkDebugUtilsMessengerCreateInfoEXT debug_create_info; - for (const auto &layerProperties : availableLayers) { - if (strcmp(layerName, layerProperties.layerName) == 0) { - layerFound = true; - break; - } - } + create_info.enabledLayerCount = static_cast(validation_layers.size()); + create_info.ppEnabledLayerNames = validation_layers.data(); - if (!layerFound) - return false; + VulkanDebugMessenger::populate_debug_messenger_create_info(debug_create_info); + create_info.pNext = (VkDebugUtilsMessengerCreateInfoEXT*) &debug_create_info; + } else { + create_info.enabledLayerCount = 0; + create_info.pNext = nullptr; } - return true; - } + if (vkCreateInstance(&create_info, nullptr, &instance) != VK_SUCCESS) { + LOG_ERROR("Failed to create instance"); + throw std::runtime_error("failed to create instance!"); + } - void VulkanInstance::createInstance() { - if (enableValidationLayers && !checkValidationLayerSupport()) { - throw std::runtime_error("validation layers requested, but not available!"); + has_gflw_required_instance_extensions(); + + if(enable_validation_layers) { + LOG_INFORMATION("Enabled vulkan validation layers"); + debug_messenger = std::make_unique(*this); } - VkApplicationInfo appInfo = {}; - appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; - appInfo.pApplicationName = "Bebone"; - appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0); - appInfo.pEngineName = "Bebone"; - appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0); - appInfo.apiVersion = VK_API_VERSION_1_2; + LOG_TRACE("Created Vulkan instance"); + } - VkInstanceCreateInfo createInfo = {}; - createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; - createInfo.pApplicationInfo = &appInfo; + VulkanInstance::~VulkanInstance() { + debug_messenger.reset(); - auto extensions = getRequiredExtensions(); - createInfo.enabledExtensionCount = static_cast(extensions.size()); - createInfo.ppEnabledExtensionNames = extensions.data(); + vkDestroyInstance(instance, nullptr); + } - if (enableValidationLayers) { - VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo; + bool VulkanInstance::check_validation_layer_support() { + uint32_t layer_count; + vkEnumerateInstanceLayerProperties(&layer_count, nullptr); - createInfo.enabledLayerCount = static_cast(validationLayers.size()); - createInfo.ppEnabledLayerNames = validationLayers.data(); + auto available_layers = std::vector(layer_count); + vkEnumerateInstanceLayerProperties(&layer_count, available_layers.data()); - VulkanDebugMessenger::populateDebugMessengerCreateInfo(debugCreateInfo); - createInfo.pNext = (VkDebugUtilsMessengerCreateInfoEXT *)&debugCreateInfo; - } else { - createInfo.enabledLayerCount = 0; - createInfo.pNext = nullptr; - } + for(const char *layer_name : validation_layers) { + bool found = false; - if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) { - throw std::runtime_error("failed to create instance!"); + for (const auto &layer_properties : available_layers) { + if (strcmp(layer_name, layer_properties.layerName) == 0) { + found = true; + break; + } + } + + if (!found) + return false; } - hasGflwRequiredInstanceExtensions(); + return true; } + void VulkanInstance::has_gflw_required_instance_extensions() { + uint32_t extension_count = 0; + vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, nullptr); - void VulkanInstance::hasGflwRequiredInstanceExtensions() { - uint32_t extensionCount = 0; - vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr); - std::vector extensions(extensionCount); - vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.data()); + auto extensions = std::vector(extension_count); + vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, extensions.data()); + + auto available = std::unordered_set{}; + for(const auto &extension : extensions) { + LOG_INFORMATION("Available extensions: {}", extension.extensionName); - std::cout << "available extensions:" << std::endl; - std::unordered_set available; - for (const auto &extension : extensions) { - std::cout << "\t" << extension.extensionName << std::endl; available.insert(extension.extensionName); } - std::cout << "required extensions:" << std::endl; - auto requiredExtensions = getRequiredExtensions(); - for (const auto &required : requiredExtensions) { - std::cout << "\t" << required << std::endl; - if (available.find(required) == available.end()) { + auto required_extensions = get_required_extensions(); + for(const auto &required : required_extensions) { + LOG_INFORMATION("Required extensions: {}", required); + + if(available.find(required) == available.end()) { + LOG_ERROR("Missing required GLFW extension"); throw std::runtime_error("Missing required glfw extension"); } } } - std::vector VulkanInstance::getRequiredExtensions() { - uint32_t glfwExtensionCount = 0; - const char **glfwExtensions; - glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount); + std::vector VulkanInstance::get_required_extensions() { + uint32_t glfw_extension_count = 0; + const char **glfw_extensions; + glfw_extensions = glfwGetRequiredInstanceExtensions(&glfw_extension_count); - std::vector extensions(glfwExtensions, glfwExtensions + glfwExtensionCount); + auto extensions = std::vector(glfw_extensions, glfw_extensions + glfw_extension_count); - if (enableValidationLayers) { + if(enable_validation_layers) extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); - } return extensions; } - std::shared_ptr VulkanInstance::create_device(std::shared_ptr& window) { - auto& vulkanWindow = *static_cast(window.get()); - return std::make_shared(*this, vulkanWindow); + VkInstance VulkanInstance::get_vk_instance() const { + return instance; } } diff --git a/src/bebone/gfx/vulkan/vulkan_instance.h b/src/bebone/gfx/vulkan/vulkan_instance.h index bb259025..7d75a93c 100644 --- a/src/bebone/gfx/vulkan/vulkan_instance.h +++ b/src/bebone/gfx/vulkan/vulkan_instance.h @@ -1,48 +1,36 @@ -#ifndef _BEBONE_GFX_VULKAN_VULKAN_INSTANCE_H_ -#define _BEBONE_GFX_VULKAN_VULKAN_INSTANCE_H_ +#ifndef _BEBONE_GFX_VULKAN_INSTANCE_H_ +#define _BEBONE_GFX_VULKAN_INSTANCE_H_ #include +#include #include "../gfx_backend.h" #include "../window/vulkan_window.h" #include "vulkan_debug_messenger.h" -namespace bebone::gfx::vulkan { - class VulkanDevice; +#include "interface/i_vulkan_instance.h" - class VulkanInstance : private core::NonCopyable { +namespace bebone::gfx { + class VulkanInstance : public IVulkanInstance, private core::NonCopyable { private: VkInstance instance; - std::unique_ptr debugMessenger; + std::unique_ptr debug_messenger; - bool checkValidationLayerSupport(); - static void hasGflwRequiredInstanceExtensions(); - static std::vector getRequiredExtensions(); + bool check_validation_layer_support(); + static void has_gflw_required_instance_extensions(); + static std::vector get_required_extensions(); - public: - bool const static enableValidationLayers = true; - - void createInstance(); - - VkInstance& get_instance(); + bool const static enable_validation_layers = true; + public: VulkanInstance(); + ~VulkanInstance() override; - std::shared_ptr create_device(std::shared_ptr& window); - - const std::vector validationLayers = { "VK_LAYER_KHRONOS_validation" }; - - static std::shared_ptr create_instance() { - return std::make_shared(); - } - - void destroy() { - if(enableValidationLayers) - debugMessenger = nullptr; + const std::vector validation_layers = { "VK_LAYER_KHRONOS_validation" }; - vkDestroyInstance(instance, nullptr); - } + // Vulkan Instance + [[nodiscard]] VkInstance get_vk_instance() const override; }; } diff --git a/src/bebone/gfx/vulkan/vulkan_pipeline.cpp b/src/bebone/gfx/vulkan/vulkan_pipeline.cpp index bb0f6cb0..73059da7 100644 --- a/src/bebone/gfx/vulkan/vulkan_pipeline.cpp +++ b/src/bebone/gfx/vulkan/vulkan_pipeline.cpp @@ -1,209 +1,254 @@ #include "vulkan_pipeline.h" -#include "vulkan_device.h" #include "vulkan_swap_chain.h" #include "vulkan_pipeline_layout.h" -namespace bebone::gfx::vulkan { - std::vector VulkanPipeline::collect_shader_stages(std::vector>& shaderModules) { - std::vector pStages; +namespace bebone::gfx { + std::vector VulkanPipeline::collect_shader_stages(const std::vector>& shader_modules) { + auto stages = std::vector{}; + stages.reserve(shader_modules.size()); - for(auto& shaderModule : shaderModules) { + for(auto& shader_module : shader_modules) { VkPipelineShaderStageCreateInfo stage; stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; stage.pNext = nullptr; stage.flags = 0; + stage.module = shader_module->shader_module; + stage.pName = "main"; + stage.pSpecializationInfo = nullptr; - if(shaderModule->shaderType == ShaderTypes::VERTEX_SHADER) + if(shader_module->type == ShaderType::VertexShader) stage.stage = VK_SHADER_STAGE_VERTEX_BIT; - else if(shaderModule->shaderType == ShaderTypes::FRAGMENT_SHADER) + else if(shader_module->type == ShaderType::FragmentShader) stage.stage = VK_SHADER_STAGE_FRAGMENT_BIT; - stage.module = shaderModule->backend; - stage.pName = "main"; - stage.pSpecializationInfo = nullptr; - - pStages.push_back(stage); + stages.push_back(stage); } - return pStages; + return stages; } - VulkanPipeline::VulkanPipeline( - VulkanDevice& device, - std::shared_ptr& swapChain, - std::shared_ptr& pipelineLayout, - std::vector>& shaderModules, - VulkanPipelineConfig& configInfo - ) { - + void VulkanPipeline::create_pipeline( + const std::unique_ptr& render_pass, + VulkanPipelineLayout& pipeline_layout, + const std::vector>& shader_modules, + VulkanPipelineConfig& config_info + ) { // VkPipelineShaderStageCreateInfo - auto pStages = VulkanPipeline::collect_shader_stages(shaderModules); + auto stages = VulkanPipeline::collect_shader_stages(shader_modules); // VulkanPipelineVertexInputStateConfig - VkPipelineVertexInputStateCreateInfo pVertexInputState{}; - pVertexInputState.sType = configInfo.pVertexInputState.sType; - pVertexInputState.pNext = configInfo.pVertexInputState.pNext; - pVertexInputState.flags = configInfo.pVertexInputState.flags; - - if(configInfo.pVertexInputState.vertexDescriptions.bindingDescriptions.size() != 0) { - pVertexInputState.vertexBindingDescriptionCount = configInfo.pVertexInputState.vertexDescriptions.bindingDescriptions.size(); - pVertexInputState.pVertexBindingDescriptions = configInfo.pVertexInputState.vertexDescriptions.bindingDescriptions.data(); + VkPipelineVertexInputStateCreateInfo vertex_input_state{}; + vertex_input_state.sType = config_info.vertex_input_state.type; + vertex_input_state.pNext = config_info.vertex_input_state.ptr_next; + vertex_input_state.flags = config_info.vertex_input_state.flags; + + if(!config_info.vertex_input_state.vertex_descriptions.binding_descriptions.empty()) { + vertex_input_state.vertexBindingDescriptionCount = config_info.vertex_input_state.vertex_descriptions.binding_descriptions.size(); + vertex_input_state.pVertexBindingDescriptions = config_info.vertex_input_state.vertex_descriptions.binding_descriptions.data(); } else { - pVertexInputState.vertexBindingDescriptionCount = 0; - pVertexInputState.pVertexBindingDescriptions = nullptr; + vertex_input_state.vertexBindingDescriptionCount = 0; + vertex_input_state.pVertexBindingDescriptions = nullptr; } - if(configInfo.pVertexInputState.vertexDescriptions.attributeDescriptions.size() != 0) { - pVertexInputState.vertexAttributeDescriptionCount = configInfo.pVertexInputState.vertexDescriptions.attributeDescriptions.size(); - pVertexInputState.pVertexAttributeDescriptions = configInfo.pVertexInputState.vertexDescriptions.attributeDescriptions.data(); + if(!config_info.vertex_input_state.vertex_descriptions.attribute_descriptions.empty()) { + vertex_input_state.vertexAttributeDescriptionCount = config_info.vertex_input_state.vertex_descriptions.attribute_descriptions.size(); + vertex_input_state.pVertexAttributeDescriptions = config_info.vertex_input_state.vertex_descriptions.attribute_descriptions.data(); } else { - pVertexInputState.vertexAttributeDescriptionCount = 0; - pVertexInputState.pVertexAttributeDescriptions = nullptr; + vertex_input_state.vertexAttributeDescriptionCount = 0; + vertex_input_state.pVertexAttributeDescriptions = nullptr; } // VulkanPipelineInputAssemblyStateConfig - VkPipelineInputAssemblyStateCreateInfo pInputAssemblyState = { - .sType = configInfo.pInputAssemblyState.sType, - .pNext = configInfo.pInputAssemblyState.pNext, - .flags = configInfo.pInputAssemblyState.flags, - .topology = configInfo.pInputAssemblyState.topology, - .primitiveRestartEnable = configInfo.pInputAssemblyState.primitiveRestartEnable + const VkPipelineInputAssemblyStateCreateInfo input_assembly_state = { + .sType = config_info.input_assembly_state.type, + .pNext = config_info.input_assembly_state.ptr_next, + .flags = config_info.input_assembly_state.flags, + .topology = config_info.input_assembly_state.topology, + .primitiveRestartEnable = config_info.input_assembly_state.primitive_restart_enable + }; + + // Static scissors + const auto scissors = VkRect2D { + { 0, 0 }, + { render_pass->get_extent().width, render_pass->get_extent().height } }; // VulkanPipelineViewportStateConfig - VkPipelineViewportStateCreateInfo pViewportState = { - .sType = configInfo.pViewportState.sType, - .pNext = configInfo.pViewportState.pNext, - .flags = configInfo.pViewportState.flags, - .viewportCount = configInfo.pViewportState.viewportCount, - .pViewports = configInfo.pViewportState.pViewports, - .scissorCount = configInfo.pViewportState.scissorCount, - .pScissors = configInfo.pViewportState.pScissors + const VkPipelineViewportStateCreateInfo viewport_state = { + .sType = config_info.viewport_state.type, + .pNext = config_info.viewport_state.ptr_next, + .flags = config_info.viewport_state.flags, + .viewportCount = config_info.viewport_state.viewport_count, + .pViewports = config_info.viewport_state.ptr_viewports, + .scissorCount = 1, + .pScissors = &scissors }; // VulkanPipelineRasterizationStateConfig - VkPipelineRasterizationStateCreateInfo pRasterizationState = { - .sType = configInfo.pRasterizationState.sType, - .pNext = configInfo.pRasterizationState.pNext, - .flags = configInfo.pRasterizationState.flags, - .depthClampEnable = configInfo.pRasterizationState.depthClampEnable, - .rasterizerDiscardEnable = configInfo.pRasterizationState.rasterizerDiscardEnable, - .polygonMode = configInfo.pRasterizationState.polygonMode, - .cullMode = configInfo.pRasterizationState.cullMode, - .frontFace = configInfo.pRasterizationState.frontFace, - .depthBiasEnable = configInfo.pRasterizationState.depthBiasEnable, - .depthBiasConstantFactor = configInfo.pRasterizationState.depthBiasConstantFactor, - .depthBiasClamp = configInfo.pRasterizationState.depthBiasClamp, - .depthBiasSlopeFactor = configInfo.pRasterizationState.depthBiasSlopeFactor, - .lineWidth = configInfo.pRasterizationState.lineWidth + const VkPipelineRasterizationStateCreateInfo rasterization_state = { + .sType = config_info.rasterization_state.type, + .pNext = config_info.rasterization_state.ptr_next, + .flags = config_info.rasterization_state.flags, + .depthClampEnable = config_info.rasterization_state.depth_clamp_enable, + .rasterizerDiscardEnable = config_info.rasterization_state.rasterizer_discard_enable, + .polygonMode = config_info.rasterization_state.polygon_mode, + .cullMode = config_info.rasterization_state.cull_mode, + .frontFace = config_info.rasterization_state.front_face, + .depthBiasEnable = config_info.rasterization_state.depth_bias_enable, + .depthBiasConstantFactor = config_info.rasterization_state.depth_bias_constant_factor, + .depthBiasClamp = config_info.rasterization_state.depth_bias_clamp, + .depthBiasSlopeFactor = config_info.rasterization_state.depth_bias_slope_factor, + .lineWidth = config_info.rasterization_state.line_width }; // VulkanPipelineMultisampleStateConfig - VkPipelineMultisampleStateCreateInfo pMultisampleState = { - .sType = configInfo.pMultisampleState.sType, - .pNext = configInfo.pMultisampleState.pNext, - .flags = configInfo.pMultisampleState.flags, - .rasterizationSamples = configInfo.pMultisampleState.rasterizationSamples, - .sampleShadingEnable = configInfo.pMultisampleState.sampleShadingEnable, - .minSampleShading = configInfo.pMultisampleState.minSampleShading, - .pSampleMask = configInfo.pMultisampleState.pSampleMask, - .alphaToCoverageEnable = configInfo.pMultisampleState.alphaToCoverageEnable, - .alphaToOneEnable = configInfo.pMultisampleState.alphaToOneEnable + const VkPipelineMultisampleStateCreateInfo multisample_state = { + .sType = config_info.multisample_state.type, + .pNext = config_info.multisample_state.ptr_next, + .flags = config_info.multisample_state.flags, + .rasterizationSamples = config_info.multisample_state.rasterization_samples, + .sampleShadingEnable = config_info.multisample_state.sample_shading_enable, + .minSampleShading = config_info.multisample_state.min_sample_shading, + .pSampleMask = config_info.multisample_state.ptr_sample_mask, + .alphaToCoverageEnable = config_info.multisample_state.alpha_to_coverage_enable, + .alphaToOneEnable = config_info.multisample_state.alpha_to_one_enable }; // VulkanPipelineDepthStencilStateConfig - VkPipelineDepthStencilStateCreateInfo pDepthStencilState = { - .sType = configInfo.pDepthStencilState.sType, - .pNext = configInfo.pDepthStencilState.pNext, - .flags = configInfo.pDepthStencilState.flags, - .depthTestEnable = configInfo.pDepthStencilState.depthTestEnable, - .depthWriteEnable = configInfo.pDepthStencilState.depthWriteEnable, - .depthCompareOp = configInfo.pDepthStencilState.depthCompareOp, - .depthBoundsTestEnable = configInfo.pDepthStencilState.depthBoundsTestEnable, - .stencilTestEnable = configInfo.pDepthStencilState.stencilTestEnable, - .front = configInfo.pDepthStencilState.front, - .back = configInfo.pDepthStencilState.back, - .minDepthBounds = configInfo.pDepthStencilState.minDepthBounds, - .maxDepthBounds = configInfo.pDepthStencilState.maxDepthBounds + const VkPipelineDepthStencilStateCreateInfo depth_stencil_state = { + .sType = config_info.depth_stencil_state.type, + .pNext = config_info.depth_stencil_state.ptr_next, + .flags = config_info.depth_stencil_state.flags, + .depthTestEnable = config_info.depth_stencil_state.depth_test_enable, + .depthWriteEnable = config_info.depth_stencil_state.depth_write_enable, + .depthCompareOp = config_info.depth_stencil_state.depth_compare_op, + .depthBoundsTestEnable = config_info.depth_stencil_state.depth_bounds_test_enable, + .stencilTestEnable = config_info.depth_stencil_state.stencil_test_enable, + .front = config_info.depth_stencil_state.front, + .back = config_info.depth_stencil_state.back, + .minDepthBounds = config_info.depth_stencil_state.min_depth_bounds, + .maxDepthBounds = config_info.depth_stencil_state.max_depth_bounds }; + // Todo fix this cringe, + auto g = config_info.color_blend_state.ptr_attachments[0]; + config_info.color_blend_state.ptr_attachments.clear(); + for(size_t i = 0; i < render_pass->get_color_attachments_count(); ++i) + config_info.color_blend_state.ptr_attachments.push_back(g); + // VulkanPipelineColorBlendStateConfig - VkPipelineColorBlendStateCreateInfo pColorBlendState = { - .sType = configInfo.pColorBlendState.sType, - .pNext = configInfo.pColorBlendState.pNext, - .flags = configInfo.pColorBlendState.flags, - .logicOpEnable = configInfo.pColorBlendState.logicOpEnable, - .logicOp = configInfo.pColorBlendState.logicOp, - .attachmentCount = static_cast(configInfo.pColorBlendState.pAttachments.size()), - .pAttachments = configInfo.pColorBlendState.pAttachments.data(), + const VkPipelineColorBlendStateCreateInfo color_blend_state = { + .sType = config_info.color_blend_state.type, + .pNext = config_info.color_blend_state.ptr_next, + .flags = config_info.color_blend_state.flags, + .logicOpEnable = config_info.color_blend_state.logic_op_enable, + .logicOp = config_info.color_blend_state.logic_op, + + // Todo, since we have may have multiple color attachments, that means that this also should be computed + .attachmentCount = static_cast(config_info.color_blend_state.ptr_attachments.size()), + .pAttachments = config_info.color_blend_state.ptr_attachments.data(), + .blendConstants = { - configInfo.pColorBlendState.blendConstants[0], - configInfo.pColorBlendState.blendConstants[1], - configInfo.pColorBlendState.blendConstants[2], - configInfo.pColorBlendState.blendConstants[3] + config_info.color_blend_state.blend_constants[0], + config_info.color_blend_state.blend_constants[1], + config_info.color_blend_state.blend_constants[2], + config_info.color_blend_state.blend_constants[3] } }; // VulkanPipelineDynamicStateConfig - VkPipelineDynamicStateCreateInfo pDynamicState = { - .sType = configInfo.pDynamicState.sType, - .pNext = configInfo.pDynamicState.pNext, - .flags = configInfo.pDynamicState.flags, - .dynamicStateCount = static_cast(configInfo.pDynamicState.pDynamicStates.size()), - .pDynamicStates = configInfo.pDynamicState.pDynamicStates.data() + const VkPipelineDynamicStateCreateInfo dynamic_state = { + .sType = config_info.dynamic_state.type, + .pNext = config_info.dynamic_state.ptr_next, + .flags = config_info.dynamic_state.flags, + .dynamicStateCount = static_cast(config_info.dynamic_state.ptr_dynamic_states.size()), + .pDynamicStates = config_info.dynamic_state.ptr_dynamic_states.data() }; - VkGraphicsPipelineCreateInfo pipelineInfo{}; - pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - pipelineInfo.pNext = nullptr; - pipelineInfo.flags = configInfo.flags; + const auto size = static_cast(stages.size()); - pipelineInfo.stageCount = pStages.size(); - pipelineInfo.pStages = pStages.data(); + const VkGraphicsPipelineCreateInfo pipeline_info = { + .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, + .pNext = nullptr, + .flags = config_info.flags, - pipelineInfo.pVertexInputState = &pVertexInputState; - pipelineInfo.pInputAssemblyState = &pInputAssemblyState; - pipelineInfo.pTessellationState = nullptr; - pipelineInfo.pViewportState = &pViewportState; - pipelineInfo.pRasterizationState = &pRasterizationState; - pipelineInfo.pMultisampleState = &pMultisampleState; - pipelineInfo.pDepthStencilState = &pDepthStencilState; - pipelineInfo.pColorBlendState = &pColorBlendState; - pipelineInfo.pDynamicState = &pDynamicState; + .stageCount = size, + .pStages = stages.data(), - pipelineInfo.layout = pipelineLayout->get_layout(); - pipelineInfo.renderPass = swapChain->renderTarget->renderPass->backend; + .pVertexInputState = &vertex_input_state, + .pInputAssemblyState = &input_assembly_state, + .pTessellationState = nullptr, + .pViewportState = &viewport_state, + .pRasterizationState = &rasterization_state, + .pMultisampleState = &multisample_state, + .pDepthStencilState = &depth_stencil_state, + .pColorBlendState = &color_blend_state, + .pDynamicState = &dynamic_state, - pipelineInfo.subpass = configInfo.subpass; - pipelineInfo.basePipelineIndex = configInfo.basePipelineIndex; - pipelineInfo.basePipelineHandle = configInfo.basePipelineHandle; + .layout = pipeline_layout.pipeline_layout, + .renderPass = render_pass->render_pass, // Todo, actually swap chain is not needed there - if (vkCreateGraphicsPipelines(device.device(), VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &backend) != VK_SUCCESS) { + .subpass = config_info.subpass, + .basePipelineHandle = config_info.base_pipeline_handle, + .basePipelineIndex = config_info.base_pipeline_index + }; + + if(vkCreateGraphicsPipelines(device_owner.get_vk_device(), VK_NULL_HANDLE, 1, &pipeline_info, nullptr, &pipeline) != VK_SUCCESS) { + LOG_ERROR("Failed to create graphics pipeline"); throw std::runtime_error("failed to create graphics pipeline"); } + + LOG_TRACE("Created Vulkan graphics pipeline"); + } + + VulkanPipeline::VulkanPipeline( + IVulkanDevice& device, + const std::unique_ptr& render_pass, + VulkanPipelineLayout& pipeline_layout, + const std::vector>& shader_modules, + VulkanPipelineConfig config_info + ) : device_owner(device) { + create_pipeline(render_pass, pipeline_layout, shader_modules, config_info); + } + + VulkanPipeline::VulkanPipeline( + IVulkanDevice& device, + const std::unique_ptr& render_pass, + VulkanPipelineLayout& pipeline_layout, + const std::string& vertex_shader_path, + const std::string& fragment_shader_path, + VulkanPipelineConfig config_info + ) : device_owner(device) { + std::vector> shader_modules; + shader_modules.push_back(std::make_unique(device_owner, utils_read_file(vertex_shader_path), ShaderType::VertexShader)); + shader_modules.push_back(std::make_unique(device_owner, utils_read_file(fragment_shader_path), ShaderType::FragmentShader)); + + create_pipeline(render_pass, pipeline_layout, shader_modules, config_info); + } + + VulkanPipeline::~VulkanPipeline() { + vkDestroyPipeline(device_owner.get_vk_device(), pipeline, nullptr); + + LOG_TRACE("Destroyed Vulkan graphics pipeline"); } /* void VulkanPipeline::recreate( - VulkanDevice& device, - std::shared_ptr& vertShaderModule, - std::shared_ptr& fragShaderModule, - const PipelineConfigInfo& configInfo + IVulkanDevice& device, + std::unique_ptr& vertShaderModule, + std::unique_ptr& fragShaderModule, + const PipelineConfigInfo& config_info ) { // Todo move this - vkDestroyPipeline(device.device(), backend, nullptr); + vkDestroyPipeline(device_owner.get_vk_device(), backend, nullptr); - create_graphics_pipeline(device, vertShaderModule, fragShaderModule, configInfo); + create_graphics_pipeline(device, vertShaderModule, fragShaderModule, config_info); } */ - void VulkanPipeline::bind(VkCommandBuffer commandBuffer) { - vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, backend); - } - - void VulkanPipeline::destroy(VulkanDevice& device) { - vkDestroyPipeline(device.device(), backend, nullptr); + void VulkanPipeline::bind(VkCommandBuffer command_buffer) { + vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); } } diff --git a/src/bebone/gfx/vulkan/vulkan_pipeline.h b/src/bebone/gfx/vulkan/vulkan_pipeline.h index cb3c2096..f5370739 100644 --- a/src/bebone/gfx/vulkan/vulkan_pipeline.h +++ b/src/bebone/gfx/vulkan/vulkan_pipeline.h @@ -1,39 +1,54 @@ -#ifndef _BEBONE_GFX_VULKAN_VULKAN_PIPELINE_H_ -#define _BEBONE_GFX_VULKAN_VULKAN_PIPELINE_H_ +#ifndef _BEBONE_GFX_VULKAN_PIPELINE_H_ +#define _BEBONE_GFX_VULKAN_PIPELINE_H_ #include "../shaders/shader_code.h" -#include "vulkan_wrapper.tpp" #include "vulkan_shader_module.h" #include "vulkan_pipeline_config_info.h" -namespace bebone::gfx::vulkan { +namespace bebone::gfx { class VulkanSwapChain; class VulkanShaderModule; class VulkanPipelineLayout; + class VulkanRenderPass; + + class VulkanPipeline : private core::NonCopyable { + public: + VkPipeline pipeline; - class VulkanPipeline : public VulkanWrapper, private core::NonCopyable { private: - static std::vector collect_shader_stages( - std::vector>& shaderModules); + IVulkanDevice& device_owner; + + protected: + static std::vector collect_shader_stages(const std::vector>& shader_modules); + + // Todo recreate method + void create_pipeline( + const std::unique_ptr& render_pass, + VulkanPipelineLayout& pipeline_layout, + const std::vector>& shader_modules, + VulkanPipelineConfig& config_info); public: VulkanPipeline( - VulkanDevice& device, - std::shared_ptr& swapChain, - std::shared_ptr& pipelineLayout, - std::vector>& shaderModules, - VulkanPipelineConfig& configInfo); + IVulkanDevice& device, + const std::unique_ptr& render_pass, + VulkanPipelineLayout& pipeline_layout, + const std::vector>& shader_modules, + VulkanPipelineConfig config_info); + + VulkanPipeline( + IVulkanDevice& device, + const std::unique_ptr& render_pass, + VulkanPipelineLayout& pipeline_layout, + const std::string& vertex_shader_path, + const std::string& fragment_shader_path, + VulkanPipelineConfig config_info); - // void recreate( - // VulkanDevice& device, - // std::shared_ptr& vertShaderModule, - // std::shared_ptr& fragShaderModule, - // const PipelineConfigInfo& configInfo); + ~VulkanPipeline(); - void bind(VkCommandBuffer commandBuffer); - void destroy(VulkanDevice& device) override; + void bind(VkCommandBuffer command_buffer); }; } diff --git a/src/bebone/gfx/vulkan/vulkan_pipeline_config_info.cpp b/src/bebone/gfx/vulkan/vulkan_pipeline_config_info.cpp deleted file mode 100644 index 8a860452..00000000 --- a/src/bebone/gfx/vulkan/vulkan_pipeline_config_info.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#include "vulkan_pipeline_config_info.h" - -namespace bebone::gfx::vulkan { - -} diff --git a/src/bebone/gfx/vulkan/vulkan_pipeline_config_info.h b/src/bebone/gfx/vulkan/vulkan_pipeline_config_info.h index f9b185ad..be97e8b1 100644 --- a/src/bebone/gfx/vulkan/vulkan_pipeline_config_info.h +++ b/src/bebone/gfx/vulkan/vulkan_pipeline_config_info.h @@ -1,110 +1,111 @@ -#ifndef _BEBONE_GFX_VULKAN_VULKAN_PIPELINE_CONFIG_INFO_H_ -#define _BEBONE_GFX_VULKAN_VULKAN_PIPELINE_CONFIG_INFO_H_ +#ifndef _BEBONE_GFX_VULKAN_PIPELINE_CONFIG_INFO_H_ +#define _BEBONE_GFX_VULKAN_PIPELINE_CONFIG_INFO_H_ #include #include "../gfx_backend.h" -namespace bebone::gfx::vulkan { +namespace bebone::gfx { + // Todo remake this VulkanPipelineVertexInputStateTuple struct VulkanPipelineVertexInputStateTuple { - std::vector bindingDescriptions = {}; - std::vector attributeDescriptions = {}; + std::vector binding_descriptions = {}; + std::vector attribute_descriptions = {}; }; // Todo make this structs noncopyable but also lets resolve gcc compilation warning // VkPipelineVertexInputStateCreateInfo struct VulkanPipelineVertexInputStateConfig { - VkStructureType sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - void* pNext = nullptr; + VkStructureType type = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; + void* ptr_next = nullptr; VkPipelineVertexInputStateCreateFlags flags = 0; - VulkanPipelineVertexInputStateTuple vertexDescriptions = {}; + VulkanPipelineVertexInputStateTuple vertex_descriptions = {}; }; // VkPipelineInputAssemblyStateCreateInfo struct VulkanPipelineInputAssemblyStateConfig { - VkStructureType sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; - void* pNext = nullptr; + VkStructureType type = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; + void* ptr_next = nullptr; VkPipelineInputAssemblyStateCreateFlags flags = 0; VkPrimitiveTopology topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; - VkBool32 primitiveRestartEnable = VK_FALSE; + VkBool32 primitive_restart_enable = VK_FALSE; }; // VkPipelineTessellationStateCreateInfo struct VulkanPipelineTessellationStateConfig { - VkStructureType sType; - void* pNext; + VkStructureType type; + void* ptr_next; VkPipelineTessellationStateCreateFlags flags; - uint32_t patchControlPoints; + uint32_t patch_control_points; }; // VkPipelineViewportStateCreateInfo struct VulkanPipelineViewportStateConfig { - VkStructureType sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; - void* pNext = nullptr; + VkStructureType type = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; + void* ptr_next = nullptr; VkPipelineViewportStateCreateFlags flags = 0; - uint32_t viewportCount = 1; - VkViewport* pViewports = nullptr; - uint32_t scissorCount = 1; - VkRect2D* pScissors = nullptr; + uint32_t viewport_count = 1; + VkViewport* ptr_viewports = nullptr; + uint32_t scissor_count = 1; + VkRect2D* ptr_scissors = nullptr; }; // VkPipelineRasterizationStateCreateInfo struct VulkanPipelineRasterizationStateConfig { - VkStructureType sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; - void* pNext = nullptr; + VkStructureType type = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; + void* ptr_next = nullptr; VkPipelineRasterizationStateCreateFlags flags = 0; - VkBool32 depthClampEnable = VK_FALSE; - VkBool32 rasterizerDiscardEnable = VK_FALSE; - VkPolygonMode polygonMode = VK_POLYGON_MODE_FILL; - VkCullModeFlags cullMode = VK_CULL_MODE_BACK_BIT; - VkFrontFace frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; - VkBool32 depthBiasEnable = VK_FALSE; - float depthBiasConstantFactor = 0.0f; - float depthBiasClamp = 0.0f; - float depthBiasSlopeFactor = 0.0f; - float lineWidth = 1.0f; + VkBool32 depth_clamp_enable = VK_FALSE; + VkBool32 rasterizer_discard_enable = VK_FALSE; + VkPolygonMode polygon_mode = VK_POLYGON_MODE_FILL; + VkCullModeFlags cull_mode = VK_CULL_MODE_BACK_BIT; + VkFrontFace front_face = VK_FRONT_FACE_COUNTER_CLOCKWISE; // Todo + VkBool32 depth_bias_enable = VK_FALSE; + float depth_bias_constant_factor = 0.0f; + float depth_bias_clamp = 0.0f; + float depth_bias_slope_factor = 0.0f; + float line_width = 1.0f; }; // VkPipelineMultisampleStateCreateInfo struct VulkanPipelineMultisampleStateConfig { - VkStructureType sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; - void* pNext = nullptr; + VkStructureType type = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; + void* ptr_next = nullptr; VkPipelineMultisampleStateCreateFlags flags = 0; - VkSampleCountFlagBits rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; - VkBool32 sampleShadingEnable = VK_FALSE; - float minSampleShading = 1.0f; - VkSampleMask* pSampleMask = nullptr; - VkBool32 alphaToCoverageEnable = VK_FALSE; - VkBool32 alphaToOneEnable = VK_FALSE; + VkSampleCountFlagBits rasterization_samples = VK_SAMPLE_COUNT_1_BIT; + VkBool32 sample_shading_enable = VK_FALSE; + float min_sample_shading = 1.0f; + VkSampleMask* ptr_sample_mask = nullptr; + VkBool32 alpha_to_coverage_enable = VK_FALSE; + VkBool32 alpha_to_one_enable = VK_FALSE; }; // VkPipelineDepthStencilStateCreateInfo struct VulkanPipelineDepthStencilStateConfig { - VkStructureType sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; - void* pNext = nullptr; + VkStructureType type = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; + void* ptr_next = nullptr; VkPipelineDepthStencilStateCreateFlags flags = 0; - VkBool32 depthTestEnable = VK_TRUE; - VkBool32 depthWriteEnable = VK_TRUE; - VkCompareOp depthCompareOp = VK_COMPARE_OP_LESS; - VkBool32 depthBoundsTestEnable = VK_FALSE; - VkBool32 stencilTestEnable = VK_FALSE; + VkBool32 depth_test_enable = VK_TRUE; + VkBool32 depth_write_enable = VK_TRUE; + VkCompareOp depth_compare_op = VK_COMPARE_OP_LESS; + VkBool32 depth_bounds_test_enable = VK_FALSE; + VkBool32 stencil_test_enable = VK_FALSE; VkStencilOpState front = {}; VkStencilOpState back = {}; - float minDepthBounds = 0.0f; - float maxDepthBounds = 1.0f; + float min_depth_bounds = 0.0f; + float max_depth_bounds = 1.0f; }; // VkPipelineColorBlendStateCreateInfo struct VulkanPipelineColorBlendStateConfig { - VkStructureType sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; - void* pNext = nullptr; + VkStructureType type = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; + void* ptr_next = nullptr; VkPipelineColorBlendStateCreateFlags flags = 0; - VkBool32 logicOpEnable = VK_FALSE; - VkLogicOp logicOp = VK_LOGIC_OP_COPY; + VkBool32 logic_op_enable = VK_FALSE; + VkLogicOp logic_op = VK_LOGIC_OP_COPY; - std::vector pAttachments = { + std::vector ptr_attachments = { { .blendEnable = VK_FALSE, .srcColorBlendFactor = VK_BLEND_FACTOR_ONE, @@ -117,44 +118,44 @@ namespace bebone::gfx::vulkan { } }; - float blendConstants[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + float blend_constants[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; }; // VkPipelineDynamicStateCreateInfo struct VulkanPipelineDynamicStateConfig { - VkStructureType sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; - void* pNext = nullptr; + VkStructureType type = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; + void* ptr_next = nullptr; VkPipelineDynamicStateCreateFlags flags = 0; - std::vector pDynamicStates = { - VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR + std::vector ptr_dynamic_states = { + VK_DYNAMIC_STATE_VIEWPORT }; }; struct VulkanPipelineConfig { - VkStructureType sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - void* pNext = nullptr; + VkStructureType type = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + void* ptr_next = nullptr; VkPipelineCreateFlags flags = 0; // uint32_t stageCount; // Stage thing // VkPipelineShaderStageCreateInfo* pStages; // Stage thing - VulkanPipelineVertexInputStateConfig pVertexInputState = {}; // - VulkanPipelineInputAssemblyStateConfig pInputAssemblyState = {}; // - VulkanPipelineTessellationStateConfig* pTessellationState = nullptr; // For now lets set this to null - VulkanPipelineViewportStateConfig pViewportState = {}; // - VulkanPipelineRasterizationStateConfig pRasterizationState = {}; // - VulkanPipelineMultisampleStateConfig pMultisampleState = {}; // - VulkanPipelineDepthStencilStateConfig pDepthStencilState = {}; // - VulkanPipelineColorBlendStateConfig pColorBlendState = {}; // - VulkanPipelineDynamicStateConfig pDynamicState = {}; // + VulkanPipelineVertexInputStateConfig vertex_input_state = {}; // + VulkanPipelineInputAssemblyStateConfig input_assembly_state = {}; // + VulkanPipelineTessellationStateConfig* ptr_tessellation_state = nullptr; // For now lets set this to null + VulkanPipelineViewportStateConfig viewport_state = {}; // + VulkanPipelineRasterizationStateConfig rasterization_state = {}; // + VulkanPipelineMultisampleStateConfig multisample_state = {}; // + VulkanPipelineDepthStencilStateConfig depth_stencil_state = {}; // + VulkanPipelineColorBlendStateConfig color_blend_state = {}; // + VulkanPipelineDynamicStateConfig dynamic_state = {}; // // VkPipelineLayout layout; // Pipeline thing - // VkRenderPass renderPass; // Pipeline thing + // VkRenderPass render_pass; // Pipeline thing uint32_t subpass = 0; - VkPipeline basePipelineHandle = VK_NULL_HANDLE; - int32_t basePipelineIndex = -1; + VkPipeline base_pipeline_handle = VK_NULL_HANDLE; + int32_t base_pipeline_index = -1; }; } diff --git a/src/bebone/gfx/vulkan/vulkan_pipeline_layout.cpp b/src/bebone/gfx/vulkan/vulkan_pipeline_layout.cpp index 054990c9..aab25bb9 100644 --- a/src/bebone/gfx/vulkan/vulkan_pipeline_layout.cpp +++ b/src/bebone/gfx/vulkan/vulkan_pipeline_layout.cpp @@ -3,41 +3,43 @@ #include "vulkan_const_range.h" #include "vulkan_descriptor_set_layout.h" -namespace bebone::gfx::vulkan { +namespace bebone::gfx { VulkanPipelineLayout::VulkanPipelineLayout( - VulkanDevice& device, - const std::vector>& descriptorSetLayouts, - const std::vector& constantRanges - ) { + IVulkanDevice& device, + const std::vector>& descriptor_set_layouts, + const std::vector& constant_ranges + ) : device_owner(device) { + auto ranges = std::vector {}; + ranges.reserve(constant_ranges.size()); - std::vector ranges; - for(auto range : constantRanges) - ranges.push_back(range.range); + for(const auto& range : constant_ranges) + ranges.push_back(range.const_range); - VkPipelineLayoutCreateInfo pipelineLayoutInfo{}; - pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + auto layouts = std::vector {}; + layouts.reserve(descriptor_set_layouts.size()); + for(const auto& layout : descriptor_set_layouts) + layouts.push_back(layout->descriptor_set_layout); - std::vector layouts; - for(const auto& layout : descriptorSetLayouts) { - layouts.push_back(layout->backend); - } + VkPipelineLayoutCreateInfo pipeline_layout_info{}; - pipelineLayoutInfo.setLayoutCount = layouts.size(); - pipelineLayoutInfo.pSetLayouts = layouts.data(); - pipelineLayoutInfo.pushConstantRangeCount = ranges.size(); - pipelineLayoutInfo.pPushConstantRanges = ranges.data(); + pipeline_layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + pipeline_layout_info.setLayoutCount = layouts.size(); + pipeline_layout_info.pSetLayouts = layouts.data(); + pipeline_layout_info.pushConstantRangeCount = ranges.size(); + pipeline_layout_info.pPushConstantRanges = ranges.data(); - if(vkCreatePipelineLayout(device.device(), &pipelineLayoutInfo, nullptr, &backend) != VK_SUCCESS) { + if(vkCreatePipelineLayout(device_owner.get_vk_device(), &pipeline_layout_info, nullptr, &pipeline_layout) != VK_SUCCESS) { + LOG_ERROR("Failed to create pipeline layout"); throw std::runtime_error("Failed to create pipeline layout"); } - } - VkPipelineLayout VulkanPipelineLayout::get_layout() { - return backend; + LOG_TRACE("Created Vulkan pipeline layout"); } - void VulkanPipelineLayout::destroy(VulkanDevice& device) { - vkDestroyPipelineLayout(device.device(), backend, nullptr); + VulkanPipelineLayout::~VulkanPipelineLayout() { + vkDestroyPipelineLayout(device_owner.get_vk_device(), pipeline_layout, nullptr); + + LOG_TRACE("Destroyed Vulkan pipeline layout"); } } diff --git a/src/bebone/gfx/vulkan/vulkan_pipeline_layout.h b/src/bebone/gfx/vulkan/vulkan_pipeline_layout.h index 5e4b4fae..260fa650 100644 --- a/src/bebone/gfx/vulkan/vulkan_pipeline_layout.h +++ b/src/bebone/gfx/vulkan/vulkan_pipeline_layout.h @@ -1,25 +1,27 @@ -#ifndef _BEBONE_GFX_VULKAN_VULKAN_PIPELINE_LAYOUT_H_ -#define _BEBONE_GFX_VULKAN_VULKAN_PIPELINE_LAYOUT_H_ +#ifndef _BEBONE_GFX_VULKAN_PIPELINE_LAYOUT_H_ +#define _BEBONE_GFX_VULKAN_PIPELINE_LAYOUT_H_ #include "../gfx_backend.h" -#include "vulkan_device.h" #include "vulkan_descriptor_pool.h" -namespace bebone::gfx::vulkan { +namespace bebone::gfx { class VulkanConstRange; - class VulkanPipelineLayout : public VulkanWrapper, private core::NonCopyable { + class VulkanPipelineLayout : private core::NonCopyable { public: - VulkanPipelineLayout( - VulkanDevice& device, - const std::vector>& descriptorSetLayouts, - const std::vector& constantRanges - ); + VkPipelineLayout pipeline_layout; + + private: + IVulkanDevice& device_owner; - VkPipelineLayout get_layout(); + public: + VulkanPipelineLayout( + IVulkanDevice& device, + const std::vector>& descriptor_set_layouts, + const std::vector& constant_ranges); - void destroy(VulkanDevice& device) override; + ~VulkanPipelineLayout(); }; } diff --git a/src/bebone/gfx/vulkan/vulkan_pipeline_manager.cpp b/src/bebone/gfx/vulkan/vulkan_pipeline_manager.cpp new file mode 100644 index 00000000..659844c8 --- /dev/null +++ b/src/bebone/gfx/vulkan/vulkan_pipeline_manager.cpp @@ -0,0 +1,168 @@ +#include "vulkan_pipeline_manager.h" + +#include + +#include "vulkan_pipeline_layout.h" +#include "vulkan_descriptor_pool.h" +#include "vulkan_descriptor_set_layout.h" +#include "vulkan_descriptor_set_layout_binding.h" +#include "vulkan_const_range.h" +#include "vulkan_descriptor_set.h" + +namespace bebone::gfx { + VulkanPipelineManager::VulkanPipelineManager(IVulkanDevice& device) : device_owner(device), bindless_uniforms_index(0), bindless_storage_index(0), bindless_samplers_index(0) { + descriptor_pool = std::make_unique(device); + + const std::vector bindless_bindings = { + { Uniform, uniform_binding }, + // { Storage, storage_binding }, Todo + { Sampler, texture_binding } + }; + + // Creating bindless descriptor set layout + bindless_descriptor_set_layout = std::make_unique(device, bindless_bindings); + bindless_descriptor_set = descriptor_pool->create_descriptor(bindless_descriptor_set_layout); + + // Creating bindless pipeline layout + const auto constant_ranges = { VulkanConstRange(const_ranges_size, 0) }; + + std::vector> layouts; + layouts.push_back(std::move(bindless_descriptor_set_layout)); + + bindless_pipeline_layout = std::make_unique(device, layouts, constant_ranges); + + std::ignore = bindless_storage_index; // Todo + + LOG_TRACE("Created Vulkan pipeline manager"); + } + + VulkanPipelineManager::~VulkanPipelineManager() { + LOG_DEBUG("Destroyed Vulkan pipeline manager"); + } + + std::unique_ptr VulkanPipelineManager::create_pipeline( + const std::unique_ptr& render_pass, + std::unique_ptr vertex_shader_module, + std::unique_ptr fragment_shader_module, + VulkanPipelineConfig config_info + ) + { + std::vector> shader_modules; + shader_modules.push_back(std::move(vertex_shader_module)); + shader_modules.push_back(std::move(fragment_shader_module)); + + return std::make_unique(device_owner, render_pass, *bindless_pipeline_layout, shader_modules, std::move(config_info));; + } + + std::unique_ptr VulkanPipelineManager::create_pipeline( + const std::unique_ptr& render_pass, + const std::string& vertex_shader_file_path, + const std::string& fragment_shader_file_path, + VulkanPipelineConfig config_info + ) { + auto vert_shader_module = std::make_unique(device_owner, utils_read_file(vertex_shader_file_path), ShaderType::VertexShader); + auto frag_shader_module = std::make_unique(device_owner, utils_read_file(fragment_shader_file_path), ShaderType::FragmentShader); + + return std::make_unique(device_owner, render_pass, *bindless_pipeline_layout, vertex_shader_file_path, fragment_shader_file_path, config_info); + } + + /* + VulkanBindlessTextureHandle VulkanPipelineManager::bind_texture( + std::unique_ptr& device, + std::unique_ptr& texture + ) { + const auto handle = bindless_samplers_index; + + device->update_descriptor_set(texture->sampler, texture->view, bindless_descriptor_set, texture_binding, bindless_samplers_index); + ++bindless_samplers_index; + + return static_cast(handle); + } + + std::vector VulkanPipelineManager::bind_textures( + std::unique_ptr& device, + std::vector>& textures + ) { + auto handles = std::vector {}; + handles.reserve(textures.size()); + + for(auto& texture : textures) + handles.push_back(bind_texture(device, texture)); + + return handles; + } + + VulkanBindlessTextureHandle VulkanPipelineManager::bind_attachment( + std::unique_ptr& device, + std::unique_ptr& attachment + ) { + // Todo + if(!attachment->get_sampler().has_value()) + LOG_WARNING("Sampler does not have any value"); + + // Todo + if(!attachment->get_view().has_value()) + LOG_WARNING("View does not have any value"); + + // Todo + auto sampler = attachment->get_sampler().value(); + auto view = attachment->get_view().value(); + + const auto handle = bindless_samplers_index; + + device->update_descriptor_set(sampler, view, bindless_descriptor_set, texture_binding, bindless_samplers_index); + ++bindless_samplers_index; + + return static_cast(handle); + } + + std::vector VulkanPipelineManager::bind_attachments( + std::unique_ptr& device, + std::vector>& attachments + ) { + auto handles = std::vector {}; + handles.reserve(attachments.size()); + + for(auto& attachment : attachments) + handles.push_back(bind_attachment(device, attachment)); + + return handles; + } + */ + + VulkanBindlessBufferHandle VulkanPipelineManager::bind_uniform_buffer(IVulkanBuffer& buffer) { + const auto handle = bindless_uniforms_index; + + bindless_descriptor_set->update_descriptor_set(buffer, uniform_binding, bindless_uniforms_index); + ++bindless_uniforms_index; + + return static_cast(handle); + } + + /* + std::vector VulkanPipelineManager::bind_uniform_buffers( + std::unique_ptr& device, + const std::vector>& buffers + ) { + auto handles = std::vector {}; + handles.reserve(buffers.size()); + + for(auto& buffer : buffers) + handles.push_back(bind_uniform_buffer(device, buffer)); + + return handles; + } + */ + + const std::unique_ptr& VulkanPipelineManager::get_descriptor_set() const { + return bindless_descriptor_set; + } + + const std::unique_ptr& VulkanPipelineManager::get_descriptor_set_layout() const { + return bindless_descriptor_set_layout; + } + + const std::unique_ptr& VulkanPipelineManager::get_pipeline_layout() const { + return bindless_pipeline_layout; + } +} diff --git a/src/bebone/gfx/vulkan/vulkan_pipeline_manager.h b/src/bebone/gfx/vulkan/vulkan_pipeline_manager.h new file mode 100644 index 00000000..782941f7 --- /dev/null +++ b/src/bebone/gfx/vulkan/vulkan_pipeline_manager.h @@ -0,0 +1,84 @@ +#ifndef _BEBONE_VULKAN_PIPELINE_MANAGER_H_ +#define _BEBONE_VULKAN_PIPELINE_MANAGER_H_ + +#include "../gfx_backend.h" + +#include "vulkan_descriptor_pool.h" + +namespace bebone::gfx { + class VulkanConstRange; + class VulkanPipelineLayout; + + enum class VulkanBindlessBufferHandle : uint32_t { Invalid = 0 }; + enum class VulkanBindlessTextureHandle : uint32_t { Invalid = 0 }; + + class VulkanPipelineManager : private core::NonCopyable { + private: + IVulkanDevice& device_owner; + + std::unique_ptr descriptor_pool; + + std::unique_ptr bindless_descriptor_set_layout; + std::unique_ptr bindless_descriptor_set; + std::unique_ptr bindless_pipeline_layout; + + u32 bindless_uniforms_index; + u32 bindless_storage_index; + u32 bindless_samplers_index; + + static constexpr u32 uniform_binding = 0; + static constexpr u32 storage_binding = 1; + static constexpr u32 texture_binding = 2; + + static constexpr size_t const_ranges_size = 128; + + public: + VulkanPipelineManager(IVulkanDevice& device); + ~VulkanPipelineManager(); + + std::unique_ptr create_pipeline( + const std::unique_ptr& render_pass, + std::unique_ptr vertex_shader_module, + std::unique_ptr fragment_shader_module, + VulkanPipelineConfig config_info = {}); + + std::unique_ptr create_pipeline( + const std::unique_ptr& render_pass, + const std::string& vertex_shader_file_path, + const std::string& fragment_shader_file_path, + VulkanPipelineConfig config_info = {}); + + /* + VulkanBindlessTextureHandle bind_texture( + std::unique_ptr& device, + std::unique_ptr& texture); + + std::vector bind_textures( + std::unique_ptr& device, + std::vector>& texture); + + * Todo lets pass not IVulkanAttachment but rather two objects, IVulkanSampler, IVulkanView + VulkanBindlessTextureHandle bind_attachment( + std::unique_ptr& device, + std::unique_ptr& attachment); + + std::vector bind_attachments( + std::unique_ptr& device, + std::vector>& attachments); + */ + + VulkanBindlessBufferHandle bind_uniform_buffer(IVulkanBuffer& buffer); + + /* + std::vector bind_uniform_buffers( + std::unique_ptr& device, + const std::vector>& buffers); + */ + + [[nodiscard]] const std::unique_ptr& get_descriptor_set() const; + [[nodiscard]] const std::unique_ptr& get_descriptor_set_layout() const; + [[nodiscard]] const std::unique_ptr& get_pipeline_layout() const; + }; +} + +#endif diff --git a/src/bebone/gfx/vulkan/vulkan_render_pass.cpp b/src/bebone/gfx/vulkan/vulkan_render_pass.cpp index 94135fdd..5d8b0eee 100644 --- a/src/bebone/gfx/vulkan/vulkan_render_pass.cpp +++ b/src/bebone/gfx/vulkan/vulkan_render_pass.cpp @@ -1,41 +1,49 @@ #include "vulkan_render_pass.h" -namespace bebone::gfx::vulkan { - VulkanRenderPass::VulkanRenderPass(VulkanDevice& device, VkFormat colorAttachmentImageFormat) { - VkAttachmentDescription depthAttachment{}; - depthAttachment.format = device.find_depth_format(); - depthAttachment.samples = VK_SAMPLE_COUNT_1_BIT; - depthAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - depthAttachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - depthAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - depthAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - depthAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - depthAttachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - - VkAttachmentReference depthAttachmentRef{}; - depthAttachmentRef.attachment = 1; - depthAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - - VkAttachmentDescription colorAttachment = {}; - colorAttachment.format = colorAttachmentImageFormat; - colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT; - colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - colorAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; - - VkAttachmentReference colorAttachmentRef = {}; - colorAttachmentRef.attachment = 0; - colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - - VkSubpassDescription subpass = {}; - subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpass.colorAttachmentCount = 1; - subpass.pColorAttachments = &colorAttachmentRef; - subpass.pDepthStencilAttachment = &depthAttachmentRef; +namespace bebone::gfx { + VulkanRenderPass::VulkanRenderPass( + IVulkanDevice& device, + VkExtent2D extent, + const std::vector& attachments + ) : device_owner(device), attachments(attachments), depth_attachment_index(0), has_depth_attachment_flag(false), color_attachment_count(0), extent(extent) { + auto descriptions = std::vector {}; + descriptions.reserve(attachments.size()); + for(const auto& attachment : attachments) + descriptions.push_back(attachment.description); + + auto color_attachments_ref = std::vector {}; + auto depth_attachment_ref = VkAttachmentReference {}; // Only one depth attachment + + for(size_t i = 0; i < attachments.size(); ++i) { + const auto& attachment = attachments[i]; + + // Todo, only one depth attachment is allowed + if(attachment.type == Depth) { + depth_attachment_ref.attachment = i; + depth_attachment_ref.layout = attachment.layout; + + depth_attachment_index = i; + has_depth_attachment_flag = true; + } else if(attachment.type == Color) + color_attachments_ref.push_back(VkAttachmentReference{ static_cast(i), attachment.layout }); + } + + // We save color attachment count + color_attachment_count = color_attachments_ref.size(); + + // Main subpass + auto subpass = VkSubpassDescription {}; + subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; // Todo + subpass.colorAttachmentCount = color_attachments_ref.size(); + subpass.pColorAttachments = color_attachments_ref.data(); + + if(has_depth_attachment_flag) + subpass.pDepthStencilAttachment = &depth_attachment_ref; + else + subpass.pDepthStencilAttachment = nullptr; + + // and it dependencies VkSubpassDependency dependency = {}; dependency.srcSubpass = VK_SUBPASS_EXTERNAL; dependency.srcAccessMask = 0; @@ -44,22 +52,47 @@ namespace bebone::gfx::vulkan { dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - std::array attachments = {colorAttachment, depthAttachment}; - VkRenderPassCreateInfo renderPassInfo = {}; - renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - renderPassInfo.attachmentCount = static_cast(attachments.size()); - renderPassInfo.pAttachments = attachments.data(); - renderPassInfo.subpassCount = 1; - renderPassInfo.pSubpasses = &subpass; - renderPassInfo.dependencyCount = 1; - renderPassInfo.pDependencies = &dependency; - - if (vkCreateRenderPass(device.device(), &renderPassInfo, nullptr, &backend) != VK_SUCCESS) { + VkRenderPassCreateInfo render_pass_info = {}; + render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + render_pass_info.attachmentCount = static_cast(descriptions.size()); + render_pass_info.pAttachments = descriptions.data(); + + render_pass_info.subpassCount = 1; + render_pass_info.pSubpasses = &subpass; + + render_pass_info.dependencyCount = 1; + render_pass_info.pDependencies = &dependency; + + if(vkCreateRenderPass(device_owner.get_vk_device(), &render_pass_info, nullptr, &render_pass) != VK_SUCCESS) { + LOG_ERROR("Failed to create render pass"); throw std::runtime_error("failed to create render pass!"); } + + LOG_TRACE("Created Vulkan render pass"); + } + + VulkanRenderPass::~VulkanRenderPass() { + vkDestroyRenderPass(device_owner.get_vk_device(), render_pass, nullptr); + + LOG_TRACE("Destroyed Vulkan render pass"); + } + + std::optional VulkanRenderPass::get_depth_attachment() const { + if(!has_depth_attachment_flag) + return std::nullopt; + + return attachments[depth_attachment_index]; + } + + const size_t& VulkanRenderPass::get_color_attachments_count() const { + return color_attachment_count; + } + + const vector& VulkanRenderPass::get_attachments() const { + return attachments; } - void VulkanRenderPass::destroy(VulkanDevice& device) { - vkDestroyRenderPass(device.device(), backend, nullptr); + const VkExtent2D& VulkanRenderPass::get_extent() const { + return extent; } } diff --git a/src/bebone/gfx/vulkan/vulkan_render_pass.h b/src/bebone/gfx/vulkan/vulkan_render_pass.h index 34cd9674..4085c291 100644 --- a/src/bebone/gfx/vulkan/vulkan_render_pass.h +++ b/src/bebone/gfx/vulkan/vulkan_render_pass.h @@ -1,19 +1,41 @@ -#ifndef _BEBONE_GFX_VULKAN_VULKAN_RENDER_PASS_H_ -#define _BEBONE_GFX_VULKAN_VULKAN_RENDER_PASS_H_ +#ifndef _BEBONE_GFX_VULKAN_RENDER_PASS_H_ +#define _BEBONE_GFX_VULKAN_RENDER_PASS_H_ #include #include "../gfx_backend.h" -#include "vulkan_device.h" -#include "vulkan_wrapper.tpp" +#include "vulkan_attachment.h" +#include "interface/i_vulkan_device.h" -namespace bebone::gfx::vulkan { - class VulkanRenderPass : public VulkanWrapper { +namespace bebone::gfx { + class VulkanRenderPass : private core::NonCopyable { public: - VulkanRenderPass(VulkanDevice& _device, VkFormat colorAttachmentImageFormat); + VkRenderPass render_pass; - void destroy(VulkanDevice& device) override; + private: + IVulkanDevice& device_owner; + + private: + vector attachments; + + size_t depth_attachment_index; + bool has_depth_attachment_flag; + + size_t color_attachment_count; + + // Todo, not sure is this needed there + VkExtent2D extent; + + public: + VulkanRenderPass(IVulkanDevice& device, VkExtent2D extent, const std::vector& attachments); + ~VulkanRenderPass(); + + std::optional get_depth_attachment() const; + + const size_t& get_color_attachments_count() const; + const vector& get_attachments() const; + const VkExtent2D& get_extent() const; }; } diff --git a/src/bebone/gfx/vulkan/vulkan_render_target.cpp b/src/bebone/gfx/vulkan/vulkan_render_target.cpp index 0acd00a2..0ff8bbda 100644 --- a/src/bebone/gfx/vulkan/vulkan_render_target.cpp +++ b/src/bebone/gfx/vulkan/vulkan_render_target.cpp @@ -4,60 +4,125 @@ #include "vulkan_image_view.h" #include "vulkan_device_memory.h" #include "vulkan_swap_chain.h" +#include "vulkan_depth_image.h" +#include "vulkan_framebuffer.h" -namespace bebone::gfx::vulkan { +namespace bebone::gfx { VulkanRenderTarget::VulkanRenderTarget( - VulkanDevice& device, - std::vector& swapChainImages, - VkFormat imageFormat, - VkExtent2D extent - ) : swapChainImages(swapChainImages) { + IVulkanDevice& device, + std::unique_ptr& render_pass + ) { + // Create color attachments + color_attachments.reserve(render_pass->get_color_attachments_count()); - // Create render pass - renderPass = std::make_shared(device, imageFormat); + for(auto& attachment : render_pass->get_attachments()) { + if (attachment.type != Color) + continue; - // Create depth resources - auto depthFormat = device.find_depth_format(); + auto frame_attachments = std::vector>{}; + frame_attachments.reserve(3); // Todo, 3 should be configurable - for(size_t i = 0; i < swapChainImages.size(); ++i) { - auto image = device.create_image(depthFormat, { extent.width, extent.height, 1}, { - .usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT - }); + for (size_t f = 0; f < 3; ++f) {// Todo, 3 should be configurable + auto tt = std::make_unique(device, attachment.extent, attachment.description.format); + std::unique_ptr texture(static_cast(tt.release())); // Todo + frame_attachments.push_back(std::move(texture)); + } - auto memRequirements = image->get_memory_requirements(device); + color_attachments.push_back(std::move(frame_attachments)); + } + + // Create depth attachments + if(render_pass->get_depth_attachment().has_value()) { + auto attachment = render_pass->get_depth_attachment().value(); - auto memory = device.create_device_memory(memRequirements, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - memory->bind_image_memory(device, *image); + auto frame_attachments = std::vector> {}; + frame_attachments.reserve(3); // Todo, 3 should be configurable - auto view = device.create_image_view(*image, depthFormat, { - .subresourceRange = { .aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT }, - }); + for(size_t f = 0; f < 3; ++f) { // Todo, 3 should be configurable + auto dit = std::make_unique(device, attachment.extent); + std::unique_ptr depth(static_cast(dit.release())); // Todo + frame_attachments.push_back(std::move(depth)); + } - depthImages.push_back({image, view, memory}); + depth_attachments = std::move(frame_attachments); } // Create frame buffers - for(size_t i = 0; i < swapChainImages.size(); ++i) { - auto attachments = std::vector { swapChainImages[i].view, depthImages[i].view }; - auto framebuffer = std::make_shared(device, attachments, renderPass, extent); + for(size_t i = 0; i < 3; ++i) { // Todo, 3 should be configurable + auto attachments = std::vector> {}; + attachments.reserve(color_attachments.size()); + + for(auto& color_attachment : color_attachments) { + auto& attachment = color_attachment[i]; + attachments.push_back(std::move(attachment)); + } - swapChainFramebuffers.push_back(framebuffer); + // Todo, depth attachment order should be configurable + if(!depth_attachments.empty()) + attachments.push_back(std::move(depth_attachments[i])); + + auto framebuffer = std::make_unique(device, attachments, render_pass, render_pass->get_extent()); + framebuffers.push_back(std::move(framebuffer)); } + + LOG_TRACE("Created Vulkan render target"); } - void VulkanRenderTarget::destroy(VulkanDevice& device) { - renderPass->destroy(device); + VulkanRenderTarget::VulkanRenderTarget( + IVulkanDevice& device, + std::unique_ptr& render_pass, + std::vector>& images + ) { + // We do need to create color attachments, since swap chain handles them - for(auto& image : swapChainImages) - image.view->destroy(device); // Since image is provided by swap chain we should not destroy it, only view + // Create depth attachments + if(render_pass->get_depth_attachment().has_value()) { + auto attachment = render_pass->get_depth_attachment().value(); - for(auto& image : depthImages) { - image.memory->destroy(device); - image.view->destroy(device); - image.image->destroy(device); + auto frame_attachments = std::vector> {}; + frame_attachments.reserve(3); // Todo, 3 should be configurable + + for(size_t f = 0; f < 3; ++f) // Todo, 3 should be configurable + { + frame_attachments.push_back(std::make_unique(device, attachment.extent)); + } + + depth_attachments = std::move(frame_attachments); } - for (auto& framebuffer : swapChainFramebuffers) - framebuffer->destroy(device); + // Create frame buffers + for(size_t i = 0; i < 3; ++i) { // Todo, 3 should be configurable + // auto attachments = std::vector { image_views[i]->get_view().value(), depth_attachments[i]->get_view().value() }; + + auto attachments = std::vector> {}; + attachments.push_back(std::move(images[i])); + + if(!depth_attachments.empty()) + attachments.push_back(std::move(depth_attachments[i])); + + auto framebuffer = std::make_unique(device, attachments, render_pass, render_pass->get_extent()); + + framebuffers.push_back(std::move(framebuffer)); + + // Todo, there we need to safe color_attachment since we how own it + color_attachments.push_back(std::move(attachments)); + } + + LOG_TRACE("Created Vulkan render target"); + } + + VulkanRenderTarget::~VulkanRenderTarget() { + // Todo + for(auto& frame : color_attachments) + for(auto& tuple : frame) + tuple.reset(); // Since image is provided by swap chain we should not destroy it, only view + + for(auto& tuple : depth_attachments) + tuple.reset(); + + for (auto& framebuffer : framebuffers) + framebuffer.reset(); + + LOG_DEBUG("Destroyed Vulkan render target"); } } diff --git a/src/bebone/gfx/vulkan/vulkan_render_target.h b/src/bebone/gfx/vulkan/vulkan_render_target.h index ac889f32..d718a2b6 100644 --- a/src/bebone/gfx/vulkan/vulkan_render_target.h +++ b/src/bebone/gfx/vulkan/vulkan_render_target.h @@ -1,33 +1,37 @@ -#ifndef _BEBONE_GFX_VULKAN_VULKAN_RENDER_TARGET_H_ -#define _BEBONE_GFX_VULKAN_VULKAN_RENDER_TARGET_H_ +#ifndef _BEBONE_GFX_VULKAN_RENDER_TARGET_H_ +#define _BEBONE_GFX_VULKAN_RENDER_TARGET_H_ #include #include "../gfx_backend.h" #include "vulkan_render_pass.h" -#include "vulkan_device.h" #include "vulkan_image.h" #include "vulkan_framebuffer.h" +#include "vulkan_swap_chain_image.h" +#include "vulkan_texture.h" -namespace bebone::gfx::vulkan { +namespace bebone::gfx { class VulkanImage; class VulkanRenderTarget { public: - std::shared_ptr renderPass; + // Vector of all FIFO attachments + vector>> color_attachments; + vector> depth_attachments; + vector> framebuffers; - std::vector> swapChainFramebuffers; - std::vector depthImages; - std::vector swapChainImages; + // This is still just a swap chain render target constructor + VulkanRenderTarget( + IVulkanDevice& device, + std::unique_ptr& render_pass); VulkanRenderTarget( - VulkanDevice& device, - std::vector& swapChainImages, - VkFormat imageFormat, - VkExtent2D extent); + IVulkanDevice& device, + std::unique_ptr& render_pass, + std::vector>& images); - void destroy(VulkanDevice& device); + ~VulkanRenderTarget(); }; } diff --git a/src/bebone/gfx/vulkan/vulkan_result.cpp b/src/bebone/gfx/vulkan/vulkan_result.cpp index 7dfb5e92..e6369a42 100644 --- a/src/bebone/gfx/vulkan/vulkan_result.cpp +++ b/src/bebone/gfx/vulkan/vulkan_result.cpp @@ -1,6 +1,6 @@ #include "vulkan_result.h" -namespace bebone::gfx::vulkan { +namespace bebone::gfx { VulkanResult::VulkanResult(const VkResult& result) : result(result) { } diff --git a/src/bebone/gfx/vulkan/vulkan_result.h b/src/bebone/gfx/vulkan/vulkan_result.h index 4e9f6058..be222567 100644 --- a/src/bebone/gfx/vulkan/vulkan_result.h +++ b/src/bebone/gfx/vulkan/vulkan_result.h @@ -1,9 +1,9 @@ -#ifndef _BEBONE_GFX_VULKAN_VULKAN_RESULT_H_ -#define _BEBONE_GFX_VULKAN_VULKAN_RESULT_H_ +#ifndef _BEBONE_GFX_VULKAN_RESULT_H_ +#define _BEBONE_GFX_VULKAN_RESULT_H_ #include "../gfx_backend.h" -namespace bebone::gfx::vulkan { +namespace bebone::gfx { class VulkanResult { private: VkResult result; diff --git a/src/bebone/gfx/vulkan/vulkan_sampler.cpp b/src/bebone/gfx/vulkan/vulkan_sampler.cpp new file mode 100644 index 00000000..41486cb7 --- /dev/null +++ b/src/bebone/gfx/vulkan/vulkan_sampler.cpp @@ -0,0 +1,40 @@ +#include "vulkan_sampler.h" + +namespace bebone::gfx { + using namespace bebone::core; + + VulkanSampler::VulkanSampler(IVulkanDevice& device) : device_owner(device) { + VkSamplerCreateInfo sampler_info{}; + + sampler_info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + sampler_info.magFilter = VK_FILTER_LINEAR; + sampler_info.minFilter = VK_FILTER_LINEAR; + sampler_info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + sampler_info.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; + sampler_info.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; + sampler_info.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; + sampler_info.mipLodBias = 0.0f; + sampler_info.compareOp = VK_COMPARE_OP_NEVER; + sampler_info.minLod = 0.0f; + sampler_info.maxLod = 0.0f; + sampler_info.maxAnisotropy = 1.0f; + sampler_info.anisotropyEnable = VK_FALSE; + sampler_info.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; + + // Todo + vkCreateSampler(device_owner.get_vk_device(), &sampler_info, nullptr, &sampler); + LOG_WARNING("vkCreateSampler result is not handled"); + + LOG_TRACE("Created Vulkan sampler"); + } + + VulkanSampler::~VulkanSampler() { + vkDestroySampler(device_owner.get_vk_device(), sampler, nullptr); + + LOG_TRACE("Destroyed Vulkan sampler"); + } + + VkSampler VulkanSampler::get_vk_image_sampler() const { + return sampler; + } +} diff --git a/src/bebone/gfx/vulkan/vulkan_sampler.h b/src/bebone/gfx/vulkan/vulkan_sampler.h new file mode 100644 index 00000000..3075f723 --- /dev/null +++ b/src/bebone/gfx/vulkan/vulkan_sampler.h @@ -0,0 +1,29 @@ +#ifndef _BEBONE_GFX_VULKAN_SAMPLER_H_ +#define _BEBONE_GFX_VULKAN_SAMPLER_H_ + +#include + +#include "../gfx_backend.h" + +#include "vulkan_device_memory.h" + +#include "interface/i_vulkan_sampler.h" + +namespace bebone::gfx { + using namespace bebone::core; + + class VulkanSampler : public IVulkanSampler, private core::NonCopyable { + private: + IVulkanDevice& device_owner; + + VkSampler sampler; + + public: + VulkanSampler(IVulkanDevice& device); + ~VulkanSampler(); + + VkSampler get_vk_image_sampler() const override; + }; +} + +#endif diff --git a/src/bebone/gfx/vulkan/vulkan_shader_module.cpp b/src/bebone/gfx/vulkan/vulkan_shader_module.cpp index 6c1220c1..08419b54 100644 --- a/src/bebone/gfx/vulkan/vulkan_shader_module.cpp +++ b/src/bebone/gfx/vulkan/vulkan_shader_module.cpp @@ -1,20 +1,48 @@ #include "vulkan_shader_module.h" -#include "vulkan_device.h" +namespace bebone::gfx { + VulkanShaderModule::VulkanShaderModule(IVulkanDevice& device, const ShaderCode& code) : device_owner(device), type(code.get_shader_type()) { + VkShaderModuleCreateInfo create_info{}; -namespace bebone::gfx::vulkan { - VulkanShaderModule::VulkanShaderModule(VulkanDevice& device, const ShaderCode& shaderCode) : shaderType(shaderCode.get_shader_type()) { - VkShaderModuleCreateInfo createInfo{}; - createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; - createInfo.codeSize = shaderCode.get_byte_code().size() * sizeof(unsigned int); - createInfo.pCode = reinterpret_cast(shaderCode.get_byte_code().data()); + create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + create_info.codeSize = code.get_byte_code().size() * sizeof(unsigned int); + create_info.pCode = reinterpret_cast(code.get_byte_code().data()); - if(vkCreateShaderModule(device.device(), &createInfo, nullptr, &backend) != VK_SUCCESS) { + if(vkCreateShaderModule(device_owner.get_vk_device(), &create_info, nullptr, &shader_module) != VK_SUCCESS) { + LOG_ERROR("Failed to create shader module"); throw std::runtime_error("Failed to create shader module"); } + + LOG_TRACE("Created Vulkan shader module"); + } + + VulkanShaderModule::VulkanShaderModule(IVulkanDevice& device, const std::string& source_code, const ShaderType& type) : device_owner(device), type(type) { + auto shader_compiler = SpirVShaderCompiler(); + + shader_compiler.add_shader_source(ShaderSource( + source_code, + type + )); + + auto shader_code = shader_compiler.compile(type); + + VkShaderModuleCreateInfo create_info{}; + + create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + create_info.codeSize = shader_code.get_byte_code().size() * sizeof(unsigned int); + create_info.pCode = reinterpret_cast(shader_code.get_byte_code().data()); + + if(vkCreateShaderModule(device_owner.get_vk_device(), &create_info, nullptr, &shader_module) != VK_SUCCESS) { + LOG_ERROR("Failed to create shader module"); + throw std::runtime_error("Failed to create shader module"); + } + + LOG_TRACE("Created Vulkan shader module"); } - void VulkanShaderModule::destroy(VulkanDevice& device) { - vkDestroyShaderModule(device.device(), backend, nullptr); + VulkanShaderModule::~VulkanShaderModule() { + vkDestroyShaderModule(device_owner.get_vk_device(), shader_module, nullptr); + + LOG_TRACE("Destroyed Vulkan shader module"); } } diff --git a/src/bebone/gfx/vulkan/vulkan_shader_module.h b/src/bebone/gfx/vulkan/vulkan_shader_module.h index 1983d1e2..2829ed15 100644 --- a/src/bebone/gfx/vulkan/vulkan_shader_module.h +++ b/src/bebone/gfx/vulkan/vulkan_shader_module.h @@ -1,26 +1,31 @@ -#ifndef _BEBONE_GFX_VULKAN_VULKAN_SHADER_MODULE_H_ -#define _BEBONE_GFX_VULKAN_VULKAN_SHADER_MODULE_H_ +#ifndef _BEBONE_GFX_VULKAN_SHADER_MODULE_H_ +#define _BEBONE_GFX_VULKAN_SHADER_MODULE_H_ #include "../gfx_backend.h" -#include "vulkan_wrapper.tpp" - #include "../shaders/shader_code.h" #include "../shaders/shader_compiler.h" #include "../shaders/shader_source.h" #include "../shaders/shader_type.h" #include "../shaders/spirv_shader_compiler.h" -namespace bebone::gfx::vulkan { - class VulkanDevice; +#include "interface/i_vulkan_device.h" + +namespace bebone::gfx { + class VulkanShaderModule : private core::NonCopyable { + public: + VkShaderModule shader_module; + + private: + IVulkanDevice& device_owner; - class VulkanShaderModule : public VulkanWrapper, private core::NonCopyable { public: - ShaderType shaderType; + ShaderType type; - VulkanShaderModule(VulkanDevice& device, const ShaderCode& shaderCode); + VulkanShaderModule(IVulkanDevice& device, const ShaderCode& code); + VulkanShaderModule(IVulkanDevice& device, const std::string& source_code, const ShaderType& type); - void destroy(VulkanDevice& device) override; + ~VulkanShaderModule(); }; } diff --git a/src/bebone/gfx/vulkan/vulkan_swap_chain.cpp b/src/bebone/gfx/vulkan/vulkan_swap_chain.cpp index 2c433948..36170f5f 100644 --- a/src/bebone/gfx/vulkan/vulkan_swap_chain.cpp +++ b/src/bebone/gfx/vulkan/vulkan_swap_chain.cpp @@ -5,237 +5,280 @@ #include "vulkan_image_view.h" #include "vulkan_command_buffer.h" -namespace bebone::gfx::vulkan { - VulkanSwapChain::VulkanSwapChain(VulkanDevice &device, VkExtent2D _windowExtent) { - SwapChainSupportDetails swapChainSupport = device.get_swap_chain_support(); - extent = choose_swap_extent(swapChainSupport.capabilities, _windowExtent); +namespace bebone::gfx { + VulkanSwapChain::VulkanSwapChain(IVulkanDevice& device_owner, VkExtent2D window_extent) : device_owner(device_owner) { + auto swap_chain_support = device_owner.get_swap_chain_support(); + extent = choose_swap_extent(swap_chain_support.capabilities, window_extent); - create_swap_chain(device); + create_swap_chain(); - auto images = create_swap_chain_images(device, surfaceFormat.format); - renderTarget = std::make_unique(device, images, surfaceFormat.format, extent); + auto images = create_swap_chain_images(surface_format.format); - create_sync_objects(device); + // This is default swap chain render pass, + // but I am not sure is swap chain should manage it own render pass + render_pass = std::make_unique(device_owner, extent, std::vector { + VulkanAttachmentDesc::color2D(extent, { .format = surface_format.format }), + VulkanAttachmentDesc::depth2D(extent, { .format = device_owner.find_depth_format() }), + }); + + render_target = std::make_unique(device_owner, render_pass, images); + + create_sync_objects(); + + LOG_TRACE("Created Vulkan swap chain"); } - VulkanResult VulkanSwapChain::acquire_next_image(std::shared_ptr& device, uint32_t *imageIndex) { - vkWaitForFences(device->device(), 1, &inFlightFences[currentFrame], VK_TRUE, std::numeric_limits::max()); + VulkanSwapChain::VulkanSwapChain(IVulkanDevice& device_owner, std::unique_ptr &window) : device_owner(device_owner) { + auto window_extent = VkExtent2D { static_cast(window->get_width()), static_cast(window->get_height()) }; - auto result = vkAcquireNextImageKHR( - device->device(), - backend, - std::numeric_limits::max(), - imageAvailableSemaphores[currentFrame], // must be a not signaled semaphore - VK_NULL_HANDLE, - imageIndex); + auto swap_chain_support = device_owner.get_swap_chain_support(); + extent = choose_swap_extent(swap_chain_support.capabilities, window_extent); - if(result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) - throw std::runtime_error("failed to acquire swap chain image!"); + create_swap_chain(); - return VulkanResult(result); - } + auto images = create_swap_chain_images(surface_format.format); - VulkanResult VulkanSwapChain::submit_command_buffers(std::shared_ptr& device, std::shared_ptr& commandBuffer, uint32_t *imageIndex) { - // Submitting and synchronization - if (imagesInFlight[*imageIndex] != VK_NULL_HANDLE) { - vkWaitForFences(device->device(), 1, &imagesInFlight[*imageIndex], VK_TRUE, UINT64_MAX); - } + // This is default swap chain render pass, + // but I am not sure is swap chain should manage it own render pass + render_pass = std::make_unique(device_owner, extent, std::vector { + VulkanAttachmentDesc::color2D(extent, { .format = surface_format.format }), + VulkanAttachmentDesc::depth2D(extent, { .format = device_owner.find_depth_format() }), + }); - imagesInFlight[*imageIndex] = inFlightFences[currentFrame]; + render_target = std::make_unique(device_owner, render_pass, images); - VkSemaphore waitSemaphores[] = {imageAvailableSemaphores[currentFrame]}; - VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT}; - VkSemaphore signalSemaphores[] = {renderFinishedSemaphores[currentFrame]}; + create_sync_objects(); - VkSubmitInfo submitInfo = {}; + LOG_TRACE("Created Vulkan swap chain"); + } - submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submitInfo.waitSemaphoreCount = 1; - submitInfo.pWaitSemaphores = waitSemaphores; - submitInfo.pWaitDstStageMask = waitStages; - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &commandBuffer->backend; - submitInfo.signalSemaphoreCount = 1; - submitInfo.pSignalSemaphores = signalSemaphores; + VulkanSwapChain::~VulkanSwapChain() { + device_owner.wait_idle(); - vkResetFences(device->device(), 1, &inFlightFences[currentFrame]); - if (vkQueueSubmit(device->graphicsQueue(), 1, &submitInfo, inFlightFences[currentFrame]) != VK_SUCCESS) { - throw std::runtime_error("failed to submit draw command buffer!"); + // Todo move this somewhere else + for (size_t i = 0; i < image_count; i++) { + vkDestroySemaphore(device_owner.get_vk_device(), render_finished_semaphores[i], nullptr); + vkDestroySemaphore(device_owner.get_vk_device(), image_available_semaphores[i], nullptr); + vkDestroyFence(device_owner.get_vk_device(), in_flight_fences[i], nullptr); } - // Presenting part - VkSwapchainKHR swapChains[] = { backend }; + vkDestroySwapchainKHR(device_owner.get_vk_device(), swap_chain, nullptr); - VkPresentInfoKHR presentInfo = {}; - presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; - presentInfo.waitSemaphoreCount = 1; - presentInfo.pWaitSemaphores = signalSemaphores; - presentInfo.swapchainCount = 1; - presentInfo.pSwapchains = swapChains; - presentInfo.pImageIndices = imageIndex; + LOG_TRACE("Destroyed Vulkan swap chain"); + } - VkResult result = vkQueuePresentKHR(device->presentQueue(), &presentInfo); + const size_t& VulkanSwapChain::get_current_frame() const { + return current_frame; + } - currentFrame = (currentFrame + 1) % imageCount; + const VkExtent2D& VulkanSwapChain::get_extent() const { + return extent; + } - if(result != VK_SUCCESS) { - throw std::runtime_error("failed to acquire submit command buffers !"); + VulkanResult VulkanSwapChain::acquire_next_image(uint32_t *image_index) { + vkWaitForFences(device_owner.get_vk_device(), 1, &in_flight_fences[current_frame], VK_TRUE, std::numeric_limits::max()); + + auto result = vkAcquireNextImageKHR( + device_owner.get_vk_device(), + swap_chain, + std::numeric_limits::max(), + image_available_semaphores[current_frame], // must be a not signaled semaphore + VK_NULL_HANDLE, + image_index); + + if(result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) { + LOG_ERROR("Failed to acquire swap chain image"); + // throw std::runtime_error("failed to acquire swap chain image!"); Todo } return { result }; } - std::vector VulkanSwapChain::create_swap_chain_images(VulkanDevice& device, VkFormat imageFormat) { - std::vector images; - uint32_t imageCount; + VulkanResult VulkanSwapChain::submit_present_command_buffers( + VulkanCommandBuffer& command_buffer, + uint32_t *image_index + ) { + // Submitting and synchronization + if (images_in_flight[*image_index] != VK_NULL_HANDLE) + vkWaitForFences(device_owner.get_vk_device(), 1, &images_in_flight[*image_index], VK_TRUE, UINT64_MAX); + + images_in_flight[*image_index] = in_flight_fences[current_frame]; + + VkSemaphore wait_semaphores[] = {image_available_semaphores[current_frame]}; + VkPipelineStageFlags wait_stages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT}; + VkSemaphore signal_semaphores[] = {render_finished_semaphores[current_frame]}; + + VkSubmitInfo submit_info = {}; + submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submit_info.waitSemaphoreCount = 1; + submit_info.pWaitSemaphores = wait_semaphores; + submit_info.pWaitDstStageMask = wait_stages; + submit_info.commandBufferCount = 1; + submit_info.pCommandBuffers = &command_buffer.command_buffer; + submit_info.signalSemaphoreCount = 1; + submit_info.pSignalSemaphores = signal_semaphores; + + vkResetFences(device_owner.get_vk_device(), 1, &in_flight_fences[current_frame]); + if(vkQueueSubmit(device_owner.get_present_queue(), 1, &submit_info, in_flight_fences[current_frame]) != VK_SUCCESS) { + LOG_ERROR("Failed to submit draw command buffer"); + // throw std::runtime_error("failed to submit draw command buffer!"); Todo + } - vkGetSwapchainImagesKHR(device.device(), backend, &imageCount, nullptr); - images.resize(imageCount); - vkGetSwapchainImagesKHR(device.device(), backend, &imageCount, images.data()); + // Todo, Presenting part + VkSwapchainKHR swap_chains[] = { swap_chain }; - std::vector out; + VkPresentInfoKHR present_info = {}; + present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; + present_info.waitSemaphoreCount = 1; + present_info.pWaitSemaphores = signal_semaphores; + present_info.swapchainCount = 1; + present_info.pSwapchains = swap_chains; + present_info.pImageIndices = image_index; - for(auto& image : images) { - VulkanSwapChainImageTuple swapChainImage; + VkResult result = vkQueuePresentKHR(device_owner.get_present_queue(), &present_info); - swapChainImage.image = device.create_image(image); - swapChainImage.view = device.create_image_view(*swapChainImage.image, imageFormat); + current_frame = (current_frame + 1) % image_count; - out.push_back(swapChainImage); + if(result != VK_SUCCESS) { + LOG_ERROR("Failed to acquire submit command buffers"); + // throw std::runtime_error("failed to acquire submit command buffers !"); Todo } - return out; + return { result }; } - void VulkanSwapChain::create_swap_chain(VulkanDevice& device) { - SwapChainSupportDetails swapChainSupport = device.get_swap_chain_support(); + std::vector> VulkanSwapChain::create_swap_chain_images(VkFormat image_format) { + uint32_t image_count; - surfaceFormat = choose_swap_surface_format(swapChainSupport.formats); - presentMode = choose_swap_present_mode(swapChainSupport.presentModes); + vkGetSwapchainImagesKHR(device_owner.get_vk_device(), swap_chain, &image_count, nullptr); + auto images = std::vector {}; + images.resize(image_count); - // Todo image count should be configurable - imageCount = swapChainSupport.capabilities.minImageCount + 1; - if (swapChainSupport.capabilities.maxImageCount > 0 && imageCount > swapChainSupport.capabilities.maxImageCount) { - imageCount = swapChainSupport.capabilities.maxImageCount; - } + auto out = std::vector> {}; + out.reserve(image_count); - std::cout << "Chosen swap chain image count " << imageCount << "\n"; + vkGetSwapchainImagesKHR(device_owner.get_vk_device(), swap_chain, &image_count, images.data()); - VkSwapchainCreateInfoKHR createInfo = {}; - createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; - createInfo.surface = device.surface(); + for(auto& vk_image : images) + out.push_back(std::make_unique(device_owner, vk_image, image_format)); - createInfo.minImageCount = imageCount; - createInfo.imageFormat = surfaceFormat.format; - createInfo.imageColorSpace = surfaceFormat.colorSpace; - createInfo.imageExtent = extent; - createInfo.imageArrayLayers = 1; - createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + return out; + } + + void VulkanSwapChain::create_swap_chain() { + auto swap_chain_support = device_owner.get_swap_chain_support(); - QueueFamilyIndices indices = device.find_physical_queue_families(); - uint32_t queueFamilyIndices[] = {indices.graphicsFamily, indices.presentFamily}; + surface_format = choose_swap_surface_format(swap_chain_support.formats); + present_mode = choose_swap_present_mode(swap_chain_support.present_modes); - if (indices.graphicsFamily != indices.presentFamily) { - createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT; - createInfo.queueFamilyIndexCount = 2; - createInfo.pQueueFamilyIndices = queueFamilyIndices; + // Todo image count should be configurable + image_count = swap_chain_support.capabilities.minImageCount + 1; + if (swap_chain_support.capabilities.maxImageCount > 0 && image_count > swap_chain_support.capabilities.maxImageCount) + image_count = swap_chain_support.capabilities.maxImageCount; + + LOG_INFORMATION("Chosen swap chain image count {}", image_count); + + VkSwapchainCreateInfoKHR create_info = {}; + create_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; + create_info.surface = device_owner.get_surface(); + create_info.minImageCount = image_count; + create_info.imageFormat = surface_format.format; + create_info.imageColorSpace = surface_format.colorSpace; + create_info.imageExtent = extent; + create_info.imageArrayLayers = 1; + create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + + VulkanQueueFamilyIndices indices = device_owner.find_physical_queue_families(); + uint32_t queue_family_indices[] = {indices.graphics_family, indices.present_family}; + + if (indices.graphics_family != indices.present_family) { + create_info.imageSharingMode = VK_SHARING_MODE_CONCURRENT; + create_info.queueFamilyIndexCount = 2; + create_info.pQueueFamilyIndices = queue_family_indices; } else { - createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; - createInfo.queueFamilyIndexCount = 0; // Optional - createInfo.pQueueFamilyIndices = nullptr; // Optional + create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; + create_info.queueFamilyIndexCount = 0; // Optional + create_info.pQueueFamilyIndices = nullptr; // Optional } - createInfo.preTransform = swapChainSupport.capabilities.currentTransform; - createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; - - createInfo.presentMode = presentMode; - createInfo.clipped = VK_TRUE; + create_info.preTransform = swap_chain_support.capabilities.currentTransform; + create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; + create_info.presentMode = present_mode; + create_info.clipped = VK_TRUE; + create_info.oldSwapchain = VK_NULL_HANDLE; - createInfo.oldSwapchain = VK_NULL_HANDLE; - - if (vkCreateSwapchainKHR(device.device(), &createInfo, nullptr, &backend) != VK_SUCCESS) { - throw std::runtime_error("failed to create swap chain!"); + if(vkCreateSwapchainKHR(device_owner.get_vk_device(), &create_info, nullptr, &swap_chain) != VK_SUCCESS) { + LOG_ERROR("Failed to create swap chain"); + // throw std::runtime_error("failed to create swap chain!"); Todo } } - void VulkanSwapChain::create_sync_objects(VulkanDevice& device) { - imageAvailableSemaphores.resize(imageCount); - renderFinishedSemaphores.resize(imageCount); - inFlightFences.resize(imageCount); - imagesInFlight.resize(renderTarget->swapChainImages.size(), VK_NULL_HANDLE); + void VulkanSwapChain::create_sync_objects() { + image_available_semaphores.resize(image_count); + render_finished_semaphores.resize(image_count); + in_flight_fences.resize(image_count); + images_in_flight.resize(image_count, VK_NULL_HANDLE); - VkSemaphoreCreateInfo semaphoreInfo = {}; - semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; + VkSemaphoreCreateInfo semaphore_info = {}; + semaphore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; - VkFenceCreateInfo fenceInfo = {}; - fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT; + VkFenceCreateInfo fence_info = {}; + fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + fence_info.flags = VK_FENCE_CREATE_SIGNALED_BIT; - for (size_t i = 0; i < imageCount; i++) { - if(vkCreateSemaphore(device.device(), &semaphoreInfo, nullptr, &imageAvailableSemaphores[i]) != VK_SUCCESS) { - throw std::runtime_error("failed to create synchronization objects for a frame!"); + for (size_t i = 0; i < image_count; i++) { + if(vkCreateSemaphore(device_owner.get_vk_device(), &semaphore_info, nullptr, &image_available_semaphores[i]) != VK_SUCCESS) { + LOG_ERROR("Failed to create synchronization objects for a frame"); + // throw std::runtime_error("failed to create synchronization objects for a frame!"); Todo } - if(vkCreateSemaphore(device.device(), &semaphoreInfo, nullptr, &renderFinishedSemaphores[i]) != VK_SUCCESS) { - throw std::runtime_error("failed to create synchronization objects for a frame!"); + if(vkCreateSemaphore(device_owner.get_vk_device(), &semaphore_info, nullptr, &render_finished_semaphores[i]) != VK_SUCCESS) { + LOG_ERROR("Failed to create synchronization objects for a frame"); + // throw std::runtime_error("failed to create synchronization objects for a frame!"); Todo } - if (vkCreateFence(device.device(), &fenceInfo, nullptr, &inFlightFences[i]) != VK_SUCCESS) { - throw std::runtime_error("failed to create synchronization objects for a frame!"); + if (vkCreateFence(device_owner.get_vk_device(), &fence_info, nullptr, &in_flight_fences[i]) != VK_SUCCESS) { + LOG_ERROR("Failed to create synchronization objects for a frame"); + // throw std::runtime_error("failed to create synchronization objects for a frame!"); Todo } } } - VkSurfaceFormatKHR VulkanSwapChain::choose_swap_surface_format(const std::vector &availableFormats) { - for (const auto &availableFormat : availableFormats) { - if (availableFormat.format == VK_FORMAT_B8G8R8A8_UNORM && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) { - return availableFormat; - } - } + VkSurfaceFormatKHR VulkanSwapChain::choose_swap_surface_format(const std::vector &available_formats) { + for (const auto &available_format : available_formats) + if (available_format.format == VK_FORMAT_B8G8R8A8_UNORM && available_format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) + return available_format; - return availableFormats[0]; + return available_formats[0]; } - VkPresentModeKHR VulkanSwapChain::choose_swap_present_mode(const std::vector &availablePresentModes) { - for (const auto &availablePresentMode : availablePresentModes) { - if (availablePresentMode == VK_PRESENT_MODE_MAILBOX_KHR) { - std::cout << "Present mode: Mailbox" << std::endl; - return availablePresentMode; + VkPresentModeKHR VulkanSwapChain::choose_swap_present_mode(const std::vector &available_present_modes) { + for (const auto &available_present_mode : available_present_modes) { + if (available_present_mode == VK_PRESENT_MODE_MAILBOX_KHR) { + LOG_INFORMATION("Present mode: Mailbox"); + return available_present_mode; } } - std::cout << "Present mode: V-Sync" << std::endl; + LOG_INFORMATION("Present mode: V-Sync"); return VK_PRESENT_MODE_FIFO_KHR; } - VkExtent2D VulkanSwapChain::choose_swap_extent(const VkSurfaceCapabilitiesKHR &capabilities, VkExtent2D _windowExtent) { + VkExtent2D VulkanSwapChain::choose_swap_extent(const VkSurfaceCapabilitiesKHR &capabilities, VkExtent2D window_extent) { if (capabilities.currentExtent.width != std::numeric_limits::max()) { return capabilities.currentExtent; } else { - VkExtent2D actualExtent = _windowExtent; + VkExtent2D actual_extent = window_extent; - actualExtent.width = std::max( + actual_extent.width = std::max( capabilities.minImageExtent.width, - std::min(capabilities.maxImageExtent.width, actualExtent.width)); - actualExtent.height = std::max( + std::min(capabilities.maxImageExtent.width, actual_extent.width)); // Todo + actual_extent.height = std::max( capabilities.minImageExtent.height, - std::min(capabilities.maxImageExtent.height, actualExtent.height)); + std::min(capabilities.maxImageExtent.height, actual_extent.height)); // Todo - return actualExtent; + return actual_extent; } } - - void VulkanSwapChain::destroy(VulkanDevice& device) { - renderTarget->destroy(device); - - // Todo move this somewhere else - for (size_t i = 0; i < imageCount; i++) { - vkDestroySemaphore(device.device(), renderFinishedSemaphores[i], nullptr); - vkDestroySemaphore(device.device(), imageAvailableSemaphores[i], nullptr); - vkDestroyFence(device.device(), inFlightFences[i], nullptr); - } - - vkDestroySwapchainKHR(device.device(), backend, nullptr); - } } diff --git a/src/bebone/gfx/vulkan/vulkan_swap_chain.h b/src/bebone/gfx/vulkan/vulkan_swap_chain.h index 0b024a67..2549b009 100644 --- a/src/bebone/gfx/vulkan/vulkan_swap_chain.h +++ b/src/bebone/gfx/vulkan/vulkan_swap_chain.h @@ -1,5 +1,5 @@ -#ifndef _BEBONE_GFX_VULKAN_VULKAN_SWAP_CHAIN_H_ -#define _BEBONE_GFX_VULKAN_VULKAN_SWAP_CHAIN_H_ +#ifndef _BEBONE_GFX_VULKAN_SWAP_CHAIN_H_ +#define _BEBONE_GFX_VULKAN_SWAP_CHAIN_H_ #include #include @@ -12,48 +12,61 @@ #include #include -#include "vulkan_device.h" +#include "../window/window.h" + #include "vulkan_render_target.h" -#include "vulkan_wrapper.tpp" -namespace bebone::gfx::vulkan { +namespace bebone::gfx { class VulkanResult; class VulkanCommandBuffer; - struct VulkanSwapChainImageTuple; - - class VulkanSwapChain : public VulkanWrapper, private core::NonCopyable { - public: - void create_swap_chain(VulkanDevice& device); - void create_sync_objects(VulkanDevice& device); + class VulkanSwapChain : private core::NonCopyable { + private: + VkSwapchainKHR swap_chain; - static VkSurfaceFormatKHR choose_swap_surface_format(const std::vector &availableFormats); - static VkPresentModeKHR choose_swap_present_mode(const std::vector &availablePresentModes); - static VkExtent2D choose_swap_extent(const VkSurfaceCapabilitiesKHR &capabilities, VkExtent2D windowExtent); + private: + IVulkanDevice& device_owner; + protected: VkExtent2D extent; - VkSurfaceFormatKHR surfaceFormat; - VkPresentModeKHR presentMode; + VkSurfaceFormatKHR surface_format; + VkPresentModeKHR present_mode; + + size_t current_frame = 0; + u32 image_count; // Todo this should be removed + + std::vector image_available_semaphores; + std::vector render_finished_semaphores; + std::vector in_flight_fences; + std::vector images_in_flight; + + static VkSurfaceFormatKHR choose_swap_surface_format(const std::vector &available_formats); + static VkPresentModeKHR choose_swap_present_mode(const std::vector &available_present_modes); + static VkExtent2D choose_swap_extent(const VkSurfaceCapabilitiesKHR &capabilities, VkExtent2D window_extent); - u32 imageCount; + void create_swap_chain(); + void create_sync_objects(); - std::vector imageAvailableSemaphores; - std::vector renderFinishedSemaphores; - std::vector inFlightFences; - std::vector imagesInFlight; + std::vector> create_swap_chain_images(VkFormat image_format); - std::unique_ptr renderTarget; + public: + VulkanSwapChain(IVulkanDevice& device, VkExtent2D window_extent); + VulkanSwapChain(IVulkanDevice& device, std::unique_ptr &window); - VulkanSwapChain(VulkanDevice &device, VkExtent2D windowExtent); + ~VulkanSwapChain(); - std::vector create_swap_chain_images(VulkanDevice& device, VkFormat imageFormat); + [[nodiscard]] const size_t& get_current_frame() const; + [[nodiscard]] const VkExtent2D& get_extent() const; - VulkanResult acquire_next_image(std::shared_ptr& device, uint32_t *imageIndex); - VulkanResult submit_command_buffers(std::shared_ptr& device, std::shared_ptr& commandBuffer, uint32_t *imageIndex); + std::unique_ptr render_pass; + std::unique_ptr render_target; - size_t currentFrame = 0; + VulkanResult acquire_next_image( + uint32_t *image_index); - void destroy(VulkanDevice& device) override; + VulkanResult submit_present_command_buffers( + VulkanCommandBuffer& command_buffer, + uint32_t *image_index); }; } diff --git a/src/bebone/gfx/vulkan/vulkan_swap_chain_image.cpp b/src/bebone/gfx/vulkan/vulkan_swap_chain_image.cpp new file mode 100644 index 00000000..9e983cac --- /dev/null +++ b/src/bebone/gfx/vulkan/vulkan_swap_chain_image.cpp @@ -0,0 +1,42 @@ +#include "vulkan_swap_chain_image.h" + +#include "vulkan_image.h" +#include "vulkan_image_view.h" +#include "vulkan_sampler.h" + +namespace bebone::gfx { + VulkanSwapChainImage::VulkanSwapChainImage( + IVulkanDevice& device, + VkImage vk_image, + VkFormat image_format + ) : device_owner(device), image(vk_image) { + VulkanImageViewInfo image_view_info{}; + view = std::make_unique(device, image, image_format, image_view_info); + } + + VulkanSwapChainImage::~VulkanSwapChainImage() { + LOG_DEBUG("Deleting vulkan swap chain image"); + view.reset(); + } + + VkImage VulkanSwapChainImage::get_vk_image() const { + return image; + } + + VkMemoryRequirements VulkanSwapChainImage::get_memory_requirements() const { + VkMemoryRequirements requirements; + + vkGetImageMemoryRequirements(device_owner.get_vk_device(), image, &requirements); + + return requirements; + } + + VkExtent3D VulkanSwapChainImage::get_extent() const { + LOG_CRITICAL("IVulkanImage::get_extent() is not implemented for VulkanSwapChainImage class"); + return VkExtent3D { 0u, 0u, 0u }; + } + + VkImageView VulkanSwapChainImage::get_vk_image_view() const { + return view->get_vk_image_view(); + } +} diff --git a/src/bebone/gfx/vulkan/vulkan_swap_chain_image.h b/src/bebone/gfx/vulkan/vulkan_swap_chain_image.h new file mode 100644 index 00000000..cfce00a0 --- /dev/null +++ b/src/bebone/gfx/vulkan/vulkan_swap_chain_image.h @@ -0,0 +1,40 @@ +#ifndef _BEBONE_GFX_VULKAN_SWAP_CHAIN_IMAGE_H_ +#define _BEBONE_GFX_VULKAN_SWAP_CHAIN_IMAGE_H_ + +#include + +#include "../gfx_backend.h" + +#include "vulkan_image.h" +#include "vulkan_sampler.h" +#include "vulkan_image_view.h" + +#include "interface/i_vulkan_image.h" +#include "interface/i_vulkan_image_view.h" +#include "interface/i_vulkan_sampler.h" + +namespace bebone::gfx { + using namespace bebone::core; + + struct VulkanSwapChainImage : public IVulkanImage, public IVulkanImageView { + private: + IVulkanDevice& device_owner; + + VkImage image; + std::unique_ptr view; + + public: + VulkanSwapChainImage(IVulkanDevice& device, VkImage vk_image, VkFormat image_format); + ~VulkanSwapChainImage() override; + + // Vulkan Image + [[nodiscard]] VkImage get_vk_image() const override; + [[nodiscard]] VkMemoryRequirements get_memory_requirements() const override; + [[nodiscard]] VkExtent3D get_extent() const override; + + // Vulkan Image View + [[nodiscard]] VkImageView get_vk_image_view() const override; + }; +} + +#endif diff --git a/src/bebone/gfx/vulkan/vulkan_texture.cpp b/src/bebone/gfx/vulkan/vulkan_texture.cpp new file mode 100644 index 00000000..c1f1cc05 --- /dev/null +++ b/src/bebone/gfx/vulkan/vulkan_texture.cpp @@ -0,0 +1,78 @@ +#include "vulkan_texture.h" + +#include "vulkan_command_buffer_pool.h" +#include "vulkan_buffer_memory.h" + +#include "vulkan_image.h" + +namespace bebone::gfx { + using namespace bebone::core; + using namespace bebone::assets; + + VulkanTexture::VulkanTexture( + IVulkanDevice& device, + const std::shared_ptr>& raw + ) { + VkExtent3D extent = { static_cast(raw->get_width()), static_cast(raw->get_height()), 1}; + + VulkanImageInfo image_info{}; + image_info.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; + image = std::make_unique(device, get_vulkan_format(), extent, image_info); + + auto req = image->get_memory_requirements(); + memory = std::make_unique(device, req, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + memory->bind_image_memory(*image); + + image->transition_layout(VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + + // Upload data + auto size = raw->get_width() * raw->get_height() * sizeof(ColorRGBA); + VulkanBufferMemory staged_buffer(device, size); + staged_buffer.upload_data(raw->data(), size); + staged_buffer.copy_to_image(*image); + + image->transition_layout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + + sampler = std::make_unique(device); + view = std::make_unique(device, *image, get_vulkan_format()); + } + + VulkanTexture::VulkanTexture( + IVulkanDevice& device, + VkExtent3D extent, + VkFormat image_format + ) { + VulkanImageInfo image_info{}; + image_info.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; + image = std::make_unique(device, get_vulkan_format(), extent, image_info); + + auto req = image->get_memory_requirements(); + memory = std::make_unique(device, req, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + memory->bind_image_memory(*image); + + sampler = std::make_unique(device); + view = std::make_unique(device, *image, image_format); + } + + VulkanTexture::~VulkanTexture() = default; + + VkMemoryRequirements VulkanTexture::get_memory_requirements() const { + return image->get_memory_requirements(); + } + + VkImage VulkanTexture::get_vk_image() const { + return image->get_vk_image(); + } + + VkExtent3D VulkanTexture::get_extent() const { + return image->get_extent(); + } + + VkImageView VulkanTexture::get_vk_image_view() const { + return view->get_vk_image_view(); + } + + VkSampler VulkanTexture::get_vk_image_sampler() const { + return sampler->get_vk_image_sampler(); + } +} diff --git a/src/bebone/gfx/vulkan/vulkan_texture.h b/src/bebone/gfx/vulkan/vulkan_texture.h new file mode 100644 index 00000000..0362513d --- /dev/null +++ b/src/bebone/gfx/vulkan/vulkan_texture.h @@ -0,0 +1,47 @@ +#ifndef _BEBONE_GFX_VULKAN_TEXTURE_TUPLE_H_ +#define _BEBONE_GFX_VULKAN_TEXTURE_TUPLE_H_ + +#include + +#include "../gfx_backend.h" +#include "../color_extensions.h" + +#include "../../assets/image/image.h" + +#include "vulkan_image.h" +#include "vulkan_sampler.h" +#include "vulkan_image_view.h" + +#include "interface/i_vulkan_image.h" +#include "interface/i_vulkan_image_view.h" +#include "interface/i_vulkan_sampler.h" + +namespace bebone::gfx { + using namespace bebone::core; + + class VulkanTexture : public IVulkanImage, public IVulkanImageView, public IVulkanSampler, private core::NonCopyable { + private: + std::unique_ptr image; + std::unique_ptr memory; + std::unique_ptr view; + std::unique_ptr sampler; + + public: + VulkanTexture(IVulkanDevice& device, const std::shared_ptr>& raw); + VulkanTexture(IVulkanDevice& device, VkExtent3D extent, VkFormat image_format); + ~VulkanTexture() override; + + // Vulkan Image + [[nodiscard]] VkImage get_vk_image() const override; + [[nodiscard]] VkMemoryRequirements get_memory_requirements() const override; + [[nodiscard]] VkExtent3D get_extent() const override; + + // Vulkan Image View + [[nodiscard]] VkImageView get_vk_image_view() const override; + + // Vulkan Sampler + [[nodiscard]] VkSampler get_vk_image_sampler() const override; + }; +} + +#endif diff --git a/src/bebone/gfx/vulkan/vulkan_wrapper.tpp b/src/bebone/gfx/vulkan/vulkan_wrapper.tpp deleted file mode 100644 index d1ba0b9f..00000000 --- a/src/bebone/gfx/vulkan/vulkan_wrapper.tpp +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef _BEBONE_GFX_VULKAN_VULKAN_WRAPPER_TPP_ -#define _BEBONE_GFX_VULKAN_VULKAN_WRAPPER_TPP_ - -namespace bebone::gfx::vulkan { - class VulkanDevice; - - template - class VulkanWrapper { - public: - T backend; - - virtual ~VulkanWrapper() = default; - - virtual void destroy(VulkanDevice& device) = 0; - }; -} - -#endif diff --git a/src/bebone/gfx/window/events/input_event.h b/src/bebone/gfx/window/events/input_event.h index dadeb127..0fa2eb2e 100644 --- a/src/bebone/gfx/window/events/input_event.h +++ b/src/bebone/gfx/window/events/input_event.h @@ -1,19 +1,20 @@ #ifndef _INPUT_EVENT_H_ #define _INPUT_EVENT_H_ -#include "../../../core/events/listeners/event.tpp" +#include "../../../core/core.h" namespace bebone::gfx { using namespace bebone::core; /// Input events enumeration enum InputEvent { - KEY, - MOUSE_BUTTON + Key, + MouseButton, + MouseScroll }; /// Key event structure - struct InputKeyEvent : public Event { + struct InputKeyEvent : public Event { i32 key; i32 scancode; i32 action; @@ -30,7 +31,7 @@ namespace bebone::gfx { }; /// Mouse button press event structure - struct InputMouseButtonEvent : public Event { + struct InputMouseButtonEvent : public Event { i32 button; i32 action; i32 mods; @@ -43,6 +44,20 @@ namespace bebone::gfx { */ InputMouseButtonEvent(const i32& button, const i32& action, const i32& mods) : button(button), action(action), mods(mods) { } }; + + /// Mouse button press event structure + struct InputMouseScrollEvent : public Event { + f32 xscroll; + f32 yscroll; + + /*! + * Default constructor + * @param button - mouse button key code + * @param action - event action + * @param mods - mouse button mod + */ + InputMouseScrollEvent(const f32& xscroll, const f32& yscroll) : xscroll(xscroll), yscroll(yscroll) { } + }; } #endif diff --git a/src/bebone/gfx/window/events/key_listener.cpp b/src/bebone/gfx/window/events/key_listener.cpp new file mode 100644 index 00000000..a82731a1 --- /dev/null +++ b/src/bebone/gfx/window/events/key_listener.cpp @@ -0,0 +1,11 @@ +#include "key_listener.h" + +namespace bebone::gfx { + KeyListener::KeyListener(std::shared_ptr& input_executor) : input_executor(input_executor) {} + + void KeyListener::operator()(gfx::InputKeyEvent &event) { + const auto key_code = static_cast(event.key); + const auto input_type = static_cast(event.action); + input_executor->queue_key(key_code, input_type); + } +} \ No newline at end of file diff --git a/src/bebone/gfx/window/events/key_listener.h b/src/bebone/gfx/window/events/key_listener.h new file mode 100644 index 00000000..019b9747 --- /dev/null +++ b/src/bebone/gfx/window/events/key_listener.h @@ -0,0 +1,22 @@ +#ifndef _KEY_LISTENER_H_ +#define _KEY_LISTENER_H_ + +#include "../../../core/core.h" +#include "input_event.h" + +namespace bebone::gfx { + using namespace core; + + class KeyListener : EventListener { + private: + std::shared_ptr& input_executor; + + public: + KeyListener() = delete; + explicit KeyListener(std::shared_ptr& input_executor); + + void operator()(InputKeyEvent& event) override; + }; +} + +#endif diff --git a/src/bebone/gfx/window/events/mouse_listener.cpp b/src/bebone/gfx/window/events/mouse_listener.cpp new file mode 100644 index 00000000..23f0c1a5 --- /dev/null +++ b/src/bebone/gfx/window/events/mouse_listener.cpp @@ -0,0 +1,11 @@ +#include "mouse_listener.h" + +namespace bebone::gfx { + MouseListener::MouseListener(std::shared_ptr& input_executor) : input_executor(input_executor) { } + + void MouseListener::operator()(InputMouseButtonEvent &event) { + const auto key_code = static_cast(event.button); + const auto input_type = static_cast(event.action); + input_executor->queue_key(key_code, input_type); + } +} \ No newline at end of file diff --git a/src/bebone/gfx/window/events/mouse_listener.h b/src/bebone/gfx/window/events/mouse_listener.h new file mode 100644 index 00000000..b8b9ec13 --- /dev/null +++ b/src/bebone/gfx/window/events/mouse_listener.h @@ -0,0 +1,22 @@ +#ifndef _MOUSE_LISTENER_H_ +#define _MOUSE_LISTENER_H_ + +#include "../../../core/core.h" +#include "input_event.h" + +namespace bebone::gfx { + using namespace core; + + class MouseListener : EventListener { + private: + std::shared_ptr& input_executor; + + public: + MouseListener() = delete; + explicit MouseListener(std::shared_ptr& input_executor); + + void operator()(InputMouseButtonEvent& event) override; + }; +} + +#endif diff --git a/src/bebone/gfx/window/events/window_event.h b/src/bebone/gfx/window/events/window_event.h index f18f6ccc..1810c6c1 100644 --- a/src/bebone/gfx/window/events/window_event.h +++ b/src/bebone/gfx/window/events/window_event.h @@ -1,39 +1,40 @@ #ifndef BEBONE_WINDOW_EVENT_H #define BEBONE_WINDOW_EVENT_H -#include "../../../core/events/listeners/event.tpp" +#include "../../../core/core.h" namespace bebone::gfx { using namespace bebone::core; /// Window events enumeration enum WindowEvent { - WINDOW_POS, - WINDOW_SIZE, - WINDOW_CLOSE, - WINDOW_REFRESH, - WINDOW_FOCUS, - WINDOW_ICONIFY, - WINDOW_MAXIMIZE, - FRAMEBUFFERS_SIZE, - WINDOW_CONTENT_SCALE + WindowPos, + WindowSize, + WindowClose, + WindowRefresh, + WindowFocus, + WindowIconify, + WindowMaximize, + FramebuffersSize, + WindowContentScale, + WindowPullEvents }; /// Window position change event structure - struct WindowPosEvent : public Event { - i32 xPos; - i32 yPos; + struct WindowPosEvent : public Event { + i32 x_pos; + i32 y_pos; /*! * Default constructor - * @param xPos - new window x position - * @param yPos - new window y position + * @param x_pos - new window x position + * @param y_pos - new window y position */ - WindowPosEvent(const i32& xPos, const i32& yPos) : xPos(xPos), yPos(yPos) {} + WindowPosEvent(const i32& x_pos, const i32& y_pos) : x_pos(x_pos), y_pos(y_pos) {} }; /// Window size change event structure - struct WindowSizeEvent : public Event { + struct WindowSizeEvent : public Event { i32 width; i32 height; @@ -46,17 +47,17 @@ namespace bebone::gfx { }; /// Window close event structure - struct WindowCloseEvent : public Event { + struct WindowCloseEvent : public Event { }; /// Window refresh event structure - struct WindowRefreshEvent : public Event { + struct WindowRefreshEvent : public Event { }; /// Window focus event structure - struct WindowFocusEvent : public Event { + struct WindowFocusEvent : public Event { i32 focused; /*! @@ -67,7 +68,7 @@ namespace bebone::gfx { }; /// Window iconify event structure - struct WindowIconifyEvent : public Event { + struct WindowIconifyEvent : public Event { i32 iconified; /*! @@ -78,7 +79,7 @@ namespace bebone::gfx { }; /// Window maximize event structure - struct WindowMaximizeEvent : public Event { + struct WindowMaximizeEvent : public Event { i32 maximized; /*! @@ -89,7 +90,7 @@ namespace bebone::gfx { }; /// Window framebuffer size change event structure - struct FrameBufferSizeEvent : public Event { + struct FrameBufferSizeEvent : public Event { i32 width; i32 height; @@ -102,16 +103,21 @@ namespace bebone::gfx { }; /// Window content scale change event structure - struct WindowContentScaleEvent : public Event { - f32 xScale; - f32 yScale; + struct WindowContentScaleEvent : public Event { + f32 x_scale; + f32 y_scale; /*! * Default constructor - * @param xScale - new window x content scale - * @param yScale - new window y content scale + * @param x_scale - new window x content scale + * @param y_scale - new window y content scale */ - WindowContentScaleEvent(const f32& xScale, const f32& yScale) : xScale(xScale), yScale(yScale) {} + WindowContentScaleEvent(const f32& x_scale, const f32& y_scale) : x_scale(x_scale), y_scale(y_scale) {} + }; + + /// Window content scale change event structure + struct WindowPullEventsEvent : public Event { + WindowPullEventsEvent() {} }; } diff --git a/src/bebone/gfx/window/opengl_window.cpp b/src/bebone/gfx/window/opengl_window.cpp index d4459081..67f87a08 100644 --- a/src/bebone/gfx/window/opengl_window.cpp +++ b/src/bebone/gfx/window/opengl_window.cpp @@ -3,5 +3,11 @@ namespace bebone::gfx { GLWindow::GLWindow(const std::string& title, const int& width, const int& height, const WindowProperties& properties) : Window(title, width, height, properties) { glfwMakeContextCurrent(get_backend()); + + LOG_TRACE("Initialized OpenGL window"); + } + + GfxAPI GLWindow::get_api() const { + return GfxAPI::OpenGL; } } diff --git a/src/bebone/gfx/window/opengl_window.h b/src/bebone/gfx/window/opengl_window.h index 2b499fc8..aac2e80f 100644 --- a/src/bebone/gfx/window/opengl_window.h +++ b/src/bebone/gfx/window/opengl_window.h @@ -14,6 +14,8 @@ namespace bebone::gfx { * @param height - desired window height */ GLWindow(const std::string& title, const int& width, const int& height, const WindowProperties& properties = {}); + + [[nodiscard]] GfxAPI get_api() const override; }; } diff --git a/src/bebone/gfx/window/vulkan_window.cpp b/src/bebone/gfx/window/vulkan_window.cpp index 0e7ac6ea..862facbd 100644 --- a/src/bebone/gfx/window/vulkan_window.cpp +++ b/src/bebone/gfx/window/vulkan_window.cpp @@ -2,12 +2,17 @@ namespace bebone::gfx { VulkanWindow::VulkanWindow(const std::string& title, const int& width, const int& height, const WindowProperties& properties) : Window(title, width, height, properties) { - + LOG_TRACE("Initialized Vulkan window"); } void VulkanWindow::create_window_surface(VkInstance instance, VkSurfaceKHR *surface) { if (glfwCreateWindowSurface(instance, get_backend(), nullptr, surface) != VK_SUCCESS) { + LOG_ERROR("Failed to create window surface"); throw std::runtime_error("failed to create window surface"); } } + + GfxAPI VulkanWindow::get_api() const { + return GfxAPI::Vulkan; + } } diff --git a/src/bebone/gfx/window/vulkan_window.h b/src/bebone/gfx/window/vulkan_window.h index 8d2f56c8..2a77b1a8 100644 --- a/src/bebone/gfx/window/vulkan_window.h +++ b/src/bebone/gfx/window/vulkan_window.h @@ -21,6 +21,8 @@ namespace bebone::gfx { * @param surface - pointer to vulkan surface */ void create_window_surface(VkInstance instance, VkSurfaceKHR *surface); + + [[nodiscard]] GfxAPI get_api() const override; }; } diff --git a/src/bebone/gfx/window/window.cpp b/src/bebone/gfx/window/window.cpp index 37ae7cb9..6a845376 100644 --- a/src/bebone/gfx/window/window.cpp +++ b/src/bebone/gfx/window/window.cpp @@ -2,11 +2,11 @@ namespace bebone::gfx { Window::Window(const std::string& title, const int& width, const int& height, const WindowProperties& properties) - : windowHandler(this), + : window_handler(this), width(width), height(height) { - if(properties.enableResize) + if(properties.enable_resize) glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); else glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); @@ -29,69 +29,78 @@ namespace bebone::gfx { // Mouse callbacks glfwSetMouseButtonCallback(window, glfw_mouse_button_callback); glfwSetKeyCallback(window, glfw_key_callback); + glfwSetScrollCallback(window, glfw_mouse_scroll_callback); - add_listener(inputHandler.get_key_listener()); - add_listener(inputHandler.get_mouse_listener()); - - add_listener(windowHandler.get_window_size_listener()); + add_listener(window_handler.get_window_size_listener()); } Window::~Window() { glfwDestroyWindow(window); + GLFWContext::terminate();// this should be moved somewhere else + } + + void Window::pull_events() { + GLFWContext::poll_events(); + fire(WindowPullEventsEvent()); } - void Window::glfw_window_pos_callback(GLFWwindow* glfwWindow, int xPos, int yPos) { - auto* window = reinterpret_cast(glfwGetWindowUserPointer(glfwWindow)); - window->fire(WindowPosEvent(xPos, yPos)); + void Window::glfw_window_pos_callback(GLFWwindow* glfw_window, int x_pos, int y_pos) { + auto* window = reinterpret_cast(glfwGetWindowUserPointer(glfw_window)); + window->fire(WindowPosEvent(x_pos, y_pos)); } - void Window::glfw_window_size_callback(GLFWwindow* glfwWindow, int width, int height) { - auto* window = reinterpret_cast(glfwGetWindowUserPointer(glfwWindow)); + void Window::glfw_window_size_callback(GLFWwindow* glfw_window, int width, int height) { + auto* window = reinterpret_cast(glfwGetWindowUserPointer(glfw_window)); window->fire(WindowSizeEvent(width, height)); } - void Window::glfw_window_close_callback(GLFWwindow* glfwWindow) { - auto* window = reinterpret_cast(glfwGetWindowUserPointer(glfwWindow)); + void Window::glfw_window_close_callback(GLFWwindow* glfw_window) { + auto* window = reinterpret_cast(glfwGetWindowUserPointer(glfw_window)); window->fire(WindowCloseEvent()); } - void Window::glfw_window_refresh_callback(GLFWwindow* glfwWindow) { - auto* window = reinterpret_cast(glfwGetWindowUserPointer(glfwWindow)); + void Window::glfw_window_refresh_callback(GLFWwindow* glfw_window) { + auto* window = reinterpret_cast(glfwGetWindowUserPointer(glfw_window)); window->fire(WindowRefreshEvent()); } - void Window::glfw_window_focus_callback(GLFWwindow* glfwWindow, int focused) { - auto* window = reinterpret_cast(glfwGetWindowUserPointer(glfwWindow)); + void Window::glfw_window_focus_callback(GLFWwindow* glfw_window, int focused) { + auto* window = reinterpret_cast(glfwGetWindowUserPointer(glfw_window)); window->fire(WindowFocusEvent(focused)); } - void Window::glfw_window_iconify_callback(GLFWwindow* glfwWindow, int iconified) { - auto* window = reinterpret_cast(glfwGetWindowUserPointer(glfwWindow)); + void Window::glfw_window_iconify_callback(GLFWwindow* glfw_window, int iconified) { + auto* window = reinterpret_cast(glfwGetWindowUserPointer(glfw_window)); window->fire(WindowIconifyEvent(iconified)); } - void Window::glfw_window_maximize_callback(GLFWwindow* glfwWindow, int maximized) { - auto* window = reinterpret_cast(glfwGetWindowUserPointer(glfwWindow)); + void Window::glfw_window_maximize_callback(GLFWwindow* glfw_window, int maximized) { + auto* window = reinterpret_cast(glfwGetWindowUserPointer(glfw_window)); window->fire(WindowMaximizeEvent(maximized)); } - void Window::glfw_framebuffer_size_callback(GLFWwindow* glfwWindow, int width, int height) { - auto* window = reinterpret_cast(glfwGetWindowUserPointer(glfwWindow)); + void Window::glfw_framebuffer_size_callback(GLFWwindow* glfw_window, int width, int height) { + auto* window = reinterpret_cast(glfwGetWindowUserPointer(glfw_window)); window->fire(FrameBufferSizeEvent(width, height)); } - void Window::glfw_window_content_scale_callback(GLFWwindow* glfwWindow, float xscale, float yscale) { - auto* window = reinterpret_cast(glfwGetWindowUserPointer(glfwWindow)); - window->fire(WindowContentScaleEvent(xscale, yscale)); + void Window::glfw_window_content_scale_callback(GLFWwindow* glfw_window, float x_scale, float y_scale) { + auto* window = reinterpret_cast(glfwGetWindowUserPointer(glfw_window)); + window->fire(WindowContentScaleEvent(x_scale, y_scale)); } - void Window::glfw_mouse_button_callback(GLFWwindow* glfwWindow, int button, int action, int mods) { - auto* window = reinterpret_cast(glfwGetWindowUserPointer(glfwWindow)); + void Window::glfw_mouse_button_callback(GLFWwindow* glfw_window, int button, int action, int mods) { + auto* window = reinterpret_cast(glfwGetWindowUserPointer(glfw_window)); window->fire(InputMouseButtonEvent(button, action, mods)); } - void Window::glfw_key_callback(GLFWwindow* glfwWindow, int key, int scancode, int action, int mods) { - auto* window = reinterpret_cast(glfwGetWindowUserPointer(glfwWindow)); + void Window::glfw_mouse_scroll_callback(GLFWwindow* glfw_window, double xoffset, double yoffset) { + auto* window = reinterpret_cast(glfwGetWindowUserPointer(glfw_window)); + window->fire(InputMouseScrollEvent(xoffset, yoffset)); + } + + void Window::glfw_key_callback(GLFWwindow* glfw_window, int key, int scancode, int action, int mods) { + auto* window = reinterpret_cast(glfwGetWindowUserPointer(glfw_window)); window->fire(InputKeyEvent(key, scancode, action, mods)); } @@ -103,6 +112,10 @@ namespace bebone::gfx { return glfwWindowShouldClose(window); } + void Window::set_title(const std::string& title) { + glfwSetWindowTitle(window, title.c_str()); + } + const int& Window::get_width() const { return width; } @@ -111,11 +124,21 @@ namespace bebone::gfx { return height; } + Vec2i Window::get_size() const { + return { width, height }; + } + f32 Window::get_aspect() const { return static_cast(width) / static_cast(height); } - void Window::execute_input_actions() const { - inputHandler.execute_input_actions(); + const Watch& Window::get_watch() const { + return watch; + } + + void Window::end_frame() { + double time_diff = watch.get_time_difference(); + Time::set_delta_time(time_diff); + watch.update_timestamp(); } } diff --git a/src/bebone/gfx/window/window.h b/src/bebone/gfx/window/window.h index 76299cac..5902233c 100644 --- a/src/bebone/gfx/window/window.h +++ b/src/bebone/gfx/window/window.h @@ -5,6 +5,8 @@ #include #include "../gfx_backend.h" +#include "../gfx_api.h" +#include "../glfw_context.h" #include "events/window_event.h" #include "events/input_event.h" @@ -12,6 +14,13 @@ #include "window_properties.h" #include "window_handler.h" +#include "../../core/timestamp/timestamp.h" +#include "../../core/timestamp/watch.h" + +namespace bebone::renderer { + class IRenderer; +} + namespace bebone::gfx { using namespace core; @@ -20,8 +29,9 @@ namespace bebone::gfx { private: GLFWwindow* window; - InputHandler inputHandler; - WindowHandler windowHandler; + WindowHandler window_handler; + + Watch watch; protected: int width; @@ -43,13 +53,15 @@ namespace bebone::gfx { * @param height - window height */ Window(const std::string& title, const int& width, const int& height, const WindowProperties& properties = {}); - ~Window(); + virtual ~Window(); /*! * Function that checks does window want to close * @return - boolean value is window closing */ - bool closing() const; + [[nodiscard]] bool closing() const; + + void set_title(const std::string& title); /// Function that returns window width const int& get_width() const; @@ -57,20 +69,28 @@ namespace bebone::gfx { /// Function that returns window height const int& get_height() const; + Vec2i get_size() const; + /// Function that returns current window aspect ration f32 get_aspect() const; /// Function returns glfw window backend GLFWwindow* get_backend() const; - /// Function that executes all queued input actions - void execute_input_actions() const; + /// Gfx api + virtual GfxAPI get_api() const = 0; + + const Watch& get_watch() const; + + void end_frame(); + + void pull_events(); private: /// GLFW window position change callbacks - static void glfw_window_pos_callback(GLFWwindow* glfwWindow, int xPos, int yPos); + static void glfw_window_pos_callback(GLFWwindow* glfw_window, int x_pos, int y_pos); /// GLFW window size change callbacks - static void glfw_window_size_callback(GLFWwindow* glfwWindow, int width, int height); + static void glfw_window_size_callback(GLFWwindow* glfw_window, int width, int height); /// GLFW window close callback static void glfw_window_close_callback(GLFWwindow* handle); /// GLFW window refresh callback @@ -82,14 +102,16 @@ namespace bebone::gfx { /// GLFW window maximize callback static void glfw_window_maximize_callback(GLFWwindow* handle, int maximized); /// GLFW window framebuffer size callback - static void glfw_framebuffer_size_callback(GLFWwindow* glfwWindow, int width, int height); + static void glfw_framebuffer_size_callback(GLFWwindow* glfw_window, int width, int height); /// GLFW window content scale callback - static void glfw_window_content_scale_callback(GLFWwindow* handle, float xScale, float yScale); + static void glfw_window_content_scale_callback(GLFWwindow* handle, float x_scale, float y_scale); /// GLFW mouse button press callback - static void glfw_mouse_button_callback(GLFWwindow* glfwWindow, int button, int action, int mods); + static void glfw_mouse_button_callback(GLFWwindow* glfw_window, int button, int action, int mods); + /// GLFW mouse scroll delta callback + static void glfw_mouse_scroll_callback(GLFWwindow* glfw_window, double xoffset, double yoffset); /// GLFW key press callback - static void glfw_key_callback(GLFWwindow* glfwWindow, int key, int scancode, int action, int mods); + static void glfw_key_callback(GLFWwindow* glfw_window, int key, int scancode, int action, int mods); }; } diff --git a/src/bebone/gfx/window/window_factory.cpp b/src/bebone/gfx/window/window_factory.cpp index 14f6ba3f..26f4dbaf 100644 --- a/src/bebone/gfx/window/window_factory.cpp +++ b/src/bebone/gfx/window/window_factory.cpp @@ -5,25 +5,29 @@ #include "../glfw_context.h" namespace bebone::gfx { - std::shared_ptr WindowFactory::create_window(const std::string& title, const int& width, const int& height, const GfxAPI& gfxAPI, const WindowProperties& properties) { - std::shared_ptr window; + std::unique_ptr WindowFactory::create_window(const std::string& title, const int& width, const int& height, const GfxAPI& gfx_api, const WindowProperties& properties) { + GLFWContext::init(); // this should be moved somewhere else + LOG_TRACE("Initializing window {} {} with title: '{}'", width, height, title); + + std::unique_ptr window; glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); - if (gfxAPI == GfxAPI::OPENGL) { + if (gfx_api == OpenGL) { glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - window = std::make_shared(title, width, height, properties); + window = std::make_unique(title, width, height, properties); } else { glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); - window = std::make_shared(title, width, height, properties); + window = std::make_unique(title, width, height, properties); } if (window->get_backend() == nullptr) { GLFWContext::terminate(); + LOG_ERROR("Failed to create GLFW window"); throw std::runtime_error("Failed to create GLFW window"); } diff --git a/src/bebone/gfx/window/window_factory.h b/src/bebone/gfx/window/window_factory.h index 609a52ac..67c3779e 100644 --- a/src/bebone/gfx/window/window_factory.h +++ b/src/bebone/gfx/window/window_factory.h @@ -16,11 +16,11 @@ namespace bebone::gfx { * @param title - window name/title * @param width - window width * @param height - window height - * @param gfxAPI - graphics API + * @param gfx_api - graphics API * * @return Window object */ - static std::shared_ptr create_window(const std::string& title, const int& width, const int& height, const GfxAPI& gfxAPI, const WindowProperties& properties = {}); + static std::unique_ptr create_window(const std::string& title, const int& width, const int& height, const GfxAPI& gfx_api, const WindowProperties& properties = {}); }; } diff --git a/src/bebone/gfx/window/window_handler.cpp b/src/bebone/gfx/window/window_handler.cpp index 58c40636..7a5b9fc2 100644 --- a/src/bebone/gfx/window/window_handler.cpp +++ b/src/bebone/gfx/window/window_handler.cpp @@ -2,11 +2,11 @@ #include "window.h" namespace bebone::gfx { - WindowHandler::WindowHandler(Window* window) : windowSizeListener(window) { + WindowHandler::WindowHandler(Window* window) : window_size_listener(window) { } const WindowSizeListener& WindowHandler::get_window_size_listener() const { - return windowSizeListener; + return window_size_listener; } } diff --git a/src/bebone/gfx/window/window_handler.h b/src/bebone/gfx/window/window_handler.h index c21a8c7a..6d8bac5f 100644 --- a/src/bebone/gfx/window/window_handler.h +++ b/src/bebone/gfx/window/window_handler.h @@ -11,7 +11,7 @@ namespace bebone::gfx { class WindowHandler : private core::NonCopyable { private: - WindowSizeListener windowSizeListener; + WindowSizeListener window_size_listener; public: public: diff --git a/src/bebone/gfx/window/window_properties.h b/src/bebone/gfx/window/window_properties.h index b6a2c3d5..3efb3109 100644 --- a/src/bebone/gfx/window/window_properties.h +++ b/src/bebone/gfx/window/window_properties.h @@ -4,7 +4,7 @@ namespace bebone::gfx { // Structured used for configuring window properties struct WindowProperties { - bool enableResize = false; + bool enable_resize = false; // Todo, default name, width and height can be moved there }; diff --git a/src/bebone/renderer/CMakeLists.txt b/src/bebone/renderer/CMakeLists.txt new file mode 100644 index 00000000..c16cd94e --- /dev/null +++ b/src/bebone/renderer/CMakeLists.txt @@ -0,0 +1,32 @@ +file(GLOB_RECURSE BEBONE_RENDERER_SRC_FILES "*.cpp") + +set(BEBONE_RENDERER_INCLUDES "${CMAKE_SOURCE_DIR}/src/bebone/renderer" ) + +list(APPEND BEBONE_RENDERER_INCLUDES + "${PROJECT_SOURCE_DIR}/3dparty/glad/include" + "${PROJECT_SOURCE_DIR}/3dparty/glfw/include" + "${PROJECT_SOURCE_DIR}/3dparty/Vulkan-Headers/include" + "${PROJECT_SOURCE_DIR}/3dparty/stb" + "${PROJECT_SOURCE_DIR}/3dparty/glfw/include" +) + +find_package(vulkan REQUIRED) + +set(BEBONE_RENDERER_LIBRARIES + glfw + stb_image + glad + glslang + SPIRV + glslang-default-resource-limits + ${Vulkan_LIBRARIES} + bebone_core + bebone_assets + bebone_gfx +) + +set(BEBONE_RENDERER_INCLUDES "${BEBONE_RENDERER_INCLUDES}" CACHE INTERNAL "") +include_directories(${BEBONE_RENDERER_INCLUDES}) + +add_library(bebone_renderer STATIC ${BEBONE_RENDERER_SRC_FILES}) +target_link_libraries(bebone_renderer ${BEBONE_RENDERER_LIBRARIES}) diff --git a/src/bebone/renderer/README.md b/src/bebone/renderer/README.md new file mode 100644 index 00000000..820bdbbf --- /dev/null +++ b/src/bebone/renderer/README.md @@ -0,0 +1 @@ +# bebone_renderer module \ No newline at end of file diff --git a/src/bebone/renderer/agnostic/README.md b/src/bebone/renderer/agnostic/README.md new file mode 100644 index 00000000..c3721001 --- /dev/null +++ b/src/bebone/renderer/agnostic/README.md @@ -0,0 +1,14 @@ +# bebone_renderer_agnostic module + +- Context + +- Device +- Swapchain + +- VertexBuffer +- IndexBuffer +- Texture + +- CommandList + +- Pipeline \ No newline at end of file diff --git a/src/bebone/renderer/agnostic/agnostic.h b/src/bebone/renderer/agnostic/agnostic.h new file mode 100644 index 00000000..e6ce7a32 --- /dev/null +++ b/src/bebone/renderer/agnostic/agnostic.h @@ -0,0 +1,6 @@ +#ifndef _BEBONE_RENDERER_AGNOSTIC_H_ +#define _BEBONE_RENDERER_AGNOSTIC_H_ + +#include "interface/i_device.h" + +#endif diff --git a/src/bebone/renderer/agnostic/interface/i_device.h b/src/bebone/renderer/agnostic/interface/i_device.h new file mode 100644 index 00000000..6cbfca64 --- /dev/null +++ b/src/bebone/renderer/agnostic/interface/i_device.h @@ -0,0 +1,14 @@ +#ifndef _BEBONE_RENDERER_AGNOSTIC_I_DEVICE_H_ +#define _BEBONE_RENDERER_AGNOSTIC_I_DEVICE_H_ + +#include "../../../renderer_backend.h" + +namespace bebone::gfx { + using namespace bebone::core; + + class IDevice : private core::NonCopyable { + public: + }; +} + +#endif diff --git a/src/bebone/renderer/agnostic/interface/i_framebuffer.h b/src/bebone/renderer/agnostic/interface/i_framebuffer.h new file mode 100644 index 00000000..e69de29b diff --git a/src/bebone/renderer/agnostic/interface/i_index_buffer.h b/src/bebone/renderer/agnostic/interface/i_index_buffer.h new file mode 100644 index 00000000..e69de29b diff --git a/src/bebone/renderer/agnostic/interface/i_pipeline.h b/src/bebone/renderer/agnostic/interface/i_pipeline.h new file mode 100644 index 00000000..e69de29b diff --git a/src/bebone/renderer/agnostic/interface/i_render_pass.h b/src/bebone/renderer/agnostic/interface/i_render_pass.h new file mode 100644 index 00000000..e69de29b diff --git a/src/bebone/renderer/agnostic/interface/i_shader.h b/src/bebone/renderer/agnostic/interface/i_shader.h new file mode 100644 index 00000000..e69de29b diff --git a/src/bebone/renderer/agnostic/interface/i_swapchain.h b/src/bebone/renderer/agnostic/interface/i_swapchain.h new file mode 100644 index 00000000..e69de29b diff --git a/src/bebone/renderer/agnostic/interface/i_texture.h b/src/bebone/renderer/agnostic/interface/i_texture.h new file mode 100644 index 00000000..e69de29b diff --git a/src/bebone/renderer/agnostic/interface/i_vertex_buffer.h b/src/bebone/renderer/agnostic/interface/i_vertex_buffer.h new file mode 100644 index 00000000..e69de29b diff --git a/src/bebone/renderer/renderer.cpp b/src/bebone/renderer/renderer.cpp new file mode 100644 index 00000000..9aa2e7c3 --- /dev/null +++ b/src/bebone/renderer/renderer.cpp @@ -0,0 +1 @@ +#include "renderer.h" \ No newline at end of file diff --git a/src/bebone/renderer/renderer.h b/src/bebone/renderer/renderer.h new file mode 100644 index 00000000..d39b0a4f --- /dev/null +++ b/src/bebone/renderer/renderer.h @@ -0,0 +1,6 @@ +#ifndef _BEBONE_RENDERER_H_ +#define _BEBONE_RENDERER_H_ + +#include "agnostic/agnostic.h" + +#endif diff --git a/src/bebone/renderer/renderer_backend.h b/src/bebone/renderer/renderer_backend.h new file mode 100644 index 00000000..b3a8626f --- /dev/null +++ b/src/bebone/renderer/renderer_backend.h @@ -0,0 +1,8 @@ +#ifndef _BEBONE_RENDERER_BACKEND_H_ +#define _BEBONE_RENDERER_BACKEND_H_ + +// Todo +#include "../gfx/gfx.h" +#include "../core/core.h" + +#endif diff --git a/src/bebone/sound/CMakeLists.txt b/src/bebone/sound/CMakeLists.txt new file mode 100644 index 00000000..e6a7fad4 --- /dev/null +++ b/src/bebone/sound/CMakeLists.txt @@ -0,0 +1,13 @@ +set(BEBONE_SOUND_INCLUDES + "${PROJECT_SOURCE_DIR}/src/bebone/sound" + "${PROJECT_SOURCE_DIR}/3dparty/miniaudio" +) + +set(BEBONE_SOUND_INCLUDES "${BEBONE_SOUND_INCLUDES}" CACHE INTERNAL "") +include_directories(${BEBONE_SOUND_INCLUDES}) + +file(GLOB_RECURSE BEBONE_SOUND_SRC_FILES "*.cpp") +add_library(bebone_sound STATIC ${BEBONE_SOUND_SRC_FILES}) + +target_link_libraries(bebone_sound miniaudio) +target_link_libraries(bebone_sound bebone_core) diff --git a/src/bebone/sound/README.md b/src/bebone/sound/README.md new file mode 100644 index 00000000..09df85d9 --- /dev/null +++ b/src/bebone/sound/README.md @@ -0,0 +1 @@ +# bebone_sound module \ No newline at end of file diff --git a/src/bebone/sound/sound.cpp b/src/bebone/sound/sound.cpp new file mode 100644 index 00000000..c3ffa326 --- /dev/null +++ b/src/bebone/sound/sound.cpp @@ -0,0 +1,135 @@ +#include "sound.h" + +namespace bebone::sound_system { + Sound::Sound() : loaded_sound(nullptr) { } + Sound::~Sound() { + free(); + } + + void Sound::play() const { + if (loaded_sound == nullptr) { + LOG_WARNING("Trying to play not loaded sound"); + // TODO: throw a warning + return; + } + + ma_sound* raw = get_raw_sound(); + ma_sound_start(raw); + } + + void Sound::stop() const { + if (loaded_sound == nullptr) { + LOG_WARNING("Trying to stop not loaded sound"); + // TODO: throw a warning + return; + } + + ma_sound* raw = get_raw_sound(); + ma_sound_stop(raw); + } + + void Sound::rewind() const { + if (loaded_sound == nullptr) { + LOG_WARNING("Trying to rewind not loaded sound"); + // TODO: throw a warning + return; + } + + ma_sound* raw = get_raw_sound(); + ma_sound_seek_to_pcm_frame(raw, 0); + } + + void Sound::set_volume(const float& volume) const { + if (loaded_sound == nullptr) { + LOG_WARNING("Trying to set volume to not loaded sound"); + // TODO: throw a warning + return; + } + + ma_sound* raw = get_raw_sound(); + ma_sound_set_volume(raw, volume); + } + + void Sound::set_pan(const float& pan) const { + if (loaded_sound == nullptr) { + LOG_WARNING("Trying to set pan to not loaded sound"); + // TODO: throw a warning + return; + } + + ma_sound* raw = get_raw_sound(); + ma_sound_set_pan(raw, pan); + } + + void Sound::set_pitch(const float& pitch) const { + if (loaded_sound == nullptr) { + LOG_WARNING("Trying to set pitch to not loaded sound"); + // TODO: throw a warning + return; + } + + ma_sound* raw = get_raw_sound(); + ma_sound_set_pitch(raw, pitch); + } + + void Sound::set_looping(const bool& loop) const { + if (loaded_sound == nullptr) { + LOG_WARNING("Trying to set looping to not loaded sound"); + + // TODO: throw a warning + return; + } + + ma_sound* raw = get_raw_sound(); + ma_sound_set_looping(raw, loop); + } + + bool Sound::is_playing() const { + if (loaded_sound == nullptr) { + LOG_WARNING("Trying to check is sound playing on not loaded sound"); + // TODO: throw a warning + return false; + } + + ma_sound* raw = get_raw_sound(); + return ma_sound_is_playing(raw); + } + + bool Sound::at_end() const { + if (loaded_sound == nullptr) { + LOG_WARNING("Trying to check is sound ending on not loaded sound"); + // TODO: throw a warning + return false; + } + + ma_sound* raw = get_raw_sound(); + return ma_sound_at_end(raw); + } + + bool Sound::is_looping() const { + if (loaded_sound == nullptr) { + LOG_WARNING("Trying to check is sound looping on not loaded sound"); + // TODO: throw a warning + return false; + } + + ma_sound* raw = get_raw_sound(); + return ma_sound_is_looping(raw); + } + + void Sound::free() { + if (loaded_sound == nullptr) { + LOG_WARNING("Trying to free not loaded sound"); + // TODO: throw a warning + return; + } + + ma_sound* raw = get_raw_sound(); + ma_sound_uninit(raw); + loaded_sound = nullptr; + } + + ma_sound* Sound::get_raw_sound() const { + return loaded_sound.get(); + } +} \ No newline at end of file diff --git a/src/bebone/sound/sound.h b/src/bebone/sound/sound.h new file mode 100644 index 00000000..78fb4699 --- /dev/null +++ b/src/bebone/sound/sound.h @@ -0,0 +1,40 @@ +#ifndef _SOUND_H_ +#define _SOUND_H_ + +#include +#include + +#include "../core/core.h" + +namespace bebone::sound_system { + class SoundEngine; + + class Sound { + private: + std::shared_ptr loaded_sound; + + void free(); + ma_sound* get_raw_sound() const; + + public: + Sound(); + ~Sound(); + + void play() const; + void stop() const; + void rewind() const; + + void set_volume(const float& volume) const; + void set_pan(const float& pan) const; + void set_pitch(const float& pitch) const; + void set_looping(const bool& loop) const; + + bool is_playing() const; + bool at_end() const; + bool is_looping() const; + + friend class SoundEngine; + }; +} + +#endif diff --git a/src/bebone/sound/sound_engine.cpp b/src/bebone/sound/sound_engine.cpp new file mode 100644 index 00000000..0bd997e9 --- /dev/null +++ b/src/bebone/sound/sound_engine.cpp @@ -0,0 +1,28 @@ +#include "sound_engine.h" + +namespace bebone::sound_system { + SoundEngine::SoundEngine() { + ma_result result = ma_engine_init(NULL, &engine); + + if (result != MA_SUCCESS) { + LOG_ERROR("Failed to initialize sound engine"); + // TODO: Throw an exception + } + } + + SoundEngine::~SoundEngine() { + ma_engine_uninit(&engine); + } + + std::shared_ptr SoundEngine::load_sound(const std::string& path, const std::shared_ptr& sound_factory) { + std::shared_ptr sound = std::make_shared(); + sound->loaded_sound = sound_factory->create_sound(engine, path); + + return sound; + } + + void SoundEngine::load_sound(const std::string& path, const std::shared_ptr& sound, const std::shared_ptr& sound_factory) { + sound->free(); + sound->loaded_sound = sound_factory->create_sound(engine, path); + } +} \ No newline at end of file diff --git a/src/bebone/sound/sound_engine.h b/src/bebone/sound/sound_engine.h new file mode 100644 index 00000000..532ee420 --- /dev/null +++ b/src/bebone/sound/sound_engine.h @@ -0,0 +1,27 @@ +#ifndef _SOUND_ENGINE_H_ +#define _SOUND_ENGINE_H_ + +#include +#include +#include +#include "sound.h" +#include "sound_factory.h" + +namespace bebone::sound_system { + class SoundEngine { + private: + ma_engine engine; + + public: + SoundEngine(); + ~SoundEngine(); + + std::shared_ptr load_sound(const std::string& path, + const std::shared_ptr& sound_factory = std::make_shared()); + + void load_sound(const std::string& path, const std::shared_ptr& sound, + const std::shared_ptr& sound_factory = std::make_shared()); + }; +} + +#endif diff --git a/src/bebone/sound/sound_factory.cpp b/src/bebone/sound/sound_factory.cpp new file mode 100644 index 00000000..9a6ee9e8 --- /dev/null +++ b/src/bebone/sound/sound_factory.cpp @@ -0,0 +1,27 @@ +#include "sound_factory.h" + +namespace bebone::sound_system { + std::shared_ptr LightweightSoundFactory::create_sound(ma_engine &engine, const std::string &path) { + auto sound = std::make_shared(); + + ma_result result = ma_sound_init_from_file(&engine, path.c_str(), 0, NULL, NULL, sound.get()); + if (result != MA_SUCCESS) { + LOG_ERROR("Failed to initialize sound from file {}", path); + // TODO: Throw an exception + } + + return sound; + } + + std::shared_ptr StreamSoundFactory::create_sound(ma_engine &engine, const std::string &path) { + auto sound = std::make_shared(); + + ma_result result = ma_sound_init_from_file(&engine, path.c_str(), MA_SOUND_FLAG_STREAM, NULL, NULL, sound.get()); + if (result != MA_SUCCESS) { + LOG_ERROR("Failed to initialize sound from file {}", path); + // TODO: Throw an exception + } + + return sound; + } +} \ No newline at end of file diff --git a/src/bebone/sound/sound_factory.h b/src/bebone/sound/sound_factory.h new file mode 100644 index 00000000..cad59056 --- /dev/null +++ b/src/bebone/sound/sound_factory.h @@ -0,0 +1,27 @@ +#ifndef _SOUND_FACTORY_H_ +#define _SOUND_FACTORY_H_ + +#include +#include +#include "sound.h" +#include + +namespace bebone::sound_system { + class SoundFactory { + public: + virtual ~SoundFactory() = default; + virtual std::shared_ptr create_sound(ma_engine& engine, const std::string& path) = 0; + }; + + class LightweightSoundFactory : public SoundFactory { + public: + std::shared_ptr create_sound(ma_engine& engine, const std::string& path) override; + }; + + class StreamSoundFactory : public SoundFactory { + public: + std::shared_ptr create_sound(ma_engine& engine, const std::string& path) override; + }; +} + +#endif diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 059f2a25..82fd25e9 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1 +1 @@ -add_subdirectory(unit) \ No newline at end of file +add_subdirectory(bebone) \ No newline at end of file diff --git a/tests/bebone/CMakeLists.txt b/tests/bebone/CMakeLists.txt new file mode 100644 index 00000000..5a0897d0 --- /dev/null +++ b/tests/bebone/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.21) +project(BeboneTests) + +include_directories("../../src") +include_directories("../../3dparty/glad/include") +include_directories("../../3dparty/glfw/include") +include_directories("../../3dparty/Vulkan-Headers/include") +include_directories("../../3dparty/stb") +include_directories("../../3dparty/imgui") + +add_subdirectory(core) + +# Register bebone all tests target +file(GLOB_RECURSE SRC_FILES "*.cpp") +add_executable(bebone_all_tests ${SRC_FILES}) +target_link_libraries(bebone_all_tests bebone_core) +target_link_libraries(bebone_all_tests gtest gtest_main) \ No newline at end of file diff --git a/tests/bebone/core/CMakeLists.txt b/tests/bebone/core/CMakeLists.txt new file mode 100644 index 00000000..d2ffd5b2 --- /dev/null +++ b/tests/bebone/core/CMakeLists.txt @@ -0,0 +1,27 @@ +include_directories(".") + +file(GLOB_RECURSE SRC_FILES "*.cpp") +set(EXECUTABLES) + +foreach(SRC_FILE ${SRC_FILES}) + get_filename_component(TEST_NAME ${SRC_FILE} NAME_WE) + add_executable(${TEST_NAME} ${SRC_FILE}) + target_link_libraries(${TEST_NAME} bebone_core) + target_link_libraries(${TEST_NAME} gtest gtest_main) + list(APPEND EXECUTABLES ${TEST_NAME}) +endforeach() + +add_custom_target(run_core_tests COMMAND ${CMAKE_COMMAND} -E echo "Running all core unit tests...") + +foreach(EXECUTABLE ${EXECUTABLES}) + add_custom_command(TARGET run_core_tests POST_BUILD + COMMAND ${EXECUTABLE} + COMMENT "Running test ${EXECUTABLE}" + ) +endforeach() + +# Register bebone core tests target +file(GLOB_RECURSE SRC_FILES "*.cpp") +add_executable(bebone_core_tests ${SRC_FILES}) +target_link_libraries(bebone_core_tests bebone_core) +target_link_libraries(bebone_core_tests gtest gtest_main) \ No newline at end of file diff --git a/tests/bebone/core/debug/console_logger_tests.cpp b/tests/bebone/core/debug/console_logger_tests.cpp new file mode 100644 index 00000000..ea8c3516 --- /dev/null +++ b/tests/bebone/core/debug/console_logger_tests.cpp @@ -0,0 +1,17 @@ +#include "bebone/core/debug/console_logger.h" +#include "gtest/gtest.h" + +using namespace bebone::core; + +TEST(LogLevelTestSuite, ConsoleLoggerLogsMessages) { + std::stringstream ss; + auto logger = ConsoleLogger(ss); + + ASSERT_EQ(ss.str().size(), 0); + + logger.log(LogLevel::Trace, "Test log message"); + ASSERT_EQ(ss.str().size(), 52); + + logger.log(LogLevel::Trace, "Another message"); + ASSERT_EQ(ss.str().size(), 103); +} diff --git a/tests/bebone/core/debug/log_level_tests.cpp b/tests/bebone/core/debug/log_level_tests.cpp new file mode 100644 index 00000000..49e21e87 --- /dev/null +++ b/tests/bebone/core/debug/log_level_tests.cpp @@ -0,0 +1,44 @@ +#include "bebone/core/debug/log_level.h" +#include "gtest/gtest.h" + +using namespace bebone::core; + +TEST(LogLevelTestSuite, UnixLogLevelColorReturnsCorrectColor) { + std::string result = unix_log_level_color(LogLevel::Trace); + ASSERT_EQ(result, UnixConsoleColors::White); + + result = unix_log_level_color(LogLevel::Debug); + ASSERT_EQ(result, UnixConsoleColors::Cyan); + + result = unix_log_level_color(LogLevel::Information); + ASSERT_EQ(result, UnixConsoleColors::Green); + + result = unix_log_level_color(LogLevel::Warning); + ASSERT_EQ(result, UnixConsoleColors::Yellow); + + result = unix_log_level_color(LogLevel::Error); + ASSERT_EQ(result, UnixConsoleColors::Red); + + result = unix_log_level_color(LogLevel::Critical); + ASSERT_EQ(result, UnixConsoleColors::DarkRed); +} + +TEST(LogLevelTestSuite, StringifyLogLevelReturnsCorrectString) { + std::string result = stringify_log_level(LogLevel::Trace); + ASSERT_EQ(result, "TRC"); + + result = stringify_log_level(LogLevel::Debug); + ASSERT_EQ(result, "DGB"); + + result = stringify_log_level(LogLevel::Information); + ASSERT_EQ(result, "INF"); + + result = stringify_log_level(LogLevel::Warning); + ASSERT_EQ(result, "WAR"); + + result = stringify_log_level(LogLevel::Error); + ASSERT_EQ(result, "ERR"); + + result = stringify_log_level(LogLevel::Critical); + ASSERT_EQ(result, "CRI"); +} diff --git a/tests/bebone/core/events/events_delegates_tests.cpp b/tests/bebone/core/events/events_delegates_tests.cpp new file mode 100644 index 00000000..a9b3e439 --- /dev/null +++ b/tests/bebone/core/events/events_delegates_tests.cpp @@ -0,0 +1,56 @@ +#include "bebone/core/core.h" +#include "gtest/gtest.h" + +using namespace bebone::core; + +TEST(DelegateTestSuite, PerformingSingleActionTest) { + Action action; + + int test = 0; + + auto fun = std::function{[&](int value) { + test += value; + }}; + + action += fun; + ASSERT_EQ(test, 0); + + action(1); + ASSERT_EQ(test, 1); + + action(8); + ASSERT_EQ(test, 9); + + action(8); + ASSERT_EQ(test, 17); + + action -= fun; + + action(8); + ASSERT_EQ(test, 17); +} + +TEST(DelegateTestSuite, PerformingMultipleActionsTest) { + Action<> action; + + int test = 0; + + auto fun0 = std::function{[&]() { + test += 1; + }}; + + auto fun1 = std::function{[&]() { + test += 3; + }}; + + action += fun0; + action += fun1; + + ASSERT_EQ(test, 0); + + action(); + ASSERT_EQ(test, 4); + + action(); + ASSERT_EQ(test, 8); +} \ No newline at end of file diff --git a/tests/bebone/core/events/events_listeners_tests.cpp b/tests/bebone/core/events/events_listeners_tests.cpp new file mode 100644 index 00000000..b0e0bc39 --- /dev/null +++ b/tests/bebone/core/events/events_listeners_tests.cpp @@ -0,0 +1,141 @@ +#include + +#include "bebone/core/core.h" +#include "gtest/gtest.h" + +using namespace bebone::core; + +enum Category { + Simple, + Complex, + Cool +}; + +struct SimpleEvent : public Event { + +}; + +struct ComplexEvent : public Event { + int field; + + explicit ComplexEvent(const int& field) : field(field) {} +}; + +struct CoolEvent : public Event { + std::string field; + + explicit CoolEvent(std::string field) : field(std::move(field)) {} +}; + +TEST(EventListenersTestSuite, FireSingleEvent) { + EventDispatcher dispatcher; + + int res = 0; + + dispatcher.add_listener([&](SimpleEvent& event) { + res += 1; + }); + + dispatcher.fire(SimpleEvent()); + + ASSERT_EQ(res, 1); +} + +TEST(EventListenersTestSuite, FireEventMultipleTimes) { + EventDispatcher dispatcher; + + int res = 0; + + dispatcher.add_listener([&](SimpleEvent& event) { + res += 1; + }); + + dispatcher.fire(SimpleEvent()); + dispatcher.fire(SimpleEvent()); + dispatcher.fire(SimpleEvent()); + + ASSERT_EQ(res, 3); +} + +TEST(EventListenersTestSuite, FireMultipleEventsSeveralTimes) { + EventDispatcher dispatcher; + + int res = 123; + + dispatcher.add_listener([&](SimpleEvent& event) { + res += 1; + }); + + dispatcher.add_listener([&](SimpleEvent& event) { + res -= 1; + }); + + dispatcher.fire(SimpleEvent()); + dispatcher.fire(SimpleEvent()); + dispatcher.fire(SimpleEvent()); + + ASSERT_EQ(res, 123); +} + +TEST(EventListenersTestSuite, AddDifferentTypesOfEvents) { + EventDispatcher dispatcher; + + int res = 0; + + dispatcher.add_listener([&](SimpleEvent& event) { + res += 1; + }); + + dispatcher.add_listener([&](ComplexEvent& event) { + res += event.field; + }); + + dispatcher.fire(SimpleEvent()); + dispatcher.fire(SimpleEvent()); + dispatcher.fire(SimpleEvent()); + + ASSERT_EQ(res, 3); +} + +TEST(EventListenersTestSuite, FireDifferentTypesOfEvents1) { + EventDispatcher dispatcher; + + int res = 0; + + dispatcher.add_listener([&](SimpleEvent& event) { + res += 1; + }); + + dispatcher.add_listener([&](ComplexEvent& event) { + res += event.field; + }); + + dispatcher.fire(SimpleEvent()); + dispatcher.fire(ComplexEvent(2)); + + ASSERT_EQ(res, 3); +} + +TEST(EventListenersTestSuite, FireDifferentTypesOfEvents2) { + EventDispatcher dispatcher; + + std::string res = "some"; + + dispatcher.add_listener([&](SimpleEvent& event) { + res += "1"; + }); + + dispatcher.add_listener([&](ComplexEvent& event) { + res += to_string(event.field); + }); + + dispatcher.add_listener([&](CoolEvent& event) { + res += event.field; + }); + + dispatcher.fire(SimpleEvent()); + dispatcher.fire(ComplexEvent(2)); + dispatcher.fire(CoolEvent("poggers")); + + ASSERT_EQ(res, "some12poggers"); +} \ No newline at end of file diff --git a/tests/bebone/core/memory/arena_allocator_tests.cpp b/tests/bebone/core/memory/arena_allocator_tests.cpp new file mode 100644 index 00000000..5a923dad --- /dev/null +++ b/tests/bebone/core/memory/arena_allocator_tests.cpp @@ -0,0 +1,66 @@ +#include "bebone/core/core.h" +#include "gtest/gtest.h" + +using namespace bebone::core; + +TEST(ArenaAllocatorTestSuite, AllocationCheckAfterInitialization) { + ArenaAllocator arena(BEBONE_MEMORY_BYTES_1KB); + + ASSERT_EQ(arena.get_allocated(), 0); +} + +TEST(ArenaAllocatorTestSuite, CapacityCheckAfterInitialization) { + ArenaAllocator arena(BEBONE_MEMORY_BYTES_1KB); + + ASSERT_EQ(arena.get_capacity(), BEBONE_MEMORY_BYTES_1KB); +} + +TEST(ArenaAllocatorTestSuite, MemoryAllocation1) { + ArenaAllocator arena(BEBONE_MEMORY_BYTES_1KB); + + int* mem = static_cast(arena.alloc(sizeof(int))); + *mem = 69; + + ASSERT_EQ(*mem, 69); +} + +TEST(ArenaAllocatorTestSuite, MemoryAllocation2) { + ArenaAllocator arena(BEBONE_MEMORY_BYTES_1KB); + + int* mem_int = static_cast(arena.alloc(sizeof(int))); + *mem_int = 69; + + struct Data{ int data[16]; }; + + Data* mem_data = static_cast(arena.alloc(sizeof(Data))); + *mem_data = Data(); + + ASSERT_EQ(*mem_int, 69); +} + +TEST(ArenaAllocatorTestSuite, MemoryAllocation3) { + ArenaAllocator arena(BEBONE_MEMORY_BYTES_1KB); + + { + int* mem_int = static_cast(arena.alloc(sizeof(int))); + *mem_int = 420; + } + + arena.clear(); + + int* mem_int = static_cast(arena.alloc(sizeof(int))); + *mem_int = 69; + + ASSERT_EQ(*mem_int, 69); +} + +TEST(ArenaAllocatorTestSuite, MemoryAllocation4) { + ArenaAllocator arena(sizeof(char)); + + char* mem_char = static_cast(arena.alloc(sizeof(char))); + *mem_char = 25; + ASSERT_EQ(*mem_char, 25); + + void* ptr = arena.alloc(sizeof(size_t)); + ASSERT_EQ(ptr, nullptr); +} \ No newline at end of file diff --git a/tests/bebone/core/memory/arena_container_tests.cpp b/tests/bebone/core/memory/arena_container_tests.cpp new file mode 100644 index 00000000..1b114353 --- /dev/null +++ b/tests/bebone/core/memory/arena_container_tests.cpp @@ -0,0 +1,59 @@ +#include "bebone/core/core.h" +#include "gtest/gtest.h" + +using namespace bebone::core; + +TEST(ArenaContainerTestSuite, First) { + ArenaContainer container(BEBONE_MEMORY_BYTES_1KB); + + int* e1 = static_cast(container.alloc(sizeof(int))); + int* e2 = static_cast(container.alloc(sizeof(int))); + int* e3 = static_cast(container.alloc(sizeof(int))); + + *e1 = 16; + *e2 = 32; + *e3 = 64; + + int* ee1 = static_cast(container.at(0)); + int* ee2 = static_cast(container.at(1)); + int* ee3 = static_cast(container.at(2)); + + ASSERT_EQ(*ee1, *e1); + ASSERT_EQ(*ee2, *e2); + ASSERT_EQ(*ee3, *e3); + + ASSERT_EQ(container.size(), 3); +} + +TEST(ArenaContainerTestSuite, Second) { + ArenaContainer container(BEBONE_MEMORY_BYTES_1KB * 256); + + for(int i = 0; i < 100; ++i) { + int* e = static_cast(container.alloc(sizeof(int))); + *e = i; + + ASSERT_EQ(container.size(), static_cast(i + 1)); + } + + for(int i = 0; i < 100; ++i) { + int* e = static_cast(container.at(i)); + ASSERT_EQ(*e, i); + } + + ASSERT_EQ(container.size(), 100); +} + +TEST(ArenaContainerTestSuite, Third) { + ArenaContainer container(BEBONE_MEMORY_BYTES_1KB * 256); + + for(int i = 0; i < 100; ++i) { + int* e = static_cast(container.alloc(sizeof(int))); + *e = i; + + ASSERT_EQ(container.size(), static_cast(i + 1)); + } + + container.clear(); + + ASSERT_EQ(container.size(), 0); +} \ No newline at end of file diff --git a/tests/bebone/core/types/matrix/matrix2x2_tests.cpp b/tests/bebone/core/types/matrix/matrix2x2_tests.cpp new file mode 100644 index 00000000..2c2c078b --- /dev/null +++ b/tests/bebone/core/types/matrix/matrix2x2_tests.cpp @@ -0,0 +1,223 @@ +#include "bebone/core/core.h" +#include "gtest/gtest.h" + +using namespace bebone::core; + +TEST(Matrix2x2Math, Initialization) { + // Arrange + Matrix2x2f a(4, 3, + 2, 1); + + Matrix2x2f b(5, 6, + 7, 8); + + // Act + + // Assert + ASSERT_EQ(a(0, 0), 4); + ASSERT_EQ(a(0, 1), 3); + ASSERT_EQ(a(1, 0), 2); + ASSERT_EQ(a(1, 1), 1); + + ASSERT_EQ(b(0, 0), 5); + ASSERT_EQ(b(0, 1), 6); + ASSERT_EQ(b(1, 0), 7); + ASSERT_EQ(b(1, 1), 8); +} + +TEST(Matrix2x2Math, MatrixAddition) { + // Arrange + Matrix2x2f a(1, 2, + 3, 4); + + Matrix2x2f b(3, 4, + 5, 6); + + Matrix2x2f c(3, 1, + 5, 4); + // Act + Matrix2x2f result0 = a + b; + Matrix2x2f result1 = b + c; + + // Assert + ASSERT_TRUE(result0 == Matrix2x2f(4, 6, + 8, 10)); + + ASSERT_TRUE(result1 == Matrix2x2f(6, 5, + 10, 10)); +} + +TEST(Matrix2x2Math, MatrixSubtraction) { + // Arrange + Matrix2x2f a(15, 7, + 3, 8); + + Matrix2x2f b(0, 1, + 4, 3); + + Matrix2x2f c(6, 4, + 3, 5); + + // Act + Matrix2x2f result0 = a - b; + Matrix2x2f result1 = a - c; + + // Assert + ASSERT_TRUE(result0 == Matrix2x2f(15, 6, + -1, 5)); + + ASSERT_TRUE(result1 == Matrix2x2f(9, 3, + 0, 3)); +} + +TEST(Matrix2x2Math, MatrixMultiplication) { + // Arrange + Matrix2x2f a(15, 7, + 3, 8); + + Matrix2x2f b(0, 1, + 4, 3); + + Matrix2x2f c(6, 4, + 3, 5); + + // Act + Matrix2x2f result0 = a * b; + Matrix2x2f result1 = b * a; + Matrix2x2f result2 = b * c; + Matrix2x2f result3 = c * b; + + // Assert + ASSERT_TRUE(result0 == Matrix2x2f(28, 36, + 32, 27)); + ASSERT_TRUE(result1 == Matrix2x2f(3, 8, + 69, 52)); + ASSERT_TRUE(result2 == Matrix2x2f(3, 5, + 33, 31)); + ASSERT_TRUE(result3 == Matrix2x2f(16, 18, + 20, 18)); +} + +TEST(Matrix2x2Math, ScalarAddition) { + // Arrange + Matrix2x2f a(5, 3, + 2, 5); + + Matrix2x2f b(6, 2, + 4, 0); + + // Act + Matrix2x2f result0 = a + 4; + Matrix2x2f result1 = b + 7; + + // Assert + ASSERT_TRUE(result0 == Matrix2x2f(9, 7, + 6, 9)); + + ASSERT_TRUE(result1 == Matrix2x2f(13, 9, + 11, 7)); +} + +TEST(Matrix2x2Math, ScalarSubtraction) { + // Arrange + Matrix2x2f a(5, 3, + 2, 5); + + Matrix2x2f b(6, 2, + 4, 0); + + // Act + Matrix2x2f result0 = a - 4; + Matrix2x2f result1 = b - 7; + + // Assert + ASSERT_TRUE(result0 == Matrix2x2f(1, -1, + -2, 1)); + + ASSERT_TRUE(result1 == Matrix2x2f(-1, -5, + -3, -7)); +} + +TEST(Matrix2x2Math, ScalarMultiplication) { + // Arrange + Matrix2x2f a(5, 3, + 2, 5); + + Matrix2x2f b(6, 2, + 4, 0); + + // Act + Matrix2x2f result0 = a * 4; + Matrix2x2f result1 = b * 7; + + // Assert + ASSERT_TRUE(result0 == Matrix2x2f(20, 12, + 8, 20)); + + ASSERT_TRUE(result1 == Matrix2x2f(42, 14, + 28, 0)); +} + +TEST(Matrix2x2Math, ScalarDivision) { + // Arrange + Matrix2x2f a(5, 25, + 10, 5); + + Matrix2x2f b(6, 2, + 4, 0); + + // Act + Matrix2x2f result0 = a / 5; + Matrix2x2f result1 = b / 2; + + // Assert + ASSERT_TRUE(result0 == Matrix2x2f(1, 5, + 2, 1)); + + ASSERT_TRUE(result1 == Matrix2x2f(3, 1, + 2, 0)); +} + +TEST(Matrix2x2Functions, Transpose) { + // Arrange + Matrix2x2f a(1, 2, + 3, 4); + + Matrix2x2f b(47, 4, + 8, 0); + + // Act + Matrix2x2f result0 = a.transpose(); + Matrix2x2f result1 = b.transpose(); + + // Assert + ASSERT_TRUE(result0 == Matrix2x2f(1, 3, + 2, 4)); + + ASSERT_TRUE(result1 == Matrix2x2f(47, 8, + 4, 0)); +} + +TEST(Matrix2x2Functions, Inverse) { + // Arrange + Matrix2x2f a(5, 2, + 4, 10); + + Matrix2x2f b(4, 4, + 0, 2); + + // Act + Matrix2x2f result0 = a.inverse(); + Matrix2x2f result1 = b.inverse(); + + // Assert + ASSERT_FLOAT_EQ(result0(0, 0), 0.2380952f); + ASSERT_FLOAT_EQ(result0(0, 1), -0.047619049f); + ASSERT_FLOAT_EQ(result0(1, 0), -0.095238097f); + ASSERT_FLOAT_EQ(result0(1, 1), 0.1190476f); + + ASSERT_FLOAT_EQ(result1(0, 0), 0.25f); + ASSERT_FLOAT_EQ(result1(0, 1), -0.5f); + ASSERT_FLOAT_EQ(result1(1, 0), 0); + ASSERT_FLOAT_EQ(result1(1, 1), 0.5f); +} \ No newline at end of file diff --git a/tests/bebone/core/types/matrix/matrix3x3_tests.cpp b/tests/bebone/core/types/matrix/matrix3x3_tests.cpp new file mode 100644 index 00000000..3285ca9f --- /dev/null +++ b/tests/bebone/core/types/matrix/matrix3x3_tests.cpp @@ -0,0 +1,287 @@ +#include "bebone/core/core.h" +#include "gtest/gtest.h" + +using namespace bebone::core; + +TEST(Matrix3x3Math, Initialization) { + // Arrange + Matrix3x3f a(4, 3, 1, + 2, 1, 0, + 5, 3, 2); + + Matrix3x3f b(5, 6, 3, + 7, 8, 2, + 6, 3, 1); + // Act + + // Assert + ASSERT_EQ(a(0, 0), 4); + ASSERT_EQ(a(0, 1), 3); + ASSERT_EQ(a(0, 2), 1); + ASSERT_EQ(a(1, 0), 2); + ASSERT_EQ(a(1, 1), 1); + ASSERT_EQ(a(1, 2), 0); + ASSERT_EQ(a(2, 0), 5); + ASSERT_EQ(a(2, 1), 3); + ASSERT_EQ(a(2, 2), 2); + + ASSERT_EQ(b(0, 0), 5); + ASSERT_EQ(b(0, 1), 6); + ASSERT_EQ(b(0, 2), 3); + ASSERT_EQ(b(1, 0), 7); + ASSERT_EQ(b(1, 1), 8); + ASSERT_EQ(b(1, 2), 2); + ASSERT_EQ(b(2, 0), 6); + ASSERT_EQ(b(2, 1), 3); + ASSERT_EQ(b(2, 2), 1); +} + +TEST(Matrix3x3Math, MatrixAddition) { + // Arrange + Matrix3x3f a(1, 2, 3, + 4, 5, 6, + 7, 8, 9); + + Matrix3x3f b(3, 4, 1, + 5, 6, 0, + 4, 2, 1); + + Matrix3x3f c(3, 1, 4, + 5, 4, 3, + 6, 0, 0); + + // Act + Matrix3x3f result0 = a + b; + Matrix3x3f result1 = b + c; + + // Assert + ASSERT_TRUE(result0 == Matrix3x3f(4, 6, 4, + 9, 11, 6, + 11, 10, 10)); + + ASSERT_TRUE(result1 == Matrix3x3f(6, 5, 5, + 10, 10, 3, + 10, 2, 1)); +} + +TEST(Matrix3x3Math, MatrixSubtraction) { + // Arrange + Matrix3x3f a(1, 2, 3, + 4, 5, 6, + 7, 8, 9); + + Matrix3x3f b(3, 4, 1, + 5, 6, 0, + 4, 2, 1); + + Matrix3x3f c(3, 1, 4, + 5, 4, 3, + 6, 0, 0); + + // Act + Matrix3x3f result0 = a - b; + Matrix3x3f result1 = a - c; + + // Assert + ASSERT_TRUE(result0 == Matrix3x3f(-2, -2, 2, + -1, -1, 6, + 3, 6, 8)); + + ASSERT_TRUE(result1 == Matrix3x3f(-2, 1, -1, + -1, 1, 3, + 1, 8, 9)); +} + +TEST(Matrix3x3Math, MatrixMultiplication) { + // Arrange + Matrix3x3f a(1, 2, 3, + 4, 5, 6, + 7, 8, 9); + + Matrix3x3f b(3, 4, 1, + 5, 6, 0, + 4, 2, 1); + + Matrix3x3f c(3, 1, 4, + 5, 4, 3, + 6, 0, 0); + + // Act + Matrix3x3f result0 = a * b; + Matrix3x3f result1 = b * a; + Matrix3x3f result2 = b * c; + Matrix3x3f result3 = c * b; + + // Assert + ASSERT_TRUE(result0 == Matrix3x3f(25, 22, 4, + 61, 58, 10, + 97, 94, 16)); + + ASSERT_TRUE(result1 == Matrix3x3f(26, 34, 42, + 29, 40, 51, + 19, 26, 33)); + + ASSERT_TRUE(result2 == Matrix3x3f(35, 19, 24, + 45, 29, 38, + 28, 12, 22)); + + ASSERT_TRUE(result3 == Matrix3x3f(30, 26, 7, + 47, 50, 8, + 18, 24, 6)); +} + +TEST(Matrix3x3Math, ScalarAddition) { + // Arrange + Matrix3x3f a(1, 2, 3, + 4, 5, 6, + 7, 8, 9); + + Matrix3x3f b(3, 4, 1, + 5, 6, 0, + 4, 2, 1); + + // Act + Matrix3x3f result0 = a + 4; + Matrix3x3f result1 = b + 7; + + // Assert + ASSERT_TRUE(result0 == Matrix3x3f(5, 6, 7, + 8, 9, 10, + 11, 12, 13)); + + ASSERT_TRUE(result1 == Matrix3x3f(10, 11, 8, + 12, 13, 7, + 11, 9, 8)); +} + +TEST(Matrix3x3Math, ScalarSubtraction) { + // Arrange + Matrix3x3f a(1, 2, 3, + 4, 5, 6, + 7, 8, 9); + + Matrix3x3f b(3, 4, 1, + 5, 6, 0, + 4, 2, 1); + + // Act + Matrix3x3f result0 = a - 4; + Matrix3x3f result1 = b - 7; + + // Assert + ASSERT_TRUE(result0 == Matrix3x3f(-3, -2, -1, + 0, 1, 2, + 3, 4, 5)); + + ASSERT_TRUE(result1 == Matrix3x3f(-4, -3, -6, + -2, -1, -7, + -3, -5, -6)); +} + +TEST(Matrix3x3Math, ScalarMultiplication) { + // Arrange + Matrix3x3f a(1, 2, 3, + 4, 5, 6, + 7, 8, 9); + + Matrix3x3f b(3, 4, 1, + 5, 6, 0, + 4, 2, 1); + + // Act + Matrix3x3f result0 = a * 4; + Matrix3x3f result1 = b * 7; + + // Assert + ASSERT_TRUE(result0 == Matrix3x3f(4, 8, 12, + 16, 20, 24, + 28, 32, 36)); + + ASSERT_TRUE(result1 == Matrix3x3f(21, 28, 7, + 35, 42, 0, + 28, 14, 7)); +} + +TEST(Matrix3x3Math, ScalarDivision) { + // Arrange + Matrix3x3f a(25, 0, 10, + 15, 5, 30, + 35, 100, 45); + + Matrix3x3f b(6, 4, 2, + 0, 8, 16, + 20, 10, 8); + + // Act + Matrix3x3f result0 = a / 5; + Matrix3x3f result1 = b / 2; + + // Assert + ASSERT_TRUE(result0 == Matrix3x3f(5, 0, 2, + 3, 1, 6, + 7, 20, 9)); + + ASSERT_TRUE(result1 == Matrix3x3f(3, 2, 1, + 0, 4, 8, + 10, 5, 4)); +} + +TEST(Matrix3x3Functions, Transpose) { + // Arrange + Matrix3x3f a(1, 2, 3, + 4, 5, 6, + 7, 8, 9); + + Matrix3x3f b(3, 4, 1, + 5, 6, 0, + 4, 2, 1); + + // Act + Matrix3x3f result0 = a.transpose(); + Matrix3x3f result1 = b.transpose(); + + // Assert + ASSERT_TRUE(result0 == Matrix3x3f(1, 4, 7, + 2, 5, 8, + 3, 6, 9)); + + ASSERT_TRUE(result1 == Matrix3x3f(3, 5, 4, + 4, 6, 2, + 1, 0, 1)); +} + +TEST(Matrix3x3Functions, Inverse) { + // Arrange + Matrix3x3f a(5, 6, 3, + 4, 5, 6, + 7, 8, 9); + + Matrix3x3f b(3, 4, 1, + 5, 6, 0, + 4, 2, 1); + + // Act + Matrix3x3f result0 = a.inverse(); + Matrix3x3f result1 = b.inverse(); + + // Assert + ASSERT_FLOAT_EQ(result0(0, 0), -0.25f); + ASSERT_FLOAT_EQ(result0(0, 1), -2.5f); + ASSERT_FLOAT_EQ(result0(0, 2), 1.75f); + ASSERT_FLOAT_EQ(result0(1, 0), 0.5f); + ASSERT_FLOAT_EQ(result0(1, 1), 2.0f); + ASSERT_FLOAT_EQ(result0(1, 2), -1.5f); + ASSERT_FLOAT_EQ(result0(2, 0), -0.25f); + ASSERT_FLOAT_EQ(result0(2, 1), 0.1666667f); + ASSERT_FLOAT_EQ(result0(2, 2), 0.08333333f); + + ASSERT_FLOAT_EQ(result1(0, 0), -0.375f); + ASSERT_FLOAT_EQ(result1(0, 1), 0.125f); + ASSERT_FLOAT_EQ(result1(0, 2), 0.375f); + ASSERT_FLOAT_EQ(result1(1, 0), 0.3125f); + ASSERT_FLOAT_EQ(result1(1, 1), 0.0625f); + ASSERT_FLOAT_EQ(result1(1, 2), -0.3125f); + ASSERT_FLOAT_EQ(result1(2, 0), 0.875f); + ASSERT_FLOAT_EQ(result1(2, 1), -0.625f); + ASSERT_FLOAT_EQ(result1(2, 2), 0.125f); +} \ No newline at end of file diff --git a/tests/bebone/core/types/matrix/matrix4x4_tests.cpp b/tests/bebone/core/types/matrix/matrix4x4_tests.cpp new file mode 100644 index 00000000..4fd5b31d --- /dev/null +++ b/tests/bebone/core/types/matrix/matrix4x4_tests.cpp @@ -0,0 +1,356 @@ +#include "bebone/core/core.h" +#include "gtest/gtest.h" + +using namespace bebone::core; + +TEST(Matrix4x4Math, Initialization) { + // Arrange + Matrix4x4f a(4, 3, 1, 3, + 2, 1, 0, 4, + 5, 3, 2, 7, + 1, 2, 3, 4); + + Matrix4x4f b(5, 6, 3, 3, + 7, 8, 2, 4, + 6, 3, 1, 3, + 5, 3, 2, 1); + // Act + + // Assert + ASSERT_EQ(a(0, 0), 4); + ASSERT_EQ(a(0, 1), 3); + ASSERT_EQ(a(0, 2), 1); + ASSERT_EQ(a(0, 3), 3); + ASSERT_EQ(a(1, 0), 2); + ASSERT_EQ(a(1, 1), 1); + ASSERT_EQ(a(1, 2), 0); + ASSERT_EQ(a(1, 3), 4); + ASSERT_EQ(a(2, 0), 5); + ASSERT_EQ(a(2, 1), 3); + ASSERT_EQ(a(2, 2), 2); + ASSERT_EQ(a(2, 3), 7); + ASSERT_EQ(a(3, 0), 1); + ASSERT_EQ(a(3, 1), 2); + ASSERT_EQ(a(3, 2), 3); + ASSERT_EQ(a(3, 3), 4); + + ASSERT_EQ(b(0, 0), 5); + ASSERT_EQ(b(0, 1), 6); + ASSERT_EQ(b(0, 2), 3); + ASSERT_EQ(b(0, 3), 3); + ASSERT_EQ(b(1, 0), 7); + ASSERT_EQ(b(1, 1), 8); + ASSERT_EQ(b(1, 2), 2); + ASSERT_EQ(b(1, 3), 4); + ASSERT_EQ(b(2, 0), 6); + ASSERT_EQ(b(2, 1), 3); + ASSERT_EQ(b(2, 2), 1); + ASSERT_EQ(b(2, 3), 3); + ASSERT_EQ(b(3, 0), 5); + ASSERT_EQ(b(3, 1), 3); + ASSERT_EQ(b(3, 2), 2); + ASSERT_EQ(b(3, 3), 1); +} + +TEST(Matrix4x4Math, MatrixAddition) { + // Arrange + Matrix4x4f a(1, 2, 3, 4, + 5, 6, 7, 8, + 9, 10, 11, 12, + 13, 14, 15, 16); + + Matrix4x4f b(3, 4, 1, 4, + 5, 6, 0, 3, + 4, 2, 1, 2, + 5, 1, 0, 3); + + Matrix4x4f c(3, 1, 4, 3, + 5, 4, 3, 5, + 6, 0, 0, 4, + 2, 3, 5, 1); + + // Act + Matrix4x4f result0 = a + b; + Matrix4x4f result1 = b + c; + + // Assert + ASSERT_TRUE(result0 == Matrix4x4f(4, 6, 4, 8, + 10, 12, 7, 11, + 13, 12, 12, 14, + 18, 15, 15, 19)); + + ASSERT_TRUE(result1 == Matrix4x4f(6, 5, 5, 7, + 10, 10, 3, 8, + 10, 2, 1, 6, + 7, 4, 5, 4)); +} + +TEST(Matrix4x4Math, MatrixSubtraction) { + // Arrange + Matrix4x4f a(1, 2, 3, 4, + 5, 6, 7, 8, + 9, 10, 11, 12, + 13, 14, 15, 16); + + Matrix4x4f b(3, 4, 1, 4, + 5, 6, 0, 3, + 4, 2, 1, 2, + 5, 1, 0, 3); + + Matrix4x4f c(3, 1, 4, 3, + 5, 4, 3, 5, + 6, 0, 0, 4, + 2, 3, 5, 1); + + // Act + Matrix4x4f result0 = a - b; + Matrix4x4f result1 = a - c; + + // Assert + ASSERT_TRUE(result0 == Matrix4x4f(-2, -2, 2, 0, + 0, 0, 7, 5, + 5, 8, 10, 10, + 8, 13, 15, 13)); + + ASSERT_TRUE(result1 == Matrix4x4f(-2, 1, -1, 1, + 0, 2, 4, 3, + 3, 10, 11, 8, + 11, 11, 10, 15)); +} + +TEST(Matrix4x4Math, MatrixMultiplication) { + // Arrange + Matrix4x4f a(1, 2, 3, 4, + 5, 6, 7, 8, + 9, 10, 11, 12, + 13, 14, 15, 16); + + Matrix4x4f b(3, 4, 1, 4, + 5, 6, 0, 3, + 4, 2, 1, 2, + 5, 1, 0, 3); + + Matrix4x4f c(3, 1, 4, 3, + 5, 4, 3, 5, + 6, 0, 0, 4, + 2, 3, 5, 1); + + // Act + Matrix4x4f result0 = a * b; + Matrix4x4f result1 = b * a; + Matrix4x4f result2 = b * c; + Matrix4x4f result3 = c * b; + + // Assert + ASSERT_TRUE(result0 == Matrix4x4f(45, 26, 4, 28, + 113, 78, 12, 76, + 181, 130, 20, 124, + 249, 182, 28, 172)); + + ASSERT_TRUE(result1 == Matrix4x4f(84, 96, 108, 120, + 74, 88, 102, 116, + 49, 58, 67, 76, + 49, 58, 67, 76)); + + ASSERT_TRUE(result2 == Matrix4x4f(43, 31, 44, 37, + 51, 38, 53, 48, + 32, 18, 32, 28, + 26, 18, 38, 23)); + + ASSERT_TRUE(result3 == Matrix4x4f(45, 29, 7, 32, + 72, 55, 8, 53, + 38, 28, 6, 36, + 46, 37, 7, 30)); +} + +TEST(Matrix4x4Math, ScalarAddition) { + // Arrange + Matrix4x4f a(1, 2, 3, 4, + 5, 6, 7, 8, + 9, 10, 11, 12, + 13, 14, 15, 16); + + Matrix4x4f b(3, 4, 1, 4, + 5, 6, 0, 3, + 4, 2, 1, 2, + 5, 1, 0, 3); + + // Act + Matrix4x4f result0 = a + 4; + Matrix4x4f result1 = b + 7; + + // Assert + ASSERT_TRUE(result0 == Matrix4x4f(5, 6, 7, 8, + 9, 10, 11, 12, + 13, 14, 15, 16, + 17, 18, 19, 20)); + + ASSERT_TRUE(result1 == Matrix4x4f(10, 11, 8, 11, + 12, 13, 7, 10, + 11, 9, 8, 9, + 12, 8, 7, 10)); +} + +TEST(Matrix4x4Math, ScalarSubtraction) { + // Arrange + Matrix4x4f a(1, 2, 3, 4, + 5, 6, 7, 8, + 9, 10, 11, 12, + 13, 14, 15, 16); + + Matrix4x4f b(3, 4, 1, 4, + 5, 6, 0, 3, + 4, 2, 1, 2, + 5, 1, 0, 3); + + // Act + Matrix4x4f result0 = a - 4; + Matrix4x4f result1 = b - 7; + + // Assert + ASSERT_TRUE(result0 == Matrix4x4f(-3, -2, -1, 0, + 1, 2, 3, 4, + 5, 6, 7, 8, + 9, 10, 11, 12)); + + ASSERT_TRUE(result1 == Matrix4x4f(-4, -3, -6, -3, + -2, -1, -7, -4, + -3, -5, -6, -5, + -2, -6, -7, -4)); +} + +TEST(Matrix4x4Math, ScalarMultiplication) { + // Arrange + Matrix4x4f a(1, 2, 3, 4, + 5, 6, 7, 8, + 9, 10, 11, 12, + 13, 14, 15, 16); + + Matrix4x4f b(3, 4, 1, 4, + 5, 6, 0, 3, + 4, 2, 1, 2, + 5, 1, 0, 3); + + // Act + Matrix4x4f result0 = a * 4; + Matrix4x4f result1 = b * 7; + + // Assert + ASSERT_TRUE(result0 == Matrix4x4f(4, 8, 12, 16, + 20, 24, 28, 32, + 36, 40, 44, 48, + 52, 56, 60, 64)); + + ASSERT_TRUE(result1 == Matrix4x4f(21, 28, 7, 28, + 35, 42, 0, 21, + 28, 14, 7, 14, + 35, 7, 0, 21)); +} + +TEST(Matrix4x4Math, ScalarDivision) { + // Arrange + Matrix4x4f a(25, 0, 10, 15, + 15, 5, 30, 30, + 35, 100, 45, 60, + 0, 5, 5, 10); + + Matrix4x4f b(6, 4, 2, 8, + 0, 8, 16, 12, + 20, 10, 8, 16, + 0, 8, 6, 2); + + // Act + Matrix4x4f result0 = a / 5; + Matrix4x4f result1 = b / 2; + + // Assert + ASSERT_TRUE(result0 == Matrix4x4f(5, 0, 2, 3, + 3, 1, 6, 6, + 7, 20, 9, 12, + 0, 1, 1, 2)); + + ASSERT_TRUE(result1 == Matrix4x4f(3, 2, 1, 4, + 0, 4, 8, 6, + 10, 5, 4, 8, + 0, 4, 3, 1)); +} + +TEST(Matrix4x4functions, Transpose) { + // Arrange + Matrix4x4f a(1, 2, 3, 4, + 5, 6, 7, 8, + 9, 10, 11, 12, + 13, 14, 15, 16); + + Matrix4x4f b(3, 4, 1, 4, + 5, 6, 0, 3, + 4, 2, 1, 2, + 5, 1, 0, 3); + + // Act + Matrix4x4f result0 = a.transpose(); + Matrix4x4f result1 = b.transpose(); + + // Assert + ASSERT_TRUE(result0 == Matrix4x4f(1, 5, 9, 13, + 2, 6, 10, 14, + 3, 7, 11, 15, + 4, 8, 12, 16)); + + ASSERT_TRUE(result1 == Matrix4x4f(3, 5, 4, 5, + 4, 6, 2, 1, + 1, 0, 1, 0, + 4, 3, 2, 3)); +} + +TEST(Matrix4x4functions, Inverse) { + // Arrange + Matrix4x4f a(7, 8, 5, 0, + 7, 5, 3, 5, + 9, 0, 8, 8, + 5, 1, 15, 8); + + Matrix4x4f b(3, 4, 1, 4, + 5, 6, 0, 3, + 4, 2, 1, 2, + 5, 1, 0, 3); + + // Act + Matrix4x4f result0 = a.inverse(); + Matrix4x4f result1 = b.inverse(); + + // Assert + ASSERT_FLOAT_EQ(result0(0, 0), 0.10485299f); + ASSERT_FLOAT_EQ(result0(0, 1), -0.14452709f); + ASSERT_FLOAT_EQ(result0(0, 2), 0.20651788f); + ASSERT_FLOAT_EQ(result0(0, 3), -0.11618845f); + ASSERT_FLOAT_EQ(result0(1, 0), -0.00460503f); + ASSERT_FLOAT_EQ(result0(1, 1), 0.19553666f); + ASSERT_FLOAT_EQ(result0(1, 2), -0.18136733f); + ASSERT_FLOAT_EQ(result0(1, 3), 0.05915692f); + ASSERT_FLOAT_EQ(result0(2, 0), 0.06057385f); + ASSERT_FLOAT_EQ(result0(2, 1), -0.11052072f); + ASSERT_FLOAT_EQ(result0(2, 2), 0.0010626987f); + ASSERT_FLOAT_EQ(result0(2, 3), 0.06801275f); + ASSERT_FLOAT_EQ(result0(3, 0), -0.17853347f); + ASSERT_FLOAT_EQ(result0(3, 1), 0.27311370f); + ASSERT_FLOAT_EQ(result0(3, 2), -0.10839532f); + ASSERT_FLOAT_EQ(result0(3, 3), 0.06269925f); + + ASSERT_FLOAT_EQ(result1(0, 0), -0.23076923f); + ASSERT_FLOAT_EQ(result1(0, 1), 0.06153846f); + ASSERT_FLOAT_EQ(result1(0, 2), 0.23076923f); + ASSERT_FLOAT_EQ(result1(0, 3), 0.09230769f); + ASSERT_FLOAT_EQ(result1(1, 0), 0.0f); + ASSERT_FLOAT_EQ(result1(1, 1), 0.2f); + ASSERT_FLOAT_EQ(result1(1, 2), 0.0f); + ASSERT_FLOAT_EQ(result1(1, 3), -0.2f); + ASSERT_FLOAT_EQ(result1(2, 0), 0.15384615f); + ASSERT_FLOAT_EQ(result1(2, 1), -0.30769230f); + ASSERT_FLOAT_EQ(result1(2, 2), 0.84615384f); + ASSERT_FLOAT_EQ(result1(2, 3), -0.46153846f); + ASSERT_FLOAT_EQ(result1(3, 0), 0.38461538f); + ASSERT_FLOAT_EQ(result1(3, 1), -0.16923076f); + ASSERT_FLOAT_EQ(result1(3, 2), -0.38461538f); + ASSERT_FLOAT_EQ(result1(3, 3), 0.24615384f); +} \ No newline at end of file diff --git a/tests/bebone/core/types/vector/vector2_tests.cpp b/tests/bebone/core/types/vector/vector2_tests.cpp new file mode 100644 index 00000000..5560e56a --- /dev/null +++ b/tests/bebone/core/types/vector/vector2_tests.cpp @@ -0,0 +1,177 @@ +#include "bebone/core/core.h" +#include "gtest/gtest.h" + +using namespace bebone::core; + +TEST(Vector2Math, Addition) { + Vec2f a(2.4f, 2.0f); + Vec2f b(3.4f, 45.0); + Vec2f result(5.8f, 47.0f); + + ASSERT_EQ(a + b, result); + ASSERT_EQ(b + a, result); + ASSERT_EQ(a, Vec2f(2.4f, 2.0f)); + ASSERT_EQ(b, Vec2f(3.4f, 45.0f)); + + a += b; + ASSERT_EQ(a, result); + ASSERT_EQ(b, Vec2f(3.4f, 45.0f)); +} + +TEST(Vector2Math, Subtraction) { + Vec2f a(4.4f, 47.0f); + Vec2f b(3.4f, 45.0); + Vec2f result(1.0f, 2.0f); + + ASSERT_EQ(a - b, result); + ASSERT_EQ(b - a, -result); + ASSERT_EQ(a, Vec2f(4.4f, 47.0f)); + ASSERT_EQ(b, Vec2f(3.4f, 45.0)); + + a -= b; + ASSERT_EQ(a, result); + ASSERT_EQ(b, Vec2f(3.4f, 45.0f)); +} + +TEST(Vector2Math, Multiplication) { + Vec2f a(5.0f, 1.0f); + Vec2f b(2.1f, 7.0f); + Vec2f result(10.5f, 7.0f); + + ASSERT_EQ(a * b, result); + ASSERT_EQ(b * a, result); + ASSERT_EQ(a, Vec2f(5.0f, 1.0f)); + ASSERT_EQ(b, Vec2f(2.1f, 7.0f)); + + a *= b; + ASSERT_EQ(a, result); + ASSERT_EQ(b, Vec2f(2.1f, 7.0f)); +} + +TEST(Vector2Math, Division) { + Vec2f a(7.0f, 8.0f); + Vec2f b(2.0f, 4.0f); + Vec2f result(3.5f, 2.0f); + + ASSERT_EQ(a / b, result); + ASSERT_FLOAT_EQ((b / a).x, 0.2857142f); + ASSERT_EQ((b / a).y, 0.5f); + ASSERT_EQ(a, Vec2f(7.0f, 8.0f)); + ASSERT_EQ(b, Vec2f(2.0f, 4.0f)); + + a /= b; + ASSERT_EQ(a, result); + ASSERT_EQ(b, Vec2f(2.0f, 4.0f)); +} + +TEST(Vector2Math, Negation) { + Vec2f a(7.0f, -8.0f); + Vec2f b(-2.0f, 0.0f); + + ASSERT_EQ(-a, Vec2f(-7.0f, 8.0f)); + ASSERT_EQ(-b, Vec2f(2.0f, 0.0f)); +} + +TEST(Vector2Functions, Absolute) { + Vec2f a(-5.0f, -3.0f); + Vec2f b(-1.0f, 2.0f); + Vec2f c(0.0f, 0.0f); + + ASSERT_EQ(a.abs(), Vec2f(5.0f, 3.0f)); + ASSERT_EQ(b.abs(), Vec2f(1.0f, 2.0f)); + ASSERT_EQ(c.abs(), Vec2f(0.0f, 0.0f)); +} + +TEST(Vector2Functions, Length) { + Vec2f a(3.0f, 4.0f); + Vec2f b(3.8f, 2.3f); + Vec2f c(23.5f, 12.4f); + + ASSERT_EQ(a.length(), 5); + ASSERT_FLOAT_EQ(b.length(), 4.4418464f); + ASSERT_FLOAT_EQ(c.length(), 26.5708486f); +} + +TEST(Vector2Functions, Normalization) { + Vec2f a(2.5f, 1.2f); + Vec2f b(-1.4f, 3.7f); + Vec2f c = Vec2f::right; + Vec2f d = Vec2f::up; + Vec2f e = Vec2f::left; + Vec2f f = Vec2f::down; + + Vec2f a_normalized = a.normalize(); + Vec2f b_normalized = b.normalize(); + + ASSERT_FLOAT_EQ(a_normalized.x, 0.9015230f); + ASSERT_FLOAT_EQ(a_normalized.y, 0.4327310f); + + ASSERT_FLOAT_EQ(b_normalized.x, -0.3538920f); + ASSERT_FLOAT_EQ(b_normalized.y, 0.9352862f); + + ASSERT_EQ(c.normalize(), Vec2f::right); + ASSERT_EQ(d.normalize(), Vec2f::up); + ASSERT_EQ(e.normalize(), Vec2f::left); + ASSERT_EQ(f.normalize(), Vec2f::down); +} + +TEST(Vector2Functions, Splat) { + ASSERT_EQ(Vec2f::splat(1.0f), Vec2f(1.0f, 1.0f)); + ASSERT_EQ(Vec2f::splat(5.0f), Vec2f(5.0f, 5.0f)); +} + +TEST(Vector2Functions, Dot) { + Vec2f a(1.3f, 4.5f); + Vec2f b(2.5f, 3.7f); + Vec2f c(6.7f, 1.3f); + + ASSERT_FLOAT_EQ(Vec2f::dot(a, b), 19.9f); + ASSERT_FLOAT_EQ(Vec2f::dot(b, a), 19.9f); + ASSERT_FLOAT_EQ(Vec2f::dot(b, c), 21.56f); + ASSERT_FLOAT_EQ(Vec2f::dot(c, b), 21.56f); +} + +TEST(Vector2Functions, Projection) { + Vec2f a(4.0f, 5.0f); + Vec2f b(3.0f, -3.0f); + Vec2f c(2.5f, -6.4f); + + ASSERT_EQ(Vec2f::project(a, b), Vec2f(-0.5f, 0.5f)); + + ASSERT_FLOAT_EQ(Vec2f::project(b, a).x, -0.2926829f); + ASSERT_FLOAT_EQ(Vec2f::project(b, a).y, -0.3658536f); + + ASSERT_FLOAT_EQ(Vec2f::project(b, c).x, 1.4138953f); + ASSERT_FLOAT_EQ(Vec2f::project(b, c).y, -3.6195721f); + + ASSERT_EQ(Vec2f::project(c, b), Vec2f(4.45f, -4.45f)); +} + +TEST(Vector2Functions, Rejection) { + Vec2f a(4.0f, 5.0f); + Vec2f b(3.0f, -3.0f); + Vec2f c(2.5f, -6.4f); + + ASSERT_EQ(Vec2f::reject(a, b), Vec2f(4.5f, 4.5f)); + + ASSERT_FLOAT_EQ(Vec2f::reject(b, a).x, 3.2926829f); + ASSERT_FLOAT_EQ(Vec2f::reject(b, a).y, -2.6341464f); + + ASSERT_FLOAT_EQ(Vec2f::reject(b, c).x, 1.5861047f); + ASSERT_FLOAT_EQ(Vec2f::reject(b, c).y, 0.6195721f); + + ASSERT_FLOAT_EQ(Vec2f::reject(c, b).x, -1.95f); + ASSERT_FLOAT_EQ(Vec2f::reject(c, b).y, -1.95f); +} + +TEST(Vector2Functions, IsNormalized) { + Vec2f a = Vec2f::up; + Vec2f b(5, 10); + + ASSERT_TRUE(a.is_normalized()); + ASSERT_FALSE(b.is_normalized()); + + Vec2f b_normalized = b.normalize(); + + ASSERT_TRUE(b_normalized.is_normalized()); +} \ No newline at end of file diff --git a/tests/bebone/core/types/vector/vector3_tests.cpp b/tests/bebone/core/types/vector/vector3_tests.cpp new file mode 100644 index 00000000..f66e5b95 --- /dev/null +++ b/tests/bebone/core/types/vector/vector3_tests.cpp @@ -0,0 +1,223 @@ +#include "bebone/core/core.h" +#include "gtest/gtest.h" + +using namespace bebone::core; + +TEST(Vector3Math, Addition) { + Vec3f a(2.4f, 2.0f, 1.0f); + Vec3f b(3.4f, 45.0, 4.0f); + Vec3f result(5.8f, 47.0f, 5.0f); + + ASSERT_EQ(a + b, result); + ASSERT_EQ(b + a, result); + ASSERT_EQ(a, Vec3f(2.4f, 2.0f, 1.0f)); + ASSERT_EQ(b, Vec3f(3.4f, 45.0f, 4.0f)); + + a += b; + ASSERT_EQ(a, result); + ASSERT_EQ(b, Vec3f(3.4f, 45.0f, 4.0f)); +} + +TEST(Vector3Math, Subtraction) { + Vec3f a(4.4f, 47.0f, 2.0f); + Vec3f b(3.4f, 45.0, 3.0f); + Vec3f result(1.0f, 2.0f, -1.0f); + + ASSERT_EQ(a - b, result); + ASSERT_EQ(b - a, -result); + ASSERT_EQ(a, Vec3f(4.4f, 47.0f, 2.0f)); + ASSERT_EQ(b, Vec3f(3.4f, 45.0, 3.0f)); + + a -= b; + ASSERT_EQ(a, result); + ASSERT_EQ(b, Vec3f(3.4f, 45.0f, 3.0f)); +} + +TEST(Vector3Math, Multiplication) { + Vec3f a(5.0f, 1.0f, 3.0f); + Vec3f b(2.1f, 7.0f, 2.0f); + Vec3f result(10.5f, 7.0f, 6.0f); + + ASSERT_EQ(a * b, result); + ASSERT_EQ(b * a, result); + ASSERT_EQ(a, Vec3f(5.0f, 1.0f, 3.0f)); + ASSERT_EQ(b, Vec3f(2.1f, 7.0f, 2.0f)); + + a *= b; + ASSERT_EQ(a, result); + ASSERT_EQ(b, Vec3f(2.1f, 7.0f, 2.0f)); +} + +TEST(Vector3Math, Division) { + Vec3f a(7.0f, 8.0f, 3.5f); + Vec3f b(2.0f, 4.0f, 0.5f); + Vec3f result(3.5f, 2.0f, 7.0f); + + ASSERT_EQ(a / b, result); + + ASSERT_FLOAT_EQ((b / a).x, 0.2857142f); + ASSERT_EQ((b / a).y, 0.5f); + ASSERT_FLOAT_EQ((b / a).z, 0.1428571f); + + ASSERT_EQ(a, Vec3f(7.0f, 8.0f, 3.5f)); + ASSERT_EQ(b, Vec3f(2.0f, 4.0f, 0.5f)); + + a /= b; + ASSERT_EQ(a, result); + ASSERT_EQ(b, Vec3f(2.0f, 4.0f, 0.5f)); +} + +TEST(Vector3Math, Negation) { + Vec3f a(7.0f, -8.0f, 4.3f); + Vec3f b(-2.0f, 0.0f, 5.4f); + + ASSERT_EQ(-a, Vec3f(-7.0f, 8.0f, -4.3f)); + ASSERT_EQ(-b, Vec3f(2.0f, 0.0f, -5.4f)); +} + +TEST(Vector3Functions, Absolute) { + Vec3f a(-5.0f, -3.0f, -2.0f); + Vec3f b(-1.0f, 2.0f, -3.0f); + Vec3f c = Vec3f::zero; + + ASSERT_EQ(a.abs(), Vec3f(5.0f, 3.0f, 2.0f)); + ASSERT_EQ(b.abs(), Vec3f(1.0f, 2.0f, 3.0f)); + ASSERT_EQ(c.abs(), Vec3f::zero); +} + +TEST(Vector3Functions, Length) { + Vec3f a(3.0f, 4.0f, 12.0f); + Vec3f b(3.8f, 2.3f, 4.5f); + Vec3f c(23.5f, 12.4f, 15.3f); + + ASSERT_EQ(a.length(), 13); + ASSERT_FLOAT_EQ(b.length(), 6.3229739f); + ASSERT_FLOAT_EQ(c.length(), 30.6610502f); +} + +TEST(Vector3Functions, Normalization) { + Vec3f a(2.5f, 1.2f, -3.0f); + Vec3f b(-1.4f, 3.7f, 2.4f); + Vec3f c = Vec3f::right; + Vec3f d = Vec3f::up; + Vec3f e = Vec3f::left; + Vec3f f = Vec3f::down; + + Vec3f a_normalized = a.normalize(); + Vec3f b_normalized = b.normalize(); + + ASSERT_FLOAT_EQ(a_normalized.x, 0.6119442f); + ASSERT_FLOAT_EQ(a_normalized.y, 0.2937332f); + ASSERT_FLOAT_EQ(a_normalized.z, -0.7343330f); + + ASSERT_FLOAT_EQ(b_normalized.x, -0.3025657f); + ASSERT_FLOAT_EQ(b_normalized.y, 0.7996379f); + ASSERT_FLOAT_EQ(b_normalized.z, 0.5186840f); + + ASSERT_EQ(c.normalize(), Vec3f::right); + ASSERT_EQ(d.normalize(), Vec3f::up); + ASSERT_EQ(e.normalize(), Vec3f::left); + ASSERT_EQ(f.normalize(), Vec3f::down); +} + +TEST(Vector3Functions, Splat) { + ASSERT_EQ(Vec3f::splat(1.0f), Vec3f(1.0f, 1.0f, 1.0f)); + ASSERT_EQ(Vec3f::splat(5.0f), Vec3f(5.0f, 5.0f, 5.0f)); +} + +TEST(Vector3Functions, Dot) { + Vec3f a(1.3f, 4.5f, 3.4f); + Vec3f b(2.5f, 3.7f, 1.4f); + Vec3f c(6.7f, 1.3f, 2.5f); + + ASSERT_FLOAT_EQ(Vec3f::dot(a, b), 24.66f); + ASSERT_FLOAT_EQ(Vec3f::dot(b, a), 24.66f); + ASSERT_FLOAT_EQ(Vec3f::dot(b, c), 25.06f); + ASSERT_FLOAT_EQ(Vec3f::dot(c, b), 25.06f); +} + +TEST(Vector3Functions, Cross) { + Vec3f a(1.3f, 4.5f, 3.4f); + Vec3f b(2.5f, 3.7f, 1.4f); + Vec3f c(6.7f, 1.3f, 2.5f); + + ASSERT_FLOAT_EQ(Vec3f::cross(a, b).x, -6.28f); + ASSERT_FLOAT_EQ(Vec3f::cross(a, b).y, 6.68f); + ASSERT_FLOAT_EQ(Vec3f::cross(a, b).z, -6.44f); + + ASSERT_FLOAT_EQ(Vec3f::cross(b, a).x, 6.28f); + ASSERT_FLOAT_EQ(Vec3f::cross(b, a).y, -6.68f); + ASSERT_FLOAT_EQ(Vec3f::cross(b, a).z, 6.44f); + + ASSERT_FLOAT_EQ(Vec3f::cross(b, c).x, 7.43f); + ASSERT_FLOAT_EQ(Vec3f::cross(b, c).y, 3.13f); + ASSERT_FLOAT_EQ(Vec3f::cross(b, c).z, -21.54f); + + ASSERT_FLOAT_EQ(Vec3f::cross(c, b).x, -7.43f); + ASSERT_FLOAT_EQ(Vec3f::cross(c, b).y, -3.13f); + ASSERT_FLOAT_EQ(Vec3f::cross(c, b).z, 21.54f); +} + +TEST(Vector3Functions, Projection) { + Vec3f a(4.0f, 5.0f, 6.0f); + Vec3f b(3.0f, -3.0f, 3.0f); + Vec3f c(2.5f, -6.4f, 4.5f); + + ASSERT_FLOAT_EQ(Vec3f::project(a, b).x, 1.666667f); + ASSERT_FLOAT_EQ(Vec3f::project(a, b).y, -1.666667f); + ASSERT_FLOAT_EQ(Vec3f::project(a, b).z, 1.666667f); + + ASSERT_FLOAT_EQ(Vec3f::project(b, a).x, 0.7792207f); + ASSERT_FLOAT_EQ(Vec3f::project(b, a).y, 0.9740259f); + ASSERT_FLOAT_EQ(Vec3f::project(b, a).z, 1.1688311f); + + ASSERT_FLOAT_EQ(Vec3f::project(b, c).x, 1.4897717f); + ASSERT_FLOAT_EQ(Vec3f::project(b, c).y, -3.8138155f); + ASSERT_FLOAT_EQ(Vec3f::project(b, c).z, 2.6815890f); + + ASSERT_FLOAT_EQ(Vec3f::project(c, b).x, 4.4666667f); + ASSERT_FLOAT_EQ(Vec3f::project(c, b).y, -4.4666667f); + ASSERT_FLOAT_EQ(Vec3f::project(c, b).z, 4.4666667f); +} + +TEST(Vector3Functions, Rejection) { + Vec3f a(4.0f, 5.0f, 6.0f); + Vec3f b(3.0f, -3.0f, 3.0f); + Vec3f c(2.5f, -6.4f, 4.5f); + + ASSERT_FLOAT_EQ(Vec3f::reject(a, b).x, 2.333333f); + ASSERT_FLOAT_EQ(Vec3f::reject(a, b).y, 6.666667f); + ASSERT_FLOAT_EQ(Vec3f::reject(a, b).z, 4.333333f); + + ASSERT_FLOAT_EQ(Vec3f::reject(b, a).x, 2.2207793f); + ASSERT_FLOAT_EQ(Vec3f::reject(b, a).y, -3.9740259f); + ASSERT_FLOAT_EQ(Vec3f::reject(b, a).z, 1.8311689f); + + ASSERT_FLOAT_EQ(Vec3f::reject(b, c).x, 1.5102283f); + ASSERT_FLOAT_EQ(Vec3f::reject(b, c).y, 0.8138155f); + ASSERT_FLOAT_EQ(Vec3f::reject(b, c).z, 0.318411f); + + ASSERT_FLOAT_EQ(Vec3f::reject(c, b).x, -1.9666667f); + ASSERT_FLOAT_EQ(Vec3f::reject(c, b).y, -1.9333333f); + ASSERT_FLOAT_EQ(Vec3f::reject(c, b).z, 0.0333333f); +} + +TEST(Vector3Functions, IsNormalized) { + Vec3f a = Vec3f::up; + Vec3f b(5, 10, 6); + + ASSERT_TRUE(a.is_normalized()); + ASSERT_FALSE(b.is_normalized()); + + Vec3f b_normalized = b.normalize(); + + ASSERT_TRUE(b_normalized.is_normalized()); +} + +TEST(Vector3Conversions, ConversionToVec2) { + Vec3f a(4.0f, 5.0f, 6.0f); + Vec3f b(2.0f, 3.0f, 1.0f); + + ASSERT_EQ(Vec2f(a), Vec2f(4.0f, 5.0f)); + ASSERT_EQ(Vec2f(b), Vec2f(2.0f, 3.0f)); +} \ No newline at end of file diff --git a/tests/bebone/core/types/vector/vector4_tests.cpp b/tests/bebone/core/types/vector/vector4_tests.cpp new file mode 100644 index 00000000..99947cb7 --- /dev/null +++ b/tests/bebone/core/types/vector/vector4_tests.cpp @@ -0,0 +1,207 @@ +#include "bebone/core/core.h" +#include "gtest/gtest.h" + +using namespace bebone::core; + +TEST(Vector4Math, Addition) { + Vec4f a(2.4f, 2.0f, 1.0f, 0.0f); + Vec4f b(3.4f, 45.0, 4.0f, 4.0f); + Vec4f result(5.8f, 47.0f, 5.0f, 4.0f); + + ASSERT_EQ(a + b, result); + ASSERT_EQ(b + a, result); + ASSERT_EQ(a, Vec4f(2.4f, 2.0f, 1.0f, 0.0f)); + ASSERT_EQ(b, Vec4f(3.4f, 45.0f, 4.0f, 4.0f)); + + a += b; + ASSERT_EQ(a, result); + ASSERT_EQ(b, Vec4f(3.4f, 45.0f, 4.0f, 4.0f)); +} + +TEST(Vector4Math, Subtraction) { + Vec4f a(4.4f, 47.0f, 2.0f, 5.0f); + Vec4f b(3.4f, 45.0, 3.0f, 2.0f); + Vec4f result(1.0f, 2.0f, -1.0f, 3.0f); + + ASSERT_EQ(a - b, result); + ASSERT_EQ(b - a, -result); + ASSERT_EQ(a, Vec4f(4.4f, 47.0f, 2.0f, 5.0f)); + ASSERT_EQ(b, Vec4f(3.4f, 45.0, 3.0f, 2.0f)); + + a -= b; + ASSERT_EQ(a, result); + ASSERT_EQ(b, Vec4f(3.4f, 45.0f, 3.0f, 2.0f)); +} + +TEST(Vector4Math, Multiplication) { + Vec4f a(5.0f, 1.0f, 3.0f, 2.0f); + Vec4f b(2.1f, 7.0f, 2.0f, 1.0f); + Vec4f result(10.5f, 7.0f, 6.0f, 2.0f); + + ASSERT_EQ(a * b, result); + ASSERT_EQ(b * a, result); + ASSERT_EQ(a, Vec4f(5.0f, 1.0f, 3.0f, 2.0f)); + ASSERT_EQ(b, Vec4f(2.1f, 7.0f, 2.0f, 1.0f)); + + a *= b; + ASSERT_EQ(a, result); + ASSERT_EQ(b, Vec4f(2.1f, 7.0f, 2.0f, 1.0f)); +} + +TEST(Vector4Math, Division) { + Vec4f a(7.0f, 8.0f, 3.5f, 5.0f); + Vec4f b(2.0f, 4.0f, 0.5f, 5.0f); + Vec4f result(3.5f, 2.0f, 7.0f, 1.0f); + + ASSERT_EQ(a / b, result); + + ASSERT_FLOAT_EQ((b / a).x, 0.2857142f); + ASSERT_EQ((b / a).y, 0.5f); + ASSERT_FLOAT_EQ((b / a).z, 0.1428571f); + ASSERT_EQ((b / a).w, 1.0f); + + ASSERT_EQ(a, Vec4f(7.0f, 8.0f, 3.5f, 5.0f)); + ASSERT_EQ(b, Vec4f(2.0f, 4.0f, 0.5f, 5.0f)); + + a /= b; + ASSERT_EQ(a, result); + ASSERT_EQ(b, Vec4f(2.0f, 4.0f, 0.5f, 5.0f)); +} + +TEST(Vector4Math, Negation) { + Vec4f a(7.0f, -8.0f, 4.3f, 3.0f); + Vec4f b(-2.0f, 0.0f, 5.4f, 2.5f); + + ASSERT_EQ(-a, Vec4f(-7.0f, 8.0f, -4.3f, -3.0f)); + ASSERT_EQ(-b, Vec4f(2.0f, 0.0f, -5.4f, -2.5f)); +} + +TEST(Vector4Functions, Absolute) { + Vec4f a(-5.0f, -3.0f, -2.0f, 3.0f); + Vec4f b(-1.0f, 2.0f, -3.0f, -3.0f); + Vec4f c = Vec4f::zero; + + ASSERT_EQ(a.abs(), Vec4f(5.0f, 3.0f, 2.0f, 3.0f)); + ASSERT_EQ(b.abs(), Vec4f(1.0f, 2.0f, 3.0f, -3.0f)); + ASSERT_EQ(c.abs(), Vec4f::zero); +} + +TEST(Vector4Functions, Length) { + Vec4f a(3.0f, 4.0f, 12.0f, 6.0f); + Vec4f b(3.8f, 2.3f, 4.5f, 6.0f); + Vec4f c(23.5f, 12.4f, 15.3f, 1.0f); + + ASSERT_FLOAT_EQ(a.length(), 14.3178210f); + ASSERT_FLOAT_EQ(b.length(), 8.7166507f); + ASSERT_FLOAT_EQ(c.length(), 30.6773532f); +} + +TEST(Vector4Functions, Normalization) { + Vec4f a(2.5f, 1.2f, -3.0f, 1.0f); + Vec4f b(-1.4f, 3.7f, 2.4f, 0.0f); + + Vec4f a_normalized = a.normalize(); + Vec4f b_normalized = b.normalize(); + + ASSERT_FLOAT_EQ(a_normalized.x, 0.5943962f); + ASSERT_FLOAT_EQ(a_normalized.y, 0.2853102f); + ASSERT_FLOAT_EQ(a_normalized.z, -0.7132755f); + ASSERT_FLOAT_EQ(a_normalized.w, 0.2377585f); + + ASSERT_FLOAT_EQ(b_normalized.x, -0.3025657f); + ASSERT_FLOAT_EQ(b_normalized.y, 0.7996379f); + ASSERT_FLOAT_EQ(b_normalized.z, 0.5186840f); + ASSERT_FLOAT_EQ(b_normalized.w, 0.0f); +} + +TEST(Vector4Functions, Splat) { + ASSERT_EQ(Vec4f::splat(1.0f), Vec4f(1.0f, 1.0f, 1.0f, 1.0f)); + ASSERT_EQ(Vec4f::splat(5.0f), Vec4f(5.0f, 5.0f, 5.0f, 5.0f)); +} + +TEST(Vector4Functions, Dot) { + Vec4f a(1.3f, 4.5f, 3.4f, 2.0f); + Vec4f b(2.5f, 3.7f, 1.4f, 1.0f); + Vec4f c(6.7f, 1.3f, 2.5f, 0.0f); + + ASSERT_FLOAT_EQ(Vec4f::dot(a, b), 26.66f); + ASSERT_FLOAT_EQ(Vec4f::dot(b, a), 26.66f); + ASSERT_FLOAT_EQ(Vec4f::dot(b, c), 25.06f); + ASSERT_FLOAT_EQ(Vec4f::dot(c, b), 25.06f); +} + +TEST(Vector4Functions, Projection) { + Vec4f a(4.0f, 5.0f, 6.0f, 7.0f); + Vec4f b(3.0f, -3.0f, 3.0f, -3.0f); + Vec4f c(2.5f, -6.4f, 4.5f, 1.0f); + + ASSERT_FLOAT_EQ(Vec4f::project(a, b).x, -0.5f); + ASSERT_FLOAT_EQ(Vec4f::project(a, b).y, 0.5f); + ASSERT_FLOAT_EQ(Vec4f::project(a, b).z, -0.5f); + ASSERT_FLOAT_EQ(Vec4f::project(a, b).w, 0.5f); + + ASSERT_FLOAT_EQ(Vec4f::project(b, a).x, -0.19047619f); + ASSERT_FLOAT_EQ(Vec4f::project(b, a).y, -0.2380952f); + ASSERT_FLOAT_EQ(Vec4f::project(b, a).z, -0.2857142f); + ASSERT_FLOAT_EQ(Vec4f::project(b, a).w, -0.3333333f); + + ASSERT_FLOAT_EQ(Vec4f::project(b, c).x, 1.3584574f); + ASSERT_FLOAT_EQ(Vec4f::project(b, c).y, -3.4776511f); + ASSERT_FLOAT_EQ(Vec4f::project(b, c).z, 2.4452234f); + ASSERT_FLOAT_EQ(Vec4f::project(b, c).w, 0.5433829f); + + ASSERT_FLOAT_EQ(Vec4f::project(c, b).x, 3.1f); + ASSERT_FLOAT_EQ(Vec4f::project(c, b).y, -3.1f); + ASSERT_FLOAT_EQ(Vec4f::project(c, b).z, 3.1f); + ASSERT_FLOAT_EQ(Vec4f::project(c, b).w, -3.1f); +} + +TEST(Vector4Functions, Rejection) { + Vec4f a(4.0f, 5.0f, 6.0f, 7.0f); + Vec4f b(3.0f, -3.0f, 3.0f, -3.0f); + Vec4f c(2.5f, -6.4f, 4.5f, 1.0f); + + ASSERT_FLOAT_EQ(Vec4f::reject(a, b).x, 4.5f); + ASSERT_FLOAT_EQ(Vec4f::reject(a, b).y, 4.5f); + ASSERT_FLOAT_EQ(Vec4f::reject(a, b).z, 6.5f); + ASSERT_FLOAT_EQ(Vec4f::reject(a, b).w, 6.5f); + + ASSERT_FLOAT_EQ(Vec4f::reject(b, a).x, 3.1904761f); + ASSERT_FLOAT_EQ(Vec4f::reject(b, a).y, -2.7619048f); + ASSERT_FLOAT_EQ(Vec4f::reject(b, a).z, 3.2857142f); + ASSERT_FLOAT_EQ(Vec4f::reject(b, a).w, -2.6666667f); + + ASSERT_FLOAT_EQ(Vec4f::reject(b, c).x, 1.6415427f); + ASSERT_FLOAT_EQ(Vec4f::reject(b, c).y, 0.47765088f); + ASSERT_FLOAT_EQ(Vec4f::reject(b, c).z, 0.55477667f); + ASSERT_FLOAT_EQ(Vec4f::reject(b, c).w, -3.5433829f); + + ASSERT_FLOAT_EQ(Vec4f::reject(c, b).x, -0.6f); + ASSERT_FLOAT_EQ(Vec4f::reject(c, b).y, -3.3f); + ASSERT_FLOAT_EQ(Vec4f::reject(c, b).z, 1.4f); + ASSERT_FLOAT_EQ(Vec4f::reject(c, b).w, 4.1f); +} + +TEST(Vector4Functions, IsNormalized) { + Vec4f b(5, 10, 4, 2); + ASSERT_FALSE(b.is_normalized()); + + Vec4f b_normalized = b.normalize(); + ASSERT_TRUE(b_normalized.is_normalized()); +} + +TEST(Vector4Conversions, ConversionToVec2) { + Vec4f a(4.0f, 5.0f, 6.0f, 4.0f); + Vec4f b(2.0f, 3.0f, 1.0f, 4.0f); + + ASSERT_EQ(Vec2f(a), Vec2f(4.0f, 5.0f)); + ASSERT_EQ(Vec2f(b), Vec2f(2.0f, 3.0f)); +} + +TEST(Vector4Conversions, ConversionToVec3) { + Vec4f a(4.0f, 5.0f, 6.0f, 4.0f); + Vec4f b(2.0f, 3.0f, 1.0f, 4.0f); + + ASSERT_EQ(Vec3f(a), Vec3f(4.0f, 5.0f, 6.0f)); + ASSERT_EQ(Vec3f(b), Vec3f(2.0f, 3.0f, 1.0f)); +} \ No newline at end of file diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt deleted file mode 100644 index fcadfdb0..00000000 --- a/tests/unit/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -enable_testing() - -include_directories("./") -include_directories("../../../src") - -add_subdirectory(bebone) diff --git a/tests/unit/bebone/CMakeLists.txt b/tests/unit/bebone/CMakeLists.txt deleted file mode 100644 index 2c787f03..00000000 --- a/tests/unit/bebone/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -cmake_minimum_required(VERSION 3.21) -project(BeboneTests) - -include_directories("../../../src") -include_directories("../../../3dparty/glad/include") -include_directories("../../../3dparty/glfw/include") -include_directories("../../../3dparty/Vulkan-Headers/include") -include_directories("../../../3dparty/omni_types/src") -include_directories("../../../3dparty/stb") -include_directories("../../../3dparty/imgui") - -add_subdirectory(core) diff --git a/tests/unit/bebone/core/CMakeLists.txt b/tests/unit/bebone/core/CMakeLists.txt deleted file mode 100644 index 0e92f202..00000000 --- a/tests/unit/bebone/core/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -add_executable(bebone_arena_allocator_tests_1 bebone_arena_allocator_tests_1.cpp) -target_link_libraries(bebone_arena_allocator_tests_1 bebone_core) - -add_executable(bebone_arena_container_tests_1 bebone_arena_container_tests_1.cpp) -target_link_libraries(bebone_arena_container_tests_1 bebone_core) - -enable_testing() - -add_test(NAME Bebone_Core_Arena_Allocator_Tests_1 COMMAND $) -add_test(NAME Bebone_Core_Arena_Container_Tests_1 COMMAND $) \ No newline at end of file diff --git a/tests/unit/bebone/core/bebone_arena_allocator_tests_1.cpp b/tests/unit/bebone/core/bebone_arena_allocator_tests_1.cpp deleted file mode 100644 index d148fe6a..00000000 --- a/tests/unit/bebone/core/bebone_arena_allocator_tests_1.cpp +++ /dev/null @@ -1,70 +0,0 @@ -#include "bebone/core/core.h" -#include "test_shared.h" - -int main() { - using namespace bebone::core; - - TEST_CASE { - ArenaAllocator arena(_BEBONE_MEMORY_BYTES_1KB_); - - ensure(arena.allocated() == 0); - } - - TEST_CASE { - ArenaAllocator arena(_BEBONE_MEMORY_BYTES_1KB_); - - ensure(arena.capacity() == _BEBONE_MEMORY_BYTES_1KB_); - } - - TEST_CASE { - ArenaAllocator arena(_BEBONE_MEMORY_BYTES_1KB_); - - int* mem = static_cast(arena.alloc(sizeof(int))); - *mem = 69; - - ensure(*mem == 69); - } - - TEST_CASE { - ArenaAllocator arena(_BEBONE_MEMORY_BYTES_1KB_); - - int* memInt = static_cast(arena.alloc(sizeof(int))); - *memInt = 69; - - struct Data{ int data[16]; }; - - Data* memData = static_cast(arena.alloc(sizeof(Data))); - *memData = Data(); - - ensure(*memInt == 69); - } - - TEST_CASE { - ArenaAllocator arena(_BEBONE_MEMORY_BYTES_1KB_); - - { - int* memInt = static_cast(arena.alloc(sizeof(int))); - *memInt = 420; - } - - arena.clear(); - - int* memInt = static_cast(arena.alloc(sizeof(int))); - *memInt = 69; - - ensure(*memInt == 69); - } - - TEST_CASE { - ArenaAllocator arena(sizeof(char)); - - char* memChar = static_cast(arena.alloc(sizeof(char))); - *memChar = 25; - ensure(*memChar == 25); - - void* ptr = arena.alloc(sizeof(size_t)); - ensure(ptr == nullptr); - } - - return 0; -} \ No newline at end of file diff --git a/tests/unit/bebone/core/bebone_arena_container_tests_1.cpp b/tests/unit/bebone/core/bebone_arena_container_tests_1.cpp deleted file mode 100644 index ad1c0008..00000000 --- a/tests/unit/bebone/core/bebone_arena_container_tests_1.cpp +++ /dev/null @@ -1,63 +0,0 @@ -#include "bebone/core/core.h" -#include "test_shared.h" - -int main() { - using namespace bebone::core; - - TEST_CASE { - ArenaContainer container(_BEBONE_MEMORY_BYTES_1KB_); - - int* e1 = static_cast(container.alloc(sizeof(int))); - int* e2 = static_cast(container.alloc(sizeof(int))); - int* e3 = static_cast(container.alloc(sizeof(int))); - - *e1 = 16; - *e2 = 32; - *e3 = 64; - - int* ee1 = static_cast(container.at(0)); - int* ee2 = static_cast(container.at(1)); - int* ee3 = static_cast(container.at(2)); - - ensure(*ee1 == *e1); - ensure(*ee2 == *e2); - ensure(*ee3 == *e3); - - ensure(container.size() == 3); - } - - TEST_CASE { - ArenaContainer container(_BEBONE_MEMORY_BYTES_1KB_ * 256); - - for(int i = 0; i < 100; ++i) { - int* e = static_cast(container.alloc(sizeof(int))); - *e = i; - - ensure(container.size() == static_cast(i + 1)); - } - - for(int i = 0; i < 100; ++i) { - int* e = static_cast(container.at(i)); - ensure(*e == i); - } - - ensure(container.size() == 100); - } - - TEST_CASE { - ArenaContainer container(_BEBONE_MEMORY_BYTES_1KB_ * 256); - - for(int i = 0; i < 100; ++i) { - int* e = static_cast(container.alloc(sizeof(int))); - *e = i; - - ensure(container.size() == static_cast(i + 1)); - } - - container.clear(); - - ensure(container.size() == 0); - } - - return 0; -} \ No newline at end of file diff --git a/tests/unit/test_shared.h b/tests/unit/test_shared.h deleted file mode 100644 index 4b7cee01..00000000 --- a/tests/unit/test_shared.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef _BEBONE_TESTING_TEST_SHARED_H_ -#define _BEBONE_TESTING_TEST_SHARED_H_ - -#define ensure(EXP) if(!(EXP)) return 1; -#define ensure_const(EXP) if constexpr (!(EXP)) return 1; -#define TEST_CASE - -#endif \ No newline at end of file