├── .github ├── 10jan2022.PNG ├── 1jan2022.PNG ├── 23dec2021.PNG ├── 26dec2021.PNG ├── 29dec2021.PNG ├── 2jan2022.PNG ├── 30dec2021.PNG ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── fxaa.PNG ├── logo.png └── no_fxaa.PNG ├── .gitignore ├── .gitmodules ├── CMakeLists.txt ├── Editor ├── Assets │ ├── Configs │ │ └── DefaultConfig.toml │ ├── EnvMaps │ │ ├── QuattroCanti │ │ │ ├── 1k.hdr │ │ │ └── 4k.hdr │ │ └── SnowyField │ │ │ ├── 1k.hdr │ │ │ └── 4k.hdr │ ├── Fonts │ │ └── Consolas.ttf │ ├── Materials │ │ ├── BRDFMaterial.toml │ │ ├── EquirectangularCubemapMaterial.toml │ │ ├── FXAAMaterial.toml │ │ ├── GeometryMaterial.toml │ │ ├── IrradianceMaterial.toml │ │ ├── MeshGeometryMaterial.toml │ │ ├── PrefilterMaterial.toml │ │ ├── SkyboxMaterial.toml │ │ └── TonemappingMaterial.toml │ ├── Models │ │ ├── Cube.bin │ │ ├── Cube.gltf │ │ ├── DamagedHelmet.bin │ │ ├── DamagedHelmet.gltf │ │ ├── Sphere.bin │ │ ├── Sphere.gltf │ │ ├── Suzanne.bin │ │ └── Suzanne.gltf │ ├── Shaders │ │ ├── BRDF │ │ │ └── Compute.glsl │ │ ├── EquirectangularCubemap │ │ │ └── Compute.glsl │ │ ├── FXAA │ │ │ ├── Fragment.glsl │ │ │ └── Vertex.glsl │ │ ├── Geometry │ │ │ ├── Fragment.glsl │ │ │ ├── Mesh.glsl │ │ │ ├── MeshFragment.glsl │ │ │ ├── Task.glsl │ │ │ └── Vertex.glsl │ │ ├── Irradiance │ │ │ └── Compute.glsl │ │ ├── Prefilter │ │ │ └── Compute.glsl │ │ ├── Skybox │ │ │ ├── Fragment.glsl │ │ │ └── Vertex.glsl │ │ └── Tonemapping │ │ │ ├── Fragment.glsl │ │ │ └── Vertex.glsl │ └── Textures │ │ ├── DamagedHelmet_Albedo.jpg │ │ ├── DamagedHelmet_MetallicRoughness.jpg │ │ ├── DamagedHelmet_Normal.jpg │ │ ├── Sphere_AO.png │ │ ├── Sphere_Albedo.png │ │ ├── Sphere_Metallic.png │ │ ├── Sphere_Normal.png │ │ ├── Sphere_Roughness.png │ │ ├── Suzanne_BaseColor.png │ │ ├── Suzanne_MetallicRoughness.png │ │ ├── awesomeface.png │ │ ├── cobblestone.png │ │ ├── paving.png │ │ └── paving2.png ├── CMakeLists.txt ├── Source │ ├── Editor.c │ ├── Editor.h │ ├── EditorCamera.c │ ├── EditorCamera.h │ ├── Panels │ │ ├── ViewportPanel.c │ │ └── ViewportPanel.h │ ├── RenderNodes │ │ ├── FXAANode.c │ │ ├── FXAANode.h │ │ ├── FinalBlitNode.c │ │ ├── FinalBlitNode.h │ │ ├── GeometryNode.c │ │ ├── GeometryNode.h │ │ ├── TonemappingNode.c │ │ └── TonemappingNode.h │ └── main.c └── imgui.ini ├── LICENSE ├── README.md ├── ThirdParty ├── cgltf │ ├── LICENSE │ └── cgltf.h ├── imgui_backends │ ├── cimgui_impl.h │ ├── imgui_impl_vulkan.cpp │ └── imgui_impl_vulkan.h ├── spirv_reflect │ ├── LICENSE │ ├── spirv.h │ ├── spirv_reflect.c │ └── spirv_reflect.h ├── stb │ ├── LICENSE │ └── stb_image.h ├── tomlc99 │ ├── LICENSE │ ├── toml.c │ └── toml.h └── vma │ ├── LICENSE │ └── vk_mem_alloc.h ├── install.bat └── src ├── CMakeLists.txt └── Euphorbe ├── Core ├── CVar.c ├── CVar.h ├── Common.h ├── Log.c ├── Log.h ├── Map.c ├── Map.h └── Vector.h ├── Euphorbe.h ├── Graphics ├── Buffer.c ├── Buffer.h ├── CommandBuffer.c ├── CommandBuffer.h ├── GPUProfiler.c ├── GPUProfiler.h ├── Image.c ├── Image.h ├── Material.c ├── Material.h ├── Mesh.c ├── Mesh.h ├── RenderGraph.c ├── RenderGraph.h ├── Renderer.c ├── Renderer.h ├── ShaderCompiler.c ├── ShaderCompiler.h └── Vulkan │ ├── ExternalBuilds.cpp │ ├── VulkanBuffer.c │ ├── VulkanBuffer.h │ ├── VulkanCommandBuffer.c │ ├── VulkanCommandBuffer.h │ ├── VulkanGPUProfiler.c │ ├── VulkanGPUProfiler.h │ ├── VulkanImage.c │ ├── VulkanImage.h │ ├── VulkanMaterial.c │ ├── VulkanMaterial.h │ ├── VulkanRenderer.c │ └── VulkanRenderer.h ├── Platform ├── FileSystem.c ├── FileSystem.h ├── Input.c ├── Input.h ├── Timer.c ├── Timer.h ├── Window.c ├── Window.h └── Windows │ ├── WindowsFileSystem.c │ ├── WindowsFileSystem.h │ ├── WindowsInput.c │ ├── WindowsInput.h │ ├── WindowsTimer.c │ ├── WindowsTimer.h │ ├── WindowsWindow.c │ └── WindowsWindow.h └── Resource ├── Resource.c └── Resource.h /.github/10jan2022.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmelieHeinrich/Euphorbe/14e4f7885844e4c733022fdb6e1bbc134b261ea5/.github/10jan2022.PNG -------------------------------------------------------------------------------- /.github/1jan2022.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmelieHeinrich/Euphorbe/14e4f7885844e4c733022fdb6e1bbc134b261ea5/.github/1jan2022.PNG -------------------------------------------------------------------------------- /.github/23dec2021.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmelieHeinrich/Euphorbe/14e4f7885844e4c733022fdb6e1bbc134b261ea5/.github/23dec2021.PNG -------------------------------------------------------------------------------- /.github/26dec2021.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmelieHeinrich/Euphorbe/14e4f7885844e4c733022fdb6e1bbc134b261ea5/.github/26dec2021.PNG -------------------------------------------------------------------------------- /.github/29dec2021.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmelieHeinrich/Euphorbe/14e4f7885844e4c733022fdb6e1bbc134b261ea5/.github/29dec2021.PNG -------------------------------------------------------------------------------- /.github/2jan2022.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmelieHeinrich/Euphorbe/14e4f7885844e4c733022fdb6e1bbc134b261ea5/.github/2jan2022.PNG -------------------------------------------------------------------------------- /.github/30dec2021.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmelieHeinrich/Euphorbe/14e4f7885844e4c733022fdb6e1bbc134b261ea5/.github/30dec2021.PNG -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/fxaa.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmelieHeinrich/Euphorbe/14e4f7885844e4c733022fdb6e1bbc134b261ea5/.github/fxaa.PNG -------------------------------------------------------------------------------- /.github/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmelieHeinrich/Euphorbe/14e4f7885844e4c733022fdb6e1bbc134b261ea5/.github/logo.png -------------------------------------------------------------------------------- /.github/no_fxaa.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmelieHeinrich/Euphorbe/14e4f7885844e4c733022fdb6e1bbc134b261ea5/.github/no_fxaa.PNG -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | euphorbe.code-workspace 3 | 4 | .vscode 5 | .vs -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "ThirdParty/volk"] 2 | path = ThirdParty/volk 3 | url = https://github.com/zeux/volk 4 | [submodule "ThirdParty/Vulkan-Headers"] 5 | path = ThirdParty/Vulkan-Headers 6 | url = https://github.com/KhronosGroup/Vulkan-Headers 7 | [submodule "ThirdParty/cimgui"] 8 | path = ThirdParty/cimgui 9 | url = https://github.com/Sausty/cimgui 10 | [submodule "ThirdParty/cglm"] 11 | path = ThirdParty/cglm 12 | url = https://github.com/recp/cglm 13 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # CMake Header 2 | project(Euphorbe LANGUAGES C CXX) 3 | 4 | cmake_minimum_required(VERSION 3.8) 5 | 6 | # Settings 7 | set(CMAKE_C_STANDARD 11) 8 | set(CMAKE_C_STANDARD_REQUIRED ON) 9 | set(CMAKE_C_EXTENSIONS OFF) 10 | 11 | # Dependency settings 12 | set(IMGUI_STATIC "on") 13 | 14 | # Dependencies 15 | add_subdirectory(ThirdParty/volk) 16 | add_subdirectory(ThirdParty/cimgui) 17 | add_subdirectory(ThirdParty/cglm) 18 | 19 | # ImGui impl 20 | add_library(imgui_impl STATIC ThirdParty/cimgui/imgui/backends/imgui_impl_win32.h 21 | ThirdParty/cimgui/imgui/backends/imgui_impl_win32.cpp 22 | ThirdParty/imgui_backends/imgui_impl_vulkan.h 23 | ThirdParty/imgui_backends/imgui_impl_vulkan.cpp 24 | ThirdParty/imgui_backends/cimgui_impl.h) 25 | target_include_directories(imgui_impl PRIVATE ThirdParty/cimgui/imgui $ENV{VULKAN_SDK}/Include ThirdParty/volk) 26 | target_link_libraries(imgui_impl PUBLIC cimgui) 27 | target_compile_definitions(imgui_impl PRIVATE IMGUI_IMPL_API=extern\ \"C\") 28 | target_compile_definitions(imgui_impl PRIVATE VK_NO_PROTOTYPES) 29 | 30 | # Toml C99 31 | add_library(TOML STATIC ThirdParty/tomlc99/toml.h ThirdParty/tomlc99/toml.c) 32 | 33 | # Main Projects 34 | add_subdirectory(src) 35 | add_subdirectory(Editor) -------------------------------------------------------------------------------- /Editor/Assets/Configs/DefaultConfig.toml: -------------------------------------------------------------------------------- 1 | [CVarTable] 2 | Table = [ 3 | ["BOOL", "dark_mode", true], 4 | ["BOOL", "enable_fxaa", true], 5 | ["BOOL", "gamma_correction", true], 6 | ["BOOL", "enable_skybox", true], 7 | ["BOOL", "enable_vsync", true], 8 | ["BOOL", "enable_mesh_shaders", true], 9 | ["BOOL", "log_renderer_events", false], 10 | ["BOOL", "log_found_layers", false], 11 | ["BOOL", "enable_debug", true], 12 | ["BOOL", "gui_should_clear", true], 13 | ["DOUBLE", "camera_friction", 10.0], 14 | ["DOUBLE", "camera_max_velocity", 15.0], 15 | ["DOUBLE", "camera_acceleration", 20.0 ], 16 | ["INT", "tonemapping_curve", 0] 17 | ] -------------------------------------------------------------------------------- /Editor/Assets/EnvMaps/QuattroCanti/1k.hdr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmelieHeinrich/Euphorbe/14e4f7885844e4c733022fdb6e1bbc134b261ea5/Editor/Assets/EnvMaps/QuattroCanti/1k.hdr -------------------------------------------------------------------------------- /Editor/Assets/EnvMaps/QuattroCanti/4k.hdr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmelieHeinrich/Euphorbe/14e4f7885844e4c733022fdb6e1bbc134b261ea5/Editor/Assets/EnvMaps/QuattroCanti/4k.hdr -------------------------------------------------------------------------------- /Editor/Assets/EnvMaps/SnowyField/1k.hdr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmelieHeinrich/Euphorbe/14e4f7885844e4c733022fdb6e1bbc134b261ea5/Editor/Assets/EnvMaps/SnowyField/1k.hdr -------------------------------------------------------------------------------- /Editor/Assets/EnvMaps/SnowyField/4k.hdr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmelieHeinrich/Euphorbe/14e4f7885844e4c733022fdb6e1bbc134b261ea5/Editor/Assets/EnvMaps/SnowyField/4k.hdr -------------------------------------------------------------------------------- /Editor/Assets/Fonts/Consolas.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmelieHeinrich/Euphorbe/14e4f7885844e4c733022fdb6e1bbc134b261ea5/Editor/Assets/Fonts/Consolas.ttf -------------------------------------------------------------------------------- /Editor/Assets/Materials/BRDFMaterial.toml: -------------------------------------------------------------------------------- 1 | [Shaders] 2 | EnableMeshShaders = false 3 | Compute = "Assets/Shaders/BRDF/Compute.glsl" 4 | 5 | [DescriptorLayout] 6 | DescriptorSetLayouts = [[["StorageImage"], 1]] 7 | DescriptorSetLayoutCount = 1 8 | 9 | [PushConstants] 10 | HasPushConstants = 0 11 | Size = 16 -------------------------------------------------------------------------------- /Editor/Assets/Materials/EquirectangularCubemapMaterial.toml: -------------------------------------------------------------------------------- 1 | [Shaders] 2 | EnableMeshShaders = false 3 | Compute = "Assets/Shaders/EquirectangularCubemap/Compute.glsl" 4 | 5 | [DescriptorLayout] 6 | DescriptorSetLayouts = [[["StorageImage", "StorageImage"], 2]] 7 | DescriptorSetLayoutCount = 1 8 | 9 | [PushConstants] 10 | HasPushConstants = 0 11 | Size = 32 -------------------------------------------------------------------------------- /Editor/Assets/Materials/FXAAMaterial.toml: -------------------------------------------------------------------------------- 1 | [MaterialProperties] 2 | CullMode = "None" 3 | DepthOperation = "Less" 4 | FrontFace = "CW" 5 | PrimitiveTopology = "TriangleStrip" 6 | PolygonMode = "Fill" 7 | 8 | [RenderInfo] 9 | ColorFormats = ["RGBA16"] 10 | ColorAttachmentCount = 1 11 | DepthFormat = "D32_Float" 12 | 13 | [Shaders] 14 | EnableMeshShaders = false 15 | Vertex = "Assets/Shaders/FXAA/Vertex.glsl" 16 | Fragment = "Assets/Shaders/FXAA/Fragment.glsl" 17 | 18 | [DescriptorLayout] 19 | DescriptorSetLayouts = [[["Sampler", "SampledImage"], 2]] 20 | DescriptorSetLayoutCount = 1 21 | 22 | [PushConstants] 23 | HasPushConstants = 1 24 | Size = 32 -------------------------------------------------------------------------------- /Editor/Assets/Materials/GeometryMaterial.toml: -------------------------------------------------------------------------------- 1 | [MaterialProperties] 2 | CullMode = "Back" 3 | DepthOperation = "Less" 4 | FrontFace = "CCW" 5 | PrimitiveTopology = "TriangleList" 6 | PolygonMode = "Fill" 7 | 8 | [RenderInfo] 9 | ColorAttachmentCount = 1 10 | DepthFormat = "D32_Float" 11 | ColorFormats = ["RGBA16"] 12 | 13 | [Shaders] 14 | EnableMeshShaders = false 15 | Vertex = "Assets/Shaders/Geometry/Vertex.glsl" 16 | Fragment = "Assets/Shaders/Geometry/Fragment.glsl" 17 | 18 | [DescriptorLayout] 19 | DescriptorSetLayouts = [ 20 | [ ["UniformBuffer", "UniformBuffer", "Sampler", "SampledImage", "SampledImage", "SampledImage"], 6], 21 | [ ["UniformBuffer", "Sampler", "Sampler", "SampledImage", "SampledImage", "SampledImage", "SampledImage", "SampledImage"], 7] 22 | ] 23 | DescriptorSetLayoutCount = 2 24 | 25 | [PushConstants] 26 | HasPushConstants = 1 27 | Size = 144 -------------------------------------------------------------------------------- /Editor/Assets/Materials/IrradianceMaterial.toml: -------------------------------------------------------------------------------- 1 | [Shaders] 2 | EnableMeshShaders = false 3 | Compute = "Assets/Shaders/Irradiance/Compute.glsl" 4 | 5 | [DescriptorLayout] 6 | DescriptorSetLayouts = [[["CombinedImageSampler", "StorageImage"], 2]] 7 | DescriptorSetLayoutCount = 1 8 | 9 | [PushConstants] 10 | HasPushConstants = 0 11 | Size = 32 -------------------------------------------------------------------------------- /Editor/Assets/Materials/MeshGeometryMaterial.toml: -------------------------------------------------------------------------------- 1 | [MaterialProperties] 2 | CullMode = "Back" 3 | DepthOperation = "Less" 4 | FrontFace = "CCW" 5 | PrimitiveTopology = "TriangleList" 6 | PolygonMode = "Fill" 7 | 8 | [RenderInfo] 9 | ColorAttachmentCount = 1 10 | DepthFormat = "D32_Float" 11 | ColorFormats = ["RGBA16"] 12 | 13 | [Shaders] 14 | EnableMeshShaders = true 15 | Task = "Assets/Shaders/Geometry/Task.glsl" 16 | Mesh = "Assets/Shaders/Geometry/Mesh.glsl" 17 | Fragment = "Assets/Shaders/Geometry/MeshFragment.glsl" 18 | 19 | [DescriptorLayout] 20 | DescriptorSetLayouts = [ 21 | [ ["StorageBuffer", "StorageBuffer"], 2], 22 | [ ["UniformBuffer", "UniformBuffer", "Sampler", "SampledImage", "SampledImage", "SampledImage"], 6], 23 | [ ["UniformBuffer", "Sampler", "Sampler", "SampledImage", "SampledImage", "SampledImage", "SampledImage", "SampledImage"], 7] 24 | ] 25 | DescriptorSetLayoutCount = 3 26 | 27 | [PushConstants] 28 | HasPushConstants = 1 29 | Size = 144 -------------------------------------------------------------------------------- /Editor/Assets/Materials/PrefilterMaterial.toml: -------------------------------------------------------------------------------- 1 | [Shaders] 2 | EnableMeshShaders = false 3 | Compute = "Assets/Shaders/Prefilter/Compute.glsl" 4 | 5 | [DescriptorLayout] 6 | DescriptorSetLayouts = [[["CombinedImageSampler", "StorageImage"], 2]] 7 | DescriptorSetLayoutCount = 1 8 | 9 | [PushConstants] 10 | HasPushConstants = 1 11 | Size = 16 -------------------------------------------------------------------------------- /Editor/Assets/Materials/SkyboxMaterial.toml: -------------------------------------------------------------------------------- 1 | [MaterialProperties] 2 | CullMode = "Front" 3 | DepthOperation = "Always" 4 | FrontFace = "CCW" 5 | PrimitiveTopology = "TriangleList" 6 | PolygonMode = "Fill" 7 | 8 | [RenderInfo] 9 | ColorAttachmentCount = 2 10 | DepthFormat = "D32_Float" 11 | ColorFormats = ["RGBA16", "RG16"] 12 | 13 | [Shaders] 14 | EnableMeshShaders = false 15 | Vertex = "Assets/Shaders/Skybox/Vertex.glsl" 16 | Fragment = "Assets/Shaders/Skybox/Fragment.glsl" 17 | 18 | [DescriptorLayout] 19 | DescriptorSetLayouts = [[["Sampler", "SampledImage"], 2]] 20 | DescriptorSetLayoutCount = 1 21 | 22 | [PushConstants] 23 | HasPushConstants = 1 24 | Size = 64 -------------------------------------------------------------------------------- /Editor/Assets/Materials/TonemappingMaterial.toml: -------------------------------------------------------------------------------- 1 | [MaterialProperties] 2 | CullMode = "None" 3 | DepthOperation = "Less" 4 | FrontFace = "CW" 5 | PrimitiveTopology = "TriangleStrip" 6 | PolygonMode = "Fill" 7 | 8 | [RenderInfo] 9 | ColorFormats = ["RGBA16"] 10 | ColorAttachmentCount = 1 11 | DepthFormat = "D32_Float" 12 | 13 | [Shaders] 14 | EnableMeshShaders = false 15 | Vertex = "Assets/Shaders/Tonemapping/Vertex.glsl" 16 | Fragment = "Assets/Shaders/Tonemapping/Fragment.glsl" 17 | 18 | [DescriptorLayout] 19 | DescriptorSetLayouts = [[["Sampler", "SampledImage"], 2]] 20 | DescriptorSetLayoutCount = 1 21 | 22 | [PushConstants] 23 | HasPushConstants = 1 24 | Size = 16 -------------------------------------------------------------------------------- /Editor/Assets/Models/Cube.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmelieHeinrich/Euphorbe/14e4f7885844e4c733022fdb6e1bbc134b261ea5/Editor/Assets/Models/Cube.bin -------------------------------------------------------------------------------- /Editor/Assets/Models/Cube.gltf: -------------------------------------------------------------------------------- 1 | { 2 | "accessors" : [ 3 | { 4 | "bufferView" : 0, 5 | "byteOffset" : 0, 6 | "componentType" : 5123, 7 | "count" : 36, 8 | "max" : [ 9 | 35 10 | ], 11 | "min" : [ 12 | 0 13 | ], 14 | "type" : "SCALAR" 15 | }, 16 | { 17 | "bufferView" : 1, 18 | "byteOffset" : 0, 19 | "componentType" : 5126, 20 | "count" : 36, 21 | "max" : [ 22 | 1.000000, 23 | 1.000000, 24 | 1.000001 25 | ], 26 | "min" : [ 27 | -1.000000, 28 | -1.000000, 29 | -1.000000 30 | ], 31 | "type" : "VEC3" 32 | }, 33 | { 34 | "bufferView" : 2, 35 | "byteOffset" : 0, 36 | "componentType" : 5126, 37 | "count" : 36, 38 | "max" : [ 39 | 1.000000, 40 | 1.000000, 41 | 1.000000 42 | ], 43 | "min" : [ 44 | -1.000000, 45 | -1.000000, 46 | -1.000000 47 | ], 48 | "type" : "VEC3" 49 | }, 50 | { 51 | "bufferView" : 3, 52 | "byteOffset" : 0, 53 | "componentType" : 5126, 54 | "count" : 36, 55 | "max" : [ 56 | 1.000000, 57 | -0.000000, 58 | -0.000000, 59 | 1.000000 60 | ], 61 | "min" : [ 62 | 0.000000, 63 | -0.000000, 64 | -1.000000, 65 | -1.000000 66 | ], 67 | "type" : "VEC4" 68 | }, 69 | { 70 | "bufferView" : 4, 71 | "byteOffset" : 0, 72 | "componentType" : 5126, 73 | "count" : 36, 74 | "max" : [ 75 | 1.000000, 76 | 1.000000 77 | ], 78 | "min" : [ 79 | -1.000000, 80 | -1.000000 81 | ], 82 | "type" : "VEC2" 83 | } 84 | ], 85 | "asset" : { 86 | "generator" : "VKTS glTF 2.0 exporter", 87 | "version" : "2.0" 88 | }, 89 | "bufferViews" : [ 90 | { 91 | "buffer" : 0, 92 | "byteLength" : 72, 93 | "byteOffset" : 0, 94 | "target" : 34963 95 | }, 96 | { 97 | "buffer" : 0, 98 | "byteLength" : 432, 99 | "byteOffset" : 72, 100 | "target" : 34962 101 | }, 102 | { 103 | "buffer" : 0, 104 | "byteLength" : 432, 105 | "byteOffset" : 504, 106 | "target" : 34962 107 | }, 108 | { 109 | "buffer" : 0, 110 | "byteLength" : 576, 111 | "byteOffset" : 936, 112 | "target" : 34962 113 | }, 114 | { 115 | "buffer" : 0, 116 | "byteLength" : 288, 117 | "byteOffset" : 1512, 118 | "target" : 34962 119 | } 120 | ], 121 | "buffers" : [ 122 | { 123 | "byteLength" : 1800, 124 | "uri" : "Cube.bin" 125 | } 126 | ], 127 | "images" : [ 128 | { 129 | "uri" : "Cube_BaseColor.png" 130 | }, 131 | { 132 | "uri" : "Cube_MetallicRoughness.png" 133 | } 134 | ], 135 | "materials" : [ 136 | { 137 | "name" : "Cube", 138 | "pbrMetallicRoughness" : { 139 | "baseColorTexture" : { 140 | "index" : 0 141 | }, 142 | "metallicRoughnessTexture" : { 143 | "index" : 1 144 | } 145 | } 146 | } 147 | ], 148 | "meshes" : [ 149 | { 150 | "name" : "Cube", 151 | "primitives" : [ 152 | { 153 | "attributes" : { 154 | "NORMAL" : 2, 155 | "POSITION" : 1, 156 | "TANGENT" : 3, 157 | "TEXCOORD_0" : 4 158 | }, 159 | "indices" : 0, 160 | "material" : 0, 161 | "mode" : 4 162 | } 163 | ] 164 | } 165 | ], 166 | "nodes" : [ 167 | { 168 | "mesh" : 0, 169 | "name" : "Cube" 170 | } 171 | ], 172 | "samplers" : [ 173 | {} 174 | ], 175 | "scene" : 0, 176 | "scenes" : [ 177 | { 178 | "nodes" : [ 179 | 0 180 | ] 181 | } 182 | ], 183 | "textures" : [ 184 | { 185 | "sampler" : 0, 186 | "source" : 0 187 | }, 188 | { 189 | "sampler" : 0, 190 | "source" : 1 191 | } 192 | ] 193 | } -------------------------------------------------------------------------------- /Editor/Assets/Models/DamagedHelmet.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmelieHeinrich/Euphorbe/14e4f7885844e4c733022fdb6e1bbc134b261ea5/Editor/Assets/Models/DamagedHelmet.bin -------------------------------------------------------------------------------- /Editor/Assets/Models/DamagedHelmet.gltf: -------------------------------------------------------------------------------- 1 | { 2 | "accessors" : [ 3 | { 4 | "bufferView" : 0, 5 | "componentType" : 5123, 6 | "count" : 46356, 7 | "max" : [ 8 | 14555 9 | ], 10 | "min" : [ 11 | 0 12 | ], 13 | "type" : "SCALAR" 14 | }, 15 | { 16 | "bufferView" : 1, 17 | "componentType" : 5126, 18 | "count" : 14556, 19 | "max" : [ 20 | 0.9424954056739807, 21 | 0.8128451108932495, 22 | 0.900973916053772 23 | ], 24 | "min" : [ 25 | -0.9474585652351379, 26 | -1.18715500831604, 27 | -0.9009949564933777 28 | ], 29 | "type" : "VEC3" 30 | }, 31 | { 32 | "bufferView" : 2, 33 | "componentType" : 5126, 34 | "count" : 14556, 35 | "max" : [ 36 | 1.0, 37 | 1.0, 38 | 1.0 39 | ], 40 | "min" : [ 41 | -1.0, 42 | -1.0, 43 | -1.0 44 | ], 45 | "type" : "VEC3" 46 | }, 47 | { 48 | "bufferView" : 3, 49 | "componentType" : 5126, 50 | "count" : 14556, 51 | "max" : [ 52 | 0.9999759793281555, 53 | 1.998665988445282 54 | ], 55 | "min" : [ 56 | 0.002448640065267682, 57 | 1.0005531199858524 58 | ], 59 | "type" : "VEC2" 60 | } 61 | ], 62 | "asset" : { 63 | "generator" : "Khronos Blender glTF 2.0 exporter", 64 | "version" : "2.0" 65 | }, 66 | "bufferViews" : [ 67 | { 68 | "buffer" : 0, 69 | "byteLength" : 92712, 70 | "byteOffset" : 0, 71 | "target" : 34963 72 | }, 73 | { 74 | "buffer" : 0, 75 | "byteLength" : 174672, 76 | "byteOffset" : 92712, 77 | "target" : 34962 78 | }, 79 | { 80 | "buffer" : 0, 81 | "byteLength" : 174672, 82 | "byteOffset" : 267384, 83 | "target" : 34962 84 | }, 85 | { 86 | "buffer" : 0, 87 | "byteLength" : 116448, 88 | "byteOffset" : 442056, 89 | "target" : 34962 90 | } 91 | ], 92 | "buffers" : [ 93 | { 94 | "byteLength" : 558504, 95 | "uri" : "DamagedHelmet.bin" 96 | } 97 | ], 98 | "images" : [ 99 | { 100 | "uri" : "Default_albedo.jpg" 101 | }, 102 | { 103 | "uri" : "Default_metalRoughness.jpg" 104 | }, 105 | { 106 | "uri" : "Default_emissive.jpg" 107 | }, 108 | { 109 | "uri" : "Default_AO.jpg" 110 | }, 111 | { 112 | "uri" : "Default_normal.jpg" 113 | } 114 | ], 115 | "materials" : [ 116 | { 117 | "emissiveFactor" : [ 118 | 1.0, 119 | 1.0, 120 | 1.0 121 | ], 122 | "emissiveTexture" : { 123 | "index" : 2 124 | }, 125 | "name" : "Material_MR", 126 | "normalTexture" : { 127 | "index" : 4 128 | }, 129 | "occlusionTexture" : { 130 | "index" : 3 131 | }, 132 | "pbrMetallicRoughness" : { 133 | "baseColorTexture" : { 134 | "index" : 0 135 | }, 136 | "metallicRoughnessTexture" : { 137 | "index" : 1 138 | } 139 | } 140 | } 141 | ], 142 | "meshes" : [ 143 | { 144 | "name" : "mesh_helmet_LP_13930damagedHelmet", 145 | "primitives" : [ 146 | { 147 | "attributes" : { 148 | "NORMAL" : 2, 149 | "POSITION" : 1, 150 | "TEXCOORD_0" : 3 151 | }, 152 | "indices" : 0, 153 | "material" : 0 154 | } 155 | ] 156 | } 157 | ], 158 | "nodes" : [ 159 | { 160 | "mesh" : 0, 161 | "name" : "node_damagedHelmet_-6514", 162 | "rotation" : [ 163 | 0.7071068286895752, 164 | 0.0, 165 | -0.0, 166 | 0.7071068286895752 167 | ] 168 | } 169 | ], 170 | "samplers" : [ 171 | {} 172 | ], 173 | "scene" : 0, 174 | "scenes" : [ 175 | { 176 | "name" : "Scene", 177 | "nodes" : [ 178 | 0 179 | ] 180 | } 181 | ], 182 | "textures" : [ 183 | { 184 | "sampler" : 0, 185 | "source" : 0 186 | }, 187 | { 188 | "sampler" : 0, 189 | "source" : 1 190 | }, 191 | { 192 | "sampler" : 0, 193 | "source" : 2 194 | }, 195 | { 196 | "sampler" : 0, 197 | "source" : 3 198 | }, 199 | { 200 | "sampler" : 0, 201 | "source" : 4 202 | } 203 | ] 204 | } -------------------------------------------------------------------------------- /Editor/Assets/Models/Sphere.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmelieHeinrich/Euphorbe/14e4f7885844e4c733022fdb6e1bbc134b261ea5/Editor/Assets/Models/Sphere.bin -------------------------------------------------------------------------------- /Editor/Assets/Models/Sphere.gltf: -------------------------------------------------------------------------------- 1 | { 2 | "accessors": [ 3 | { 4 | "bufferView": 2, 5 | "componentType": 5126, 6 | "count": 2399, 7 | "max": [ 8 | 1, 9 | 2, 10 | 1 11 | ], 12 | "min": [ 13 | -1, 14 | 0, 15 | -1 16 | ], 17 | "type": "VEC3" 18 | }, 19 | { 20 | "bufferView": 2, 21 | "byteOffset": 28788, 22 | "componentType": 5126, 23 | "count": 2399, 24 | "max": [ 25 | 1, 26 | 1, 27 | 1 28 | ], 29 | "min": [ 30 | -1, 31 | -1, 32 | -1 33 | ], 34 | "type": "VEC3" 35 | }, 36 | { 37 | "bufferView": 1, 38 | "componentType": 5126, 39 | "count": 2399, 40 | "max": [ 41 | 1, 42 | 1 43 | ], 44 | "min": [ 45 | 0, 46 | 0 47 | ], 48 | "type": "VEC2" 49 | }, 50 | { 51 | "bufferView": 0, 52 | "componentType": 5125, 53 | "count": 13536, 54 | "max": [ 55 | 2398 56 | ], 57 | "min": [ 58 | 0 59 | ], 60 | "type": "SCALAR" 61 | } 62 | ], 63 | "asset": { 64 | "extras": { 65 | "author": "rawwerks (https://sketchfab.com/rawwerks)", 66 | "license": "CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/)", 67 | "source": "https://sketchfab.com/3d-models/sphere-gltf-example-cd602a89287b4cf1a704c13e15cf48f8", 68 | "title": "sphere-gltf-example" 69 | }, 70 | "generator": "Sketchfab-9.94.0", 71 | "version": "2.0" 72 | }, 73 | "bufferViews": [ 74 | { 75 | "buffer": 0, 76 | "byteLength": 54144, 77 | "byteOffset": 0, 78 | "name": "floatBufferViews", 79 | "target": 34963 80 | }, 81 | { 82 | "buffer": 0, 83 | "byteLength": 19192, 84 | "byteOffset": 54144, 85 | "byteStride": 8, 86 | "name": "floatBufferViews", 87 | "target": 34962 88 | }, 89 | { 90 | "buffer": 0, 91 | "byteLength": 57576, 92 | "byteOffset": 73336, 93 | "byteStride": 12, 94 | "name": "floatBufferViews", 95 | "target": 34962 96 | } 97 | ], 98 | "buffers": [ 99 | { 100 | "byteLength": 130912, 101 | "uri": "Sphere.bin" 102 | } 103 | ], 104 | "materials": [ 105 | { 106 | "doubleSided": false, 107 | "name": "GLASS", 108 | "pbrMetallicRoughness": { 109 | "baseColorFactor": [ 110 | 0.98999999999999999, 111 | 0.98999999999999999, 112 | 0.98999999999999999, 113 | 1 114 | ], 115 | "metallicFactor": 0, 116 | "roughnessFactor": 0 117 | } 118 | } 119 | ], 120 | "meshes": [ 121 | { 122 | "primitives": [ 123 | { 124 | "attributes": { 125 | "NORMAL": 1, 126 | "POSITION": 0, 127 | "TEXCOORD_0": 2 128 | }, 129 | "indices": 3, 130 | "material": 0, 131 | "mode": 4 132 | } 133 | ] 134 | } 135 | ], 136 | "nodes": [ 137 | { 138 | "children": [ 139 | 1 140 | ], 141 | "name": "RootNode (gltf orientation matrix)", 142 | "rotation": [ 143 | -0.70710678118654746, 144 | -0, 145 | -0, 146 | 0.70710678118654757 147 | ] 148 | }, 149 | { 150 | "children": [ 151 | 2 152 | ], 153 | "name": "RootNode (model correction matrix)" 154 | }, 155 | { 156 | "children": [ 157 | 3 158 | ], 159 | "name": "root" 160 | }, 161 | { 162 | "children": [ 163 | 4 164 | ], 165 | "matrix": [ 166 | 1, 167 | 0, 168 | 0, 169 | 0, 170 | 0, 171 | 2.2204460492503131e-16, 172 | 1, 173 | 0, 174 | 0, 175 | -1, 176 | 2.2204460492503131e-16, 177 | 0, 178 | 0, 179 | 0, 180 | 0, 181 | 1 182 | ], 183 | "name": "GLTF_SceneRootNode" 184 | }, 185 | { 186 | "children": [ 187 | 5 188 | ], 189 | "name": "Sphere_1" 190 | }, 191 | { 192 | "mesh": 0, 193 | "name": "" 194 | } 195 | ], 196 | "scene": 0, 197 | "scenes": [ 198 | { 199 | "name": "OSG_Scene", 200 | "nodes": [ 201 | 0 202 | ] 203 | } 204 | ] 205 | } 206 | 207 | -------------------------------------------------------------------------------- /Editor/Assets/Models/Suzanne.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmelieHeinrich/Euphorbe/14e4f7885844e4c733022fdb6e1bbc134b261ea5/Editor/Assets/Models/Suzanne.bin -------------------------------------------------------------------------------- /Editor/Assets/Models/Suzanne.gltf: -------------------------------------------------------------------------------- 1 | { 2 | "accessors" : [ 3 | { 4 | "bufferView" : 0, 5 | "byteOffset" : 0, 6 | "componentType" : 5123, 7 | "count" : 11808, 8 | "max" : [ 9 | 11807 10 | ], 11 | "min" : [ 12 | 0 13 | ], 14 | "type" : "SCALAR" 15 | }, 16 | { 17 | "bufferView" : 1, 18 | "byteOffset" : 0, 19 | "componentType" : 5126, 20 | "count" : 11808, 21 | "max" : [ 22 | 1.336914, 23 | 0.950195, 24 | 0.825684 25 | ], 26 | "min" : [ 27 | -1.336914, 28 | -0.974609, 29 | -0.800781 30 | ], 31 | "type" : "VEC3" 32 | }, 33 | { 34 | "bufferView" : 2, 35 | "byteOffset" : 0, 36 | "componentType" : 5126, 37 | "count" : 11808, 38 | "max" : [ 39 | 0.996339, 40 | 0.999958, 41 | 0.999929 42 | ], 43 | "min" : [ 44 | -0.996339, 45 | -0.985940, 46 | -0.999994 47 | ], 48 | "type" : "VEC3" 49 | }, 50 | { 51 | "bufferView" : 3, 52 | "byteOffset" : 0, 53 | "componentType" : 5126, 54 | "count" : 11808, 55 | "max" : [ 56 | 0.998570, 57 | 0.999996, 58 | 0.999487, 59 | 1.000000 60 | ], 61 | "min" : [ 62 | -0.999233, 63 | -0.999453, 64 | -0.999812, 65 | 1.000000 66 | ], 67 | "type" : "VEC4" 68 | }, 69 | { 70 | "bufferView" : 4, 71 | "byteOffset" : 0, 72 | "componentType" : 5126, 73 | "count" : 11808, 74 | "max" : [ 75 | 0.999884, 76 | 0.884359 77 | ], 78 | "min" : [ 79 | 0.000116, 80 | 0.000116 81 | ], 82 | "type" : "VEC2" 83 | } 84 | ], 85 | "asset" : { 86 | "generator" : "VKTS glTF 2.0 exporter", 87 | "version" : "2.0" 88 | }, 89 | "bufferViews" : [ 90 | { 91 | "buffer" : 0, 92 | "byteLength" : 23616, 93 | "byteOffset" : 0, 94 | "target" : 34963 95 | }, 96 | { 97 | "buffer" : 0, 98 | "byteLength" : 141696, 99 | "byteOffset" : 23616, 100 | "target" : 34962 101 | }, 102 | { 103 | "buffer" : 0, 104 | "byteLength" : 141696, 105 | "byteOffset" : 165312, 106 | "target" : 34962 107 | }, 108 | { 109 | "buffer" : 0, 110 | "byteLength" : 188928, 111 | "byteOffset" : 307008, 112 | "target" : 34962 113 | }, 114 | { 115 | "buffer" : 0, 116 | "byteLength" : 94464, 117 | "byteOffset" : 495936, 118 | "target" : 34962 119 | } 120 | ], 121 | "buffers" : [ 122 | { 123 | "byteLength" : 590400, 124 | "uri" : "Suzanne.bin" 125 | } 126 | ], 127 | "images" : [ 128 | { 129 | "uri" : "Suzanne_BaseColor.png" 130 | }, 131 | { 132 | "uri" : "Suzanne_MetallicRoughness.png" 133 | } 134 | ], 135 | "materials" : [ 136 | { 137 | "name" : "Suzanne", 138 | "pbrMetallicRoughness" : { 139 | "baseColorTexture" : { 140 | "index" : 0 141 | }, 142 | "metallicRoughnessTexture" : { 143 | "index" : 1 144 | } 145 | } 146 | } 147 | ], 148 | "meshes" : [ 149 | { 150 | "name" : "Suzanne", 151 | "primitives" : [ 152 | { 153 | "attributes" : { 154 | "NORMAL" : 2, 155 | "POSITION" : 1, 156 | "TANGENT" : 3, 157 | "TEXCOORD_0" : 4 158 | }, 159 | "indices" : 0, 160 | "material" : 0, 161 | "mode" : 4 162 | } 163 | ] 164 | } 165 | ], 166 | "nodes" : [ 167 | { 168 | "mesh" : 0, 169 | "name" : "Suzanne" 170 | } 171 | ], 172 | "samplers" : [ 173 | {} 174 | ], 175 | "scene" : 0, 176 | "scenes" : [ 177 | { 178 | "nodes" : [ 179 | 0 180 | ] 181 | } 182 | ], 183 | "textures" : [ 184 | { 185 | "sampler" : 0, 186 | "source" : 0 187 | }, 188 | { 189 | "sampler" : 0, 190 | "source" : 1 191 | } 192 | ] 193 | } -------------------------------------------------------------------------------- /Editor/Assets/Shaders/BRDF/Compute.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | #define PI 3.141592654 4 | 5 | layout(local_size_x = 32, local_size_y = 32) in; 6 | 7 | layout(rg16f, binding = 0) writeonly uniform image2D brdfIntMap; 8 | 9 | float SBGeometry(float NdotV, float roughness); 10 | float SSBGeometry(vec3 N, vec3 V, vec3 L, float roughness); 11 | vec2 Hammersley(uint i, uint N); 12 | vec3 SSBImportance(vec2 Xi, vec3 N, float roughness); 13 | 14 | const uint SAMPLE_COUNT = 1024u; 15 | 16 | void main() 17 | { 18 | ivec2 invoke = ivec2(gl_GlobalInvocationID.xy); 19 | 20 | vec2 size = vec2(imageSize(brdfIntMap).xy); 21 | 22 | float NdotV = float(invoke.x) * (1.0 / size.x); 23 | float roughness = float(invoke.y) * (1.0 / size.y); 24 | 25 | vec3 V; 26 | V.x = sqrt(1.0 - NdotV * NdotV); 27 | V.y = 0.0; 28 | V.z = NdotV; 29 | 30 | float A = 0.0; 31 | float B = 0.0; 32 | 33 | vec3 N = vec3(0.0, 0.0, 1.0); 34 | 35 | for (uint i = 0u; i < SAMPLE_COUNT; ++i) 36 | { 37 | vec2 Xi = Hammersley(i, SAMPLE_COUNT); 38 | vec3 H = SSBImportance(Xi, N, roughness); 39 | vec3 L = normalize(2.0 * dot(V, H) * H - V); 40 | 41 | float NdotL = max(L.z, 0.0); 42 | float NdotH = max(H.z, 0.0); 43 | float VdotH = dot(V, H); 44 | 45 | if (NdotL > 0.0) 46 | { 47 | VdotH = max(dot(V, H), 0.0); 48 | float G = SSBGeometry(N, V, L, roughness); 49 | float G_Vis = (G * VdotH) / max(NdotH * NdotV, 1e-4); 50 | float Fc = pow(1.0 - VdotH, 5.0); 51 | 52 | A += (1.0 - Fc) * G_Vis; 53 | B += Fc * G_Vis; 54 | } 55 | } 56 | 57 | A /= float(SAMPLE_COUNT); 58 | B /= float(SAMPLE_COUNT); 59 | 60 | imageStore(brdfIntMap, invoke, vec4(A, B, 0.0, 1.0)); 61 | } 62 | 63 | // Schlick-Beckmann geometry function. 64 | float SBGeometry(float NdotV, float roughness) 65 | { 66 | float a = roughness; 67 | float k = (a * a) / 2.0; 68 | 69 | float nom = NdotV; 70 | float denom = NdotV * (1.0 - k) + k; 71 | 72 | return nom / max(denom, 1e-4); 73 | } 74 | 75 | // Smith-Schlick-Beckmann geometry function. 76 | float SSBGeometry(vec3 N, vec3 V, vec3 L, float roughness) 77 | { 78 | float NdotV = max(dot(N, V), 0.0); 79 | float NdotL = max(dot(N, L), 0.0); 80 | float ggx2 = SBGeometry(NdotV, roughness); 81 | float ggx1 = SBGeometry(NdotL, roughness); 82 | 83 | return ggx1 * ggx2; 84 | } 85 | 86 | // Hammersley sequence pseudorandom number generator. 87 | vec2 Hammersley(uint i, uint N) 88 | { 89 | float fbits; 90 | uint bits = i; 91 | 92 | bits = (bits << 16u) | (bits >> 16u); 93 | bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); 94 | bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); 95 | bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); 96 | bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); 97 | fbits = float(bits) * 2.3283064365386963e-10; 98 | 99 | return vec2(float(i) / float(N), fbits); 100 | } 101 | 102 | // Importance sampling of the Smith-Schlick-Beckmann geometry function. 103 | vec3 SSBImportance(vec2 Xi, vec3 N, float roughness) 104 | { 105 | float a = roughness * roughness; 106 | 107 | float phi = 2.0 * PI * Xi.x; 108 | float cosTheta = sqrt((1.0 - Xi.y) / max(1.0 + (a*a - 1.0) * Xi.y, 1e-4)); 109 | float sinTheta = sqrt(1.0 - cosTheta * cosTheta); 110 | 111 | // from spherical coordinates to cartesian coordinates - halfway vector 112 | vec3 H; 113 | H.x = cos(phi) * sinTheta; 114 | H.y = sin(phi) * sinTheta; 115 | H.z = cosTheta; 116 | 117 | // from tangent-space H vector to world-space sample vector 118 | vec3 up = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); 119 | vec3 tangent = normalize(cross(up, N)); 120 | vec3 bitangent = cross(N, tangent); 121 | 122 | vec3 sampleVec = tangent * H.x + bitangent * H.y + N * H.z; 123 | return normalize(sampleVec); 124 | } -------------------------------------------------------------------------------- /Editor/Assets/Shaders/EquirectangularCubemap/Compute.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | // CREDIT: IronFist, Strontium Engine 4 | // https://github.com/ksawatzky777/Strontium/blob/main/assets/shaders/compute/ibl/equiConversion.srshader 5 | 6 | /* 7 | * A compute shader to convert an equirectangular map to a cubemap. Many thanks 8 | * to http://alinloghin.com/articles/compute_ibl.html, some of the code here was 9 | * adapted from their excellent article. 10 | */ 11 | 12 | #define invAtan vec2(0.1591, 0.3183) 13 | 14 | layout (local_size_x = 32, local_size_y = 32) in; 15 | 16 | layout (rgba16f, binding = 0) uniform readonly image2D equirectangularMap; 17 | layout (rgba16f, binding = 1) writeonly uniform imageCube environmentMap; 18 | 19 | vec3 cubeToWorld(ivec3 cubeCoord, vec2 cubeSize); 20 | ivec3 texToCube(vec3 texCoord, vec2 cubeSize); 21 | ivec2 texToImage2D(vec2 texCoord, vec2 imageSize); 22 | vec2 sampleSphericalMap(vec3 v); 23 | 24 | void main() 25 | { 26 | // Fetch the world position of the cubemap. 27 | vec2 equiSize = vec2(imageSize(equirectangularMap)); 28 | vec2 enviSize = vec2(imageSize(environmentMap).xy); 29 | vec3 worldPos = cubeToWorld(ivec3(gl_GlobalInvocationID), enviSize); 30 | 31 | // Convert the cubemap coords to equirectangular coords. 32 | vec2 uv = sampleSphericalMap(normalize(worldPos)); 33 | // Convert the UV coordinates to image coordinates. 34 | ivec2 imgCoords = texToImage2D(uv, equiSize); 35 | 36 | // Fetch the colour and store it in the cubemap. 37 | vec3 colour = imageLoad(equirectangularMap, imgCoords).rgb; 38 | imageStore(environmentMap, ivec3(gl_GlobalInvocationID), vec4(colour, 1.0)); 39 | } 40 | 41 | // I need to figure out how to make these branchless one of these days... 42 | vec3 cubeToWorld(ivec3 cubeCoord, vec2 cubeSize) 43 | { 44 | vec2 texCoord = vec2(cubeCoord.xy) / cubeSize; 45 | texCoord = texCoord * 2.0 - 1.0; // Swap to -1 -> +1 46 | switch(cubeCoord.z) 47 | { 48 | case 0: return vec3(1.0, -texCoord.yx); // CUBE_MAP_POS_X 49 | case 1: return vec3(-1.0, -texCoord.y, texCoord.x); // CUBE_MAP_NEG_X 50 | case 2: return vec3(texCoord.x, 1.0, texCoord.y); // CUBE_MAP_POS_Y 51 | case 3: return vec3(texCoord.x, -1.0, -texCoord.y); // CUBE_MAP_NEG_Y 52 | case 4: return vec3(texCoord.x, -texCoord.y, 1.0); // CUBE_MAP_POS_Z 53 | case 5: return vec3(-texCoord.xy, -1.0); // CUBE_MAP_NEG_Z 54 | } 55 | return vec3(0.0); 56 | } 57 | 58 | ivec3 texToCube(vec3 texCoord, vec2 cubeSize) 59 | { 60 | vec3 abst = abs(texCoord); 61 | texCoord /= max(max(abst.x, abst.y), abst.z); 62 | 63 | float cubeFace; 64 | vec2 uvCoord; 65 | if (abst.x > abst.y && abst.x > abst.z) 66 | { 67 | // X major. 68 | float negx = step(texCoord.x, 0.0); 69 | uvCoord = mix(-texCoord.zy, vec2(texCoord.z, -texCoord.y), negx); 70 | cubeFace = negx; 71 | } 72 | else if (abst.y > abst.z) 73 | { 74 | // Y major. 75 | float negy = step(texCoord.y, 0.0); 76 | uvCoord = mix(texCoord.xz, vec2(texCoord.x, -texCoord.z), negy); 77 | cubeFace = 2.0 + negy; 78 | } 79 | else 80 | { 81 | // Z major. 82 | float negz = step(texCoord.z, 0.0); 83 | uvCoord = mix(vec2(texCoord.x, -texCoord.y), -texCoord.xy, negz); 84 | cubeFace = 4.0 + negz; 85 | } 86 | uvCoord = (uvCoord + 1.0) * 0.5; // 0..1 87 | uvCoord = uvCoord * cubeSize; 88 | uvCoord = clamp(uvCoord, vec2(0.0), cubeSize - vec2(1.0)); 89 | 90 | return ivec3(ivec2(uvCoord), int(cubeFace)); 91 | } 92 | 93 | ivec2 texToImage2D(vec2 texCoord, vec2 imageSize) 94 | { 95 | vec2 result = texCoord * imageSize; 96 | return ivec2(result); 97 | } 98 | 99 | vec2 sampleSphericalMap(vec3 v) 100 | { 101 | vec2 uv = vec2(atan(v.z, v.x), asin(v.y)); 102 | uv *= invAtan; 103 | uv += 0.5; 104 | return uv; 105 | } -------------------------------------------------------------------------------- /Editor/Assets/Shaders/FXAA/Fragment.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | layout (location = 0) in vec3 OutPosition; 4 | layout (location = 1) in vec2 OutUV; 5 | 6 | layout (location = 0) out vec4 OutColor; 7 | 8 | layout (binding = 0, set = 0) uniform sampler screen_sampler; 9 | layout (binding = 1, set = 0) uniform texture2D color_image; 10 | 11 | layout (push_constant) uniform FXAASettings { 12 | // FXAA enabled 13 | bool enabled; 14 | bool show_edges; 15 | vec2 screen_size; 16 | 17 | // FXAA settings 18 | float luma_threshold; 19 | float mul_reduce; 20 | float min_reduce; 21 | float max_span; 22 | } settings; 23 | 24 | vec3 apply_fxaa(vec4 uv, texture2D tex, sampler samp, vec2 rcpFrame) 25 | { 26 | vec3 rgbNW = textureLod(sampler2D(tex, samp), uv.zw, 0.0).xyz; 27 | vec3 rgbNE = textureLod(sampler2D(tex, samp), uv.zw + vec2(1,0) * rcpFrame.xy, 0.0).xyz; 28 | vec3 rgbSW = textureLod(sampler2D(tex, samp), uv.zw + vec2(0,1) * rcpFrame.xy, 0.0).xyz; 29 | vec3 rgbSE = textureLod(sampler2D(tex, samp), uv.zw + vec2(1,1) * rcpFrame.xy, 0.0).xyz; 30 | vec3 rgbM = textureLod(sampler2D(tex, samp), uv.xy, 0.0).xyz; 31 | 32 | vec3 luma = vec3(0.299, 0.587, 0.114); 33 | float lumaNW = dot(rgbNW, luma); 34 | float lumaNE = dot(rgbNE, luma); 35 | float lumaSW = dot(rgbSW, luma); 36 | float lumaSE = dot(rgbSE, luma); 37 | float lumaM = dot(rgbM, luma); 38 | 39 | float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE))); 40 | float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE))); 41 | 42 | vec2 dir; 43 | dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE)); 44 | dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE)); 45 | 46 | float dirReduce = max( 47 | (lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * settings.mul_reduce), 48 | settings.min_reduce); 49 | float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce); 50 | 51 | dir = min(vec2( settings.max_span, settings.max_span), 52 | max(vec2(-settings.max_span, -settings.max_span), 53 | dir * rcpDirMin)) * rcpFrame.xy; 54 | 55 | vec3 rgbA = (1.0/2.0) * ( 56 | textureLod(sampler2D(tex, samp), uv.xy + dir * (1.0/3.0 - 0.5), 0.0).xyz + 57 | textureLod(sampler2D(tex, samp), uv.xy + dir * (2.0/3.0 - 0.5), 0.0).xyz); 58 | vec3 rgbB = rgbA * (1.0/2.0) + (1.0/4.0) * ( 59 | textureLod(sampler2D(tex, samp), uv.xy + dir * (0.0/3.0 - 0.5), 0.0).xyz + 60 | textureLod(sampler2D(tex, samp), uv.xy + dir * (3.0/3.0 - 0.5), 0.0).xyz); 61 | 62 | float lumaB = dot(rgbB, luma); 63 | 64 | if((lumaB < lumaMin) || (lumaB > lumaMax)) return rgbA; 65 | 66 | return rgbB; 67 | } 68 | 69 | void main() 70 | { 71 | vec2 rcpFrame = 1.0 / settings.screen_size; 72 | vec2 uv2 = OutUV; 73 | 74 | vec3 col; 75 | 76 | if (settings.enabled) 77 | { 78 | vec4 uv = vec4( uv2, uv2 - (rcpFrame * (0.5 + settings.luma_threshold))); 79 | col = apply_fxaa(uv, color_image, screen_sampler, 1.0 / settings.screen_size.xy); 80 | } 81 | else 82 | { 83 | col = texture(sampler2D(color_image, screen_sampler), OutUV).xyz; 84 | } 85 | 86 | OutColor = vec4(col, 1.0); 87 | } -------------------------------------------------------------------------------- /Editor/Assets/Shaders/FXAA/Vertex.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | layout (location = 0) in vec3 Position; 4 | layout (location = 1) in vec2 UV; 5 | 6 | layout (location = 0) out vec3 OutPosition; 7 | layout (location = 1) out vec2 OutUV; 8 | layout (location = 3) out vec2 rgbNW; 9 | layout (location = 4) out vec2 rgbNE; 10 | layout (location = 5) out vec2 rgbSW; 11 | layout (location = 6) out vec2 rgbSE; 12 | layout (location = 7) out vec2 rgbM; 13 | 14 | void texcoords(vec2 fragCoord, vec2 resolution, 15 | out vec2 v_rgbNW, out vec2 v_rgbNE, 16 | out vec2 v_rgbSW, out vec2 v_rgbSE, 17 | out vec2 v_rgbM) { 18 | vec2 inverseVP = 1.0 / resolution.xy; 19 | v_rgbNW = (fragCoord + vec2(-1.0, -1.0)) * inverseVP; 20 | v_rgbNE = (fragCoord + vec2(1.0, -1.0)) * inverseVP; 21 | v_rgbSW = (fragCoord + vec2(-1.0, 1.0)) * inverseVP; 22 | v_rgbSE = (fragCoord + vec2(1.0, 1.0)) * inverseVP; 23 | v_rgbM = vec2(fragCoord * inverseVP); 24 | } 25 | 26 | void main() 27 | { 28 | gl_Position = vec4(Position, 1.0); 29 | 30 | OutPosition = Position; 31 | OutUV = UV; 32 | } -------------------------------------------------------------------------------- /Editor/Assets/Shaders/Geometry/Mesh.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | #extension GL_NV_mesh_shader : require 4 | #extension GL_EXT_shader_8bit_storage : require 5 | #extension GL_EXT_shader_16bit_storage : require 6 | 7 | layout(local_size_x = 32, local_size_y = 1, local_size_z = 1) in; 8 | layout(triangles, max_vertices = 64, max_primitives = 124) out; 9 | 10 | layout (push_constant) uniform SceneData { 11 | mat4 projection; 12 | mat4 view; 13 | vec3 camera_position; 14 | float padding0; 15 | } scene; 16 | 17 | struct Vertex 18 | { 19 | float px, py, pz; 20 | float ux, uy; 21 | float nx, ny, nz; 22 | }; 23 | 24 | layout (binding = 0, set = 0) readonly buffer Vertices 25 | { 26 | Vertex vertex_data[]; 27 | }; 28 | 29 | struct Meshlet 30 | { 31 | vec4 cone; 32 | uint vertices[64]; 33 | uint indices_packed[124*3/4]; 34 | uint8_t vertex_count; 35 | uint8_t triangle_count; 36 | }; 37 | 38 | layout (binding = 1, set = 0) readonly buffer Meshlets 39 | { 40 | Meshlet meshlets[]; 41 | }; 42 | 43 | in taskNV block 44 | { 45 | uint meshletIndices[32]; 46 | }; 47 | 48 | layout (binding = 0, set = 1) uniform ObjectData { 49 | mat4 transform; 50 | } ModelTransform; 51 | 52 | layout (location = 0) out PerVertexData { 53 | vec2 OutUV; 54 | vec3 OutNormals; 55 | vec3 WorldPos; 56 | vec3 CameraPos; 57 | vec3 MeshletColor; 58 | } VertexOut[]; 59 | 60 | uint hash(uint a) 61 | { 62 | a = (a+0x7ed55d16) + (a<<12); 63 | a = (a^0xc761c23c) ^ (a>>19); 64 | a = (a+0x165667b1) + (a<<5); 65 | a = (a+0xd3a2646c) ^ (a<<9); 66 | a = (a+0xfd7046c5) + (a<<3); 67 | a = (a^0xb55a4f09) ^ (a>>16); 68 | return a; 69 | } 70 | 71 | bool ConeCull(vec4 cone, vec3 view) 72 | { 73 | return dot(cone.xyz, view) > cone.w; 74 | } 75 | 76 | void main() 77 | { 78 | uint ti = gl_LocalInvocationID.x; 79 | uint mi = meshletIndices[gl_WorkGroupID.x]; 80 | 81 | if (ConeCull(meshlets[mi].cone, vec3(0, 0, 1))) 82 | { 83 | if (ti == 0) 84 | gl_PrimitiveCountNV = 0; 85 | return; 86 | } 87 | 88 | uint mhash = hash(mi); 89 | vec3 mcolor = vec3(float(mhash & 255), float((mhash >> 8) & 255), float((mhash >> 16) & 255)) / 255.0; 90 | 91 | uint vertexCount = uint(meshlets[mi].vertex_count); 92 | uint indexCount = uint(meshlets[mi].triangle_count) * 3; 93 | uint triangleCount = uint(meshlets[mi].triangle_count); 94 | 95 | for (uint i = ti; i < vertexCount; i += 32) 96 | { 97 | uint vi = meshlets[mi].vertices[i]; 98 | 99 | vec3 position = vec3(vertex_data[vi].px, vertex_data[vi].py, vertex_data[vi].pz); 100 | vec2 uv = vec2(vertex_data[vi].ux, vertex_data[vi].uy); 101 | vec3 normals = vec3(vertex_data[vi].nx, vertex_data[vi].ny, vertex_data[vi].nz); 102 | 103 | vec4 Pw = scene.projection * scene.view * ModelTransform.transform * vec4(position, 1.0); 104 | 105 | VertexOut[i].OutUV = uv; 106 | VertexOut[i].OutNormals = transpose(inverse(mat3(ModelTransform.transform))) * normals; 107 | VertexOut[i].WorldPos = vec3(ModelTransform.transform * vec4(position, 1.0)); 108 | VertexOut[i].CameraPos = scene.camera_position; 109 | VertexOut[i].MeshletColor = mcolor; 110 | 111 | gl_MeshVerticesNV[i].gl_Position = Pw; 112 | } 113 | 114 | uint indexGroupCount = (indexCount + 3) / 4; 115 | 116 | for (uint i = ti; i < indexGroupCount; i += 32) 117 | writePackedPrimitiveIndices4x8NV(i * 4, meshlets[mi].indices_packed[i]); 118 | 119 | if (ti == 0) 120 | gl_PrimitiveCountNV = triangleCount; 121 | } -------------------------------------------------------------------------------- /Editor/Assets/Shaders/Geometry/Task.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | #extension GL_NV_mesh_shader : require 4 | #extension GL_EXT_shader_8bit_storage : require 5 | #extension GL_EXT_shader_16bit_storage : require 6 | 7 | layout(local_size_x = 32, local_size_y = 1, local_size_z = 1) in; 8 | 9 | struct Meshlet 10 | { 11 | vec4 cone; 12 | uint vertices[64]; 13 | uint indices_packed[124*3/4]; 14 | uint8_t vertex_count; 15 | uint8_t triangle_count; 16 | }; 17 | 18 | layout (binding = 1, set = 0) readonly buffer Meshlets 19 | { 20 | Meshlet meshlets[]; 21 | }; 22 | 23 | out taskNV block 24 | { 25 | uint meshletIndices[32]; 26 | }; 27 | 28 | bool coneCull(vec4 cone, vec3 view) 29 | { 30 | return dot(cone.xyz, view) > cone.w; 31 | } 32 | 33 | shared uint meshletCount; 34 | 35 | void main() 36 | { 37 | uint ti = gl_LocalInvocationID.x; 38 | uint mgi = gl_WorkGroupID.x; 39 | uint mi = mgi * 32 + ti; 40 | 41 | meshletCount = 0; 42 | 43 | memoryBarrierShared(); 44 | 45 | if (!coneCull(meshlets[mi].cone, vec3(0, 0, 1))) 46 | { 47 | uint index = atomicAdd(meshletCount, 1); 48 | 49 | meshletIndices[index] = mi; 50 | } 51 | 52 | memoryBarrierShared(); 53 | 54 | if (ti == 0) 55 | gl_TaskCountNV = meshletCount; 56 | } -------------------------------------------------------------------------------- /Editor/Assets/Shaders/Geometry/Vertex.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | layout (push_constant) uniform SceneUniform { 4 | mat4 projection; 5 | mat4 view; 6 | vec3 camera_pos; 7 | float padding_0; 8 | } scene; 9 | 10 | layout (location = 0) in vec3 Position; 11 | layout (location = 1) in vec2 UV; 12 | layout (location = 2) in vec3 Normals; 13 | 14 | layout (location = 0) out PerVertexData { 15 | vec2 OutUV; 16 | vec3 OutNormals; 17 | vec3 WorldPos; 18 | vec3 CameraPos; 19 | } VertexOut; 20 | 21 | layout (binding = 0, set = 0) uniform ModelData { 22 | mat4 model; 23 | } model_data; 24 | 25 | void main() 26 | { 27 | gl_Position = scene.projection * scene.view * model_data.model * vec4(Position, 1.0); 28 | 29 | VertexOut.OutUV = UV; 30 | VertexOut.OutNormals = transpose(inverse(mat3(model_data.model))) * Normals; 31 | VertexOut.WorldPos = vec3(model_data.model * vec4(Position, 1.0)); 32 | VertexOut.CameraPos = scene.camera_pos; 33 | } -------------------------------------------------------------------------------- /Editor/Assets/Shaders/Irradiance/Compute.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | /* 4 | * A compute shader to convert an equirectangular map to a cubemap. Many thanks 5 | * to http://alinloghin.com/articles/compute_ibl.html, some of the code here was 6 | * adapted from their excellent article. 7 | */ 8 | 9 | layout (local_size_x = 32, local_size_y = 32) in; 10 | 11 | layout (binding = 0) uniform samplerCube cube_map; 12 | layout (rgba16f, binding = 1) writeonly uniform imageCube irradiance_map; 13 | 14 | vec3 view_pos = vec3(0, 0, 0); 15 | 16 | vec3 view_target[6] = { 17 | vec3(1, 0, 0), 18 | vec3(-1, 0, 0), 19 | vec3(0, -1, 0), 20 | vec3(0, 1, 0), 21 | vec3(0, 0, 1), 22 | vec3(0, 0, -1) 23 | }; 24 | 25 | vec3 view_up[6] = { 26 | vec3(0, 1, 0), 27 | vec3(0, 1, 0), 28 | vec3(0, 0, 1), // +Y 29 | vec3(0, 0, -1), // -Y 30 | vec3(0, 1, 0), 31 | vec3(0, 1, 0) 32 | }; 33 | 34 | mat4 look_at(vec3 pos, vec3 target, vec3 world_up) { 35 | vec3 fwd = normalize(target - pos); 36 | vec3 right = cross(world_up, fwd); 37 | vec3 up = cross(fwd, right); 38 | return mat4(vec4(right, 0), vec4(up, 0), vec4(fwd, 0), vec4(pos, 1)); 39 | } 40 | 41 | // Remaps uv coordinates to a position in range [-1, 1] 42 | vec2 uv_to_quad_pos(vec2 uv) { 43 | return uv * 2.0f - 1.0f; 44 | } 45 | 46 | vec3 to_local_direction(vec2 uv, int face) { 47 | mat4 view = look_at(view_pos, view_target[face], view_up[face]); 48 | return (view * vec4(uv_to_quad_pos(uv), 1, 0)).xyz; 49 | } 50 | 51 | #define PI 3.14159265359 52 | 53 | vec3 calculate_irradiance(vec3 local_direction) { 54 | vec3 normal = normalize(local_direction); 55 | vec3 irradiance = vec3(0.0); 56 | 57 | vec3 up = vec3(0.0, 1.0, 0.0); 58 | vec3 right = normalize(cross(up, normal)); 59 | up = cross(normal, right); 60 | 61 | float sample_delta = 0.025; 62 | float n_samples = 0.0; 63 | for(float phi = 0.0; phi < 2.0 * PI; phi += sample_delta) { 64 | for(float theta = 0.0; theta < 0.5 * PI; theta += sample_delta) { 65 | vec3 tangent = vec3(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta)); 66 | vec3 sample_vec = tangent.x * right + tangent.y * up + tangent.z * normal; 67 | 68 | vec3 sample_color = texture(cube_map, sample_vec).rgb * cos(theta) * sin(theta); 69 | irradiance += sample_color; 70 | n_samples++; 71 | } 72 | } 73 | irradiance = PI * irradiance * (1.0 / float(n_samples)); 74 | 75 | return irradiance; 76 | } 77 | 78 | void main() { 79 | int face_size = imageSize(irradiance_map).x; 80 | ivec3 real_invocation_id = ivec3(gl_GlobalInvocationID.xyz); 81 | vec2 uv = (vec2(real_invocation_id.xy)) / float(face_size); 82 | // Avoid accessing out of bounds 83 | if (uv.x > 1 || uv.y > 1) return; 84 | vec3 local_direction = normalize(to_local_direction(uv, int(real_invocation_id.z))); 85 | local_direction.y = -local_direction.y; 86 | 87 | vec4 color = vec4(calculate_irradiance(local_direction), 1); 88 | 89 | ivec3 cube_texels = real_invocation_id; 90 | imageStore(irradiance_map, cube_texels, color); 91 | } -------------------------------------------------------------------------------- /Editor/Assets/Shaders/Prefilter/Compute.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | // CREDIT: IronFist, Strontium Engine 4 | // https://github.com/tuxalin/vulkanri/blob/master/examples/pbr_ibl/shaders/prefilterGGX.comp 5 | 6 | /* 7 | * A compute shader to convert an equirectangular map to a cubemap. Many thanks 8 | * to http://alinloghin.com/articles/compute_ibl.html, some of the code here was 9 | * adapted from their excellent article. 10 | */ 11 | 12 | layout (local_size_x = 32, local_size_y = 32) in; 13 | 14 | layout (binding = 0) uniform samplerCube environmentMap; 15 | layout (rgba16f, binding = 1) writeonly uniform imageCube prefilterMap; 16 | 17 | layout (push_constant) uniform ParameterBuffer { 18 | vec4 u_iblParams; 19 | }; 20 | 21 | #define PI 3.141592654 22 | 23 | vec3 cubeToWorld(ivec3 cubeCoord, vec2 cubeSize); 24 | ivec3 texToCube(vec3 texCoord, vec2 cubeSize); 25 | float SSBGeometry(vec3 N, vec3 H, float roughness); 26 | vec2 Hammersley(uint i, uint N); 27 | vec3 SSBImportance(vec2 Xi, vec3 N, float roughness); 28 | 29 | void main() 30 | { 31 | const uint SAMPLE_COUNT = 1; 32 | vec2 enviSize = vec2(textureSize(environmentMap, 0).xy); 33 | vec2 mipSize = vec2(imageSize(prefilterMap).xy); 34 | ivec3 cubeCoord = ivec3(gl_GlobalInvocationID); 35 | 36 | vec3 worldPos = cubeToWorld(cubeCoord, mipSize); 37 | vec3 N = normalize(worldPos); 38 | 39 | vec3 prefilteredColor = vec3(0.0); 40 | float totalWeight = 0.0; 41 | 42 | for (uint i = 0u; i < SAMPLE_COUNT; ++i) 43 | { 44 | vec2 Xi = Hammersley(i, SAMPLE_COUNT); 45 | vec3 H = SSBImportance(Xi, N, u_iblParams.x); 46 | vec3 L = normalize(2.0 * dot(N, H) * H - N); 47 | 48 | float NdotL = max(dot(N, L), 0.0); 49 | if (NdotL > 0.0) 50 | { 51 | float D = SSBGeometry(N, H, u_iblParams.x); 52 | float NdotH = max(dot(N, H), 0.0); 53 | float HdotV = max(dot(H, N), 0.0); 54 | float pdf = D * NdotH / (4.0 * HdotV + 0.0001); 55 | 56 | float saTexel = 4.0 * PI / (6.0 * enviSize.x * enviSize.x); 57 | float saSample = 1.0 / (float(SAMPLE_COUNT) * pdf + 0.0001); 58 | 59 | float mipLevel = u_iblParams.x == 0.0 ? 0.0 : 0.5 * log2(saSample / saTexel); 60 | 61 | prefilteredColor += textureLod(environmentMap, L, mipLevel).rgb * NdotL; 62 | totalWeight += NdotL; 63 | } 64 | } 65 | 66 | prefilteredColor = prefilteredColor / totalWeight; 67 | 68 | imageStore(prefilterMap, cubeCoord, vec4(prefilteredColor, 1.0)); 69 | } 70 | 71 | // I need to figure out how to make these branchless one of these days... 72 | vec3 cubeToWorld(ivec3 cubeCoord, vec2 cubeSize) 73 | { 74 | vec2 texCoord = vec2(cubeCoord.xy) / cubeSize; 75 | texCoord = texCoord * 2.0 - 1.0; // Swap to -1 -> +1 76 | switch(cubeCoord.z) 77 | { 78 | case 0: return vec3(1.0, -texCoord.yx); // CUBE_MAP_POS_X 79 | case 1: return vec3(-1.0, -texCoord.y, texCoord.x); // CUBE_MAP_NEG_X 80 | case 2: return vec3(texCoord.x, 1.0, texCoord.y); // CUBE_MAP_POS_Y 81 | case 3: return vec3(texCoord.x, -1.0, -texCoord.y); // CUBE_MAP_NEG_Y 82 | case 4: return vec3(texCoord.x, -texCoord.y, 1.0); // CUBE_MAP_POS_Z 83 | case 5: return vec3(-texCoord.xy, -1.0); // CUBE_MAP_NEG_Z 84 | } 85 | return vec3(0.0); 86 | } 87 | 88 | ivec3 texToCube(vec3 texCoord, vec2 cubeSize) 89 | { 90 | vec3 abst = abs(texCoord); 91 | texCoord /= max(max(abst.x, abst.y), abst.z); 92 | 93 | float cubeFace; 94 | vec2 uvCoord; 95 | if (abst.x > abst.y && abst.x > abst.z) 96 | { 97 | // X major. 98 | float negx = step(texCoord.x, 0.0); 99 | uvCoord = mix(-texCoord.zy, vec2(texCoord.z, -texCoord.y), negx); 100 | cubeFace = negx; 101 | } 102 | else if (abst.y > abst.z) 103 | { 104 | // Y major. 105 | float negy = step(texCoord.y, 0.0); 106 | uvCoord = mix(texCoord.xz, vec2(texCoord.x, -texCoord.z), negy); 107 | cubeFace = 2.0 + negy; 108 | } 109 | else 110 | { 111 | // Z major. 112 | float negz = step(texCoord.z, 0.0); 113 | uvCoord = mix(vec2(texCoord.x, -texCoord.y), -texCoord.xy, negz); 114 | cubeFace = 4.0 + negz; 115 | } 116 | uvCoord = (uvCoord + 1.0) * 0.5; // 0..1 117 | uvCoord = uvCoord * cubeSize; 118 | uvCoord = clamp(uvCoord, vec2(0.0), cubeSize - vec2(1.0)); 119 | 120 | return ivec3(ivec2(uvCoord), int(cubeFace)); 121 | } 122 | 123 | // Smith-Schlick-Beckmann geometry function. 124 | float SSBGeometry(vec3 N, vec3 H, float roughness) 125 | { 126 | float a = roughness * roughness; 127 | float a2 = a * a; 128 | float NdotH = max(dot(N, H), 0.0); 129 | float NdotH2 = NdotH * NdotH; 130 | 131 | float nom = a2; 132 | float denom = (NdotH2 * (a2 - 1.0) + 1.0); 133 | denom = PI * denom * denom; 134 | 135 | return nom / denom; 136 | } 137 | 138 | // Hammersley sequence, generates a low discrepancy pseudorandom number. 139 | vec2 Hammersley(uint i, uint N) 140 | { 141 | float fbits; 142 | uint bits = i; 143 | 144 | bits = (bits << 16u) | (bits >> 16u); 145 | bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); 146 | bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); 147 | bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); 148 | bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); 149 | fbits = float(bits) * 2.3283064365386963e-10; 150 | 151 | return vec2(float(i) / float(N), fbits); 152 | } 153 | 154 | // Importance sampling of the Smith-Schlick-Beckmann geometry function. 155 | vec3 SSBImportance(vec2 Xi, vec3 N, float roughness) 156 | { 157 | float a = roughness * roughness; 158 | 159 | float phi = 2.0 * PI * Xi.x; 160 | float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a*a - 1.0) * Xi.y)); 161 | float sinTheta = sqrt(1.0 - cosTheta * cosTheta); 162 | 163 | // from spherical coordinates to cartesian coordinates - halfway vector 164 | vec3 H; 165 | H.x = cos(phi) * sinTheta; 166 | H.y = sin(phi) * sinTheta; 167 | H.z = cosTheta; 168 | 169 | // from tangent-space H vector to world-space sample vector 170 | vec3 up = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); 171 | vec3 tangent = normalize(cross(up, N)); 172 | vec3 bitangent = cross(N, tangent); 173 | 174 | vec3 sampleVec = tangent * H.x + bitangent * H.y + N * H.z; 175 | return normalize(sampleVec); 176 | } -------------------------------------------------------------------------------- /Editor/Assets/Shaders/Skybox/Fragment.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | layout (location = 0) out vec4 OutColor; 4 | 5 | layout (location = 0) in vec2 OutUV; 6 | layout (location = 1) in vec3 OutPosition; 7 | 8 | layout (binding = 0) uniform sampler cube_sampler; 9 | layout (binding = 1) uniform textureCube CubemapTexture; 10 | 11 | void main() 12 | { 13 | OutColor = vec4(texture(samplerCube(CubemapTexture, cube_sampler), OutPosition).rgb, 1.0); 14 | } -------------------------------------------------------------------------------- /Editor/Assets/Shaders/Skybox/Vertex.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | layout (push_constant) uniform SceneUniform { 4 | mat4 mvp; 5 | } scene; 6 | 7 | layout (location = 0) in vec3 Position; 8 | layout (location = 1) in vec2 UV; 9 | layout (location = 2) in vec3 Normals; 10 | 11 | layout (location = 0) out vec2 OutUV; 12 | layout (location = 1) out vec3 OutPosition; 13 | layout (location = 2) out vec3 WorldPos; 14 | 15 | void main() 16 | { 17 | gl_Position = scene.mvp * vec4(Position, 1.0); 18 | OutUV = UV; 19 | OutPosition = Position; 20 | } -------------------------------------------------------------------------------- /Editor/Assets/Shaders/Tonemapping/Fragment.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | #extension GL_KHR_vulkan_glsl: enable 4 | 5 | layout (location = 0) out vec4 OutColor; 6 | 7 | layout (location = 0) in vec3 OutPosition; 8 | layout (location = 1) in vec2 OutUV; 9 | 10 | layout (push_constant) uniform HDRSettings { 11 | bool gamma_correction; 12 | int mode; 13 | 14 | vec2 padding_0; 15 | } settings; 16 | 17 | layout (binding = 0, set = 0) uniform sampler screen_sampler; 18 | layout (binding = 1, set = 0) uniform texture2D color_texture; 19 | 20 | // Tonemapping curves: https://www.shadertoy.com/view/lslGzl 21 | // ACES: https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/ 22 | // ACES impl: https://github.com/TheRealMJP/BakingLab/blob/master/BakingLab/ACES.hlsl 23 | 24 | vec3 aces(vec3 color, float gamma) 25 | { 26 | const mat3 inputMatrix = mat3 27 | ( 28 | vec3(0.59719, 0.07600, 0.02840), 29 | vec3(0.35458, 0.90834, 0.13383), 30 | vec3(0.04823, 0.01566, 0.83777) 31 | ); 32 | 33 | const mat3 outputMatrix = mat3 34 | ( 35 | vec3(1.60475, -0.10208, -0.00327), 36 | vec3(-0.53108, 1.10813, -0.07276), 37 | vec3(-0.07367, -0.00605, 1.07602) 38 | ); 39 | 40 | vec3 inputColour = inputMatrix * color; 41 | vec3 a = inputColour * (inputColour + vec3(0.0245786)) - vec3(0.000090537); 42 | vec3 b = inputColour * (0.983729 * inputColour + 0.4329510) + 0.238081; 43 | vec3 c = a / b; 44 | return pow(max(outputMatrix * c, 0.0.xxx), vec3(1. / gamma)); 45 | } 46 | 47 | vec3 filmic(vec3 color, float gamma) 48 | { 49 | color = max(vec3(0.), color - vec3(0.004)); 50 | color = (color * (6.2 * color + .5)) / (color * (6.2 * color + 1.7) + 0.06); 51 | return pow(color, vec3(1. / gamma)); 52 | } 53 | 54 | vec3 reinhard(vec3 color, float gamma) 55 | { 56 | float exposure = 1.5; 57 | color *= exposure/(1. + color / exposure); 58 | color = pow(color, vec3(1.0 / gamma)); 59 | return color; 60 | } 61 | 62 | vec3 lumaReinhard(vec3 color, float gamma) 63 | { 64 | float luma = dot(color, vec3(0.2126, 0.7152, 0.0722)); 65 | float toneMappedLuma = luma / (1. + luma); 66 | color *= toneMappedLuma / luma; 67 | color = pow(color, vec3(1. / gamma)); 68 | return color; 69 | } 70 | 71 | vec3 whitePreservingLumaReinhard(vec3 color, float gamma) 72 | { 73 | float white = 2.; 74 | float luma = dot(color, vec3(0.2126, 0.7152, 0.0722)); 75 | float toneMappedLuma = luma * (1. + luma / (white*white)) / (1. + luma); 76 | color *= toneMappedLuma / luma; 77 | color = pow(color, vec3(1. / gamma)); 78 | return color; 79 | } 80 | 81 | vec3 romBinDaHouse(vec3 color, float gamma) 82 | { 83 | color = exp( -1.0 / ( 2.72*color + 0.15 ) ); 84 | color = pow(color, vec3(1. / gamma)); 85 | return color; 86 | } 87 | 88 | vec3 uncharted2(vec3 color, float gamma) { 89 | float A = 0.15; 90 | float B = 0.50; 91 | float C = 0.10; 92 | float D = 0.20; 93 | float E = 0.02; 94 | float F = 0.30; 95 | float W = 11.2; 96 | float exposure = 2.0; 97 | color *= exposure; 98 | color = ((color * (A * color + C * B) + D * E) / (color * (A * color + B) + D * F)) - E / F; 99 | float white = ((W * (A * W + C * B) + D * E) / (W * (A * W + B) + D * F)) - E / F; 100 | color /= white; 101 | color = pow(color, vec3(1.0 / gamma)); 102 | return color; 103 | } 104 | 105 | void main() 106 | { 107 | vec3 color = texture(sampler2D(color_texture, screen_sampler), OutUV).rgb; 108 | float gamma; 109 | 110 | if (settings.gamma_correction) 111 | gamma = 2.2; 112 | else 113 | gamma = 1.0; 114 | 115 | switch (settings.mode) 116 | { 117 | case 0: // aces 118 | color.rgb = aces(color.rgb, gamma); 119 | break; 120 | case 1: // reinhard 121 | color.rgb = reinhard(color.rgb, gamma); 122 | break; 123 | case 2: // luma reinhard 124 | color.rgb = lumaReinhard(color.rgb, gamma); 125 | break; 126 | case 3: // white perserving luma reinhard 127 | color.rgb = whitePreservingLumaReinhard(color.rgb, gamma); 128 | break; 129 | case 4: // rom bin da house 130 | color.rgb = romBinDaHouse(color.rgb, gamma); 131 | break; 132 | case 5: // filmic 133 | color.rgb = filmic(color.rgb, gamma); 134 | break; 135 | case 6: // uncharted2 136 | color.rgb = uncharted2(color.rgb, gamma); 137 | break; 138 | case 7: // none 139 | color.rgb = pow(color.rgb, vec3(1. / gamma)); 140 | break; 141 | } 142 | 143 | OutColor = vec4(color, 1.0); 144 | } -------------------------------------------------------------------------------- /Editor/Assets/Shaders/Tonemapping/Vertex.glsl: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | layout (location = 0) in vec3 Position; 4 | layout (location = 1) in vec2 UV; 5 | 6 | layout (location = 0) out vec3 OutPosition; 7 | layout (location = 1) out vec2 OutUV; 8 | 9 | void main() 10 | { 11 | gl_Position = vec4(Position, 1.0); 12 | 13 | OutPosition = Position; 14 | OutUV = UV; 15 | } -------------------------------------------------------------------------------- /Editor/Assets/Textures/DamagedHelmet_Albedo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmelieHeinrich/Euphorbe/14e4f7885844e4c733022fdb6e1bbc134b261ea5/Editor/Assets/Textures/DamagedHelmet_Albedo.jpg -------------------------------------------------------------------------------- /Editor/Assets/Textures/DamagedHelmet_MetallicRoughness.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmelieHeinrich/Euphorbe/14e4f7885844e4c733022fdb6e1bbc134b261ea5/Editor/Assets/Textures/DamagedHelmet_MetallicRoughness.jpg -------------------------------------------------------------------------------- /Editor/Assets/Textures/DamagedHelmet_Normal.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmelieHeinrich/Euphorbe/14e4f7885844e4c733022fdb6e1bbc134b261ea5/Editor/Assets/Textures/DamagedHelmet_Normal.jpg -------------------------------------------------------------------------------- /Editor/Assets/Textures/Sphere_AO.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmelieHeinrich/Euphorbe/14e4f7885844e4c733022fdb6e1bbc134b261ea5/Editor/Assets/Textures/Sphere_AO.png -------------------------------------------------------------------------------- /Editor/Assets/Textures/Sphere_Albedo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmelieHeinrich/Euphorbe/14e4f7885844e4c733022fdb6e1bbc134b261ea5/Editor/Assets/Textures/Sphere_Albedo.png -------------------------------------------------------------------------------- /Editor/Assets/Textures/Sphere_Metallic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmelieHeinrich/Euphorbe/14e4f7885844e4c733022fdb6e1bbc134b261ea5/Editor/Assets/Textures/Sphere_Metallic.png -------------------------------------------------------------------------------- /Editor/Assets/Textures/Sphere_Normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmelieHeinrich/Euphorbe/14e4f7885844e4c733022fdb6e1bbc134b261ea5/Editor/Assets/Textures/Sphere_Normal.png -------------------------------------------------------------------------------- /Editor/Assets/Textures/Sphere_Roughness.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmelieHeinrich/Euphorbe/14e4f7885844e4c733022fdb6e1bbc134b261ea5/Editor/Assets/Textures/Sphere_Roughness.png -------------------------------------------------------------------------------- /Editor/Assets/Textures/Suzanne_BaseColor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmelieHeinrich/Euphorbe/14e4f7885844e4c733022fdb6e1bbc134b261ea5/Editor/Assets/Textures/Suzanne_BaseColor.png -------------------------------------------------------------------------------- /Editor/Assets/Textures/Suzanne_MetallicRoughness.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmelieHeinrich/Euphorbe/14e4f7885844e4c733022fdb6e1bbc134b261ea5/Editor/Assets/Textures/Suzanne_MetallicRoughness.png -------------------------------------------------------------------------------- /Editor/Assets/Textures/awesomeface.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmelieHeinrich/Euphorbe/14e4f7885844e4c733022fdb6e1bbc134b261ea5/Editor/Assets/Textures/awesomeface.png -------------------------------------------------------------------------------- /Editor/Assets/Textures/cobblestone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmelieHeinrich/Euphorbe/14e4f7885844e4c733022fdb6e1bbc134b261ea5/Editor/Assets/Textures/cobblestone.png -------------------------------------------------------------------------------- /Editor/Assets/Textures/paving.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmelieHeinrich/Euphorbe/14e4f7885844e4c733022fdb6e1bbc134b261ea5/Editor/Assets/Textures/paving.png -------------------------------------------------------------------------------- /Editor/Assets/Textures/paving2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AmelieHeinrich/Euphorbe/14e4f7885844e4c733022fdb6e1bbc134b261ea5/Editor/Assets/Textures/paving2.png -------------------------------------------------------------------------------- /Editor/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # CMake Header 2 | cmake_minimum_required(VERSION 3.8) 3 | 4 | # Source files 5 | file(GLOB_RECURSE EDITOR_SOURCE Source/*.c Source/*.h) 6 | add_executable(Editor ${EDITOR_SOURCE}) 7 | 8 | # Project settings 9 | add_definitions(-DCIMGUI_DEFINE_ENUMS_AND_STRUCTS) 10 | target_include_directories(Editor PUBLIC 11 | "Euphorbe" 12 | ${THIRD_PARTY}/cimgui 13 | ${THIRD_PARTY}/cimgui/imgui 14 | ${THIRD_PARTY}/cglm/include) 15 | target_link_libraries(Editor PUBLIC Euphorbe cimgui cglm) 16 | add_definitions(-D_CRT_SECURE_NO_WARNINGS) 17 | set_target_properties(Editor PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) 18 | 19 | 20 | source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${EDITOR_SOURCE}) -------------------------------------------------------------------------------- /Editor/Source/Editor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "Panels/ViewportPanel.h" 8 | #include "EditorCamera.h" 9 | 10 | #include "RenderNodes/GeometryNode.h" 11 | #include "RenderNodes/FXAANode.h" 12 | #include "RenderNodes/TonemappingNode.h" 13 | #include "RenderNodes/FinalBlitNode.h" 14 | 15 | typedef struct EditorPerformance EditorPerformance; 16 | struct EditorPerformance 17 | { 18 | f64 begin_render; 19 | f64 execute_render_graph; 20 | f64 draw_gui; 21 | f64 end_render; 22 | }; 23 | 24 | typedef struct EditorData EditorData; 25 | struct EditorData 26 | { 27 | // Config 28 | E_CVarSystem cvar_sys; 29 | 30 | // Window and misc 31 | E_Window* window; 32 | b32 is_viewport_focused; 33 | b32 is_viewport_hovered; 34 | f32 last_frame; 35 | b32 running; 36 | b32 mesh_shader_enabled; 37 | 38 | // Render state 39 | E_RenderGraph* graph; 40 | E_RenderGraphExecuteInfo execute_info; 41 | 42 | E_RenderGraphNode* geometry_node; 43 | E_RenderGraphNode* fxaa_node; 44 | E_RenderGraphNode* tonemapping_node; 45 | E_RenderGraphNode* final_blit_node; 46 | 47 | // Textured mesh 48 | E_Mesh* mesh; 49 | 50 | E_ResourceFile* albedo_texture; 51 | E_ResourceFile* metallic_roughness_texture; 52 | E_ResourceFile* normal_texture; 53 | 54 | E_Buffer* transform_buffer; 55 | E_Buffer* material_settings; 56 | 57 | b32 material_buffer[4]; 58 | E_MaterialInstance* material_instance; 59 | 60 | // Performance 61 | EditorPerformance perf; 62 | E_PipelineStatistics* stats; 63 | 64 | // Editor Camera 65 | EditorCamera camera; 66 | }; 67 | 68 | extern EditorData editor_state; 69 | 70 | void EditorInit(); 71 | void EditorCleanup(); 72 | void EditorUpdate(); 73 | void EditorResize(i32 width, i32 height); 74 | void EditorScroll(f32 scroll); 75 | 76 | // 77 | void EditorInitialiseWindow(); 78 | void EditorInitialiseRenderState(); 79 | void EditorInitialiseTexturedMesh(); 80 | void EditorLaunch(); 81 | void EditorAssureViewportSize(); 82 | void EditorBeginRender(); 83 | void EditorEndRender(); 84 | void EditorDraw(); 85 | void EditorCreateDockspace(); 86 | void EditorDestroyDockspace(); 87 | void EditorDrawGUI(); 88 | void EditorUpdateCameraInput(f32 dt); 89 | f64 EditorBeginProfiling(); 90 | f64 EditorEndProfiling(f64 start); -------------------------------------------------------------------------------- /Editor/Source/EditorCamera.c: -------------------------------------------------------------------------------- 1 | #include "EditorCamera.h" 2 | 3 | #include 4 | 5 | void EditorCameraUpdateVectors(EditorCamera* camera) 6 | { 7 | vec3 front; 8 | glm_vec3_zero(front); 9 | front[0] = cos(glm_rad(camera->yaw)) * cos(glm_rad(camera->pitch)); 10 | front[1] = sin(glm_rad(camera->pitch)); 11 | front[2] = sin(glm_rad(camera->yaw)) * cos(glm_rad(camera->pitch)); 12 | glm_normalize_to(front, camera->front); 13 | 14 | vec3 right_crossed; 15 | vec3 up_crossed; 16 | glm_vec3_zero(right_crossed); 17 | glm_vec3_zero(up_crossed); 18 | glm_cross(camera->front, camera->worldup, right_crossed); 19 | glm_cross(camera->right, camera->front, up_crossed); 20 | 21 | glm_normalize_to(right_crossed, camera->right); 22 | glm_normalize_to(up_crossed, camera->up); 23 | } 24 | 25 | void EditorCameraInit(EditorCamera* camera) 26 | { 27 | glm_vec3_zero(camera->position); 28 | glm_vec3_zero(camera->up); 29 | glm_vec3_zero(camera->front); 30 | glm_vec3_zero(camera->right); 31 | glm_vec3_zero(camera->worldup); 32 | 33 | camera->up[1] = 1.0f; 34 | camera->front[2] = -1.0f; 35 | camera->worldup[1] = 1.0f; 36 | camera->yaw = CAMERA_DEFAULT_YAW; 37 | camera->pitch = CAMERA_DEFAULT_PITCH; 38 | camera->zoom = CAMERA_DEFAULT_ZOOM; 39 | camera->friction = 10.0f; 40 | camera->acceleration = 20.0f; 41 | camera->max_velocity = 15.0f; 42 | camera->viewport_width = 1280; 43 | camera->viewport_height = 720; 44 | 45 | EditorCameraUpdateVectors(camera); 46 | } 47 | 48 | void EditorCameraUpdate(EditorCamera* camera, f32 dt) 49 | { 50 | f32 mouse_x = E_GetMousePosX(); 51 | f32 mouse_y = E_GetMousePosY(); 52 | 53 | camera->mouse_pos[0] = mouse_x; 54 | camera->mouse_pos[1] = mouse_y; 55 | 56 | glm_mat4_identity(camera->view); 57 | glm_mat4_identity(camera->proj); 58 | glm_mat4_identity(camera->camera_matrix); 59 | 60 | vec3 center; 61 | glm_vec3_zero(center); 62 | glm_vec3_add(camera->position, camera->front, center); 63 | glm_lookat(camera->position, center, camera->worldup, camera->view); 64 | 65 | glm_perspective(glm_rad(camera->zoom), camera->viewport_width / camera->viewport_height, 0.0001f, 100000.0f, camera->proj); 66 | camera->proj[1][1] *= -1; 67 | 68 | glm_mat4_mul(camera->proj, camera->view, camera->camera_matrix); 69 | } 70 | 71 | void EditorCameraProcessInput(EditorCamera* camera, f32 dt) 72 | { 73 | // keyboard 74 | f32 speed_multiplier = camera->acceleration * dt; 75 | if (E_IsKeyPressed(EUPHORBE_KEY_Z) || E_IsKeyPressed(EUPHORBE_KEY_W)) 76 | glm_vec3_add(camera->velocity, (vec3) { camera->front[0] * speed_multiplier, camera->front[1] * speed_multiplier, camera->front[2] * speed_multiplier }, camera->velocity); 77 | if (E_IsKeyPressed(EUPHORBE_KEY_S)) 78 | glm_vec3_sub(camera->velocity, (vec3) { camera->front[0] * speed_multiplier, camera->front[1] * speed_multiplier, camera->front[2] * speed_multiplier }, camera->velocity); 79 | if (E_IsKeyPressed(EUPHORBE_KEY_Q) || E_IsKeyPressed(EUPHORBE_KEY_A)) 80 | glm_vec3_sub(camera->velocity, (vec3) { camera->right[0] * speed_multiplier, camera->right[1] * speed_multiplier, camera->right[2] * speed_multiplier }, camera->velocity); 81 | if (E_IsKeyPressed(EUPHORBE_KEY_D)) 82 | glm_vec3_add(camera->velocity, (vec3) { camera->right[0] * speed_multiplier, camera->right[1] * speed_multiplier, camera->right[2] * speed_multiplier }, camera->velocity); 83 | 84 | f32 friction_multiplier = 1.0f / (1.0f + (camera->friction * dt)); 85 | glm_vec3_mul(camera->velocity, (vec3) { friction_multiplier, friction_multiplier, friction_multiplier }, camera->velocity); 86 | 87 | f32 vec_length = (camera->velocity[0] * camera->velocity[0]) + (camera->velocity[1] * camera->velocity[1]) + (camera->velocity[2] * camera->velocity[2]); 88 | if (vec_length > camera->max_velocity) 89 | { 90 | vec3 normalised_velocity; 91 | glm_vec3_normalize_to(camera->velocity, normalised_velocity); 92 | glm_vec3_mul(normalised_velocity, (vec3) { camera->max_velocity, camera->max_velocity, camera->max_velocity }, camera->velocity); 93 | } 94 | 95 | glm_vec3_add(camera->position, (vec3) { camera->velocity[0] * dt, camera->velocity[1] * dt, camera->velocity[2] * dt }, camera->position); 96 | 97 | EditorCameraUpdateVectors(camera); 98 | } 99 | 100 | void EditorCameraProcessMouse(EditorCamera* camera, f32 dt) 101 | { 102 | f32 mouse_x = E_GetMousePosX(); 103 | f32 mouse_y = E_GetMousePosY(); 104 | 105 | f32 dx = (mouse_x - camera->mouse_pos[0]) * (CAMERA_DEFAULT_MOUSE_SENSITIVITY * dt); 106 | f32 dy = (mouse_y - camera->mouse_pos[1]) * (CAMERA_DEFAULT_MOUSE_SENSITIVITY * dt); 107 | 108 | if (E_IsMouseButtonPressed(EUPHORBE_MOUSE_LEFT)) 109 | { 110 | camera->yaw += dx; // Inverse camera controls 111 | camera->pitch -= dy; // Inverse camera controls 112 | } 113 | 114 | EditorCameraUpdateVectors(camera); 115 | } 116 | 117 | void EditorCameraOnMouseScroll(EditorCamera* camera, f32 scroll) 118 | { 119 | camera->zoom -= scroll; 120 | if (camera->zoom < 1.0f) 121 | camera->zoom = 1.0f; 122 | if (camera->zoom > 90.0f) 123 | camera->zoom = 90.0f; 124 | 125 | EditorCameraUpdateVectors(camera); 126 | } 127 | 128 | void EditorCameraResize(EditorCamera* camera, i32 width, i32 height) 129 | { 130 | camera->viewport_width = (f32)width; 131 | camera->viewport_height = (f32)height; 132 | 133 | EditorCameraUpdateVectors(camera); 134 | } 135 | -------------------------------------------------------------------------------- /Editor/Source/EditorCamera.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define CAMERA_DEFAULT_YAW -90.0f 9 | #define CAMERA_DEFAULT_PITCH 0.0f 10 | #define CAMERA_DEFAULT_SPEED 1.0f 11 | #define CAMERA_DEFAULT_MOUSE_SENSITIVITY 5.0f 12 | #define CAMERA_DEFAULT_ZOOM 90.0f 13 | 14 | typedef struct EditorCamera EditorCamera; 15 | struct EditorCamera 16 | { 17 | f32 yaw; 18 | f32 pitch; 19 | f32 zoom; 20 | 21 | vec3 position; 22 | vec3 front; 23 | vec3 up; 24 | vec3 right; 25 | vec3 worldup; 26 | 27 | vec2 mouse_pos; 28 | b32 first_mouse; 29 | 30 | mat4 view; 31 | mat4 proj; 32 | mat4 camera_matrix; // view * proj 33 | 34 | f32 viewport_width; 35 | f32 viewport_height; 36 | 37 | f32 acceleration; 38 | f32 friction; 39 | vec3 velocity; 40 | f32 max_velocity; 41 | }; 42 | 43 | void EditorCameraInit(EditorCamera* camera); 44 | void EditorCameraUpdate(EditorCamera* camera, f32 dt); 45 | void EditorCameraProcessInput(EditorCamera* camera, f32 dt); 46 | void EditorCameraProcessMouse(EditorCamera* camera, f32 dt); 47 | void EditorCameraOnMouseScroll(EditorCamera* camera, f32 scroll); 48 | void EditorCameraResize(EditorCamera* camera, i32 width, i32 height); -------------------------------------------------------------------------------- /Editor/Source/Panels/ViewportPanel.c: -------------------------------------------------------------------------------- 1 | #include "ViewportPanel.h" 2 | 3 | ViewportPanel viewport_panel; 4 | 5 | void InitViewportPanel(int width, int height) 6 | { 7 | viewport_panel.viewport_size[0] = (f32)width; 8 | viewport_panel.viewport_size[1] = (f32)height; 9 | } 10 | 11 | void DrawViewportPanel(E_Image* buffer, b32* is_viewport_focused, b32* is_viewport_hovered) 12 | { 13 | igPushStyleVar_Float(ImGuiStyleVar_WindowPadding, 0.0f); 14 | 15 | igBegin("Viewport", NULL, ImGuiWindowFlags_None); 16 | 17 | *is_viewport_focused = igIsWindowFocused(ImGuiFocusedFlags_None); 18 | *is_viewport_hovered = igIsWindowHovered(ImGuiFocusedFlags_None); 19 | ImVec2 panel_content_size = { 0.0f, 0.0f }; 20 | igGetContentRegionAvail(&panel_content_size); 21 | 22 | viewport_panel.viewport_size[0] = panel_content_size.x; 23 | viewport_panel.viewport_size[1] = panel_content_size.y; 24 | 25 | E_ImageDrawToGUI(buffer, (i32)viewport_panel.viewport_size[0], (i32)viewport_panel.viewport_size[1], E_NearestSampler); 26 | igEnd(); 27 | 28 | igPopStyleVar(0); 29 | } 30 | -------------------------------------------------------------------------------- /Editor/Source/Panels/ViewportPanel.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | typedef struct ViewportPanel ViewportPanel; 8 | struct ViewportPanel 9 | { 10 | vec2 viewport_size; 11 | }; 12 | 13 | extern ViewportPanel viewport_panel; 14 | 15 | void InitViewportPanel(int width, int height); 16 | void DrawViewportPanel(E_Image* buffer, b32* is_viewport_focused, b32* is_viewport_hovered); -------------------------------------------------------------------------------- /Editor/Source/RenderNodes/FXAANode.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | enum FXAANodeInput 6 | { 7 | FXAANodeInput_Color = EUPHORBE_DECLARE_NODE_INPUT(0), 8 | }; 9 | 10 | enum FXAANodeOutput 11 | { 12 | FXAANodeOutput_ImageOut = EUPHORBE_DECLARE_NODE_OUTPUT(0), 13 | }; 14 | 15 | E_RenderGraphNode* CreateFXAANode(); 16 | void FXAANodeDrawGUI(E_RenderGraphNode* node); -------------------------------------------------------------------------------- /Editor/Source/RenderNodes/FinalBlitNode.c: -------------------------------------------------------------------------------- 1 | #include "FinalBlitNode.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | typedef struct FinalBlitNodeData FinalBlitNodeData; 8 | struct FinalBlitNodeData 9 | { 10 | b32 first_render; 11 | }; 12 | 13 | void FinalBlitNodeInit(E_RenderGraphNode* node, E_RenderGraphExecuteInfo* info) 14 | { 15 | FinalBlitNodeData* data = node->node_data; 16 | data->first_render = 1; 17 | 18 | node->outputs[0] = E_MakeImage(info->width, info->height, E_ImageFormatRGBA16, E_ImageUsageSampled | E_ImageUsageTransferDest); 19 | node->output_count++; 20 | } 21 | 22 | void FinalBlitNodeClean(E_RenderGraphNode* node, E_RenderGraphExecuteInfo* info) 23 | { 24 | FinalBlitNodeData* data = node->node_data; 25 | 26 | E_FreeImage(node->outputs[0]); 27 | free(data); 28 | } 29 | 30 | void FinalBlitNodeExecute(E_RenderGraphNode* node, E_RenderGraphExecuteInfo* info) 31 | { 32 | FinalBlitNodeData* data = node->node_data; 33 | E_ImageLayout src_layout = data->first_render ? E_ImageLayoutUndefined : E_ImageLayoutShaderRead; 34 | 35 | E_CommandBuffer* cmd_buf = E_GetSwapchainCommandBuffer(); 36 | 37 | E_CommandBufferImageTransitionLayout(cmd_buf, node->outputs[0], 38 | E_ImageAccessShaderRead, E_ImageAccessTransferWrite, 39 | src_layout, E_ImageLayoutTransferDest, 40 | E_ImagePipelineStageFragmentShader, E_ImagePipelineStageTransfer, 0); 41 | 42 | E_CommandBufferBlitImage(cmd_buf, E_GetRenderGraphNodeInputImage(&node->inputs[0]), node->outputs[0], E_ImageLayoutTransferSource, E_ImageLayoutTransferDest); 43 | 44 | E_CommandBufferImageTransitionLayout(cmd_buf, node->outputs[0], 45 | E_ImageAccessTransferWrite, E_ImageAccessShaderRead, 46 | E_ImageLayoutTransferDest, E_ImageLayoutShaderRead, 47 | E_ImagePipelineStageTransfer, E_ImagePipelineStageFragmentShader, 0); 48 | } 49 | 50 | void FinalBlitNodeResize(E_RenderGraphNode* node, E_RenderGraphExecuteInfo* info) 51 | { 52 | FinalBlitNodeData* data = node->node_data; 53 | 54 | data->first_render = 1; 55 | E_FreeImage(node->outputs[0]); 56 | node->outputs[0] = E_MakeImage(info->width, info->height, E_ImageFormatRGBA16, E_ImageUsageSampled | E_ImageUsageTransferDest); 57 | } 58 | 59 | E_RenderGraphNode* CreateFinalBlitNode() 60 | { 61 | E_RenderGraphNode* node = malloc(sizeof(E_RenderGraphNode)); 62 | 63 | node->enabled = 1; 64 | node->init_func = FinalBlitNodeInit; 65 | node->clean_func = FinalBlitNodeClean; 66 | node->resize_func = FinalBlitNodeResize; 67 | node->execute_func = FinalBlitNodeExecute; 68 | node->name = "FinalBlitNode"; 69 | node->node_data = malloc(sizeof(E_Image)); 70 | 71 | node->input_count = 0; 72 | memset(node->inputs, 0, sizeof(node->inputs)); 73 | 74 | return node; 75 | } -------------------------------------------------------------------------------- /Editor/Source/RenderNodes/FinalBlitNode.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | enum FinalBlitNodeInput 6 | { 7 | FinalBlitNodeInput_ImageIn = EUPHORBE_DECLARE_NODE_INPUT(0) 8 | }; 9 | 10 | E_RenderGraphNode* CreateFinalBlitNode(); -------------------------------------------------------------------------------- /Editor/Source/RenderNodes/GeometryNode.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | enum GeometryNodeOutput 8 | { 9 | GeometryNodeOutput_Color = EUPHORBE_DECLARE_NODE_OUTPUT(0), 10 | GeometryNodeOutput_Depth = EUPHORBE_DECLARE_NODE_OUTPUT(1) 11 | }; 12 | 13 | E_RenderGraphNode* CreateGeometryNode(); 14 | E_ResourceFile* GetGeometryNodeMaterial(E_RenderGraphNode* node); 15 | void GeometryNodeDrawGUI(E_RenderGraphNode* node); -------------------------------------------------------------------------------- /Editor/Source/RenderNodes/TonemappingNode.c: -------------------------------------------------------------------------------- 1 | #include "TonemappingNode.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | typedef struct TonemappingConstants TonemappingConstants; 9 | struct TonemappingConstants 10 | { 11 | b32 gamma_correct; 12 | i32 mode; 13 | 14 | vec2 pad; 15 | }; 16 | 17 | typedef struct TonemappingNodeData TonemappingNodeData; 18 | struct TonemappingNodeData 19 | { 20 | E_ResourceFile* screen_shader; 21 | E_MaterialInstance* material_instance; 22 | 23 | E_Buffer* quad_vertex_buffer; 24 | b32 first_render; 25 | 26 | // params 27 | TonemappingConstants constants; 28 | }; 29 | 30 | void TonemappingNodeInit(E_RenderGraphNode* node, E_RenderGraphExecuteInfo* info) 31 | { 32 | TonemappingNodeData* data = (TonemappingNodeData*)node->node_data; 33 | 34 | data->constants.gamma_correct = E_GetCVar(info->cvar_table_ptr, "gamma_correction").u.b; 35 | data->constants.mode = (i32)E_GetCVar(info->cvar_table_ptr, "tonemapping_curve").u.i; 36 | 37 | // Shaders 38 | E_Image* color_buffer = E_GetRenderGraphNodeInputImage(&node->inputs[0]); 39 | assert(color_buffer && color_buffer->rhi_handle); 40 | 41 | f64 start = E_TimerGetTime(); 42 | data->screen_shader = E_LoadResource("Assets/Materials/TonemappingMaterial.toml", E_ResourceTypeMaterial); 43 | f64 end = E_TimerGetTime(); 44 | E_LogInfo("TONEMAPPING NODE: Compiled shaders in %f seconds", end - start); 45 | 46 | data->material_instance = E_CreateMaterialInstance(data->screen_shader->as.material, 0); 47 | E_MaterialInstanceWriteSampler(data->material_instance, 0, E_LinearSampler); 48 | E_MaterialInstanceWriteSampledImage(data->material_instance, 1, color_buffer); 49 | 50 | // Screen Quad 51 | f32 quad_vertices[] = { 52 | -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 53 | -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 54 | 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 55 | 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 56 | }; 57 | 58 | data->quad_vertex_buffer = E_CreateVertexBuffer(sizeof(quad_vertices)); 59 | E_SetBufferData(data->quad_vertex_buffer, quad_vertices, sizeof(quad_vertices)); 60 | 61 | // Actual output hdr buffer 62 | node->outputs[0] = E_MakeImage(info->width, info->height, E_ImageFormatRGBA16, E_ImageUsageRenderGraphNodeOutput); 63 | node->output_count++; 64 | data->first_render = 1; 65 | } 66 | 67 | void TonemappingNodeClean(E_RenderGraphNode* node, E_RenderGraphExecuteInfo* info) 68 | { 69 | TonemappingNodeData* data = (TonemappingNodeData*)node->node_data; 70 | 71 | E_FreeImage(node->outputs[0]); 72 | E_FreeBuffer(data->quad_vertex_buffer); 73 | E_FreeMaterialInstance(data->material_instance); 74 | E_FreeResource(data->screen_shader); 75 | 76 | free(data); 77 | } 78 | 79 | void TonemappingNodeExecute(E_RenderGraphNode* node, E_RenderGraphExecuteInfo* info) 80 | { 81 | TonemappingNodeData* data = (TonemappingNodeData*)node->node_data; 82 | 83 | E_CommandBuffer* cmd_buf = E_GetSwapchainCommandBuffer(); 84 | 85 | E_ImageLayout src_layout = data->first_render ? E_ImageLayoutUndefined : E_ImageLayoutTransferSource; 86 | data->first_render = 0; 87 | 88 | vec2 render_size = { (f32)info->width, (f32)info->height }; 89 | 90 | E_CommandBufferImageTransitionLayout(cmd_buf, node->outputs[0], 91 | E_ImageAccessShaderRead, E_ImageAccessColorWrite, 92 | src_layout, E_ImageLayoutColor, 93 | E_ImagePipelineStageFragmentShader, E_ImagePipelineStageColorOutput, 0); 94 | 95 | E_ClearValue color_clear = { 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0 }; 96 | 97 | E_ImageAttachment attachments[1] = { 98 | { node->outputs[0], E_ImageLayoutColor, color_clear}, 99 | }; 100 | 101 | E_CommandBufferSetViewport(cmd_buf, info->width, info->height); 102 | E_CommandBufferStartRender(cmd_buf, attachments, 1, render_size, 0); 103 | 104 | E_CommandBufferBindMaterial(cmd_buf, data->screen_shader->as.material); 105 | E_CommandBufferBindMaterialInstance(cmd_buf, data->material_instance, data->screen_shader->as.material, 0); 106 | E_CommandBufferPushConstants(cmd_buf, data->screen_shader->as.material, &data->constants, sizeof(TonemappingConstants)); 107 | E_CommandBufferBindBuffer(cmd_buf, data->quad_vertex_buffer); 108 | E_CommandBufferDraw(cmd_buf, 0, 4); 109 | 110 | E_CommandBufferEndRender(cmd_buf); 111 | 112 | E_CommandBufferImageTransitionLayout(cmd_buf, node->outputs[0], 113 | E_ImageAccessColorWrite, E_ImageAccessShaderRead, 114 | E_ImageLayoutColor, E_ImageLayoutTransferSource, 115 | E_ImagePipelineStageColorOutput, E_ImagePipelineStageFragmentShader, 0); 116 | } 117 | 118 | void TonemappingNodeResize(E_RenderGraphNode* node, E_RenderGraphExecuteInfo* info) 119 | { 120 | TonemappingNodeData* data = (TonemappingNodeData*)node->node_data; 121 | 122 | E_FreeImage(node->outputs[0]); 123 | node->outputs[0] = E_MakeImage(info->width, info->height, E_ImageFormatRGBA16, E_ImageUsageRenderGraphNodeOutput); 124 | data->first_render = 1; 125 | 126 | E_Image* color_buffer = E_GetRenderGraphNodeInputImage(&node->inputs[0]); 127 | assert(color_buffer && color_buffer->rhi_handle); 128 | 129 | E_MaterialInstanceWriteSampledImage(data->material_instance, 1, color_buffer); 130 | } 131 | 132 | E_RenderGraphNode* CreateTonemappingNode() 133 | { 134 | E_RenderGraphNode* node = malloc(sizeof(E_RenderGraphNode)); 135 | 136 | node->enabled = 1; 137 | node->init_func = TonemappingNodeInit; 138 | node->clean_func = TonemappingNodeClean; 139 | node->execute_func = TonemappingNodeExecute; 140 | node->resize_func = TonemappingNodeResize; 141 | node->node_data = malloc(sizeof(TonemappingNodeData)); 142 | memset(node->node_data, 0, sizeof(node->node_data)); 143 | node->name = "TonemappingNode"; 144 | 145 | node->input_count = 0; 146 | memset(node->inputs, 0, sizeof(node->inputs)); 147 | 148 | return node; 149 | } 150 | 151 | void TonemappingNodeDrawGUI(E_RenderGraphNode* node) 152 | { 153 | TonemappingNodeData* data = (TonemappingNodeData*)node->node_data; 154 | 155 | static const char* modes[] = { "ACES", "Reinhard", "Luma Reinhard", "White Preserving Luma Reinhard", "Rom Bin Da House", "Filmic", "Uncharted 2", "None" }; 156 | 157 | b32 tone_enabled = igTreeNodeEx_Str("Tonemapping Node", ImGuiTreeNodeFlags_DefaultOpen | ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_SpanAvailWidth | ImGuiTreeNodeFlags_AllowItemOverlap | ImGuiTreeNodeFlags_FramePadding); 158 | if (tone_enabled) 159 | { 160 | igCheckbox("Enable Gamma Correction", &data->constants.gamma_correct); 161 | igCombo_Str_arr("Tonemapping Algorithms", &data->constants.mode, modes, 8, 0); 162 | igTreePop(); 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /Editor/Source/RenderNodes/TonemappingNode.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | enum TonemappingNodeInput 6 | { 7 | TonemappingNodeInput_Geometry = EUPHORBE_DECLARE_NODE_INPUT(0) 8 | }; 9 | 10 | enum TonemappingNodeOutput 11 | { 12 | TonemappingNodeOutput_Color = EUPHORBE_DECLARE_NODE_OUTPUT(0) 13 | }; 14 | 15 | E_RenderGraphNode* CreateTonemappingNode(); 16 | void TonemappingNodeDrawGUI(E_RenderGraphNode* node); -------------------------------------------------------------------------------- /Editor/Source/main.c: -------------------------------------------------------------------------------- 1 | #pragma warning(disable: C6011) 2 | #include "Editor.h" 3 | 4 | int main() 5 | { 6 | EditorInit(); 7 | EditorUpdate(); 8 | EditorCleanup(); 9 | } -------------------------------------------------------------------------------- /Editor/imgui.ini: -------------------------------------------------------------------------------- 1 | [Window][Debug##Default] 2 | Pos=60,60 3 | Size=400,400 4 | Collapsed=0 5 | 6 | [Window][Dear ImGui Demo] 7 | Pos=338,197 8 | Size=773,500 9 | Collapsed=0 10 | DockId=0x00000003,1 11 | 12 | [Window][DockSpace Demo] 13 | Size=1264,681 14 | Collapsed=0 15 | 16 | [Window][Example: Log] 17 | Pos=60,60 18 | Size=550,354 19 | Collapsed=0 20 | 21 | [Window][Log] 22 | Pos=340,847 23 | Size=1357,290 24 | Collapsed=0 25 | DockId=0x0000000B,0 26 | 27 | [Window][Viewport] 28 | Pos=340,19 29 | Size=1357,826 30 | Collapsed=0 31 | DockId=0x00000009,0 32 | 33 | [Window][Example: Custom rendering] 34 | Pos=548,273 35 | Size=485,414 36 | Collapsed=0 37 | 38 | [Window][Example: Console] 39 | Pos=60,60 40 | Size=520,600 41 | Collapsed=0 42 | 43 | [Window][Example: Simple layout] 44 | Pos=300,171 45 | Size=500,440 46 | Collapsed=0 47 | 48 | [Window][Example: Property editor] 49 | Pos=60,60 50 | Size=430,450 51 | Collapsed=0 52 | 53 | [Window][Color Panel] 54 | Pos=0,19 55 | Size=368,820 56 | Collapsed=0 57 | DockId=0x00000004,0 58 | 59 | [Window][Dockspace] 60 | Pos=0,0 61 | Size=1920,1137 62 | Collapsed=0 63 | 64 | [Window][Material Viewer] 65 | Pos=1699,19 66 | Size=221,1118 67 | Collapsed=0 68 | DockId=0x0000000E,0 69 | 70 | [Window][Performance Viewer] 71 | Pos=0,19 72 | Size=338,634 73 | Collapsed=0 74 | DockId=0x0000000A,0 75 | 76 | [Window][Camera Panel] 77 | Pos=0,19 78 | Size=298,1118 79 | Collapsed=0 80 | DockId=0x00000007,1 81 | 82 | [Window][Camera Info] 83 | Pos=0,990 84 | Size=393,147 85 | Collapsed=0 86 | DockId=0x00000007,0 87 | 88 | [Window][Scene Settings] 89 | Pos=1234,484 90 | Size=302,317 91 | Collapsed=0 92 | DockId=0x00000006,0 93 | 94 | [Window][Render Graph Viewer] 95 | Pos=0,633 96 | Size=442,744 97 | Collapsed=0 98 | DockId=0x0000000C,0 99 | 100 | [Window][Light Manager] 101 | Pos=0,655 102 | Size=338,482 103 | Collapsed=0 104 | DockId=0x0000000C,1 105 | 106 | [Window][Scene Renderer] 107 | Pos=0,655 108 | Size=338,482 109 | Collapsed=0 110 | DockId=0x0000000C,0 111 | 112 | [Table][0xD0F0C6E3,2] 113 | Column 0 Weight=1.0000 114 | Column 1 Weight=1.0000 115 | 116 | [Docking][Data] 117 | DockSpace ID=0x1ED03EE2 Window=0x5B816B74 Pos=0,19 Size=1920,1118 Split=X 118 | DockNode ID=0x0000000D Parent=0x1ED03EE2 SizeRef=1697,1355 Split=X 119 | DockNode ID=0x00000001 Parent=0x0000000D SizeRef=338,1355 Split=Y Selected=0xDAABCCA0 120 | DockNode ID=0x0000000A Parent=0x00000001 SizeRef=479,634 Selected=0x237E9FF3 121 | DockNode ID=0x0000000C Parent=0x00000001 SizeRef=479,482 Selected=0x5349D603 122 | DockNode ID=0x00000002 Parent=0x0000000D SizeRef=1357,1355 Split=X 123 | DockNode ID=0x00000007 Parent=0x00000002 SizeRef=464,1118 Selected=0x237E9FF3 124 | DockNode ID=0x00000008 Parent=0x00000002 SizeRef=2094,1118 Split=X 125 | DockNode ID=0x00000003 Parent=0x00000008 SizeRef=1806,1118 Split=X 126 | DockNode ID=0x00000004 Parent=0x00000003 SizeRef=368,1118 Selected=0x6E489E7A 127 | DockNode ID=0x00000005 Parent=0x00000003 SizeRef=1550,1118 Split=Y Selected=0x995B0CF8 128 | DockNode ID=0x00000009 Parent=0x00000005 SizeRef=1357,826 CentralNode=1 Selected=0x995B0CF8 129 | DockNode ID=0x0000000B Parent=0x00000005 SizeRef=1357,290 Selected=0xB7722E25 130 | DockNode ID=0x00000006 Parent=0x00000008 SizeRef=286,1118 Selected=0x0727BC04 131 | DockNode ID=0x0000000E Parent=0x1ED03EE2 SizeRef=221,1355 Selected=0x0727BC04 132 | 133 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Milo Heinrich 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Euphorbe 2 | 3 | ![Euphorbe](.github/logo.png) 4 | 5 | Euphorbe is a fresh early-stage game engine written entirely in C. 6 | It's purpose is mainly to try and build an efficient yet developped Vulkan renderer, and this with the usage of the **VK_KHR_dynamic_rendering** extension. 7 | *** 8 | 9 | # Getting started 10 | 11 | Note that only MSVC is supported to build Euphorbe! 12 | 13 | **1. Download the repository** 14 | ```bat 15 | git clone https://github.com/Sausty/Euphorbe 16 | install.bat 17 | ``` 18 | 19 | **2. Generate the project** 20 | ```bat 21 | cmake -G "Visual Studio 17 2022" -B build 22 | ``` 23 | 24 | # Requirements 25 | 26 | ## Vulkan Extensions 27 | - VK_KHR_dynamic_rendering 28 | - VK_KHR_16bit_storage 29 | - VK_KHR_8bit_storage 30 | - VK_KHR_swapchain 31 | - VK_KHR_synchronisation2 32 | - VK_KHR_shader_non_semantic_info 33 | - VK_NV_mesh_shader 34 | 35 | ## Instance Extensions 36 | - VK_KHR_surface 37 | - VK_KHR_win32_surface 38 | - VK_EXT_debug_utils 39 | 40 | # Dependencies 41 | 42 | - [volk](https://github.com/zeux/volk) 43 | - [Vulkan-Headers](https://github.com/KhronosGroup/Vulkan-Headers) 44 | - [shaderc](https://github.com/google/shaderc) 45 | - [VMA](https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator) 46 | - [SPIRV-Reflect](https://github.com/KhronosGroup/SPIRV-Reflect) 47 | - [cimgui](https://github.com/Sausty/cimgui) 48 | - [tomlc99](https://github.com/cktan/tomlc99) 49 | - [cglm](https://github.com/recp/cglm) 50 | - [cgltf](https://github.com/jkuhlmann/cgltf) 51 | 52 | # Screenshots 53 | 54 | ## Screenshot from January 10 2022 55 | ![Jan 10 2022](.github/10jan2022.PNG) 56 | 57 | # Contributing 58 | 59 | ## Contributions to Euphorbe is accepted and encouraged ; let's make a great engine together! 60 | 61 | ## FXAA Demo 62 | ### Without: 63 | ![Without FXAA](.github/no_fxaa.PNG)\ 64 | ### With: 65 | ![With FXAA](.github/fxaa.PNG)\ 66 | 67 | ## Current features 68 | 69 | - Fully customisable render graph 70 | - Vulkan backend 71 | - Model loading (glTF) with cgltf 72 | - HDR texture support 73 | - Built-in editor 74 | - Custom material file format 75 | - Window management 76 | - Input system 77 | - Runtime shader compiling with shaderc 78 | - Resource system 79 | - GUI system with cimgui 80 | - Timer 81 | - FXAA anti-aliasing 82 | - PBR pipeline with IBL 83 | - Turing mesh shaders 84 | 85 | ## Additional information 86 | 87 | **Note that you need the Beta Vulkan drivers to run this program!** 88 | -------------------------------------------------------------------------------- /ThirdParty/cgltf/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018-2021 Johannes Kuhlmann 2 | 3 | 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: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | 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. 8 | -------------------------------------------------------------------------------- /ThirdParty/imgui_backends/cimgui_impl.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | typedef struct ImGui_ImplVulkanH_FrameSemaphores ImGui_ImplVulkanH_FrameSemaphores; 4 | typedef struct ImGui_ImplVulkanH_Window ImGui_ImplVulkanH_Window; 5 | typedef struct ImGui_ImplVulkanH_Frame ImGui_ImplVulkanH_Frame; 6 | typedef struct ImGui_ImplVulkan_InitInfo ImGui_ImplVulkan_InitInfo; 7 | 8 | struct ImGui_ImplVulkanH_Frame; 9 | struct ImGui_ImplVulkanH_Window; 10 | struct ImGui_ImplVulkan_InitInfo 11 | { 12 | VkInstance Instance; 13 | VkPhysicalDevice PhysicalDevice; 14 | VkDevice Device; 15 | uint32_t QueueFamily; 16 | VkQueue Queue; 17 | VkPipelineCache PipelineCache; 18 | VkDescriptorPool DescriptorPool; 19 | uint32_t Subpass; 20 | uint32_t MinImageCount; 21 | uint32_t ImageCount; 22 | VkSampleCountFlagBits MSAASamples; 23 | const VkAllocationCallbacks* Allocator; 24 | void (*CheckVkResultFn)(VkResult err); 25 | }; 26 | struct ImGui_ImplVulkanH_Frame 27 | { 28 | VkCommandPool CommandPool; 29 | VkCommandBuffer CommandBuffer; 30 | VkFence Fence; 31 | VkImage Backbuffer; 32 | VkImageView BackbufferView; 33 | VkFramebuffer Framebuffer; 34 | }; 35 | struct ImGui_ImplVulkanH_FrameSemaphores 36 | { 37 | VkSemaphore ImageAcquiredSemaphore; 38 | VkSemaphore RenderCompleteSemaphore; 39 | }; 40 | struct ImGui_ImplVulkanH_Window 41 | { 42 | int Width; 43 | int Height; 44 | VkSwapchainKHR Swapchain; 45 | VkSurfaceKHR Surface; 46 | VkSurfaceFormatKHR SurfaceFormat; 47 | VkPresentModeKHR PresentMode; 48 | VkRenderPass RenderPass; 49 | VkPipeline Pipeline; 50 | bool ClearEnable; 51 | VkClearValue ClearValue; 52 | uint32_t FrameIndex; 53 | uint32_t ImageCount; 54 | uint32_t SemaphoreIndex; 55 | ImGui_ImplVulkanH_Frame* Frames; 56 | ImGui_ImplVulkanH_FrameSemaphores* FrameSemaphores; 57 | }; 58 | CIMGUI_API bool ImGui_ImplWin32_Init(void* hwnd); 59 | CIMGUI_API void ImGui_ImplWin32_Shutdown(); 60 | CIMGUI_API void ImGui_ImplWin32_NewFrame(); 61 | CIMGUI_API void ImGui_ImplWin32_EnableDpiAwareness(); 62 | CIMGUI_API float ImGui_ImplWin32_GetDpiScaleForHwnd(void* hwnd); 63 | CIMGUI_API float ImGui_ImplWin32_GetDpiScaleForMonitor(void* monitor); 64 | CIMGUI_API void ImGui_ImplWin32_EnableAlphaCompositing(void* hwnd); 65 | 66 | CIMGUI_API bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info,VkRenderPass render_pass); 67 | CIMGUI_API void ImGui_ImplVulkan_Shutdown(); 68 | CIMGUI_API void ImGui_ImplVulkan_NewFrame(); 69 | CIMGUI_API void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer command_buffer, VkPipeline pipeline); 70 | CIMGUI_API bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer); 71 | CIMGUI_API void ImGui_ImplVulkan_DestroyFontUploadObjects(); 72 | CIMGUI_API void ImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_count); 73 | CIMGUI_API void* ImGui_ImplVulkan_AddTexture(VkImageView image_view, VkImageLayout image_layout, VkSampler sampler, VkDescriptorSet descriptor_set); 74 | CIMGUI_API VkDescriptorSetLayout ImGui_ImplVulkan_GetDescriptorSetLayout(); 75 | 76 | CIMGUI_API void ImGui_ImplVulkanH_CreateOrResizeWindow(VkInstance instance,VkPhysicalDevice physical_device,VkDevice device,ImGui_ImplVulkanH_Window* wnd,uint32_t queue_family,const VkAllocationCallbacks* allocator,int w,int h,uint32_t min_image_count); 77 | CIMGUI_API void ImGui_ImplVulkanH_DestroyWindow(VkInstance instance,VkDevice device,ImGui_ImplVulkanH_Window* wnd,const VkAllocationCallbacks* allocator); 78 | CIMGUI_API VkSurfaceFormatKHR ImGui_ImplVulkanH_SelectSurfaceFormat(VkPhysicalDevice physical_device,VkSurfaceKHR surface,const VkFormat* request_formats,int request_formats_count,VkColorSpaceKHR request_color_space); 79 | CIMGUI_API VkPresentModeKHR ImGui_ImplVulkanH_SelectPresentMode(VkPhysicalDevice physical_device,VkSurfaceKHR surface,const VkPresentModeKHR* request_modes,int request_modes_count); 80 | CIMGUI_API int ImGui_ImplVulkanH_GetMinImageCountFromPresentMode(VkPresentModeKHR present_mode); 81 | -------------------------------------------------------------------------------- /ThirdParty/stb/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | Copyright (c) 2017 Sean Barrett 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 7 | of the Software, and to permit persons to whom the Software is furnished to do 8 | so, subject to the following conditions: 9 | The above copyright notice and this permission notice shall be included in all 10 | copies or substantial portions of the Software. 11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 17 | SOFTWARE. -------------------------------------------------------------------------------- /ThirdParty/tomlc99/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) CK Tan 4 | https://github.com/cktan/tomlc99 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. -------------------------------------------------------------------------------- /ThirdParty/vma/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017-2021 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. -------------------------------------------------------------------------------- /install.bat: -------------------------------------------------------------------------------- 1 | git submodule update --init 2 | cd ThirdParty/cimgui 3 | git checkout docking_inter 4 | git submodule update --init 5 | cd imgui 6 | git checkout docking 7 | cd ../../../ -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # CMake Header 2 | cmake_minimum_required(VERSION 3.8) 3 | 4 | # Get source files 5 | file(GLOB_RECURSE EUPHORBE_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/Euphorbe/*.h ${CMAKE_CURRENT_SOURCE_DIR}/Euphorbe/*.c ${CMAKE_CURRENT_SOURCE_DIR}/Euphorbe/*.cpp) 6 | 7 | find_package(Vulkan) 8 | set(THIRD_PARTY ${CMAKE_CURRENT_SOURCE_DIR}/../ThirdParty) 9 | 10 | # Project settings 11 | add_definitions(-DCIMGUI_DEFINE_ENUMS_AND_STRUCTS) 12 | add_definitions(-D_CRT_SECURE_NO_WARNINGS) 13 | add_definitions(-DVK_NO_PROTOTYPES) 14 | add_library(Euphorbe ${EUPHORBE_SOURCE}) 15 | 16 | target_include_directories(Euphorbe PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} 17 | ${THIRD_PARTY}/Vulkan-Headers/include 18 | ${THIRD_PARTY}/volk 19 | ${THIRD_PARTY}/vma 20 | ${THIRD_PARTY}/spirv_reflect 21 | ${THIRD_PARTY}/cimgui 22 | ${THIRD_PARTY}/cimgui/imgui 23 | ${THIRD_PARTY}/imgui_backends 24 | ${THIRD_PARTY}/tomlc99 25 | ${THIRD_PARTY}/stb 26 | ${THIRD_PARTY}/cglm/include 27 | ${THIRD_PARTY}/cgltf 28 | $ENV{VULKAN_SDK}/Include) 29 | 30 | target_link_libraries(Euphorbe PUBLIC volk cimgui imgui_impl TOML cglm) 31 | target_link_libraries(Euphorbe PUBLIC $ENV{VULKAN_SDK}/Lib/shaderc_combined.lib) 32 | target_compile_definitions(Euphorbe PUBLIC IMGUI_IMPL_API=) 33 | 34 | # Platform dependent settings 35 | if (WIN32) 36 | set(VOLK_STATIC_DEFINES VK_USE_PLATFORM_WIN32_KHR) 37 | add_definitions(-DVK_USE_PLATFORM_WIN32_KHR) 38 | endif() 39 | 40 | source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${EUPHORBE_SOURCE}) -------------------------------------------------------------------------------- /src/Euphorbe/Core/CVar.c: -------------------------------------------------------------------------------- 1 | #include "CVar.h" 2 | 3 | #include 4 | #include 5 | 6 | typedef enum E_CVarType E_CVarType; 7 | enum E_CVarType 8 | { 9 | E_CVarTypeString, 10 | E_CVarTypeInt, 11 | E_CVarTypeBool, 12 | E_CVarTypeDouble 13 | }; 14 | 15 | E_CVarType E_GetCVarTypeFromString(char* str); 16 | 17 | void E_CreateCVarSystem(char* path, E_CVarSystem* dst) 18 | { 19 | dst->path = path; 20 | 21 | FILE* fp = NULL; 22 | char errbuf[200] = { 0 }; 23 | 24 | fp = fopen(path, "r"); 25 | if (!fp) 26 | E_LogError("CVAR SYSTEM ERROR: Failed to read file (path=%s)", path); 27 | 28 | toml_table_t* conf = toml_parse_file(fp, errbuf, sizeof(errbuf)); 29 | fclose(fp); 30 | 31 | if (!conf) 32 | E_LogError("TOML READ ERROR: Failed to parse - %s", errbuf); 33 | 34 | toml_table_t* cvar_table = toml_table_in(conf, "CVarTable"); 35 | if (!cvar_table) 36 | E_LogError("TOML READ ERROR: Failed to parse CVar Table - %s", errbuf); 37 | 38 | toml_array_t* cvar_map = toml_array_in(cvar_table, "Table"); 39 | i32 cvar_count = toml_array_nelem(cvar_map); 40 | 41 | assert(cvar_count < EUPHORBE_MAX_CVAR_COUNT); 42 | dst->cvar_count = cvar_count; 43 | 44 | E_INIT_MAP(dst->cvar_map); 45 | 46 | for (i32 i = 0; i < cvar_count; i++) 47 | { 48 | toml_array_t* cvar_descriptor = toml_array_at(cvar_map, i); 49 | 50 | toml_datum_t cvar_type = toml_string_at(cvar_descriptor, 0); 51 | assert(cvar_type.ok); 52 | 53 | toml_datum_t accessor = toml_string_at(cvar_descriptor, 1); 54 | assert(accessor.ok); 55 | 56 | E_CVarType type = E_GetCVarTypeFromString(cvar_type.u.s); 57 | switch (type) 58 | { 59 | case E_CVarTypeInt: 60 | { 61 | i64 value = toml_int_at(cvar_descriptor, 2).u.i; 62 | 63 | E_LogInfo("Loaded Integer CVar with name [%s] and value %d", accessor.u.s, value); 64 | E_MAP_GET(dst->cvar_map, accessor.u.s).u.i = value; 65 | E_MAP_GET(dst->cvar_map, accessor.u.s).ok = 1; 66 | 67 | free(accessor.u.s); 68 | free(cvar_type.u.s); 69 | break; 70 | } 71 | case E_CVarTypeBool: 72 | { 73 | b32 value = toml_bool_at(cvar_descriptor, 2).u.b; 74 | 75 | E_CVar temp = { 0 }; 76 | temp.u.b = value; 77 | 78 | E_LogInfo("Loaded Boolean CVar with name [%s] and value %d", accessor.u.s, value); 79 | E_MAP_GET(dst->cvar_map, accessor.u.s).u.b = value; 80 | E_MAP_GET(dst->cvar_map, accessor.u.s).ok = 1; 81 | 82 | free(accessor.u.s); 83 | free(cvar_type.u.s); 84 | break; 85 | } 86 | case E_CVarTypeDouble: 87 | { 88 | f64 value = toml_double_at(cvar_descriptor, 2).u.d; 89 | 90 | E_CVar temp = { 0 }; 91 | temp.u.d = value; 92 | 93 | E_LogInfo("Loaded Double CVar with name [%s] and value %f", accessor.u.s, value); 94 | E_MAP_GET(dst->cvar_map, accessor.u.s).u.d = value; 95 | E_MAP_GET(dst->cvar_map, accessor.u.s).ok = 1; 96 | 97 | free(accessor.u.s); 98 | free(cvar_type.u.s); 99 | break; 100 | } 101 | } 102 | } 103 | 104 | toml_free(conf); 105 | } 106 | 107 | void E_FreeCVarSystem(E_CVarSystem* sys) 108 | { 109 | 110 | } 111 | 112 | E_CVar E_GetCVar(E_CVarSystem* sys, char* cvar_name) 113 | { 114 | return E_MAP_GET(sys->cvar_map, cvar_name); 115 | } 116 | 117 | void E_SetCVar_Double(E_CVarSystem* sys, char* cvar_name, f64 value) 118 | { 119 | E_CVar var = { 0 }; 120 | var.u.d = value; 121 | E_MAP_MODIFY(sys->cvar_map, cvar_name, var); 122 | } 123 | 124 | void E_SetCVar_Bool(E_CVarSystem* sys, char* cvar_name, b32 value) 125 | { 126 | E_CVar var = { 0 }; 127 | var.u.b = value; 128 | E_MAP_MODIFY(sys->cvar_map, cvar_name, var); 129 | } 130 | 131 | void E_SetCVar_Int(E_CVarSystem* sys, char* cvar_name, i64 value) 132 | { 133 | E_CVar var = { 0 }; 134 | var.u.i = value; 135 | E_MAP_MODIFY(sys->cvar_map, cvar_name, var); 136 | } 137 | 138 | E_CVarType E_GetCVarTypeFromString(char* str) 139 | { 140 | if (!strcmp(str, "INT")) 141 | return E_CVarTypeInt; 142 | if (!strcmp(str, "BOOL")) 143 | return E_CVarTypeBool; 144 | if (!strcmp(str, "DOUBLE")) 145 | return E_CVarTypeDouble; 146 | } -------------------------------------------------------------------------------- /src/Euphorbe/Core/CVar.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Map.h" 4 | 5 | #define EUPHORBE_MAX_CVAR_NAME 128 6 | #define EUPHORBE_MAX_CVAR_COUNT 512 7 | 8 | typedef struct E_CVar E_CVar; 9 | struct E_CVar 10 | { 11 | u32 ok; 12 | union { 13 | i64 i; 14 | b32 b; 15 | f64 d; 16 | } u; 17 | }; 18 | 19 | E_DEFINE_MAP_T(CVar, E_CVar) 20 | 21 | typedef struct E_CVarSystem E_CVarSystem; 22 | struct E_CVarSystem 23 | { 24 | E_MapCVar cvar_map; 25 | i32 cvar_count; 26 | 27 | char* path; 28 | }; 29 | 30 | void E_CreateCVarSystem(char* path, E_CVarSystem* dst); 31 | void E_FreeCVarSystem(E_CVarSystem* sys); 32 | E_CVar E_GetCVar(E_CVarSystem* sys, char* cvar_name); 33 | 34 | // 35 | void E_SetCVar_Double(E_CVarSystem* sys, char* cvar_name, f64 value); 36 | void E_SetCVar_Bool(E_CVarSystem* sys, char* cvar_name, b32 value); 37 | void E_SetCVar_Int(E_CVarSystem* sys, char* cvar_name, i64 value); -------------------------------------------------------------------------------- /src/Euphorbe/Core/Common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | // Typedefs 9 | typedef char i8; 10 | typedef unsigned char u8; 11 | typedef short i16; 12 | typedef unsigned short u16; 13 | typedef int i32; 14 | typedef unsigned int u32; 15 | typedef long long i64; 16 | typedef unsigned long long u64; 17 | typedef u8 b8; 18 | typedef u16 b16; 19 | typedef u32 b32; 20 | typedef float f32; 21 | typedef double f64; 22 | 23 | // Useful defines 24 | #define ARRAY_SIZE(arr) sizeof(arr) / sizeof(arr[0]) 25 | #define KILOBYTES(bytes) bytes * 1024 26 | #define MEGABYTES(bytes) KILOBYTES(bytes) * 1024 27 | #define GIGABYTES(bytes) MEGABYTES(bytes) * 1024 28 | #define OFFSET_PTR_BYTES(type, ptr, offset) ((type*)((u8*)ptr + (offset))) 29 | #define FRAMES_IN_FLIGHT 3 30 | #define PAD_SIZE_16(s) ( ((s) + 15) & ~15 ) 31 | 32 | // Platform detection 33 | #ifdef _WIN32 34 | #define EUPHORBE_WINDOWS 35 | #else 36 | #error "Platform not yet supported!" 37 | #endif 38 | 39 | // Platform includes 40 | 41 | #ifdef EUPHORBE_WINDOWS 42 | #pragma warning(disable: 5105) 43 | #define WIN32_LEAN_AND_MEAN 44 | #include 45 | #endif -------------------------------------------------------------------------------- /src/Euphorbe/Core/Log.c: -------------------------------------------------------------------------------- 1 | #include "Log.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define RESET "\033[0m" 9 | #define BLACK "\033[30m" /* Black */ 10 | #define RED "\033[31m" /* Red */ 11 | #define GREEN "\033[32m" /* Green */ 12 | #define YELLOW "\033[33m" /* Yellow */ 13 | #define BLUE "\033[34m" /* Blue */ 14 | #define MAGENTA "\033[35m" /* Magenta */ 15 | #define CYAN "\033[36m" /* Cyan */ 16 | #define WHITE "\033[37m" /* White */ 17 | #define BOLDBLACK "\033[1m\033[30m" /* Bold Black */ 18 | #define BOLDRED "\033[1m\033[31m" /* Bold Red */ 19 | #define BOLDGREEN "\033[1m\033[32m" /* Bold Green */ 20 | #define BOLDYELLOW "\033[1m\033[33m" /* Bold Yellow */ 21 | #define BOLDBLUE "\033[1m\033[34m" /* Bold Blue */ 22 | #define BOLDMAGENTA "\033[1m\033[35m" /* Bold Magenta */ 23 | #define BOLDCYAN "\033[1m\033[36m" /* Bold Cyan */ 24 | #define BOLDWHITE "\033[1m\033[37m" /* Bold White */ 25 | 26 | E_LogGUI log_gui; 27 | 28 | void LogInfo(const char* message) 29 | { 30 | time_t now; 31 | time(&now); 32 | printf(RESET); 33 | printf(CYAN); 34 | char* time_string = ctime(&now); 35 | time_string[strcspn(time_string, "\n")] = 0; 36 | char final_string[255] = { 0 }; 37 | sprintf(final_string, "%s [EUPHORBE] : %s\n", time_string, message); 38 | ImGuiTextBuffer_append(&log_gui.text_buffer, final_string, NULL); 39 | printf("%s", final_string); 40 | printf(RESET); 41 | } 42 | 43 | void LogWarn(const char* message) 44 | { 45 | time_t now; 46 | time(&now); 47 | printf(RESET); 48 | printf(YELLOW); 49 | char* time_string = ctime(&now); 50 | time_string[strcspn(time_string, "\n")] = 0; 51 | char final_string[255] = {0}; 52 | sprintf(final_string, "%s [EUPHORBE] : %s\n", time_string, message); 53 | ImGuiTextBuffer_append(&log_gui.text_buffer, final_string, NULL); 54 | printf("%s", final_string); 55 | printf(RESET); 56 | } 57 | 58 | void LogError(const char* message) 59 | { 60 | time_t now; 61 | time(&now); 62 | printf(RESET); 63 | printf(RED); 64 | char* time_string = ctime(&now); 65 | time_string[strcspn(time_string, "\n")] = 0; 66 | char final_string[255] = { 0 }; 67 | sprintf(final_string, "%s [EUPHORBE] : %s\n", time_string, message); 68 | ImGuiTextBuffer_append(&log_gui.text_buffer, final_string, NULL); 69 | printf("%s", final_string); 70 | printf(RESET); 71 | } 72 | 73 | void E_LogInfo(const char* message, ...) 74 | { 75 | char buf[100]; 76 | va_list vl; 77 | va_start(vl, message); 78 | 79 | vsnprintf(buf, sizeof(buf), message, vl); 80 | 81 | va_end(vl); 82 | 83 | LogInfo(buf); 84 | } 85 | 86 | void E_LogWarn(const char* message, ...) 87 | { 88 | char buf[100]; 89 | va_list vl; 90 | va_start(vl, message); 91 | 92 | vsnprintf(buf, sizeof(buf), message, vl); 93 | 94 | va_end(vl); 95 | 96 | LogWarn(buf); 97 | } 98 | 99 | void E_LogError(const char* message, ...) 100 | { 101 | char buf[100]; 102 | va_list vl; 103 | va_start(vl, message); 104 | 105 | vsnprintf(buf, sizeof(buf), message, vl); 106 | 107 | va_end(vl); 108 | 109 | LogError(buf); 110 | } 111 | 112 | void E_LogDraw() 113 | { 114 | ImVec2 next_window_size = { 500, 400 }; 115 | ImVec2 null_vec = { 0, 0 }; 116 | ImVec2 style_size = { 0, 1 }; 117 | 118 | igSetNextWindowSize(next_window_size, ImGuiCond_FirstUseEver); 119 | igBegin("Log", NULL, ImGuiWindowFlags_None); 120 | if (igButton("Clear", null_vec)) 121 | ImGuiTextBuffer_clear(&log_gui.text_buffer); 122 | igSameLine(0.0f, 5.0f); 123 | b32 copy = igButton("Copy", null_vec); 124 | igSeparator(); 125 | igBeginChild_Str("Scrolling", null_vec, 0, ImGuiWindowFlags_None); 126 | 127 | igPushStyleVar_Vec2(ImGuiStyleVar_ItemSpacing, style_size); 128 | if (copy) igLogToClipboard(0); 129 | igTextWrapped(ImGuiTextBuffer_begin(&log_gui.text_buffer)); 130 | if (log_gui.scroll_to_bottom) 131 | igSetScrollHereY(1.0f); 132 | log_gui.scroll_to_bottom = 0; 133 | igPopStyleVar(1); 134 | igEndChild(); 135 | igEnd(); 136 | } 137 | -------------------------------------------------------------------------------- /src/Euphorbe/Core/Log.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | typedef struct E_LogGUI E_LogGUI; 7 | struct E_LogGUI 8 | { 9 | ImGuiTextBuffer text_buffer; 10 | b32 scroll_to_bottom; 11 | }; 12 | 13 | extern E_LogGUI log_gui; 14 | 15 | // Print a message in green to the console 16 | void E_LogInfo(const char* message, ...); 17 | 18 | // Print a message in yellow to the console 19 | void E_LogWarn(const char* message, ...); 20 | 21 | // Print a message in red to the console 22 | void E_LogError(const char* message, ...); 23 | 24 | // Draw the Log GUI 25 | void E_LogDraw(); -------------------------------------------------------------------------------- /src/Euphorbe/Core/Map.c: -------------------------------------------------------------------------------- 1 | #include "Map.h" 2 | 3 | u32 E_Hash(char* name) 4 | { 5 | i32 len = strlen(name); 6 | u32 result = 0; 7 | for (i32 i = 0; i < len; i++) { 8 | result += name[i]; 9 | result = (result * name[i]) % EUPHORBE_CONSTANT_MAP_SIZE; 10 | } 11 | return result; 12 | } 13 | -------------------------------------------------------------------------------- /src/Euphorbe/Core/Map.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #define EUPHORBE_CONSTANT_MAP_SIZE 128 6 | 7 | #define E_DEFINE_MAP_T(name, type) typedef struct E_Map##name E_Map##name;\ 8 | struct E_Map##name\ 9 | {\ 10 | ##type data[EUPHORBE_CONSTANT_MAP_SIZE];\ 11 | ##type size_check;\ 12 | }; 13 | 14 | u32 E_Hash(char* name); 15 | 16 | #define E_INIT_MAP(map) memset(map.data, 0, sizeof(map.size_check) * EUPHORBE_CONSTANT_MAP_SIZE); 17 | #define E_HASH_MAP(map, name) E_Hash(name) 18 | 19 | #define E_MAP_INSERT(map, name, value) i32 index = E_HASH_MAP(map, name);\ 20 | map.data[index] = value; 21 | 22 | #define E_MAP_GET(map, name) map.data[E_HASH_MAP(map, name)] 23 | #define E_MAP_REMOVE(map, name) memset(&E_MAP_GET(map, name), 0, sizeof(map.size_check)) 24 | #define E_MAP_MODIFY(map, name, value) map.data[E_HASH_MAP(map, name)] = value 25 | -------------------------------------------------------------------------------- /src/Euphorbe/Core/Vector.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #define E_DEFINE_VECTOR(name, type) typedef struct E_Vector##name E_Vector##name;\ 6 | struct E_Vector##name\ 7 | {\ 8 | ##type *data;\ 9 | ##type size_check;\ 10 | u32 used;\ 11 | u32 size;\ 12 | }; 13 | 14 | #define E_INIT_VECTOR(vec, init_size) vec.data = malloc(init_size * sizeof(vec.size_check)); vec.size = init_size; vec.used = 0 15 | #define E_FREE_VECTOR(vec) free(vec.data); vec.size = vec.used = 0 16 | #define E_PUSH_BACK_VECTOR(vec, elem) if (vec.used >= vec.size) { vec.size *= 2; vec.data = realloc(vec.data, vec.size * sizeof(vec.size_check)); } vec.data[vec.used++] = elem 17 | #define E_POP_BACK_VECTOR(vec) memset(&vec.data[vec.used], 0, sizeof(vec.size_check)); vec.used-- 18 | #define E_SIZE_VECTOR(vec) vec.size 19 | #define E_CAPACITY_VECTOR(vec) vec.size -------------------------------------------------------------------------------- /src/Euphorbe/Euphorbe.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Core 4 | #include "Core/Common.h" 5 | #include "Core/Log.h" 6 | #include "Core/Map.h" 7 | #include "Core/CVar.h" 8 | 9 | // Platform 10 | #include "Platform/Window.h" 11 | #include "Platform/Input.h" 12 | #include "Platform/Timer.h" 13 | 14 | // Renderer 15 | #include "Graphics/Renderer.h" 16 | #include "Graphics/Image.h" 17 | #include "Graphics/ShaderCompiler.h" 18 | #include "Graphics/Material.h" 19 | #include "Graphics/Buffer.h" 20 | #include "Graphics/Mesh.h" 21 | #include "Graphics/RenderGraph.h" 22 | #include "Graphics/CommandBuffer.h" 23 | #include "Graphics/GPUProfiler.h" 24 | 25 | // Resource 26 | #include "Resource/Resource.h" -------------------------------------------------------------------------------- /src/Euphorbe/Graphics/Buffer.c: -------------------------------------------------------------------------------- 1 | #include "Buffer.h" 2 | 3 | #ifdef EUPHORBE_WINDOWS 4 | #include 5 | #endif 6 | 7 | E_Buffer* E_CreateVertexBuffer(i64 size) 8 | { 9 | E_Buffer* buffer = malloc(sizeof(E_Buffer)); 10 | buffer->usage = E_BufferUsageVertex; 11 | 12 | #ifdef EUPHORBE_WINDOWS 13 | buffer->rhi_handle = E_Vk_AllocateVertexBuffer(size); 14 | #endif 15 | 16 | return buffer; 17 | } 18 | 19 | E_Buffer* E_CreateIndexBuffer(i64 size) 20 | { 21 | E_Buffer* buffer = malloc(sizeof(E_Buffer)); 22 | buffer->usage = E_BufferUsageIndex; 23 | 24 | #ifdef EUPHORBE_WINDOWS 25 | buffer->rhi_handle = E_Vk_AllocateIndexBuffer(size); 26 | #endif 27 | 28 | return buffer; 29 | } 30 | 31 | E_Buffer* E_CreateUniformBuffer(i64 size) 32 | { 33 | E_Buffer* buffer = malloc(sizeof(E_Buffer)); 34 | buffer->usage = E_BufferUsageUniform; 35 | 36 | #ifdef EUPHORBE_WINDOWS 37 | buffer->rhi_handle = E_Vk_AllocateUniformBuffer(size); 38 | #endif 39 | 40 | return buffer; 41 | } 42 | 43 | E_Buffer* E_CreateStorageBuffer(i64 size) 44 | { 45 | E_Buffer* buffer = malloc(sizeof(E_Buffer)); 46 | buffer->usage = E_BufferUsageStorage; 47 | 48 | #ifdef EUPHORBE_WINDOWS 49 | buffer->rhi_handle = E_Vk_AllocateStorageBuffer(size); 50 | #endif 51 | 52 | return buffer; 53 | } 54 | 55 | void E_SetBufferData(E_Buffer* buffer, void* data, i64 size) 56 | { 57 | #ifdef EUPHORBE_WINDOWS 58 | E_Vk_SetBufferData((E_VulkanBuffer*)buffer->rhi_handle, data, size); 59 | #endif 60 | } 61 | 62 | void E_FreeBuffer(E_Buffer* buffer) 63 | { 64 | #ifdef EUPHORBE_WINDOWS 65 | E_Vk_FreeBuffer((E_VulkanBuffer*)buffer->rhi_handle); 66 | #endif 67 | free(buffer); 68 | } -------------------------------------------------------------------------------- /src/Euphorbe/Graphics/Buffer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | typedef enum E_BufferUsage E_BufferUsage; 6 | enum E_BufferUsage 7 | { 8 | E_BufferUsageVertex, 9 | E_BufferUsageIndex, 10 | E_BufferUsageUniform, 11 | E_BufferUsageStorage 12 | }; 13 | 14 | typedef struct E_Buffer E_Buffer; 15 | struct E_Buffer 16 | { 17 | E_BufferUsage usage; 18 | void* rhi_handle; // E_VulkanBuffer for example 19 | }; 20 | 21 | E_Buffer* E_CreateVertexBuffer(i64 size); 22 | E_Buffer* E_CreateIndexBuffer(i64 size); 23 | E_Buffer* E_CreateUniformBuffer(i64 size); 24 | E_Buffer* E_CreateStorageBuffer(i64 size); 25 | 26 | void E_SetBufferData(E_Buffer* buffer, void* data, i64 size); 27 | void E_FreeBuffer(E_Buffer* buffer); -------------------------------------------------------------------------------- /src/Euphorbe/Graphics/CommandBuffer.c: -------------------------------------------------------------------------------- 1 | #include "CommandBuffer.h" 2 | 3 | #ifdef EUPHORBE_WINDOWS 4 | #include 5 | #endif 6 | 7 | #include "Renderer.h" 8 | 9 | E_CommandBuffer* E_CreateCommandBuffer(E_CommandBufferType type) 10 | { 11 | E_CommandBuffer* cmd_buf = malloc(sizeof(E_CommandBuffer)); 12 | cmd_buf->type = type; 13 | 14 | #ifdef EUPHORBE_WINDOWS 15 | cmd_buf->rhi_handle = E_Vk_CreateCommandBuffer(type); 16 | #endif 17 | return cmd_buf; 18 | } 19 | 20 | void E_FreeCommandBuffer(E_CommandBuffer* buffer) 21 | { 22 | #ifdef EUPHORBE_WINDOWS 23 | E_Vk_FreeCommandBuffer(buffer->rhi_handle); 24 | #endif 25 | } 26 | 27 | void E_SubmitCommandBuffer(E_CommandBuffer* buffer) 28 | { 29 | #ifdef EUPHORBE_WINDOWS 30 | E_Vk_SubmitCommandBuffer(buffer->rhi_handle); 31 | #endif 32 | } 33 | 34 | void E_BeginCommandBuffer(E_CommandBuffer* cmd) 35 | { 36 | #ifdef EUPHORBE_WINDOWS 37 | E_Vk_BeginCommandBuffer(cmd->rhi_handle); 38 | #endif 39 | } 40 | 41 | void E_EndCommandBuffer(E_CommandBuffer* cmd) 42 | { 43 | #ifdef EUPHORBE_WINDOWS 44 | E_Vk_EndCommandBuffer(cmd->rhi_handle); 45 | #endif 46 | } 47 | 48 | void E_CommandBufferSetViewport(E_CommandBuffer* cmd, i32 width, i32 height) 49 | { 50 | #ifdef EUPHORBE_WINDOWS 51 | E_Vk_CommandBufferSetViewport(cmd->rhi_handle, width, height); 52 | #endif 53 | } 54 | 55 | void E_CommandBufferBindMaterial(E_CommandBuffer* cmd, E_Material* material) 56 | { 57 | #ifdef EUPHORBE_WINDOWS 58 | E_Vk_CommandBufferBindMaterial(cmd->rhi_handle, material->rhi_handle); 59 | #endif 60 | } 61 | 62 | void E_CommandBufferBindComputeMaterial(E_CommandBuffer* cmd, E_Material* material) 63 | { 64 | #ifdef EUPHORBE_WINDOWS 65 | E_Vk_CommandBufferBindComputeMaterial(cmd->rhi_handle, material->rhi_handle); 66 | #endif 67 | } 68 | 69 | void E_CommandBufferBindBuffer(E_CommandBuffer* cmd, E_Buffer* buffer) 70 | { 71 | #ifdef EUPHORBE_WINDOWS 72 | E_Vk_CommandBufferBindBuffer(cmd->rhi_handle, buffer->rhi_handle, buffer->usage); 73 | #endif 74 | } 75 | 76 | void E_CommandBufferBindMaterialInstance(E_CommandBuffer* cmd, E_MaterialInstance* instance, E_Material* material, i32 set_index) 77 | { 78 | #ifdef EUPHORBE_WINDOWS 79 | E_Vk_CommandBufferBindMaterialInstance((E_VulkanCommandBuffer*)cmd->rhi_handle, (E_VulkanMaterialInstance*)instance->rhi_handle, (E_VulkanMaterial*)material->rhi_handle, set_index); 80 | #endif 81 | } 82 | 83 | void E_CommandBufferBindComputeMaterialInstance(E_CommandBuffer* cmd, E_MaterialInstance* instance, E_Material* material, i32 set_index) 84 | { 85 | #ifdef EUPHORBE_WINDOWS 86 | E_Vk_CommandBufferBindComputeMaterialInstance(cmd->rhi_handle, instance->rhi_handle, material->rhi_handle, set_index); 87 | #endif 88 | } 89 | 90 | void E_CommandBufferDraw(E_CommandBuffer* cmd, u32 first, u32 count) 91 | { 92 | #ifdef EUPHORBE_WINDOWS 93 | E_Vk_CommandBufferDraw(cmd->rhi_handle, first, count); 94 | #endif 95 | 96 | E_CurrentRendererStatistics.total_draw_calls += 1; 97 | E_CurrentRendererStatistics.total_vertex_count += count; 98 | E_CurrentRendererStatistics.total_index_count += count / 6; 99 | E_CurrentRendererStatistics.total_triangle_count += count / 3; 100 | } 101 | 102 | void E_CommandBufferDrawIndexed(E_CommandBuffer* cmd, u32 first, u32 count) 103 | { 104 | #ifdef EUPHORBE_WINDOWS 105 | E_Vk_CommandBufferDrawIndexed(cmd->rhi_handle, first, count); 106 | #endif 107 | 108 | E_CurrentRendererStatistics.total_draw_calls += 1; 109 | E_CurrentRendererStatistics.total_vertex_count += count * 6; 110 | E_CurrentRendererStatistics.total_index_count += count; 111 | E_CurrentRendererStatistics.total_triangle_count += count / 3; 112 | } 113 | 114 | void E_CommandBufferDrawMeshlets(E_CommandBuffer* cmd, u32 first, u32 count) 115 | { 116 | #ifdef EUPHORBE_WINDOWS 117 | E_Vk_CommandBufferDrawMeshlets(cmd->rhi_handle, first, count); 118 | #endif 119 | 120 | E_CurrentRendererStatistics.total_draw_calls += 1; 121 | E_CurrentRendererStatistics.total_meshlet_count += count; 122 | } 123 | 124 | void E_CommandBufferDispatch(E_CommandBuffer* cmd, u32 groupX, u32 groupY, u32 groupZ) 125 | { 126 | #ifdef EUPHORBE_WINDOWS 127 | E_Vk_CommandBufferDispatch(cmd->rhi_handle, groupX, groupY, groupZ); 128 | #endif 129 | } 130 | 131 | void E_CommandBufferStartRender(E_CommandBuffer* cmd, E_ImageAttachment* attachments, i32 attachment_count, vec2 render_size, b32 has_depth) 132 | { 133 | #ifdef EUPHORBE_WINDOWS 134 | E_Vk_CommandBufferStartRender(cmd->rhi_handle, attachments, attachment_count, render_size, has_depth); 135 | #endif 136 | } 137 | 138 | void E_CommandBufferEndRender(E_CommandBuffer* cmd) 139 | { 140 | #ifdef EUPHORBE_WINDOWS 141 | E_Vk_CommandBufferEndRender(cmd->rhi_handle); 142 | #endif 143 | } 144 | 145 | void E_CommandBufferPushConstants(E_CommandBuffer* cmd_buf, E_Material* material, void* data, i64 size) 146 | { 147 | #ifdef EUPHORBE_WINDOWS 148 | E_Vk_CommandBufferPushConstants(cmd_buf->rhi_handle, material->rhi_handle, data, size); 149 | #endif 150 | } 151 | 152 | void E_CommandBufferBlitImage(E_CommandBuffer* cmd_buf, E_Image* src, E_Image* dst, E_ImageLayout src_layout, E_ImageLayout dst_layout) 153 | { 154 | #ifdef EUPHORBE_WINDOWS 155 | E_Vk_CommandBufferBlitImage(cmd_buf->rhi_handle, src->rhi_handle, dst->rhi_handle, src_layout, dst_layout); 156 | #endif 157 | } 158 | 159 | void E_CommandBufferImageTransitionLayout(E_CommandBuffer* cmd_buf, E_Image* image, E_ImageAccess srcAccess, E_ImageAccess dstAccess, E_ImageLayout old, E_ImageLayout new, E_ImagePipelineStage srcStage, E_ImagePipelineStage dstStage, u32 layer) 160 | { 161 | #ifdef EUPHORBE_WINDOWS 162 | E_Vk_CommandBufferImageTransitionLayout(cmd_buf->rhi_handle, image->rhi_handle, srcAccess, dstAccess, old, new, srcStage, dstStage, layer); 163 | #endif 164 | } 165 | 166 | void E_ResetPipelineQuery(E_CommandBuffer* cmd_buf, E_PipelineStatistics* stats) 167 | { 168 | #ifdef EUPHORBE_WINDOWS 169 | E_Vk_ResetPipelineQuery(cmd_buf->rhi_handle, stats->rhi_handle); 170 | #endif 171 | } 172 | 173 | void E_BeginPipelineQuery(E_CommandBuffer* cmd_buf, E_PipelineStatistics* stats) 174 | { 175 | #ifdef EUPHORBE_WINDOWS 176 | E_Vk_BeginPipelineQuery(cmd_buf->rhi_handle, stats->rhi_handle); 177 | #endif 178 | } 179 | 180 | void E_EndPipelineQuery(E_CommandBuffer* cmd_buf, E_PipelineStatistics* stats) 181 | { 182 | #ifdef EUPHORBE_WINDOWS 183 | E_Vk_EndPipelineQuery(cmd_buf->rhi_handle, stats->rhi_handle); 184 | #endif 185 | } 186 | -------------------------------------------------------------------------------- /src/Euphorbe/Graphics/CommandBuffer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Buffer.h" 4 | #include "Material.h" 5 | #include "Renderer.h" 6 | #include "GPUProfiler.h" 7 | 8 | typedef enum E_CommandBufferType E_CommandBufferType; 9 | enum E_CommandBufferType 10 | { 11 | E_CommandBufferTypeGraphics, 12 | E_CommandBufferTypeCompute 13 | }; 14 | 15 | typedef struct E_CommandBuffer E_CommandBuffer; 16 | struct E_CommandBuffer 17 | { 18 | E_CommandBufferType type; 19 | void* rhi_handle; 20 | }; 21 | 22 | E_CommandBuffer* E_CreateCommandBuffer(E_CommandBufferType type); 23 | void E_FreeCommandBuffer(E_CommandBuffer* buffer); 24 | void E_SubmitCommandBuffer(E_CommandBuffer* buffer); 25 | 26 | // 27 | void E_BeginCommandBuffer(E_CommandBuffer* cmd); 28 | void E_EndCommandBuffer(E_CommandBuffer* cmd); 29 | 30 | // 31 | void E_CommandBufferSetViewport(E_CommandBuffer* cmd, i32 width, i32 height); 32 | void E_CommandBufferBindMaterial(E_CommandBuffer* cmd, E_Material* material); 33 | void E_CommandBufferBindComputeMaterial(E_CommandBuffer* cmd, E_Material* material); 34 | void E_CommandBufferBindBuffer(E_CommandBuffer* cmd, E_Buffer* buffer); 35 | void E_CommandBufferBindMaterialInstance(E_CommandBuffer* cmd, E_MaterialInstance* instance, E_Material* material, i32 set_index); 36 | void E_CommandBufferBindComputeMaterialInstance(E_CommandBuffer* cmd, E_MaterialInstance* instance, E_Material* material, i32 set_index); 37 | void E_CommandBufferDraw(E_CommandBuffer* cmd, u32 first, u32 count); 38 | void E_CommandBufferDrawIndexed(E_CommandBuffer* cmd, u32 first, u32 count); 39 | void E_CommandBufferDrawMeshlets(E_CommandBuffer* cmd, u32 first, u32 count); 40 | void E_CommandBufferDispatch(E_CommandBuffer* cmd, u32 groupX, u32 groupY, u32 groupZ); 41 | void E_CommandBufferStartRender(E_CommandBuffer* cmd, E_ImageAttachment* attachments, i32 attachment_count, vec2 render_size, b32 has_depth); 42 | void E_CommandBufferEndRender(E_CommandBuffer* cmd); 43 | void E_CommandBufferPushConstants(E_CommandBuffer* cmd_buf, E_Material* material, void* data, i64 size); 44 | void E_CommandBufferBlitImage(E_CommandBuffer* cmd_buf, E_Image* src, E_Image* dst, E_ImageLayout src_layout, E_ImageLayout dst_layout); 45 | void E_CommandBufferImageTransitionLayout(E_CommandBuffer* cmd_buf, E_Image* image, E_ImageAccess srcAccess, E_ImageAccess dstAccess, E_ImageLayout old, E_ImageLayout new, E_ImagePipelineStage srcStage, E_ImagePipelineStage dstStage, u32 layer); 46 | void E_ResetPipelineQuery(E_CommandBuffer* cmd_buf, E_PipelineStatistics* stats); 47 | void E_BeginPipelineQuery(E_CommandBuffer* cmd_buf, E_PipelineStatistics* stats); 48 | void E_EndPipelineQuery(E_CommandBuffer* cmd_buf, E_PipelineStatistics* stats); -------------------------------------------------------------------------------- /src/Euphorbe/Graphics/GPUProfiler.c: -------------------------------------------------------------------------------- 1 | #include "GPUProfiler.h" 2 | 3 | #ifdef EUPHORBE_WINDOWS 4 | #include 5 | #endif 6 | 7 | #define SPAGHETTI_CODE_KEKW(function) E_Vk_##function(stats->rhi_handle) 8 | 9 | E_PipelineStatistics* E_CreatePipelineStatistics() 10 | { 11 | E_PipelineStatistics* stats = malloc(sizeof(E_PipelineStatistics)); 12 | 13 | #ifdef EUPHORBE_WINDOWS 14 | stats->rhi_handle = E_Vk_CreatePipelineStatistics(); 15 | #endif 16 | 17 | return stats; 18 | } 19 | 20 | void E_FreePipelineStatistics(E_PipelineStatistics* stats) 21 | { 22 | #ifdef EUPHORBE_WINDOWS 23 | E_Vk_FreePipelineStatistics(stats->rhi_handle); 24 | #endif 25 | 26 | free(stats); 27 | } 28 | 29 | void E_GetQueryResults(E_PipelineStatistics* stats) 30 | { 31 | #ifdef EUPHORBE_WINDOWS 32 | E_Vk_GetQueryResults(stats->rhi_handle); 33 | #endif 34 | } 35 | 36 | void E_DrawPipelineStatisticsGUI(E_PipelineStatistics* stats) 37 | { 38 | #ifdef EUPHORBE_WINDOWS 39 | E_Vk_DrawPipelineStatisticsGUI(stats->rhi_handle); 40 | #endif 41 | } 42 | 43 | u64 E_GetInputAssemblyVertices(E_PipelineStatistics* stats) 44 | { 45 | #ifdef EUPHORBE_WINDOWS 46 | SPAGHETTI_CODE_KEKW(GetInputAssemblyVertices); 47 | #endif 48 | } 49 | 50 | u64 E_GetInputAssemblyPrimitives(E_PipelineStatistics* stats) 51 | { 52 | #ifdef EUPHORBE_WINDOWS 53 | SPAGHETTI_CODE_KEKW(GetInputAssemblyPrimitives); 54 | #endif 55 | } 56 | 57 | u64 E_GetVertexShaderInvocations(E_PipelineStatistics* stats) 58 | { 59 | #ifdef EUPHORBE_WINDOWS 60 | SPAGHETTI_CODE_KEKW(GetVertexShaderInvocations); 61 | #endif 62 | } 63 | 64 | u64 E_GetClippingInvocations(E_PipelineStatistics* stats) 65 | { 66 | #ifdef EUPHORBE_WINDOWS 67 | SPAGHETTI_CODE_KEKW(GetClippingInvocations); 68 | #endif 69 | } 70 | 71 | u64 E_GetClippingPrimitives(E_PipelineStatistics* stats) 72 | { 73 | #ifdef EUPHORBE_WINDOWS 74 | SPAGHETTI_CODE_KEKW(GetClippingPrimitives); 75 | #endif 76 | } 77 | 78 | u64 E_GetFragmentShaderInvocations(E_PipelineStatistics* stats) 79 | { 80 | #ifdef EUPHORBE_WINDOWS 81 | SPAGHETTI_CODE_KEKW(GetFragmentShaderInvocations); 82 | #endif 83 | } 84 | 85 | u64 E_GetHullShaderInvocations(E_PipelineStatistics* stats) 86 | { 87 | #ifdef EUPHORBE_WINDOWS 88 | SPAGHETTI_CODE_KEKW(GetHullShaderInvocations); 89 | #endif 90 | } 91 | 92 | u64 E_GetDomainShaderInvocations(E_PipelineStatistics* stats) 93 | { 94 | #ifdef EUPHORBE_WINDOWS 95 | SPAGHETTI_CODE_KEKW(GetDomainShaderInvocations); 96 | #endif 97 | } 98 | 99 | u64 E_GetComputeShaderInvocations(E_PipelineStatistics* stats) 100 | { 101 | #ifdef EUPHORBE_WINDOWS 102 | SPAGHETTI_CODE_KEKW(GetComputeShaderInvocations); 103 | #endif 104 | } 105 | -------------------------------------------------------------------------------- /src/Euphorbe/Graphics/GPUProfiler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | E_DEFINE_VECTOR(U64, u64); 7 | 8 | typedef enum E_PipelineStatisticsQuery E_PipelineStatisticsQuery; 9 | enum E_PipelineStatisticsQuery 10 | { 11 | E_PipelineStatisticsQueryInputAssemblyVertices = 0x00000001, 12 | E_PipelineStatisticsQueryInputAssemblyPrimitives = 0x00000002, 13 | E_PipelineStatisticsQueryVertexShaderInvocations = 0x00000003, 14 | E_PipelineStatisticsQueryClippingInvocations = 0x00000020, 15 | E_PipelineStatisticsQueryClippingPrimitives = 0x00000040, 16 | E_PipelineStatisticsQueryFragmentShaderInvocations = 0x00000080, 17 | E_PipelineStatisticsQueryHullShaderInvocations = 0x00000100, 18 | E_PipelineStatisticsQueryDomainShaderInvocations = 0x00000200, 19 | E_PipelineStatisticsQueryComputeShaderInvocations = 0x00000400, 20 | }; 21 | 22 | typedef struct E_PipelineStatistics E_PipelineStatistics; 23 | struct E_PipelineStatistics 24 | { 25 | E_PipelineStatisticsQuery query; 26 | void* rhi_handle; 27 | }; 28 | 29 | E_PipelineStatistics* E_CreatePipelineStatistics(); 30 | void E_FreePipelineStatistics(E_PipelineStatistics* stats); 31 | void E_GetQueryResults(E_PipelineStatistics* stats); 32 | void E_DrawPipelineStatisticsGUI(E_PipelineStatistics* stats); 33 | 34 | // Get Stats 35 | u64 E_GetInputAssemblyVertices(E_PipelineStatistics* stats); 36 | u64 E_GetInputAssemblyPrimitives(E_PipelineStatistics* stats); 37 | u64 E_GetVertexShaderInvocations(E_PipelineStatistics* stats); 38 | u64 E_GetClippingInvocations(E_PipelineStatistics* stats); 39 | u64 E_GetClippingPrimitives(E_PipelineStatistics* stats); 40 | u64 E_GetFragmentShaderInvocations(E_PipelineStatistics* stats); 41 | u64 E_GetHullShaderInvocations(E_PipelineStatistics* stats); 42 | u64 E_GetDomainShaderInvocations(E_PipelineStatistics* stats); 43 | u64 E_GetComputeShaderInvocations(E_PipelineStatistics* stats); -------------------------------------------------------------------------------- /src/Euphorbe/Graphics/Image.c: -------------------------------------------------------------------------------- 1 | #include "Image.h" 2 | 3 | #ifdef EUPHORBE_WINDOWS 4 | #include "Vulkan/VulkanImage.h" 5 | #include "Vulkan/VulkanRenderer.h" 6 | #endif 7 | 8 | E_Image* E_MakeImage(i32 width, i32 height, E_ImageFormat format, E_ImageUsage usage) 9 | { 10 | E_Image* image = malloc(sizeof(E_Image)); 11 | 12 | image->format = format; 13 | image->width = width; 14 | image->height = height; 15 | image->usage = usage; 16 | 17 | #ifdef EUPHORBE_WINDOWS 18 | image->rhi_handle = E_Vk_MakeImage(width, height, format, usage); 19 | #endif 20 | 21 | return image; 22 | } 23 | 24 | E_Image* E_MakeImageFromFile(const char* path) 25 | { 26 | E_Image* image = malloc(sizeof(E_Image)); 27 | image->format = E_ImageFormatRGBA8; 28 | 29 | #ifdef EUPHORBE_WINDOWS 30 | image->rhi_handle = E_Vk_MakeImageFromFile(path); 31 | 32 | E_VulkanImage* vulkan_image = (E_VulkanImage*)image->rhi_handle; 33 | 34 | image->width = vulkan_image->image_extent.width; 35 | image->height = vulkan_image->image_extent.height; 36 | #endif 37 | 38 | return image; 39 | } 40 | 41 | E_Image* E_MakeHDRImageFromFile(const char* path) 42 | { 43 | E_Image* image = malloc(sizeof(E_Image)); 44 | image->format = E_ImageFormatRGBA16; 45 | 46 | #ifdef EUPHORBE_WINDOWS 47 | image->rhi_handle = E_Vk_MakeHDRImageFromFile(path); 48 | 49 | E_VulkanImage* vulkan_image = (E_VulkanImage*)image->rhi_handle; 50 | 51 | image->width = vulkan_image->image_extent.width; 52 | image->height = vulkan_image->image_extent.height; 53 | #endif 54 | 55 | return image; 56 | } 57 | 58 | E_Image* E_MakeCubeMap(i32 width, i32 height, E_ImageFormat format, E_ImageUsage usage) 59 | { 60 | E_Image* image = malloc(sizeof(E_Image)); 61 | 62 | #ifdef EUPHORBE_WINDOWS 63 | image->rhi_handle = E_Vk_MakeCubeMap(width, height, format, usage); 64 | #endif 65 | return image; 66 | } 67 | 68 | void E_FreeImage(E_Image* image) 69 | { 70 | #ifdef EUPHORBE_WINDOWS 71 | E_Vk_FreeImage(image->rhi_handle); 72 | #endif 73 | 74 | free(image); 75 | } 76 | 77 | void E_ImageResize(E_Image* image, i32 width, i32 height) 78 | { 79 | image->width = width; 80 | image->height = height; 81 | 82 | #ifdef EUPHORBE_WINDOWS 83 | E_Vk_ResizeImage(image->rhi_handle, width, height); 84 | #endif 85 | } 86 | 87 | void E_ImageDrawToGUI(E_Image* image, i32 width, i32 height, E_Sampler* sampler) 88 | { 89 | #ifdef EUPHORBE_WINDOWS 90 | E_Vk_DrawImageToGUI(image->rhi_handle, width, height, sampler->rhi_handle); 91 | #endif 92 | } 93 | 94 | E_Sampler* E_LinearSampler; 95 | E_Sampler* E_NearestSampler; 96 | E_Sampler* E_CubemapSampler; 97 | 98 | void E_InitDefaultSamplers() 99 | { 100 | #ifdef EUPHORBE_WINDOWS 101 | E_Vk_InitDefaultSamplers(); 102 | #endif 103 | 104 | E_LinearSampler = malloc(sizeof(E_Sampler)); 105 | E_LinearSampler->address_mode = E_ImageAddressModeRepeat; 106 | E_LinearSampler->filter = E_ImageFilterLinear; 107 | 108 | E_NearestSampler = malloc(sizeof(E_Sampler)); 109 | E_NearestSampler->address_mode = E_ImageAddressModeRepeat; 110 | E_NearestSampler->filter = E_ImageFilterNearest; 111 | 112 | E_CubemapSampler = malloc(sizeof(E_Sampler)); 113 | E_CubemapSampler->address_mode = E_ImageAddressModeClampToBorder; 114 | E_CubemapSampler->filter = E_ImageFilterLinear; 115 | 116 | #ifdef EUPHORBE_WINDOWS 117 | E_LinearSampler->rhi_handle = E_Vk_LinearSampler; 118 | E_NearestSampler->rhi_handle = E_Vk_NearestSampler; 119 | E_CubemapSampler->rhi_handle = E_Vk_CubemapSampler; 120 | #endif 121 | } 122 | 123 | void E_FreeDefaultSamplers() 124 | { 125 | free(E_LinearSampler); 126 | free(E_NearestSampler); 127 | free(E_CubemapSampler); 128 | 129 | #ifdef EUPHORBE_WINDOWS 130 | E_Vk_FreeDefaultSamplers(); 131 | #endif 132 | } 133 | 134 | E_Sampler* E_CreateSampler(E_ImageAddressMode mode, E_ImageFilter filter) 135 | { 136 | E_Sampler* sampler = malloc(sizeof(E_Sampler)); 137 | sampler->address_mode = mode; 138 | sampler->filter = filter; 139 | 140 | #ifdef EUPHORBE_WINDOWS 141 | sampler->rhi_handle = E_Vk_CreateSampler(mode, filter); 142 | #endif 143 | 144 | return sampler; 145 | } 146 | 147 | void E_FreeSampler(E_Sampler* sampler) 148 | { 149 | #ifdef EUPHORBE_WINDOWS 150 | E_Vk_FreeSampler(sampler->rhi_handle); 151 | #endif 152 | 153 | free(sampler); 154 | } 155 | -------------------------------------------------------------------------------- /src/Euphorbe/Graphics/Image.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | typedef struct E_CommandBuffer E_CommandBuffer; 6 | 7 | typedef enum E_ImageFormat E_ImageFormat; 8 | enum E_ImageFormat 9 | { 10 | E_ImageFormatRGBA8 = 37, 11 | E_ImageFormatRG16 = 83, 12 | E_ImageFormatRGBA16_Unorm = 91, 13 | E_ImageFormatRGBA16 = 97, 14 | E_ImageFormatRGBA32 = 109, 15 | E_ImageFormatD32_Float = 126, 16 | }; 17 | 18 | typedef enum E_ImageLayout E_ImageLayout; 19 | enum E_ImageLayout 20 | { 21 | E_ImageLayoutUndefined = 0, 22 | E_ImageLayoutGeneral = 1, 23 | E_ImageLayoutColor = 2, 24 | E_ImageLayoutDepth = 3, 25 | E_ImageLayoutDepthReadOnly = 4, 26 | E_ImageLayoutShaderRead = 5, 27 | E_ImageLayoutTransferSource = 6, 28 | E_ImageLayoutTransferDest = 7, 29 | E_ImageLayoutSwapchainPresent = 1000001002, 30 | E_ImageLayoutReadOnlyOptimal = 1000314000 31 | }; 32 | 33 | typedef enum E_ImageUsage E_ImageUsage; 34 | enum E_ImageUsage 35 | { 36 | E_ImageUsageTransferSource = 0x00000001, 37 | E_ImageUsageTransferDest = 0x00000002, 38 | E_ImageUsageSampled = 0x00000004, 39 | E_ImageUsageStorage = 0x00000008, 40 | E_ImageUsageColorAttachment = 0x00000010, 41 | E_ImageUsageDepthStencilAttachment = 0x00000020 42 | }; 43 | 44 | #define E_ImageUsageRenderGraphNodeOutput E_ImageUsageTransferSource | E_ImageUsageColorAttachment | E_ImageUsageSampled 45 | 46 | typedef enum E_ImageAccess E_ImageAccess; 47 | enum E_ImageAccess 48 | { 49 | E_ImageAccessNone = 0x00000000, 50 | E_ImageAccessShaderRead = 0x00000020, 51 | E_ImageAccessShaderWrite = 0x00000040, 52 | E_ImageAccessColorRead = 0x00000080, 53 | E_ImageAccessColorWrite = 0x00000100, 54 | E_ImageAccessDepthRead = 0x00000200, 55 | E_ImageAccessDepthWrite = 0x00000400, 56 | E_ImageAccessTransferRead = 0x00000800, 57 | E_ImageAccessTransferWrite = 0x00001000 58 | }; 59 | 60 | typedef enum E_ImagePipelineStage E_ImagePipelineStage; 61 | enum E_ImagePipelineStage 62 | { 63 | E_ImagePipelineStageTop = 0x00000001, 64 | E_ImagePipelineStageVertexShader = 0x00000008, 65 | E_ImagePipelineStageFragmentShader = 0x00000080, 66 | E_ImagePipelineStageBottom = 0x00002000, 67 | E_ImagePipelineStageColorOutput = 0x00000400, 68 | E_ImagePipelineStageComputeShader = 0x00000800, 69 | E_ImagePipelineStageTransfer = 0x00001000, 70 | E_ImagePipelineStageEarlyFragment = 0x00000100, 71 | E_ImagePipelineStageLateFragment = 0x00000200 72 | }; 73 | 74 | typedef enum E_ImageFilter E_ImageFilter; 75 | enum E_ImageFilter 76 | { 77 | E_ImageFilterNearest = 0, 78 | E_ImageFilterLinear = 1 79 | }; 80 | 81 | typedef enum E_ImageAddressMode E_ImageAddressMode; 82 | enum E_ImageAddressMode 83 | { 84 | E_ImageAddressModeRepeat = 0, 85 | E_ImageAddressModeMirroredRepeat = 1, 86 | E_ImageAddressModeClampToEdge = 2, 87 | E_ImageAddressModeClampToBorder = 3 88 | }; 89 | 90 | typedef struct E_Sampler E_Sampler; 91 | struct E_Sampler 92 | { 93 | E_ImageFilter filter; 94 | E_ImageAddressMode address_mode; 95 | void* rhi_handle; 96 | }; 97 | 98 | typedef struct E_Image E_Image; 99 | struct E_Image 100 | { 101 | i32 width; 102 | i32 height; 103 | E_ImageFormat format; 104 | E_ImageUsage usage; 105 | void* rhi_handle; 106 | }; 107 | 108 | E_Image* E_MakeImage(i32 width, i32 height, E_ImageFormat format, E_ImageUsage usage); 109 | E_Image* E_MakeImageFromFile(const char* path); 110 | E_Image* E_MakeHDRImageFromFile(const char* path); 111 | E_Image* E_MakeCubeMap(i32 width, i32 height, E_ImageFormat format, E_ImageUsage usage); 112 | void E_FreeImage(E_Image* image); 113 | void E_ImageResize(E_Image* image, i32 width, i32 height); 114 | void E_ImageDrawToGUI(E_Image* image, i32 width, i32 height, E_Sampler* sampler); 115 | 116 | // Sampler stuff 117 | void E_InitDefaultSamplers(); 118 | void E_FreeDefaultSamplers(); 119 | 120 | extern E_Sampler* E_NearestSampler; 121 | extern E_Sampler* E_LinearSampler; 122 | extern E_Sampler* E_CubemapSampler; 123 | 124 | E_Sampler* E_CreateSampler(E_ImageAddressMode mode, E_ImageFilter filter); 125 | void E_FreeSampler(E_Sampler* sampler); -------------------------------------------------------------------------------- /src/Euphorbe/Graphics/Material.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "Image.h" 6 | #include "Buffer.h" 7 | #include "ShaderCompiler.h" 8 | 9 | #define EUPHORBE_MAX_DESCRIPTORS 32 10 | 11 | typedef enum E_PrimitiveTopology E_PrimitiveTopology; 12 | enum E_PrimitiveTopology 13 | { 14 | E_PrimitiveTopologyPointList = 0, 15 | E_PrimitiveTopologyLineList = 1, 16 | E_PrimitiveTopologyLineStrip = 2, 17 | E_PrimitiveTopologyTriangleList = 3, 18 | E_PrimitiveTopologyTriangleStrip = 4 19 | }; 20 | 21 | typedef enum E_PolygonMode E_PolygonMode; 22 | enum E_PolygonMode 23 | { 24 | E_PolygonModeFill = 0, 25 | E_PolygonModeLine = 1, 26 | E_PolygonModePoint = 2 27 | }; 28 | 29 | typedef enum E_CullMode E_CullMode; 30 | enum E_CullMode 31 | { 32 | E_CullModeNone = 0, 33 | E_CullModeFront = 0x00000001, 34 | E_CullModeBack = 0x00000002, 35 | E_CullModeFrontAndBack = 0x00000003 36 | }; 37 | 38 | typedef enum E_FrontFace E_FrontFace; 39 | enum E_FrontFace 40 | { 41 | E_FrontFaceCCW = 0, 42 | E_FrontFaceCW = 1 43 | }; 44 | 45 | typedef enum E_CompareOP E_CompareOP; 46 | enum E_CompareOP 47 | { 48 | E_CompareOPNever = 0, 49 | E_CompareOPLess = 1, 50 | E_CompareOPEqual = 2, 51 | E_CompareOPLessEqual = 3, 52 | E_CompareOPGreater = 4, 53 | E_CompareOPNotEqual = 5, 54 | E_CompareOPGreaterEqual = 6, 55 | E_CompareOPAlways = 7 56 | }; 57 | 58 | typedef struct E_MaterialRenderInfo E_MaterialRenderInfo; 59 | struct E_MaterialRenderInfo 60 | { 61 | E_ImageFormat color_formats[32]; 62 | E_ImageFormat depth_format; 63 | i32 color_attachment_count; 64 | }; 65 | 66 | // Descriptor info 67 | typedef enum E_DescriptorType E_DescriptorType; 68 | enum E_DescriptorType 69 | { 70 | E_DescriptorTypeSampler = 0, 71 | E_DescriptorTypeCombinedImageSampler = 1, 72 | E_DescriptorTypeSampledImage = 2, 73 | E_DescriptorTypeStorageImage = 3, 74 | E_DescriptorTypeUniformBuffer = 6, 75 | E_DescriptorTypeStorageBuffer = 7 76 | }; 77 | 78 | typedef struct E_Descriptor E_Descriptor; 79 | struct E_Descriptor 80 | { 81 | E_DescriptorType type; 82 | i32 binding; 83 | }; 84 | 85 | typedef struct E_DescriptorSetLayout E_DescriptorSetLayout; 86 | struct E_DescriptorSetLayout 87 | { 88 | E_Descriptor descriptors[EUPHORBE_MAX_DESCRIPTORS]; 89 | i32 descriptor_count; 90 | }; 91 | 92 | typedef struct E_MaterialCreateInfo E_MaterialCreateInfo; 93 | struct E_MaterialCreateInfo 94 | { 95 | // Pipeline render info 96 | E_PrimitiveTopology primitive_topology; 97 | E_PolygonMode polygon_mode; 98 | E_CullMode cull_mode; 99 | E_FrontFace front_face; 100 | E_CompareOP depth_op; 101 | E_MaterialRenderInfo render_info; 102 | 103 | // Shaders 104 | b32 mesh_shader_enabled; 105 | E_ResourceFile* vertex_shader; 106 | E_ResourceFile* fragment_shader; 107 | E_ResourceFile* compute_shader; 108 | E_ResourceFile* task_shader; 109 | E_ResourceFile* mesh_shader; 110 | 111 | // Descriptors 112 | E_DescriptorSetLayout descriptor_set_layouts[EUPHORBE_MAX_DESCRIPTORS]; 113 | i32 descriptor_set_layout_count; 114 | 115 | // Push constants 116 | b32 has_push_constants; 117 | i32 push_constants_size; 118 | }; 119 | 120 | typedef struct E_Material E_Material; 121 | struct E_Material 122 | { 123 | E_MaterialCreateInfo* material_create_info; 124 | void* rhi_handle; // E_VulkanMaterial for example 125 | b32 loaded_from_file; 126 | }; 127 | 128 | typedef struct E_MaterialInstance E_MaterialInstance; 129 | struct E_MaterialInstance 130 | { 131 | E_Material* material; 132 | void* rhi_handle; 133 | }; 134 | 135 | // WARNING: Vertex shader MUST contain input variables! 136 | E_Material* E_CreateMaterial(E_MaterialCreateInfo* create_info); 137 | E_Material* E_CreateMaterialFromFile(const char* path); 138 | E_Material* E_CreateComputeMaterialFromFile(const char* path); 139 | void E_FreeMaterial(E_Material* material); 140 | 141 | // Instances 142 | E_MaterialInstance* E_CreateMaterialInstance(E_Material* material, i32 set_layout_index); 143 | void E_MaterialInstanceWriteBuffer(E_MaterialInstance* instance, i32 binding, E_Buffer* buffer, i64 buffer_size); 144 | void E_MaterialInstanceWriteStorageBuffer(E_MaterialInstance* instance, i32 binding, E_Buffer* buffer, i64 buffer_size); 145 | void E_MaterialInstanceWriteSampler(E_MaterialInstance* instance, i32 binding, E_Sampler* sampler); 146 | void E_MaterialInstanceWriteSampledImage(E_MaterialInstance* instance, i32 binding, E_Image* image); 147 | void E_MaterialInstanceWriteImage(E_MaterialInstance* instance, i32 binding, E_Image* image, E_Sampler* sampler); 148 | void E_MaterialInstanceWriteStorageImage(E_MaterialInstance* instance, i32 binding, E_Image* image, E_Sampler* sampler); 149 | void E_FreeMaterialInstance(E_MaterialInstance* instance); -------------------------------------------------------------------------------- /src/Euphorbe/Graphics/Mesh.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define EUPHORBE_MAX_SUBMESHES 128 4 | #define EUPHORBE_MAX_MESHLET_VERTICES 64 5 | #define EUPHORBE_MAX_MESHLET_INDICES 372 6 | #define EUPHORBE_MAX_MESHLET_TRIANGLES 124 7 | 8 | #include 9 | #include 10 | 11 | #include "Buffer.h" 12 | #include "Material.h" 13 | 14 | typedef struct E_MeshVertex E_MeshVertex; 15 | struct E_MeshVertex 16 | { 17 | vec3 Position; 18 | vec2 UV; 19 | vec3 Normals; 20 | }; 21 | 22 | typedef struct E_Meshlet E_Meshlet; 23 | struct E_Meshlet 24 | { 25 | vec4 cone; 26 | u32 vertices[EUPHORBE_MAX_MESHLET_VERTICES]; 27 | u8 indices[EUPHORBE_MAX_MESHLET_INDICES]; 28 | u8 vertex_count; 29 | u8 triangle_count; 30 | }; 31 | 32 | typedef struct E_Submesh E_Submesh; 33 | struct E_Submesh 34 | { 35 | E_Buffer* vertex_buffer; 36 | E_Buffer* index_buffer; 37 | E_Buffer* meshlet_buffer; 38 | 39 | E_MaterialInstance* geometry_instance; 40 | 41 | u32 vertices_size; 42 | u32 indices_size; 43 | 44 | u32 vertex_count; 45 | u32 index_count; 46 | u32 tri_count; 47 | u32 meshlet_count; 48 | }; 49 | 50 | typedef struct E_Mesh E_Mesh; 51 | struct E_Mesh 52 | { 53 | E_Submesh submeshes[EUPHORBE_MAX_SUBMESHES]; 54 | i32 submesh_count; 55 | 56 | u32 total_vertex_count; 57 | u32 total_index_count; 58 | u32 total_tri_count; 59 | u32 total_meshlet_count; 60 | }; 61 | 62 | E_Mesh* E_LoadMesh(E_Material* material, const char* path); 63 | void E_FreeMesh(E_Mesh* mesh); -------------------------------------------------------------------------------- /src/Euphorbe/Graphics/RenderGraph.c: -------------------------------------------------------------------------------- 1 | #include "RenderGraph.h" 2 | 3 | #include 4 | 5 | E_RenderGraph* E_CreateRenderGraph() 6 | { 7 | E_RenderGraph* graph = malloc(sizeof(E_RenderGraph)); 8 | 9 | graph->node_vector.node_count = 0; 10 | graph->node_vector.nodes = malloc(sizeof(E_RenderGraphNode*) * EUPHORBE_MAX_RENDER_GRAPH_NODES); 11 | 12 | return graph; 13 | } 14 | 15 | void E_RenderGraphConnectNodes(E_RenderGraphNode* src_node, u32 src_id, E_RenderGraphNode* dst_node, u32 dst_id) 16 | { 17 | assert(src_node); 18 | assert(dst_node); 19 | assert(!EUPHORBE_IS_NODE_PORT_INPUT(src_id)); // Make sure srcId is an output - to be used as an input 20 | assert(EUPHORBE_IS_NODE_PORT_INPUT(dst_id)); // Make sure dstId is an input port. 21 | 22 | dst_node->inputs[EUPHORBE_GET_NODE_PORT_INDEX(dst_id)].owner = src_node; 23 | dst_node->inputs[EUPHORBE_GET_NODE_PORT_INDEX(dst_id)].index = EUPHORBE_GET_NODE_PORT_INDEX(src_id); 24 | dst_node->input_count++; 25 | } 26 | 27 | void RecursivelyAddNodes(E_RenderGraphNode* node, E_RenderGraphNodeVector* vec) 28 | { 29 | if (node) 30 | { 31 | vec->nodes[vec->node_count] = node; 32 | vec->node_count++; 33 | 34 | for (u32 i = 0; i < node->input_count; ++i) 35 | { 36 | E_RenderGraphNode* owner = node->inputs[i].owner; 37 | 38 | if (!owner) break; 39 | 40 | RecursivelyAddNodes(owner, vec); 41 | } 42 | } 43 | } 44 | 45 | E_Image* E_GetRenderGraphNodeInputImage(E_RenderGraphNodeInput* input) 46 | { 47 | assert(input->owner); 48 | return input->owner->outputs[input->index]; 49 | } 50 | 51 | void E_BuildRenderGraph(E_RenderGraph* graph, E_RenderGraphExecuteInfo* info, E_RenderGraphNode* last_node) 52 | { 53 | // Add the nodes to a temporary vector 54 | 55 | E_RenderGraphNodeVector* temp = malloc(sizeof(E_RenderGraphNodeVector)); 56 | temp->nodes = malloc(sizeof(E_RenderGraphNode*) * EUPHORBE_MAX_RENDER_GRAPH_NODES); 57 | temp->node_count = 0; 58 | RecursivelyAddNodes(last_node, temp); 59 | 60 | // Add the nodes to the graph 61 | 62 | for (i32 candidate_index = temp->node_count - 1; candidate_index >= 0; --candidate_index) 63 | { 64 | E_RenderGraphNode* node = temp->nodes[candidate_index]; 65 | b32 already_in_array = 0; 66 | 67 | for (u32 i = 0; i < graph->node_vector.node_count; i++) 68 | { 69 | if (graph->node_vector.nodes[i] == node) // If the node is already in the array, don't add it. 70 | { 71 | already_in_array = 1; 72 | break; 73 | } 74 | } 75 | 76 | if (!already_in_array) 77 | { 78 | graph->node_vector.nodes[graph->node_vector.node_count] = node; 79 | graph->node_vector.node_count++; 80 | } 81 | } 82 | 83 | free(temp->nodes); 84 | free(temp); 85 | 86 | // Initialize 87 | 88 | for (u32 i = 0; i < graph->node_vector.node_count; i++) 89 | { 90 | E_RenderGraphNode* node = graph->node_vector.nodes[i]; 91 | node->init_func(node, info); 92 | } 93 | 94 | E_LogInfo("RENDER GRAPH BUILD: Built render graph with %d nodes", graph->node_vector.node_count); 95 | } 96 | 97 | void E_CleanRenderGraph(E_RenderGraph* graph, E_RenderGraphExecuteInfo* info) 98 | { 99 | for (u32 i = 0; i < graph->node_vector.node_count; i++) 100 | { 101 | E_RenderGraphNode* node = graph->node_vector.nodes[i]; 102 | 103 | node->clean_func(node, info); 104 | free(node); 105 | } 106 | 107 | free(graph->node_vector.nodes); 108 | free(graph); 109 | } 110 | 111 | void E_ResizeRenderGraph(E_RenderGraph* graph, E_RenderGraphExecuteInfo* info) 112 | { 113 | for (u32 i = 0; i < graph->node_vector.node_count; i++) 114 | { 115 | E_RenderGraphNode* node = graph->node_vector.nodes[i] ; 116 | 117 | node->resize_func(node, info); 118 | } 119 | } 120 | 121 | void E_ExecuteRenderGraph(E_RenderGraph* graph, E_RenderGraphExecuteInfo* info) 122 | { 123 | for (u32 i = 0; i < graph->node_vector.node_count; i++) 124 | { 125 | E_RenderGraphNode* node = graph->node_vector.nodes[i]; 126 | 127 | if (node->enabled) 128 | node->execute_func(node, info); 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /src/Euphorbe/Graphics/RenderGraph.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define EUPHORBE_MAX_DRAWABLE_COUNT 128 12 | #define EUPHORBE_MAX_LIGHT_COUNT 64 13 | #define EUPHORBE_MAX_RENDER_NODE_OUTPUTS 8 14 | #define EUPHORBE_MAX_RENDER_NODE_INPUTS 8 15 | #define EUPHORBE_MAX_RENDER_GRAPH_NODES 16 16 | 17 | #define EUPHORBE_DECLARE_NODE_OUTPUT(index) ((~(1u << 31u)) & index) 18 | #define EUPHORBE_DECLARE_NODE_INPUT(index) ((1u << 31u) | index) 19 | #define EUPHORBE_IS_NODE_INPUT(id) (((1u << 31u) & id) > 0) 20 | #define EUPHORBE_GET_NODE_PORT_INDEX(id) (((1u << 31u) - 1u) & id) 21 | 22 | typedef struct E_RenderGraphExecuteInfo E_RenderGraphExecuteInfo; 23 | typedef struct E_RenderGraphNode E_RenderGraphNode; 24 | typedef struct E_RenderGraphNodeInput E_RenderGraphNodeInput; 25 | typedef struct E_RenderGraph E_RenderGraph; 26 | typedef struct E_Drawable E_Drawable; 27 | typedef struct E_RenderGraphNodeVector E_RenderGraphNodeVector; 28 | 29 | struct E_Drawable 30 | { 31 | E_Mesh* mesh; 32 | E_MaterialInstance* geometry_instance; // Contains transform, vertex buffer and meshlet buffer 33 | E_MaterialInstance* material_instance; 34 | mat4 transform; 35 | }; 36 | 37 | struct E_RenderGraphExecuteInfo 38 | { 39 | E_CVarSystem* cvar_table_ptr; 40 | 41 | E_Drawable drawables[EUPHORBE_MAX_DRAWABLE_COUNT]; 42 | u32 drawable_count; 43 | 44 | E_PointLight point_lights[EUPHORBE_MAX_LIGHT_COUNT]; 45 | 46 | mat4 projection; 47 | mat4 view; 48 | vec3 camera_position; 49 | 50 | i32 width; 51 | i32 height; 52 | i32 frame_index; 53 | }; 54 | 55 | typedef void (*E_RenderGraphNodeInitFunc)(E_RenderGraphNode* node, E_RenderGraphExecuteInfo* info); 56 | typedef void (*E_RenderGraphNodeCleanFunc)(E_RenderGraphNode* node, E_RenderGraphExecuteInfo* info); 57 | typedef void (*E_RenderGraphNodeExecuteFunc)(E_RenderGraphNode* node, E_RenderGraphExecuteInfo* info); 58 | typedef void (*E_RenderGraphNodeResizeFunc)(E_RenderGraphNode* node, E_RenderGraphExecuteInfo* info); 59 | 60 | struct E_RenderGraphNodeInput 61 | { 62 | E_RenderGraphNode* owner; 63 | u32 index; 64 | }; 65 | 66 | struct E_RenderGraphNode 67 | { 68 | void* node_data; 69 | b32 enabled; 70 | char* name; 71 | 72 | E_RenderGraphNodeInitFunc init_func; 73 | E_RenderGraphNodeCleanFunc clean_func; 74 | E_RenderGraphNodeExecuteFunc execute_func; 75 | E_RenderGraphNodeResizeFunc resize_func; 76 | 77 | E_Image* outputs[EUPHORBE_MAX_RENDER_NODE_OUTPUTS]; 78 | u32 output_count; 79 | 80 | E_RenderGraphNodeInput inputs[EUPHORBE_MAX_RENDER_NODE_INPUTS]; 81 | u32 input_count; 82 | }; 83 | 84 | struct E_RenderGraphNodeVector 85 | { 86 | E_RenderGraphNode** nodes; 87 | u32 node_count; 88 | }; 89 | 90 | struct E_RenderGraph 91 | { 92 | E_RenderGraphNodeVector node_vector; 93 | }; 94 | 95 | E_RenderGraph* E_CreateRenderGraph(); 96 | void E_RenderGraphConnectNodes(E_RenderGraphNode* src_node, u32 src_id, E_RenderGraphNode* dst_node, u32 dst_id); 97 | E_Image* E_GetRenderGraphNodeInputImage(E_RenderGraphNodeInput* input); 98 | 99 | void E_BuildRenderGraph(E_RenderGraph* graph, E_RenderGraphExecuteInfo* info, E_RenderGraphNode* last_node); 100 | void E_CleanRenderGraph(E_RenderGraph* graph, E_RenderGraphExecuteInfo* info); 101 | void E_ResizeRenderGraph(E_RenderGraph* graph, E_RenderGraphExecuteInfo* info); 102 | void E_ExecuteRenderGraph(E_RenderGraph* graph, E_RenderGraphExecuteInfo* info); -------------------------------------------------------------------------------- /src/Euphorbe/Graphics/Renderer.c: -------------------------------------------------------------------------------- 1 | #include "Renderer.h" 2 | 3 | #ifdef EUPHORBE_WINDOWS 4 | #include "Vulkan/VulkanRenderer.h" 5 | #endif 6 | 7 | E_RendererStats E_CurrentRendererStatistics; 8 | 9 | void E_RendererInit(E_Window* window, E_RendererInitSettings settings) 10 | { 11 | #ifdef EUPHORBE_WINDOWS 12 | E_Vk_RendererInit(window, settings); 13 | #endif 14 | } 15 | 16 | void E_RendererShutdown() 17 | { 18 | #ifdef EUPHORBE_WINDOWS 19 | E_Vk_RendererShutdown(); 20 | #endif 21 | } 22 | 23 | void E_RendererBegin() 24 | { 25 | E_CurrentRendererStatistics.total_draw_calls = 0; 26 | E_CurrentRendererStatistics.total_index_count = 0; 27 | E_CurrentRendererStatistics.total_vertex_count = 0; 28 | E_CurrentRendererStatistics.total_triangle_count = 0; 29 | E_CurrentRendererStatistics.total_meshlet_count = 0; 30 | 31 | #ifdef EUPHORBE_WINDOWS 32 | E_Vk_Begin(); 33 | #endif 34 | } 35 | 36 | void E_RendererEnd() 37 | { 38 | #ifdef EUPHORBE_WINDOWS 39 | E_Vk_End(); 40 | #endif 41 | } 42 | 43 | void E_RendererPresent() 44 | { 45 | #ifdef EUPHORBE_WINDOWS 46 | E_Vk_Present(); 47 | #endif 48 | } 49 | 50 | void E_RendererWait() 51 | { 52 | #ifdef EUPHORBE_WINDOWS 53 | E_Vk_DeviceWait(); 54 | #endif 55 | } 56 | 57 | void E_RendererDrawMemoryUsageGUI() 58 | { 59 | #ifdef EUPHORBE_WINDOWS 60 | E_Vk_DrawMemoryUsageGUI(); 61 | #endif 62 | } 63 | 64 | void E_RendererDrawRendererStats() 65 | { 66 | igText("Vertices: %d", E_CurrentRendererStatistics.total_vertex_count); 67 | igText("Indices: %d", E_CurrentRendererStatistics.total_index_count); 68 | igText("Triangles: %d", E_CurrentRendererStatistics.total_triangle_count); 69 | igText("Meshlets: %d", E_CurrentRendererStatistics.total_meshlet_count); 70 | igText("Draw Calls: %d", E_CurrentRendererStatistics.total_draw_calls); 71 | } 72 | 73 | void E_RendererDrawGraphicsCardInfo() 74 | { 75 | #ifdef EUPHORBE_WINDOWS 76 | E_Vk_DrawGraphicsCardInfo(); 77 | #endif 78 | } 79 | 80 | E_Image* E_GetSwapchainImage() 81 | { 82 | #ifdef EUPHORBE_WINDOWS 83 | return E_Vk_GetSwapchainImage(); 84 | #endif 85 | } 86 | 87 | u32 E_GetSwapchainImageIndex() 88 | { 89 | #ifdef EUPHORBE_WINDOWS 90 | return E_Vk_GetSwapchainImageIndex(); 91 | #endif 92 | } 93 | 94 | E_CommandBuffer* E_GetSwapchainCommandBuffer() 95 | { 96 | #ifdef EUPHORBE_WINDOWS 97 | return E_Vk_GetSwapchainCommandBuffer(); 98 | #endif 99 | } 100 | 101 | void E_BeginGUI() 102 | { 103 | #ifdef EUPHORBE_WINDOWS 104 | E_Vk_BeginGUI(); 105 | #endif 106 | } 107 | 108 | void E_EndGUI() 109 | { 110 | #ifdef EUPHORBE_WINDOWS 111 | E_Vk_EndGUI(); 112 | #endif 113 | } 114 | 115 | void E_RendererResize(i32 width, i32 height) 116 | { 117 | #ifdef EUPHORBE_WINDOWS 118 | E_Vk_Resize(width, height); 119 | #endif 120 | } -------------------------------------------------------------------------------- /src/Euphorbe/Graphics/Renderer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "Image.h" 8 | #include "Material.h" 9 | #include "Buffer.h" 10 | 11 | typedef struct E_CommandBuffer E_CommandBuffer; 12 | 13 | typedef struct E_RendererInitSettings E_RendererInitSettings; 14 | struct E_RendererInitSettings 15 | { 16 | b32 log_found_layers; // Default: true 17 | b32 log_renderer_events; // Default: true 18 | b32 enable_debug; // Default: false 19 | b32 gui_should_clear; // If viewport is in a gui window 20 | b32 enable_vsync; // Enable vsync 21 | }; 22 | 23 | typedef struct E_ClearValue E_ClearValue; 24 | struct E_ClearValue 25 | { 26 | f32 r; 27 | f32 g; 28 | f32 b; 29 | f32 a; 30 | f32 depth; 31 | u32 stencil; 32 | }; 33 | 34 | typedef struct E_ImageAttachment E_ImageAttachment; 35 | struct E_ImageAttachment 36 | { 37 | E_Image* image; 38 | E_ImageLayout layout; 39 | E_ClearValue clear_value; 40 | }; 41 | 42 | // Light info 43 | typedef struct E_PointLight E_PointLight; 44 | struct E_PointLight 45 | { 46 | vec4 position; 47 | vec4 color; 48 | }; 49 | 50 | // Renderer stats 51 | typedef struct E_RendererStats E_RendererStats; 52 | struct E_RendererStats 53 | { 54 | u32 total_vertex_count; 55 | u32 total_index_count; 56 | u32 total_triangle_count; 57 | u32 total_meshlet_count; 58 | u32 total_draw_calls; 59 | }; 60 | 61 | extern E_RendererStats E_CurrentRendererStatistics; 62 | 63 | void E_RendererInit(E_Window* window, E_RendererInitSettings settings); 64 | void E_RendererShutdown(); 65 | 66 | void E_RendererBegin(); 67 | void E_RendererEnd(); 68 | void E_RendererPresent(); 69 | void E_RendererWait(); 70 | 71 | void E_RendererDrawMemoryUsageGUI(); 72 | void E_RendererDrawRendererStats(); 73 | void E_RendererDrawGraphicsCardInfo(); 74 | 75 | E_Image* E_GetSwapchainImage(); 76 | u32 E_GetSwapchainImageIndex(); 77 | E_CommandBuffer* E_GetSwapchainCommandBuffer(); 78 | 79 | // 80 | void E_BeginGUI(); 81 | void E_EndGUI(); 82 | 83 | void E_RendererResize(i32 width, i32 height); -------------------------------------------------------------------------------- /src/Euphorbe/Graphics/ShaderCompiler.c: -------------------------------------------------------------------------------- 1 | #include "ShaderCompiler.h" 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | shaderc_shader_kind E_ShaderKindToShaderC(E_ShaderType type) 10 | { 11 | switch (type) 12 | { 13 | case E_ShaderTypeVertex: 14 | return shaderc_vertex_shader; 15 | case E_ShaderTypeGeometry: 16 | return shaderc_geometry_shader; 17 | case E_ShaderTypeFragment: 18 | return shaderc_fragment_shader; 19 | case E_ShaderTypeCompute: 20 | return shaderc_compute_shader; 21 | case E_ShaderTypeTaskNV: 22 | return shaderc_task_shader; 23 | case E_ShaderTypeMeshNV: 24 | return shaderc_mesh_shader; 25 | } 26 | 27 | return 0; 28 | } 29 | 30 | char* E_ReadFile(const char* path, i32* output_size) 31 | { 32 | FILE* file = fopen(path, "rb"); 33 | 34 | if (!file) 35 | { 36 | E_LogError("FILE READ ERROR (path=%s)", path); 37 | assert(false); 38 | return NULL; 39 | } 40 | else 41 | { 42 | long currentpos = ftell(file); 43 | fseek(file, 0, SEEK_END); 44 | long size = ftell(file); 45 | fseek(file, currentpos, SEEK_SET); 46 | 47 | u32 filesizepadded = (size % 4 == 0 ? size * 4 : (size + 1) * 4) / 4; 48 | 49 | char* buffer = malloc(filesizepadded); 50 | if (buffer) 51 | { 52 | fread(buffer, size, sizeof(char), file); 53 | fclose(file); 54 | 55 | *output_size = size; 56 | return buffer; 57 | } 58 | else 59 | { 60 | fclose(file); 61 | E_LogError("FILE READ ERROR: Failed to allocate file output buffer!"); 62 | *output_size = -1; 63 | assert(0); 64 | return NULL; 65 | } 66 | } 67 | 68 | return NULL; 69 | } 70 | 71 | void E_CompileShader(char* source, i32 source_size, E_Shader* shader) 72 | { 73 | shaderc_compiler_t compiler = shaderc_compiler_initialize(); 74 | shaderc_compile_options_t options = shaderc_compile_options_initialize(); 75 | 76 | shaderc_compile_options_set_source_language(options, shaderc_source_language_glsl); 77 | shaderc_compile_options_set_target_spirv(options, shaderc_spirv_version_1_4); 78 | shaderc_compile_options_set_target_env(options, shaderc_target_env_vulkan, shaderc_env_version_vulkan_1_2); 79 | shaderc_compile_options_set_optimization_level(options, shaderc_optimization_level_size); 80 | 81 | shaderc_compilation_result_t result = shaderc_compile_into_spv(compiler, source, source_size, E_ShaderKindToShaderC(shader->type), "shader", "main", options); 82 | 83 | shaderc_compilation_status status = shaderc_result_get_compilation_status(result); 84 | if (status != shaderc_compilation_status_success) 85 | { 86 | E_LogError("SHADERC ERROR: %s", shaderc_result_get_error_message(result)); 87 | assert(false); 88 | } 89 | 90 | shader->code = (u8*)shaderc_result_get_bytes(result); 91 | shader->code_size = shaderc_result_get_length(result); 92 | 93 | shaderc_compiler_release(compiler); 94 | } -------------------------------------------------------------------------------- /src/Euphorbe/Graphics/ShaderCompiler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | typedef enum E_ShaderType E_ShaderType; 6 | enum E_ShaderType 7 | { 8 | E_ShaderTypeVertex = 0x00000001, 9 | E_ShaderTypeGeometry = 0x00000008, 10 | E_ShaderTypeFragment = 0x00000010, 11 | E_ShaderTypeCompute = 0x00000020, 12 | E_ShaderTypeTaskNV = 0x00000040, 13 | E_ShaderTypeMeshNV = 0x00000080, 14 | }; 15 | 16 | typedef struct E_Shader E_Shader; 17 | struct E_Shader 18 | { 19 | E_ShaderType type; 20 | u8* code; 21 | i64 code_size; 22 | }; 23 | 24 | char* E_ReadFile(const char* path, i32* output_size); 25 | void E_CompileShader(char* source, i32 source_size, E_Shader* shader); -------------------------------------------------------------------------------- /src/Euphorbe/Graphics/Vulkan/ExternalBuilds.cpp: -------------------------------------------------------------------------------- 1 | #define VMA_IMPLEMENTATION 2 | #include 3 | #include 4 | 5 | #define STB_IMAGE_IMPLEMENTATION 6 | #include 7 | 8 | #define CGLTF_IMPLEMENTATION 9 | #include -------------------------------------------------------------------------------- /src/Euphorbe/Graphics/Vulkan/VulkanBuffer.c: -------------------------------------------------------------------------------- 1 | #include "VulkanBuffer.h" 2 | #include "VulkanRenderer.h" 3 | 4 | E_VulkanBuffer* E_Vk_AllocateVertexBuffer(i64 size) 5 | { 6 | E_VulkanBuffer* buffer = malloc(sizeof(E_VulkanBuffer)); 7 | 8 | VkBufferCreateInfo buffer_create_info = {0}; 9 | buffer_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; 10 | buffer_create_info.size = size; 11 | buffer_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; 12 | buffer_create_info.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; 13 | 14 | VmaAllocationCreateInfo allocation_create_info = {0}; 15 | allocation_create_info.usage = VMA_MEMORY_USAGE_CPU_TO_GPU; 16 | 17 | VkResult result = vmaCreateBuffer(rhi.allocator, &buffer_create_info, &allocation_create_info, &buffer->buffer, &buffer->allocation, NULL); 18 | assert(result == VK_SUCCESS); 19 | 20 | return buffer; 21 | } 22 | 23 | E_VulkanBuffer* E_Vk_AllocateIndexBuffer(i64 size) 24 | { 25 | E_VulkanBuffer* buffer = malloc(sizeof(E_VulkanBuffer)); 26 | 27 | VkBufferCreateInfo buffer_create_info = { 0 }; 28 | buffer_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; 29 | buffer_create_info.size = size; 30 | buffer_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; 31 | buffer_create_info.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; 32 | 33 | VmaAllocationCreateInfo allocation_create_info = { 0 }; 34 | allocation_create_info.usage = VMA_MEMORY_USAGE_CPU_TO_GPU; 35 | 36 | VkResult result = vmaCreateBuffer(rhi.allocator, &buffer_create_info, &allocation_create_info, &buffer->buffer, &buffer->allocation, NULL); 37 | assert(result == VK_SUCCESS); 38 | 39 | return buffer; 40 | } 41 | 42 | E_VulkanBuffer* E_Vk_AllocateUniformBuffer(i64 size) 43 | { 44 | E_VulkanBuffer* buffer = malloc(sizeof(E_VulkanBuffer)); 45 | 46 | VkBufferCreateInfo buffer_create_info = {0}; 47 | buffer_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; 48 | buffer_create_info.size = size; 49 | buffer_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; 50 | buffer_create_info.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; 51 | 52 | VmaAllocationCreateInfo allocation_create_info = {0}; 53 | allocation_create_info.usage = VMA_MEMORY_USAGE_CPU_ONLY; 54 | 55 | VkResult result = vmaCreateBuffer(rhi.allocator, &buffer_create_info, &allocation_create_info, &buffer->buffer, &buffer->allocation, NULL); 56 | assert(result == VK_SUCCESS); 57 | 58 | return buffer; 59 | } 60 | 61 | E_VulkanBuffer* E_Vk_AllocateStorageBuffer(i64 size) 62 | { 63 | E_VulkanBuffer* buffer = malloc(sizeof(E_VulkanBuffer)); 64 | 65 | VkBufferCreateInfo buffer_create_info = { 0 }; 66 | buffer_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; 67 | buffer_create_info.size = size; 68 | buffer_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; 69 | buffer_create_info.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; 70 | 71 | VmaAllocationCreateInfo allocation_create_info = { 0 }; 72 | allocation_create_info.usage = VMA_MEMORY_USAGE_CPU_TO_GPU; 73 | 74 | VkResult result = vmaCreateBuffer(rhi.allocator, &buffer_create_info, &allocation_create_info, &buffer->buffer, &buffer->allocation, NULL); 75 | assert(result == VK_SUCCESS); 76 | 77 | return buffer; 78 | } 79 | 80 | void E_Vk_SetBufferData(E_VulkanBuffer* buffer, void* data, i64 size) 81 | { 82 | void* buf; 83 | vmaMapMemory(rhi.allocator, buffer->allocation, &buf); 84 | memcpy(buf, data, size); 85 | vmaUnmapMemory(rhi.allocator, buffer->allocation); 86 | } 87 | 88 | void E_Vk_FreeBuffer(E_VulkanBuffer* buffer) 89 | { 90 | vmaDestroyBuffer(rhi.allocator, buffer->buffer, buffer->allocation); 91 | free(buffer); 92 | } -------------------------------------------------------------------------------- /src/Euphorbe/Graphics/Vulkan/VulkanBuffer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | typedef struct E_VulkanBuffer E_VulkanBuffer; 7 | struct E_VulkanBuffer 8 | { 9 | VkBuffer buffer; 10 | VmaAllocation allocation; 11 | VmaAllocationInfo allocation_info; 12 | }; 13 | 14 | E_VulkanBuffer* E_Vk_AllocateVertexBuffer(i64 size); 15 | E_VulkanBuffer* E_Vk_AllocateIndexBuffer(i64 size); 16 | E_VulkanBuffer* E_Vk_AllocateUniformBuffer(i64 size); 17 | E_VulkanBuffer* E_Vk_AllocateStorageBuffer(i64 size); 18 | 19 | void E_Vk_SetBufferData(E_VulkanBuffer* buffer, void* data, i64 size); 20 | void E_Vk_FreeBuffer(E_VulkanBuffer* buffer); 21 | -------------------------------------------------------------------------------- /src/Euphorbe/Graphics/Vulkan/VulkanCommandBuffer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "VulkanMaterial.h" 8 | #include "VulkanBuffer.h" 9 | #include "VulkanGPUProfiler.h" 10 | 11 | typedef struct E_VulkanCommandBuffer E_VulkanCommandBuffer; 12 | struct E_VulkanCommandBuffer 13 | { 14 | E_CommandBufferType type; 15 | VkCommandPool* pool_ptr; 16 | VkCommandBuffer handle; 17 | }; 18 | 19 | E_VulkanCommandBuffer* E_Vk_CreateCommandBuffer(E_CommandBufferType type); 20 | void E_Vk_FreeCommandBuffer(E_VulkanCommandBuffer* buffer); 21 | void E_Vk_SubmitCommandBuffer(E_VulkanCommandBuffer* buffer); 22 | 23 | E_VulkanCommandBuffer* E_Vk_CreateUploadCommandBuffer(); 24 | void E_Vk_SubmitUploadCommandBuffer(E_VulkanCommandBuffer* buffer); 25 | 26 | void E_Vk_BeginCommandBuffer(E_VulkanCommandBuffer* cmd); 27 | void E_Vk_EndCommandBuffer(E_VulkanCommandBuffer* cmd); 28 | void E_Vk_CommandBufferSetViewport(E_VulkanCommandBuffer* cmd, i32 width, i32 height); 29 | void E_Vk_CommandBufferBindMaterial(E_VulkanCommandBuffer* cmd, E_VulkanMaterial* material); 30 | void E_Vk_CommandBufferBindComputeMaterial(E_VulkanCommandBuffer* cmd, E_VulkanMaterial* material); 31 | void E_Vk_CommandBufferBindBuffer(E_VulkanCommandBuffer* cmd, E_VulkanBuffer* buffer, E_BufferUsage usage); 32 | void E_Vk_CommandBufferBindMaterialInstance(E_VulkanCommandBuffer* cmd, E_VulkanMaterialInstance* instance, E_VulkanMaterial* material, i32 set_index); 33 | void E_Vk_CommandBufferBindComputeMaterialInstance(E_VulkanCommandBuffer* cmd, E_VulkanMaterialInstance* instance, E_VulkanMaterial* material, i32 set_index); 34 | void E_Vk_CommandBufferDraw(E_VulkanCommandBuffer* cmd, u32 first, u32 count); 35 | void E_Vk_CommandBufferDrawIndexed(E_VulkanCommandBuffer* cmd, u32 first, u32 count); 36 | void E_Vk_CommandBufferDrawMeshlets(E_VulkanCommandBuffer* cmd, u32 start, u32 count); 37 | void E_Vk_CommandBufferDispatch(E_VulkanCommandBuffer* cmd, u32 groupX, u32 groupY, u32 groupZ); 38 | void E_Vk_CommandBufferStartRender(E_VulkanCommandBuffer* cmd, E_ImageAttachment* attachments, i32 attachment_count, vec2 render_size, b32 has_depth); 39 | void E_Vk_CommandBufferEndRender(E_VulkanCommandBuffer* cmd); 40 | void E_Vk_CommandBufferPushConstants(E_VulkanCommandBuffer* cmd_buf, E_VulkanMaterial* material, void* data, i64 size); 41 | void E_Vk_CommandBufferBlitImage(E_VulkanCommandBuffer* cmd_buf, E_VulkanImage* src, E_VulkanImage* dst, E_ImageLayout src_layout, E_ImageLayout dst_layout); 42 | void E_Vk_CommandBufferImageTransitionLayout(E_VulkanCommandBuffer* cmd_buf, E_VulkanImage* image, E_ImageAccess srcAccess, E_ImageAccess dstAccess, E_ImageLayout old, E_ImageLayout new, E_ImagePipelineStage srcStage, E_ImagePipelineStage dstStage, u32 layer); 43 | void E_Vk_ResetPipelineQuery(E_VulkanCommandBuffer* cmd_buf, E_VulkanPipelineStatistics* stats); 44 | void E_Vk_BeginPipelineQuery(E_VulkanCommandBuffer* cmd_buf, E_VulkanPipelineStatistics* stats); 45 | void E_Vk_EndPipelineQuery(E_VulkanCommandBuffer* cmd_buf, E_VulkanPipelineStatistics* stats); -------------------------------------------------------------------------------- /src/Euphorbe/Graphics/Vulkan/VulkanGPUProfiler.c: -------------------------------------------------------------------------------- 1 | #include "VulkanGPUProfiler.h" 2 | 3 | #include "VulkanRenderer.h" 4 | 5 | #include 6 | 7 | #define E_STATS_ARRAY(idx) return stats->query_vector.data[idx]; 8 | #define E_STATS_GUI(idx) stats->query_vector.data[idx] 9 | 10 | E_VulkanPipelineStatistics* E_Vk_CreatePipelineStatistics() 11 | { 12 | E_VulkanPipelineStatistics* stats = malloc(sizeof(E_VulkanPipelineStatistics)); 13 | E_INIT_VECTOR(stats->query_vector, 10); 14 | 15 | VkQueryPoolCreateInfo query_pool_info = {0}; 16 | query_pool_info.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO; 17 | query_pool_info.queryType = VK_QUERY_TYPE_PIPELINE_STATISTICS; 18 | query_pool_info.pipelineStatistics = VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_VERTICES_BIT | 19 | VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_PRIMITIVES_BIT | 20 | VK_QUERY_PIPELINE_STATISTIC_VERTEX_SHADER_INVOCATIONS_BIT | 21 | VK_QUERY_PIPELINE_STATISTIC_CLIPPING_INVOCATIONS_BIT | 22 | VK_QUERY_PIPELINE_STATISTIC_CLIPPING_PRIMITIVES_BIT | 23 | VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT | 24 | VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_CONTROL_SHADER_PATCHES_BIT | 25 | VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_EVALUATION_SHADER_INVOCATIONS_BIT | 26 | VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT; 27 | query_pool_info.queryCount = 9; 28 | 29 | stats->query_flags = (E_PipelineStatisticsQuery)query_pool_info.pipelineStatistics; 30 | 31 | VkResult res = vkCreateQueryPool(rhi.device.handle, &query_pool_info, NULL, &stats->query_pool); 32 | assert(res == VK_SUCCESS); 33 | 34 | return stats; 35 | } 36 | 37 | void E_Vk_FreePipelineStatistics(E_VulkanPipelineStatistics* stats) 38 | { 39 | E_FREE_VECTOR(stats->query_vector); 40 | vkDestroyQueryPool(rhi.device.handle, stats->query_pool, NULL); 41 | free(stats); 42 | } 43 | 44 | void E_Vk_GetQueryResults(E_VulkanPipelineStatistics* stats) 45 | { 46 | vkGetQueryPoolResults( 47 | rhi.device.handle, 48 | stats->query_pool, 49 | 0, 50 | 1, 51 | stats->query_vector.size * sizeof(uint64_t), 52 | stats->query_vector.data, 53 | sizeof(uint64_t), 54 | VK_QUERY_RESULT_64_BIT); 55 | } 56 | 57 | void E_Vk_DrawPipelineStatisticsGUI(E_VulkanPipelineStatistics* stats) 58 | { 59 | igText("Input Assembly Vertices: %u", E_STATS_GUI(0)); 60 | igText("Input Assembly Primitives: %u", E_STATS_GUI(1)); 61 | igText("Vertex Shader Invocations: %u", E_STATS_GUI(2)); 62 | igText("Clipping Invocations: %u", E_STATS_GUI(3)); 63 | igText("Clipping Primitives: %u", E_STATS_GUI(4)); 64 | igText("Fragment Shader Invocations: %u", E_STATS_GUI(5)); 65 | igText("Hull Shader Invocations: %u", E_STATS_GUI(6)); 66 | igText("Domain Shader Invocations: %u", E_STATS_GUI(7)); 67 | igText("Compute Shader Invocations: %u", E_STATS_GUI(8)); 68 | } 69 | 70 | u64 E_Vk_GetInputAssemblyVertices(E_VulkanPipelineStatistics* stats) 71 | { 72 | E_STATS_ARRAY(0) 73 | } 74 | 75 | u64 E_Vk_GetInputAssemblyPrimitives(E_VulkanPipelineStatistics* stats) 76 | { 77 | E_STATS_ARRAY(1) 78 | } 79 | 80 | u64 E_Vk_GetVertexShaderInvocations(E_VulkanPipelineStatistics* stats) 81 | { 82 | E_STATS_ARRAY(2) 83 | } 84 | 85 | u64 E_Vk_GetClippingInvocations(E_VulkanPipelineStatistics* stats) 86 | { 87 | E_STATS_ARRAY(3) 88 | } 89 | 90 | u64 E_Vk_GetClippingPrimitives(E_VulkanPipelineStatistics* stats) 91 | { 92 | E_STATS_ARRAY(4) 93 | } 94 | 95 | u64 E_Vk_GetFragmentShaderInvocations(E_VulkanPipelineStatistics* stats) 96 | { 97 | E_STATS_ARRAY(5) 98 | } 99 | 100 | u64 E_Vk_GetHullShaderInvocations(E_VulkanPipelineStatistics* stats) 101 | { 102 | E_STATS_ARRAY(6) 103 | } 104 | 105 | u64 E_Vk_GetDomainShaderInvocations(E_VulkanPipelineStatistics* stats) 106 | { 107 | E_STATS_ARRAY(7) 108 | } 109 | 110 | u64 E_Vk_GetComputeShaderInvocations(E_VulkanPipelineStatistics* stats) 111 | { 112 | E_STATS_ARRAY(8) 113 | } 114 | -------------------------------------------------------------------------------- /src/Euphorbe/Graphics/Vulkan/VulkanGPUProfiler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | typedef struct E_VulkanPipelineStatistics E_VulkanPipelineStatistics; 7 | struct E_VulkanPipelineStatistics 8 | { 9 | VkQueryPool query_pool; 10 | VkQueryPipelineStatisticFlagBits query_flags; 11 | E_VectorU64 query_vector; 12 | }; 13 | 14 | E_VulkanPipelineStatistics* E_Vk_CreatePipelineStatistics(); 15 | void E_Vk_FreePipelineStatistics(E_VulkanPipelineStatistics* stats); 16 | void E_Vk_GetQueryResults(E_VulkanPipelineStatistics* stats); 17 | void E_Vk_DrawPipelineStatisticsGUI(E_VulkanPipelineStatistics* stats); 18 | 19 | // Get Stats 20 | u64 E_Vk_GetInputAssemblyVertices(E_VulkanPipelineStatistics* stats); 21 | u64 E_Vk_GetInputAssemblyPrimitives(E_VulkanPipelineStatistics* stats); 22 | u64 E_Vk_GetVertexShaderInvocations(E_VulkanPipelineStatistics* stats); 23 | u64 E_Vk_GetClippingInvocations(E_VulkanPipelineStatistics* stats); 24 | u64 E_Vk_GetClippingPrimitives(E_VulkanPipelineStatistics* stats); 25 | u64 E_Vk_GetFragmentShaderInvocations(E_VulkanPipelineStatistics* stats); 26 | u64 E_Vk_GetHullShaderInvocations(E_VulkanPipelineStatistics* stats); 27 | u64 E_Vk_GetDomainShaderInvocations(E_VulkanPipelineStatistics* stats); 28 | u64 E_Vk_GetComputeShaderInvocations(E_VulkanPipelineStatistics* stats); -------------------------------------------------------------------------------- /src/Euphorbe/Graphics/Vulkan/VulkanImage.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | typedef struct E_VulkanSampler E_VulkanSampler; 8 | struct E_VulkanSampler 9 | { 10 | VkSamplerAddressMode address_mode; 11 | VkFilter filter; 12 | VkSampler sampler; 13 | }; 14 | 15 | typedef struct E_VulkanImage E_VulkanImage; 16 | struct E_VulkanImage 17 | { 18 | VkImage image; 19 | VkImageView image_view; 20 | VkFormat format; 21 | VkExtent3D image_extent; 22 | VkDescriptorSet gui_descriptor_set[FRAMES_IN_FLIGHT]; 23 | 24 | VmaAllocation allocation; 25 | VmaAllocationInfo allocation_info; 26 | 27 | E_ImageFormat euphorbe_format; 28 | E_ImageUsage euphorbe_usage; 29 | b32 cube_map; 30 | }; 31 | 32 | E_VulkanImage* E_Vk_MakeImage(i32 width, i32 height, E_ImageFormat format, E_ImageUsage usage); 33 | E_VulkanImage* E_Vk_MakeImageFromFile(const char* path); 34 | E_VulkanImage* E_Vk_MakeHDRImageFromFile(const char* path); 35 | E_VulkanImage* E_Vk_MakeCubeMap(i32 width, i32 height, E_ImageFormat format, E_ImageUsage usage); 36 | void E_Vk_FreeImage(E_VulkanImage* image); 37 | void E_Vk_ResizeImage(E_VulkanImage* image, i32 width, i32 height); 38 | void E_Vk_DrawImageToGUI(E_VulkanImage* image, i32 width, i32 height, E_VulkanSampler* sampler); 39 | 40 | // Samplers 41 | void E_Vk_InitDefaultSamplers(); 42 | void E_Vk_FreeDefaultSamplers(); 43 | 44 | extern E_VulkanSampler* E_Vk_NearestSampler; 45 | extern E_VulkanSampler* E_Vk_LinearSampler; 46 | extern E_VulkanSampler* E_Vk_CubemapSampler; 47 | 48 | E_VulkanSampler* E_Vk_CreateSampler(E_ImageAddressMode mode, E_ImageFilter filter); 49 | void E_Vk_FreeSampler(E_VulkanSampler* sampler); -------------------------------------------------------------------------------- /src/Euphorbe/Graphics/Vulkan/VulkanMaterial.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "VulkanBuffer.h" 7 | #include "VulkanImage.h" 8 | 9 | typedef struct E_VulkanMaterial E_VulkanMaterial; 10 | struct E_VulkanMaterial 11 | { 12 | VkPipeline pipeline; 13 | VkPipelineLayout pipeline_layout; 14 | 15 | VkDescriptorSetLayout set_layouts[EUPHORBE_MAX_DESCRIPTORS]; 16 | i32 set_layout_count; 17 | }; 18 | 19 | typedef struct E_VulkanMaterialInstance E_VulkanMaterialInstance; 20 | struct E_VulkanMaterialInstance 21 | { 22 | VkDescriptorSet set; 23 | }; 24 | 25 | E_VulkanMaterial* E_Vk_CreateMaterial(E_MaterialCreateInfo* create_info); 26 | void E_Vk_FreeMaterial(E_VulkanMaterial* material); 27 | E_VulkanMaterial* E_Vk_CreateComputeMaterial(E_MaterialCreateInfo* create_info); 28 | 29 | E_VulkanMaterialInstance* E_Vk_CreateMaterialInstance(E_VulkanMaterial* material, i32 set_layout_index); 30 | void E_Vk_MaterialInstanceWriteBuffer(E_VulkanMaterialInstance* instance, i32 binding, E_VulkanBuffer* buffer, i64 buffer_size); 31 | void E_Vk_MaterialInstanceWriteStorageBuffer(E_VulkanMaterialInstance* instance, i32 binding, E_VulkanBuffer* buffer, i64 buffer_size); 32 | void E_Vk_MaterialInstanceWriteSampler(E_VulkanMaterialInstance* instance, i32 binding, E_VulkanSampler* sampler); 33 | void E_Vk_MaterialInstanceWriteSampledImage(E_VulkanMaterialInstance* instance, i32 binding, E_VulkanImage* image); 34 | void E_Vk_MaterialInstanceWriteImage(E_VulkanMaterialInstance* instance, i32 binding, E_VulkanImage* image, E_VulkanSampler* sampler); 35 | void E_Vk_MaterialInstanceWriteStorageImage(E_VulkanMaterialInstance* instance, i32 binding, E_VulkanImage* image, E_VulkanSampler* sampler); 36 | void E_Vk_FreeMaterialInstance(E_VulkanMaterialInstance* instance); -------------------------------------------------------------------------------- /src/Euphorbe/Graphics/Vulkan/VulkanRenderer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #pragma warning(disable: 28251) 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | typedef struct E_Vk_Data E_Vk_Data; 13 | struct E_Vk_Data 14 | { 15 | E_Window* window; 16 | 17 | // Instance data 18 | struct { 19 | VkInstance handle; 20 | char* layers[64]; 21 | char* extensions[64]; 22 | i32 layer_count; 23 | i32 extension_count; 24 | VkDebugUtilsMessengerEXT debug_messenger; 25 | } instance; 26 | 27 | // Window surface 28 | VkSurfaceKHR surface; 29 | 30 | // Physical Device Data 31 | struct { 32 | VkPhysicalDevice handle; 33 | u32 graphics_family; 34 | u32 compute_family; 35 | VkPhysicalDeviceMeshShaderPropertiesNV mesh_shader_props; 36 | VkPhysicalDeviceProperties2 handle_props; 37 | VkPhysicalDeviceFeatures2 features; 38 | } physical_device; 39 | 40 | // Device data 41 | struct { 42 | VkDevice handle; 43 | VkQueue graphics_queue; 44 | VkQueue compute_queue; 45 | char* extensions[64]; 46 | i32 extension_count; 47 | } device; 48 | 49 | // Swapchain data 50 | struct { 51 | VkSwapchainKHR handle; 52 | VkImage* images; 53 | VkImageView image_views[FRAMES_IN_FLIGHT]; 54 | VkFormat image_format; 55 | VkExtent2D extent; 56 | E_Image* euphorbe_images[FRAMES_IN_FLIGHT]; 57 | } swapchain; 58 | 59 | // Sync data 60 | struct { 61 | VkFence fences[FRAMES_IN_FLIGHT]; 62 | VkSemaphore image_available_semaphore; 63 | VkSemaphore image_rendered_semaphore; 64 | i32 image_index; 65 | } sync; 66 | 67 | // Command data 68 | struct { 69 | VkCommandPool graphics_command_pool; 70 | E_CommandBuffer** swapchain_command_buffers; 71 | 72 | VkCommandPool compute_command_pool; 73 | VkFence compute_fence; 74 | 75 | VkCommandPool upload_command_pool; 76 | VkFence upload_fence; 77 | } command; 78 | 79 | // ImGui 80 | struct { 81 | VkDescriptorPool descriptor_pool; 82 | VkRenderPass render_pass; 83 | VkFramebuffer swapchain_framebuffers[FRAMES_IN_FLIGHT]; 84 | } imgui; 85 | 86 | // Other 87 | VkDescriptorPool global_descriptor_pool; 88 | 89 | // VMA 90 | VmaAllocator allocator; 91 | }; 92 | 93 | extern E_Vk_Data rhi; 94 | extern E_RendererInitSettings rhi_settings; 95 | 96 | void E_Vk_RendererInit(E_Window* window, E_RendererInitSettings settings); 97 | void E_Vk_RendererShutdown(); 98 | 99 | void E_Vk_Begin(); 100 | void E_Vk_End(); 101 | void E_Vk_Present(); 102 | void E_Vk_DeviceWait(); 103 | void E_Vk_DrawMemoryUsageGUI(); 104 | void E_Vk_DrawGraphicsCardInfo(); 105 | 106 | void E_Vk_Resize(i32 width, i32 height); 107 | 108 | void E_Vk_BeginGUI(); 109 | void E_Vk_EndGUI(); 110 | 111 | E_Image* E_Vk_GetSwapchainImage(); 112 | u32 E_Vk_GetSwapchainImageIndex(); 113 | E_CommandBuffer* E_Vk_GetSwapchainCommandBuffer(); 114 | 115 | // Most useful function for dynamic rendering 116 | void E_Vk_Image_Memory_Barrier(VkCommandBuffer command_buffer, 117 | VkImage image, 118 | VkAccessFlags src_access_mask, 119 | VkAccessFlags dst_access_mask, 120 | VkImageLayout old_layout, 121 | VkImageLayout new_layout, 122 | VkPipelineStageFlags src_stage_mask, 123 | VkPipelineStageFlags dst_stage_mask, 124 | VkImageSubresourceRange subresource_range); 125 | -------------------------------------------------------------------------------- /src/Euphorbe/Platform/FileSystem.c: -------------------------------------------------------------------------------- 1 | #include "FileSystem.h" 2 | 3 | #ifdef EUPHORBE_WINDOWS 4 | #include "Windows/WindowsFileSystem.h" 5 | #endif 6 | 7 | const char* E_GetAbsolutePath(const char* relative_path) 8 | { 9 | #ifdef EUPHORBE_WINDOWS 10 | return E_Window_GetAbsolutePath(relative_path); 11 | #endif 12 | } 13 | -------------------------------------------------------------------------------- /src/Euphorbe/Platform/FileSystem.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | const char* E_GetAbsolutePath(const char* relative_path); -------------------------------------------------------------------------------- /src/Euphorbe/Platform/Input.c: -------------------------------------------------------------------------------- 1 | #include "Input.h" 2 | 3 | #ifdef EUPHORBE_WINDOWS 4 | #include 5 | #endif 6 | 7 | 8 | b32 E_IsKeyPressed(u16 key) 9 | { 10 | #ifdef EUPHORBE_WINDOWS 11 | return E_WindowsIsKeyPressed(key); 12 | #endif 13 | } 14 | 15 | b32 E_IsMouseButtonPressed(u16 button) 16 | { 17 | #ifdef EUPHORBE_WINDOWS 18 | return E_WindowsIsMouseButtonPressed(button); 19 | #endif 20 | } 21 | 22 | f32 E_GetMousePosX() 23 | { 24 | #ifdef EUPHORBE_WINDOWS 25 | return E_WindowsGetMousePosX(); 26 | #endif 27 | } 28 | 29 | f32 E_GetMousePosY() 30 | { 31 | #ifdef EUPHORBE_WINDOWS 32 | return E_WindowsGetMousePosY(); 33 | #endif 34 | } 35 | -------------------------------------------------------------------------------- /src/Euphorbe/Platform/Input.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #define EUPHORBE_KEY_SPACE 32 7 | #define EUPHORBE_KEY_COMMA 188 8 | #define EUPHORBE_KEY_MINUS 189 9 | #define EUPHORBE_KEY_PERIOD 190 10 | #define EUPHORBE_KEY_D0 48 11 | #define EUPHORBE_KEY_D1 49 12 | #define EUPHORBE_KEY_D2 50 13 | #define EUPHORBE_KEY_D3 51 14 | #define EUPHORBE_KEY_D4 52 15 | #define EUPHORBE_KEY_D5 53 16 | #define EUPHORBE_KEY_D6 54 17 | #define EUPHORBE_KEY_D7 55 18 | #define EUPHORBE_KEY_D8 56 19 | #define EUPHORBE_KEY_D9 57 20 | #define EUPHORBE_KEY_SEMICOLON 186 21 | #define EUPHORBE_KEY_A 65 22 | #define EUPHORBE_KEY_B 66 23 | #define EUPHORBE_KEY_C 67 24 | #define EUPHORBE_KEY_D 68 25 | #define EUPHORBE_KEY_E 69 26 | #define EUPHORBE_KEY_F 70 27 | #define EUPHORBE_KEY_G 71 28 | #define EUPHORBE_KEY_H 72 29 | #define EUPHORBE_KEY_I 73 30 | #define EUPHORBE_KEY_J 74 31 | #define EUPHORBE_KEY_K 75 32 | #define EUPHORBE_KEY_L 76 33 | #define EUPHORBE_KEY_M 77 34 | #define EUPHORBE_KEY_N 78 35 | #define EUPHORBE_KEY_O 79 36 | #define EUPHORBE_KEY_P 80 37 | #define EUPHORBE_KEY_Q 81 38 | #define EUPHORBE_KEY_R 82 39 | #define EUPHORBE_KEY_S 83 40 | #define EUPHORBE_KEY_T 84 41 | #define EUPHORBE_KEY_U 85 42 | #define EUPHORBE_KEY_V 86 43 | #define EUPHORBE_KEY_W 87 44 | #define EUPHORBE_KEY_X 88 45 | #define EUPHORBE_KEY_Y 89 46 | #define EUPHORBE_KEY_Z 90 47 | #define EUPHORBE_KEY_LEFTBRACKET 219 48 | #define EUPHORBE_KEY_BACKSLASH 220 49 | #define EUPHORBE_KEY_RIGHTBRACKENT 221 50 | #define EUPHORBE_KEY_GRAVEACCENT 222 51 | #define EUPHORBE_KEY_BACKSPACE 8 52 | #define EUPHORBE_KEY_ENTER 13 53 | #define EUPHORBE_KEY_TAB 9 54 | #define EUPHORBE_KEY_PAUSE 19 55 | #define EUPHORBE_KEY_NUMLOCK 144 56 | #define EUPHORBE_KEY_SCROLLLOCK 145 57 | #define EUPHORBE_KEY_CAPSLOCK 20 58 | #define EUPHORBE_KEY_ESCAPE 27 59 | #define EUPHORBE_KEY_PAGEUP 33 60 | #define EUPHORBE_KEY_PAGEDOWN 34 61 | #define EUPHORBE_KEY_END 35 62 | #define EUPHORBE_KEY_HOME 36 63 | #define EUPHORBE_KEY_LEFT 37 64 | #define EUPHORBE_KEY_UP 38 65 | #define EUPHORBE_KEY_RIGHT 39 66 | #define EUPHORBE_KEY_DOWN 40 67 | #define EUPHORBE_KEY_PRINTSCREEN 44 68 | #define EUPHORBE_KEY_INSERT 45 69 | #define EUPHORBE_KEY_DELETE 46 70 | #define EUPHORBE_KEY_F1 112 71 | #define EUPHORBE_KEY_F2 113 72 | #define EUPHORBE_KEY_F3 114 73 | #define EUPHORBE_KEY_F4 115 74 | #define EUPHORBE_KEY_F5 116 75 | #define EUPHORBE_KEY_F6 117 76 | #define EUPHORBE_KEY_F7 118 77 | #define EUPHORBE_KEY_F8 119 78 | #define EUPHORBE_KEY_F9 120 79 | #define EUPHORBE_KEY_F10 121 80 | #define EUPHORBE_KEY_F11 122 81 | #define EUPHORBE_KEY_F12 123 82 | #define EUPHORBE_KEY_F13 124 83 | #define EUPHORBE_KEY_F14 125 84 | #define EUPHORBE_KEY_F15 126 85 | #define EUPHORBE_KEY_F16 127 86 | #define EUPHORBE_KEY_F17 128 87 | #define EUPHORBE_KEY_F18 129 88 | #define EUPHORBE_KEY_F19 130 89 | #define EUPHORBE_KEY_F20 131 90 | #define EUPHORBE_KEY_F21 132 91 | #define EUPHORBE_KEY_F22 133 92 | #define EUPHORBE_KEY_F23 134 93 | #define EUPHORBE_KEY_F24 135 94 | #define EUPHORBE_KEY_KP0 96 95 | #define EUPHORBE_KEY_KP1 97 96 | #define EUPHORBE_KEY_KP2 98 97 | #define EUPHORBE_KEY_KP3 99 98 | #define EUPHORBE_KEY_KP4 100 99 | #define EUPHORBE_KEY_KP5 101 100 | #define EUPHORBE_KEY_KP6 102 101 | #define EUPHORBE_KEY_KP7 103 102 | #define EUPHORBE_KEY_KP8 104 103 | #define EUPHORBE_KEY_KP9 105 104 | #define EUPHORBE_KEY_KPMULTIPLY 106 105 | #define EUPHORBE_KEY_KPADD 107 106 | #define EUPHORBE_KEY_KPEQUAL 108 107 | #define EUPHORBE_KEY_KPSUBSTRACT 109 108 | #define EUPHORBE_KEY_KPDECIMAL 110 109 | #define EUPHORBE_KEY_KPDIVIDE 111 110 | #define EUPHORBE_KEY_LEFTSHIFT 160 111 | #define EUPHORBE_KEY_RIGHTSHIFT 161 112 | #define EUPHORBE_KEY_LEFTCONTROL 162 113 | #define EUPHORBE_KEY_RIGHTCONTROL 163 114 | #define EUPHORBE_KEY_LEFTALT 164 115 | #define EUPHORBE_KEY_RIGHTALT 165 116 | 117 | #define EUPHORBE_MOUSE_LEFT 1 118 | #define EUPHORBE_MOUSE_RIGHT 2 119 | #define EUPHORBE_MOUSE_MIDDLE 3 120 | 121 | b32 E_IsKeyPressed(u16 key); 122 | b32 E_IsMouseButtonPressed(u16 button); 123 | f32 E_GetMousePosX(); 124 | f32 E_GetMousePosY(); 125 | -------------------------------------------------------------------------------- /src/Euphorbe/Platform/Timer.c: -------------------------------------------------------------------------------- 1 | #include "Timer.h" 2 | 3 | #ifdef EUPHORBE_WINDOWS 4 | #include "Windows/WindowsTimer.h" 5 | #endif 6 | 7 | void E_TimerInit() 8 | { 9 | #ifdef EUPHORBE_WINDOWS 10 | E_WindowsTimerInit(); 11 | #endif 12 | } 13 | 14 | f32 E_TimerGetTime() 15 | { 16 | #ifdef EUPHORBE_WINDOWS 17 | return E_WindowsTimerGetTime(); 18 | #endif 19 | } 20 | -------------------------------------------------------------------------------- /src/Euphorbe/Platform/Timer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | void E_TimerInit(); 6 | f32 E_TimerGetTime(); -------------------------------------------------------------------------------- /src/Euphorbe/Platform/Window.c: -------------------------------------------------------------------------------- 1 | #include "Window.h" 2 | 3 | #ifdef EUPHORBE_WINDOWS 4 | #include "Windows/WindowsWindow.h" 5 | #endif 6 | 7 | #include 8 | 9 | E_Window* E_CreateWindow(i32 width, i32 height, const char* title, b32 dark_mode) 10 | { 11 | srand(time(NULL)); 12 | 13 | assert(width != 0 && height != 0); 14 | 15 | E_Window* window = malloc(sizeof(E_Window)); 16 | window->width = width; 17 | window->height = height; 18 | window->title = title; 19 | 20 | #ifdef EUPHORBE_WINDOWS 21 | window->platform_data = E_CreateWindowsWindow(&window->width, &window->height, title, dark_mode); 22 | #endif 23 | 24 | return window; 25 | } 26 | 27 | void E_LaunchWindow(E_Window* window) 28 | { 29 | #ifdef EUPHORBE_WINDOWS 30 | E_LaunchWindowsWindow(window->platform_data); 31 | #endif 32 | } 33 | 34 | void E_FreeWindow(E_Window* window) 35 | { 36 | #ifdef EUPHORBE_WINDOWS 37 | E_FreeWindowsWindow(window->platform_data); 38 | #endif 39 | 40 | free(window); 41 | } 42 | 43 | b32 E_IsWindowOpen(E_Window* window) 44 | { 45 | #ifdef EUPHORBE_WINDOWS 46 | E_WindowsWindow* win32 = (E_WindowsWindow*)window->platform_data; 47 | return win32->is_open; 48 | #endif 49 | } 50 | 51 | void E_WindowUpdate(E_Window* window) 52 | { 53 | #ifdef EUPHORBE_WINDOWS 54 | E_UpdateWindowsWindow(window->platform_data); 55 | #endif 56 | } 57 | 58 | void E_WindowSetResizeCallback(E_Window* window, E_WindowResizeCallback callback) 59 | { 60 | #ifdef EUPHORBE_WINDOWS 61 | E_WindowsWindow* win32 = (E_WindowsWindow*)window->platform_data; 62 | win32->resize_callback = callback; 63 | #endif 64 | } 65 | 66 | void E_WindowSetScrollCallback(E_Window* window, E_WindowScrollCallback callback) 67 | { 68 | #ifdef EUPHORBE_WINDOWS 69 | E_WindowsWindow* win32 = (E_WindowsWindow*)window->platform_data; 70 | win32->scroll_callback = callback; 71 | #endif 72 | } 73 | -------------------------------------------------------------------------------- /src/Euphorbe/Platform/Window.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | typedef void (*E_WindowResizeCallback)(int, int); 6 | typedef void (*E_WindowScrollCallback)(f32); 7 | 8 | typedef struct E_Window E_Window; 9 | struct E_Window 10 | { 11 | u32 width; 12 | u32 height; 13 | const char* title; 14 | // Platform handle for the window. See E_WindowsWindow (Euphorbe/Platform/Windows/WindowsWindow.h) for more details 15 | void* platform_data; 16 | }; 17 | 18 | E_Window* E_CreateWindow(i32 width, i32 height, const char* title, b32 dark_mode); 19 | void E_LaunchWindow(E_Window* window); 20 | void E_FreeWindow(E_Window* window); 21 | b32 E_IsWindowOpen(E_Window* window); 22 | void E_WindowUpdate(E_Window* window); 23 | 24 | // Callbacks 25 | void E_WindowSetResizeCallback(E_Window* window, E_WindowResizeCallback callback); 26 | void E_WindowSetScrollCallback(E_Window* window, E_WindowScrollCallback callback); -------------------------------------------------------------------------------- /src/Euphorbe/Platform/Windows/WindowsFileSystem.c: -------------------------------------------------------------------------------- 1 | #include "WindowsFileSystem.h" 2 | 3 | #include 4 | 5 | const char* E_Window_GetAbsolutePath(const char* relative_path) 6 | { 7 | DWORD result = GetFullPathNameA(relative_path, 0, NULL, NULL); 8 | if (result) 9 | { 10 | char* buf = (char*)malloc(result); 11 | result = GetFullPathNameA(relative_path, result, buf, NULL); 12 | if (result == 0) 13 | { 14 | free(buf); 15 | return NULL; 16 | } 17 | return buf; 18 | } 19 | return NULL; 20 | } -------------------------------------------------------------------------------- /src/Euphorbe/Platform/Windows/WindowsFileSystem.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | const char* E_Window_GetAbsolutePath(const char* relative_path); -------------------------------------------------------------------------------- /src/Euphorbe/Platform/Windows/WindowsInput.c: -------------------------------------------------------------------------------- 1 | #include "WindowsInput.h" 2 | 3 | b32 E_WindowsIsKeyPressed(u16 key) 4 | { 5 | SHORT state = GetAsyncKeyState((int)key); 6 | return state & 0x8000; 7 | } 8 | 9 | b32 E_WindowsIsMouseButtonPressed(u16 btn) 10 | { 11 | SHORT state = GetAsyncKeyState((int)btn); 12 | return state & 0x8000; 13 | } 14 | 15 | f32 E_WindowsGetMousePosX() 16 | { 17 | POINT p; 18 | GetCursorPos(&p); 19 | return p.x; 20 | } 21 | 22 | f32 E_WindowsGetMousePosY() 23 | { 24 | POINT p; 25 | GetCursorPos(&p); 26 | return p.y; 27 | } 28 | -------------------------------------------------------------------------------- /src/Euphorbe/Platform/Windows/WindowsInput.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | b32 E_WindowsIsKeyPressed(u16 key); 6 | b32 E_WindowsIsMouseButtonPressed(u16 btn); 7 | f32 E_WindowsGetMousePosX(); 8 | f32 E_WindowsGetMousePosY(); -------------------------------------------------------------------------------- /src/Euphorbe/Platform/Windows/WindowsTimer.c: -------------------------------------------------------------------------------- 1 | #include "WindowsTimer.h" 2 | 3 | #define SECONDS_PER_FRAME(start_counter, end_counter, frequency) ((f32)(end_counter.QuadPart - start_counter.QuadPart) / (f32)frequency.QuadPart) 4 | 5 | E_WindowsTimer timer; 6 | 7 | void E_WindowsTimerInit() 8 | { 9 | LARGE_INTEGER large; 10 | 11 | QueryPerformanceCounter(&large); 12 | timer.start = large.QuadPart; 13 | 14 | QueryPerformanceFrequency(&large); 15 | timer.frequency = (f64)large.QuadPart; 16 | } 17 | 18 | f32 E_WindowsTimerGetTime() 19 | { 20 | LARGE_INTEGER large_int; 21 | QueryPerformanceCounter(&large_int); 22 | 23 | i64 now = large_int.QuadPart; 24 | i64 time = now - timer.start; 25 | 26 | return (f32)((f64)time / timer.frequency); 27 | } 28 | -------------------------------------------------------------------------------- /src/Euphorbe/Platform/Windows/WindowsTimer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | typedef struct E_WindowsTimer E_WindowsTimer; 6 | struct E_WindowsTimer 7 | { 8 | i64 start; 9 | f64 frequency; 10 | }; 11 | 12 | void E_WindowsTimerInit(); 13 | f32 E_WindowsTimerGetTime(); -------------------------------------------------------------------------------- /src/Euphorbe/Platform/Windows/WindowsWindow.c: -------------------------------------------------------------------------------- 1 | #include "WindowsWindow.h" 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | extern LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); 12 | 13 | LRESULT CALLBACK WinProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) 14 | { 15 | if (ImGui_ImplWin32_WndProcHandler(hwnd, msg, wparam, lparam)) 16 | return 1; 17 | 18 | switch (msg) 19 | { 20 | case WM_CREATE: 21 | { 22 | LPCREATESTRUCT create_struct = (LPCREATESTRUCT)lparam; 23 | E_WindowsWindow* window = (E_WindowsWindow*)create_struct->lpCreateParams; 24 | SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)window); 25 | 26 | break; 27 | } 28 | case WM_DESTROY: 29 | { 30 | E_WindowsWindow* window = (E_WindowsWindow*)GetWindowLongPtr(hwnd, GWLP_USERDATA); 31 | window->is_open = 0; 32 | break; 33 | } 34 | 35 | case WM_SIZE: 36 | { 37 | i32 width = LOWORD(lparam); 38 | i32 height = HIWORD(lparam); 39 | E_WindowsWindow* window = (E_WindowsWindow*)GetWindowLongPtr(hwnd, GWLP_USERDATA); 40 | *window->width_pointer = width; 41 | *window->height_pointer = height; 42 | 43 | if (window->resize_callback != NULL) 44 | window->resize_callback(width, height); 45 | 46 | break; 47 | } 48 | 49 | case WM_MOUSEWHEEL: 50 | { 51 | E_WindowsWindow* window = (E_WindowsWindow*)GetWindowLongPtr(hwnd, GWLP_USERDATA); 52 | f32 scroll = (f32)GET_WHEEL_DELTA_WPARAM(wparam) / (f32)WHEEL_DELTA; 53 | 54 | if (window->scroll_callback != NULL) 55 | window->scroll_callback(scroll); 56 | 57 | break; 58 | } 59 | 60 | default: 61 | return DefWindowProc(hwnd, msg, wparam, lparam); 62 | } 63 | 64 | return 0; 65 | } 66 | 67 | E_WindowsWindow* E_CreateWindowsWindow(i32* width, i32* height, const char* title, b32 dark_mode) 68 | { 69 | E_WindowsWindow* result = malloc(sizeof(E_WindowsWindow)); 70 | if (result) 71 | { 72 | result->width_pointer = width; 73 | result->height_pointer = height; 74 | result->resize_callback = NULL; 75 | 76 | WNDCLASSA window_class = { 0 }; 77 | window_class.lpfnWndProc = WinProc; 78 | window_class.hInstance = GetModuleHandleA(NULL); 79 | window_class.lpszClassName = "EuphorbeWindowClass"; 80 | 81 | RegisterClassA(&window_class); 82 | 83 | result->hwnd = CreateWindowA(window_class.lpszClassName, 84 | title, 85 | WS_OVERLAPPEDWINDOW, 86 | CW_USEDEFAULT, CW_USEDEFAULT, 87 | *width, *height, 88 | NULL, NULL, window_class.hInstance, 89 | result); 90 | 91 | if (!result->hwnd) 92 | E_LogError("Failed to create HWND!"); 93 | 94 | result->is_open = 1; 95 | 96 | if (result->hwnd) 97 | { 98 | RECT rect; 99 | GetClientRect(result->hwnd, &rect); 100 | *width = rect.right - rect.left; 101 | *height = rect.bottom - rect.top; 102 | } 103 | 104 | igCreateContext(NULL); 105 | 106 | ImGuiIO* io = igGetIO(); 107 | //io->FontDefault = ImFontAtlas_AddFontFromFileTTF(io->Fonts, "Assets/Fonts/Consolas.ttf", 16.0f, NULL, NULL); 108 | 109 | ImGuiStyle* style = igGetStyle(); 110 | io->ConfigFlags |= ImGuiConfigFlags_DockingEnable; 111 | 112 | if (dark_mode) 113 | igStyleColorsDark(NULL); 114 | else 115 | igStyleColorsLight(NULL); 116 | 117 | ImGui_ImplWin32_Init(result->hwnd); 118 | 119 | return result; 120 | } 121 | 122 | return NULL; 123 | } 124 | 125 | void E_LaunchWindowsWindow(E_WindowsWindow* window) 126 | { 127 | ShowWindow(window->hwnd, SW_MAXIMIZE); 128 | 129 | RECT rect; 130 | GetClientRect(window->hwnd, &rect); 131 | *window->width_pointer = rect.right - rect.left; 132 | *window->height_pointer = rect.bottom - rect.top; 133 | } 134 | 135 | void E_FreeWindowsWindow(E_WindowsWindow* window) 136 | { 137 | ImGui_ImplWin32_Shutdown(); 138 | 139 | DestroyWindow(window->hwnd); 140 | free(window); 141 | } 142 | 143 | void E_UpdateWindowsWindow(E_WindowsWindow* window) 144 | { 145 | MSG msg; 146 | while (PeekMessageA(&msg, window->hwnd, 0, 0, PM_REMOVE)) 147 | { 148 | TranslateMessage(&msg); 149 | DispatchMessageA(&msg); 150 | } 151 | } -------------------------------------------------------------------------------- /src/Euphorbe/Platform/Windows/WindowsWindow.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | // Struct containing all the necessary information to create a Win32 window 6 | typedef struct E_WindowsWindow E_WindowsWindow; 7 | struct E_WindowsWindow 8 | { 9 | HWND hwnd; 10 | b32 is_open; 11 | i32* width_pointer; 12 | i32* height_pointer; 13 | 14 | E_WindowResizeCallback resize_callback; 15 | E_WindowScrollCallback scroll_callback; 16 | }; 17 | 18 | E_WindowsWindow* E_CreateWindowsWindow(i32* width, i32* height, const char* title, b32 dark_mode); 19 | void E_LaunchWindowsWindow(E_WindowsWindow* window); 20 | void E_FreeWindowsWindow(E_WindowsWindow* window); 21 | void E_UpdateWindowsWindow(E_WindowsWindow* window); -------------------------------------------------------------------------------- /src/Euphorbe/Resource/Resource.c: -------------------------------------------------------------------------------- 1 | #include "Resource.h" 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | E_ResourceFile* E_LoadResource(const char* path, E_ResourceType type) 11 | { 12 | E_ResourceFile* resource = malloc(sizeof(E_ResourceFile)); 13 | memset(resource, 0, sizeof(E_ResourceFile)); 14 | resource->type = type; 15 | resource->path = (char*)path; 16 | 17 | switch (resource->type) 18 | { 19 | case E_ResourceTypeUndefined: 20 | break; 21 | case E_ResourceTypeVertexShader: 22 | resource->as.shader = malloc(sizeof(E_Shader)); 23 | if (resource->as.shader != NULL) 24 | { 25 | char* source = E_ReadFile(path, &resource->resource_size); 26 | 27 | resource->as.shader->type = E_ShaderTypeVertex; 28 | E_CompileShader(source, resource->resource_size, resource->as.shader); 29 | 30 | free(source); 31 | break; 32 | } 33 | else 34 | { 35 | E_LogError("RESOURCE SHADER ALLOCATION: Failed to allocate resource shader!"); 36 | assert(0); 37 | return NULL; 38 | } 39 | break; 40 | case E_ResourceTypeGeometryShader: 41 | resource->as.shader = malloc(sizeof(E_Shader)); 42 | if (resource->as.shader != NULL) 43 | { 44 | char* source = E_ReadFile(path, &resource->resource_size); 45 | 46 | resource->as.shader->type = E_ShaderTypeGeometry; 47 | E_CompileShader(source, resource->resource_size, resource->as.shader); 48 | 49 | free(source); 50 | break; 51 | } 52 | else 53 | { 54 | E_LogError("RESOURCE SHADER ALLOCATION: Failed to allocate resource shader!"); 55 | assert(0); 56 | return NULL; 57 | } 58 | break; 59 | case E_ResourceTypeFragmentShader: 60 | resource->as.shader = malloc(sizeof(E_Shader)); 61 | if (resource->as.shader != NULL) 62 | { 63 | char* source = E_ReadFile(path, &resource->resource_size); 64 | 65 | resource->as.shader->type = E_ShaderTypeFragment; 66 | E_CompileShader(source, resource->resource_size, resource->as.shader); 67 | 68 | free(source); 69 | break; 70 | } 71 | else 72 | { 73 | E_LogError("RESOURCE SHADER ALLOCATION: Failed to allocate resource shader!"); 74 | assert(0); 75 | return NULL; 76 | } 77 | break; 78 | case E_ResourceTypeComputeShader: 79 | resource->as.shader = malloc(sizeof(E_Shader)); 80 | if (resource->as.shader != NULL) 81 | { 82 | char* source = E_ReadFile(path, &resource->resource_size); 83 | 84 | resource->as.shader->type = E_ShaderTypeCompute; 85 | E_CompileShader(source, resource->resource_size, resource->as.shader); 86 | 87 | free(source); 88 | break; 89 | } 90 | else 91 | { 92 | E_LogError("RESOURCE SHADER ALLOCATION: Failed to allocate resource shader!"); 93 | assert(0); 94 | return NULL; 95 | } 96 | break; 97 | case E_ResourceTypeTaskShader: 98 | resource->as.shader = malloc(sizeof(E_Shader)); 99 | if (resource->as.shader != NULL) 100 | { 101 | char* source = E_ReadFile(path, &resource->resource_size); 102 | 103 | resource->as.shader->type = E_ShaderTypeTaskNV; 104 | E_CompileShader(source, resource->resource_size, resource->as.shader); 105 | 106 | free(source); 107 | break; 108 | } 109 | else 110 | { 111 | E_LogError("RESOURCE SHADER ALLOCATION: Failed to allocate resource shader!"); 112 | assert(0); 113 | return NULL; 114 | } 115 | break; 116 | case E_ResourceTypeMeshShader: 117 | resource->as.shader = malloc(sizeof(E_Shader)); 118 | if (resource->as.shader != NULL) 119 | { 120 | char* source = E_ReadFile(path, &resource->resource_size); 121 | 122 | resource->as.shader->type = E_ShaderTypeMeshNV; 123 | E_CompileShader(source, resource->resource_size, resource->as.shader); 124 | 125 | free(source); 126 | break; 127 | } 128 | else 129 | { 130 | E_LogError("RESOURCE SHADER ALLOCATION: Failed to allocate resource shader!"); 131 | assert(0); 132 | return NULL; 133 | } 134 | break; 135 | case E_ResourceTypeTexture: 136 | resource->as.image = E_MakeImageFromFile(resource->path); 137 | break; 138 | case E_ResourceTypeMaterial: 139 | resource->as.material = E_CreateMaterialFromFile(resource->path); 140 | break; 141 | case E_ResourceTypeComputeMaterial: 142 | resource->as.material = E_CreateComputeMaterialFromFile(resource->path); 143 | break; 144 | } 145 | 146 | return resource; 147 | } 148 | 149 | void E_FreeResource(E_ResourceFile* file) 150 | { 151 | switch (file->type) 152 | { 153 | case E_ResourceTypeVertexShader: 154 | case E_ResourceTypeGeometryShader: 155 | case E_ResourceTypeFragmentShader: 156 | case E_ResourceTypeComputeShader: 157 | case E_ResourceTypeTaskShader: 158 | case E_ResourceTypeMeshShader: 159 | free(file->as.shader); 160 | break; 161 | case E_ResourceTypeTexture: 162 | E_FreeImage(file->as.image); 163 | break; 164 | case E_ResourceTypeMaterial: 165 | case E_ResourceTypeComputeMaterial: 166 | E_FreeMaterial(file->as.material); 167 | break; 168 | case E_ResourceTypeUndefined: 169 | break; 170 | } 171 | 172 | free(file); 173 | } 174 | -------------------------------------------------------------------------------- /src/Euphorbe/Resource/Resource.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | typedef struct E_CommandBuffer E_CommandBuffer; 7 | 8 | typedef struct E_Material E_Material; 9 | 10 | typedef enum E_ResourceType E_ResourceType; 11 | enum E_ResourceType 12 | { 13 | E_ResourceTypeUndefined = 0, 14 | E_ResourceTypeVertexShader, 15 | E_ResourceTypeGeometryShader, 16 | E_ResourceTypeFragmentShader, 17 | E_ResourceTypeComputeShader, 18 | E_ResourceTypeTaskShader, 19 | E_ResourceTypeMeshShader, 20 | E_ResourceTypeTexture, 21 | E_ResourceTypeMaterial, 22 | E_ResourceTypeComputeMaterial 23 | }; 24 | 25 | typedef struct E_ResourceFile E_ResourceFile; 26 | struct E_ResourceFile 27 | { 28 | E_ResourceType type; 29 | char* path; 30 | i32 resource_size; 31 | 32 | struct { 33 | E_Shader* shader; 34 | E_Image* image; 35 | E_Material* material; 36 | } as; 37 | }; 38 | 39 | E_ResourceFile* E_LoadResource(const char* path, E_ResourceType type); 40 | void E_FreeResource(E_ResourceFile* file); --------------------------------------------------------------------------------