├── .gitignore ├── CMakeLists.txt ├── CMakeSettings.json ├── README.md ├── executables ├── demo1_cubemap │ └── main.cpp ├── demo2_distancefields │ └── main.cpp ├── demo3_shadertest │ └── main.cpp ├── demo4_shadowmapping │ └── main.cpp ├── demo5_pbr │ └── main.cpp ├── demo6_octree │ └── main.cpp ├── project1_volumetric_debug │ └── main.cpp ├── project1_volumetric_rendering │ └── main.cpp └── test1_model │ └── main.cpp ├── external ├── glshader │ ├── include │ │ └── glsp │ │ │ ├── compiler.hpp │ │ │ ├── config.hpp │ │ │ ├── definition.hpp │ │ │ ├── glsp.hpp │ │ │ ├── huffman.hpp │ │ │ └── preprocess.hpp │ └── src │ │ ├── compiler │ │ └── compiler.cpp │ │ ├── compress │ │ └── huffman.cpp │ │ ├── definition.cpp │ │ ├── opengl │ │ ├── loader.cpp │ │ └── loader.hpp │ │ ├── preprocessor │ │ ├── classify.cpp │ │ ├── classify.hpp │ │ ├── control.cpp │ │ ├── control.hpp │ │ ├── eval.cpp │ │ ├── eval.hpp │ │ ├── extensions.cpp │ │ ├── extensions.hpp │ │ ├── files.hpp │ │ ├── macro.cpp │ │ ├── macro.hpp │ │ ├── preprocessor.cpp │ │ ├── skip.cpp │ │ └── skip.hpp │ │ └── strings.hpp ├── imgui │ ├── imconfig.h │ ├── imgui.cpp │ ├── imgui.h │ ├── imgui_demo.cpp │ ├── imgui_draw.cpp │ ├── imgui_impl_glfw_gl3.cpp │ ├── imgui_impl_glfw_gl3.h │ ├── imgui_internal.h │ ├── stb_rect_pack.h │ ├── stb_textedit.h │ └── stb_truetype.h └── stb │ ├── stb_image.h │ └── stb_image_write.h ├── libraries ├── IO │ ├── GuiFont.cpp │ ├── ModelImporter.cpp │ └── ModelImporter.h ├── Rendering │ ├── Binding.h │ ├── Buffer.cpp │ ├── Buffer.h │ ├── Camera.cpp │ ├── Camera.h │ ├── Cubemap.cpp │ ├── Cubemap.h │ ├── FrameBuffer.cpp │ ├── FrameBuffer.h │ ├── IBLCubemapMaker.cpp │ ├── IBLCubemapMaker.h │ ├── Image.cpp │ ├── Image.h │ ├── Light.cpp │ ├── Light.h │ ├── LightManager.cpp │ ├── LightManager.h │ ├── Mesh.cpp │ ├── Mesh.h │ ├── Parameters.h │ ├── Pilotview.cpp │ ├── Pilotview.h │ ├── Quad.cpp │ ├── Quad.h │ ├── Shader.cpp │ ├── Shader.h │ ├── ShaderProgram.cpp │ ├── ShaderProgram.h │ ├── SimplexNoise.cpp │ ├── SimplexNoise.h │ ├── SkyBoxCube.cpp │ ├── SkyBoxCube.h │ ├── SparseVoxelOctree.cpp │ ├── SparseVoxelOctree.h │ ├── Texture.cpp │ ├── Texture.h │ ├── Trackball.cpp │ ├── Trackball.h │ ├── Uniform.h │ ├── VertexArray.cpp │ ├── VertexArray.h │ ├── VoxelDebugRenderer.cpp │ └── VoxelDebugRenderer.h └── Utils │ ├── Timer.cpp │ ├── Timer.h │ ├── UtilCollection.cpp │ └── UtilCollection.h ├── resources ├── Newport_Loft │ ├── Newport_Loft.ibl │ ├── Newport_Loft_8k.jpg │ ├── Newport_Loft_Env.hdr │ ├── Newport_Loft_Ref.hdr │ ├── Newport_Loft_Thumb.jpg │ └── Newport_Loft_preview.jpg ├── bunny.obj ├── cover2.png ├── screenshots │ └── 1.png ├── skybox │ ├── skybox0.jpg │ ├── skybox1.jpg │ ├── skybox2.jpg │ ├── skybox3.jpg │ ├── skybox4.jpg │ └── skybox5.jpg └── teapot.obj ├── set_vcpkg_path.ps1 └── shaders ├── CMakeLists.txt ├── HDRtoLDR.frag ├── IBLtoCube.frag ├── IBLtoCube.vert ├── SparseVoxelOctree ├── CreateNodes.comp ├── FlagNodes.comp ├── InitLeafNodes.comp ├── MipMapNodes.comp ├── TraceSparseVoxelOctree.frag ├── VoxelGen.frag ├── VoxelGen.geom ├── VoxelGen.vert └── sfq_rayDir.vert ├── accumulateVoxels.comp ├── accumulateVoxelsSM.comp ├── brdfLUT.frag ├── common ├── light.glsl ├── material.glsl ├── shadowMapping.glsl └── volumetricLighting.glsl ├── cubemap.frag ├── cubemap.vert ├── cubemap2.frag ├── cubemap2.vert ├── demo1.frag ├── demo1.vert ├── drawIBLskybox.frag ├── drawIBLskybox.vert ├── fbo.frag ├── frustumCulling.comp ├── fxaa.frag ├── irradianceMapCalc.frag ├── lightDebug.geom ├── lightDebug.vert ├── lightTransform.vert ├── modelFragMD.frag ├── modelFragMDBump.frag ├── modelFragVolumetric.frag ├── modelFragVolumetricMD.frag ├── modelFragVolumetricMDBump.frag ├── modelVert.vert ├── modelVertMultiDraw.vert ├── modelVertVolumetric.vert ├── modelVertVolumetricMD.vert ├── mondrian.frag ├── nothing.frag ├── omnidirectional.frag ├── omnidirectional.geom ├── pbr1.frag ├── pbr1.vert ├── pbr2.frag ├── pbr3.frag ├── postProcess.frag ├── prefilterEnvMap.frag ├── quadSDF.vert ├── scatterLight.comp ├── sfq.vert ├── sfq1.frag ├── shadowmapping.frag ├── shadowmapping.vert ├── smAlpha.frag ├── smfbo.frag ├── tangentSpace.geom ├── tangentSpace2.geom ├── texSFQ.frag ├── texSFQ.vert ├── traceSDF.frag ├── transform.vert ├── voxelDebug.frag ├── voxelDebug.geom └── voxeldebug.vert /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | 34 | /BUILD* 35 | /bin* 36 | /.vs 37 | /CMakeBuild/ -------------------------------------------------------------------------------- /CMakeSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "name": "Debug-x64", 5 | "generator": "Ninja", 6 | "configurationType": "Debug", 7 | "inheritEnvironments": [ 8 | "msvc_x64_x64" 9 | ], 10 | "buildRoot": "${projectDir}\\CMakeBuild\\${name}", 11 | "cmakeCommandArgs": "", 12 | "buildCommandArgs": "", 13 | "variables": [ 14 | { 15 | "name": "CMAKE_TOOLCHAIN_FILE", 16 | "value": "C:\\Users\\mm\\Documents\\Uni-Archiv\\vcpkg\\vcpkg\\scripts\\buildsystems\\vcpkg.cmake" 17 | }, 18 | { 19 | "name": "VCPKG_TARGET_TRIPLET", 20 | "value": "x64-windows" 21 | } 22 | ] 23 | }, 24 | { 25 | "name": "Release-x64", 26 | "generator": "Ninja", 27 | "configurationType": "Release", 28 | "inheritEnvironments": [ 29 | "msvc_x64_x64" 30 | ], 31 | "buildRoot": "${projectDir}\\CMakeBuild\\${name}", 32 | "cmakeCommandArgs": "", 33 | "buildCommandArgs": "", 34 | "variables": [ 35 | { 36 | "name": "CMAKE_TOOLCHAIN_FILE", 37 | "value": "C:\\Users\\mm\\Documents\\Uni-Archiv\\vcpkg\\vcpkg\\scripts\\buildsystems\\vcpkg.cmake" 38 | }, 39 | { 40 | "name": "VCPKG_TARGET_TRIPLET", 41 | "value": "x64-windows" 42 | } 43 | ] 44 | } 45 | ] 46 | } 47 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Graphics2 2 | 3 | ![Volumetric Rendering](/resources/screenshots/1.png) 4 | 5 | ### Description 6 | OpenGL project for prototyping. 7 | Contains abstractions for major OpenGL features with focus on code reusability, modern OpenGL usage and ease of use. 8 | Also contains some demos and examples. 9 | 10 | ### OpenGL version and extensions: 11 | * 4.5 and up should work 12 | * [ARB_bindless_texture](https://www.khronos.org/opengl/wiki/Bindless_Texture) 13 | * I'm trying to use [direct state access](https://www.khronos.org/opengl/wiki/Direct_State_Access) wherever possible 14 | 15 | ### Used libraries: 16 | * [ImGui](https://github.com/ocornut/imgui) 17 | * [stb_image & stb_image_write](https://github.com/nothings/stb) 18 | * [GLshader](https://gitlab.uni-koblenz.de/johannesbraun/glshader) by Johannes Braun 19 | * [Assimp](http://assimp.org/) (tested with 3.3.1) 20 | * [glfw3](http://www.glfw.org/) (tested with 3.2.1) 21 | * [glbinding](https://github.com/cginternals/glbinding) (tested with 2.1.1) 22 | * [glm](https://glm.g-truc.net/0.9.8/index.html) (tested with 0.9.8.4) 23 | 24 | ### Usage 25 | #### Windows 26 | * Please use [vcpkg](https://github.com/Microsoft/vcpkg) for dependency management when using windows to use this project 27 | * Install assimp:x64-windows, glfw3:x64-windows, glbinding:x64-windows and glm:x64-windows using vcpkg 28 | * Set the correct path to your installation of vcpkg (vcpkg.cmake) in the CMakeSettings.json-file or use the included script (set_vcpkg_path.ps1) to select it 29 | * Open the project folder in Visual Studio 30 | #### Linux 31 | * Currently not tested 32 | * Install assimp, glfw3, glbinding and glm using your package manager 33 | * Using CMake to generate makefiles might already work 34 | 35 | ### Executables 36 | #### Project: Volumetric Lighting 37 | * University Project for the Lecture 'Real-Time Rendering' 38 | * Uses [this approach](http://advances.realtimerendering.com/s2014/wronski/bwronski_volumetric_fog_siggraph2014.pdf) 39 | 40 | 41 | #### demo 1: cubemap, reflections, lighting 42 | * work in progress 43 | * phong lighting (spotlights, directional lights, specular & diffuse, fog) 44 | * toon shading 45 | * cubemap reflections 46 | * postprocessing 47 | * GUI-controllable parameters for basically everything in this demo 48 | * shader live reloading 49 | 50 | #### demo 2: distance fields 51 | * work in progress 52 | * raymarching distance fields: soft shadows, simple distance field ambient occlusion 53 | * shader live reloading 54 | * heavily inspired by http://www.iquilezles.org/, university lectures 55 | 56 | #### demo 3: shaders 57 | * work in progress 58 | * testing some shader-only drawing stuff, "the book of shaders"-style 59 | 60 | #### demo 4: shadowmapping 61 | * work in progress 62 | * shadow mapping with PCF 63 | 64 | #### demo 5: PBR & IBL 65 | * PBR using Cook-Torrance BRDF 66 | * IBL using HDR cubemaps 67 | * HDR texture -> cubemap -> specular & diffuse IBL 68 | 69 | ### Resources/Licensing 70 | 71 | * PBR & IBL code adapted (with changes), skybox texture from [Joey de Vries](https://twitter.com/JoeyDeVriez)' [learnopengl.com](learnopengl.com), licensed under [CC BY-NC 4.0](https://creativecommons.org/licenses/by/4.0/legalcode). 72 | * IBL Textures are from the [sIBL archive](http://www.hdrlabs.com/sibl/archive.html), licensed under [CC BY-NC-SA 3.0 US](https://creativecommons.org/licenses/by-nc-sa/3.0/us/legalcode). 73 | -------------------------------------------------------------------------------- /executables/demo3_shadertest/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace gl; 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | #include "Utils/UtilCollection.h" 12 | #include "Utils/Timer.h" 13 | #include "Rendering/Shader.h" 14 | #include "Rendering/ShaderProgram.h" 15 | #include "Rendering/Buffer.h" 16 | #include "Rendering/Uniform.h" 17 | #include "Rendering/Mesh.h" 18 | #include "Rendering/Binding.h" 19 | 20 | 21 | #include "imgui/imgui.h" 22 | #include "imgui/imgui_impl_glfw_gl3.h" 23 | #include 24 | 25 | const unsigned int width = 800; 26 | const unsigned int height = 800; 27 | 28 | int main() 29 | { 30 | // init glfw, open window, manage context 31 | GLFWwindow* window = util::setupGLFWwindow(width, height, "Demo 3"); 32 | glfwSwapInterval(0); 33 | // init opengl 34 | util::initGL(); 35 | 36 | // print OpenGL info 37 | util::printOpenGLInfo(); 38 | 39 | util::enableDebugCallback(); 40 | 41 | // set up imgui 42 | ImGui::CreateContext(); 43 | ImGui_ImplGlfwGL3_Init(window, true); 44 | 45 | // get list of OpenGL extensions (can be searched later if needed) 46 | std::vector extensions = util::getGLExtenstions(); 47 | 48 | Shader vs("sfq.vert", GL_VERTEX_SHADER); 49 | Shader fs("mondrian.frag", GL_FRAGMENT_SHADER); 50 | ShaderProgram sp(vs, fs); 51 | sp.use(); 52 | 53 | std::vector quadData = 54 | { 55 | {-1.0, -1.0}, 56 | {1.0, -1.0}, 57 | {-1.0, 1.0}, 58 | {-1.0, 1.0}, 59 | {1.0, -1.0}, 60 | {1.0, 1.0} 61 | }; 62 | 63 | Buffer QuadBuffer(GL_ARRAY_BUFFER); 64 | QuadBuffer.setStorage(quadData, GL_DYNAMIC_STORAGE_BIT); 65 | VertexArray quadVAO; 66 | quadVAO.connectBuffer(QuadBuffer, BufferBindings::VertexAttributeLocation::vertices, 2, GL_FLOAT, GL_FALSE); 67 | quadVAO.bind(); 68 | 69 | auto resolutionUniform = std::make_shared>("u_resolution", glm::vec2(width, height)); 70 | sp.addUniform(resolutionUniform); 71 | 72 | auto time = std::chrono::high_resolution_clock::now(); 73 | auto time2 = std::chrono::high_resolution_clock::now(); 74 | auto dur = (time2 - time).count(); 75 | auto duration = dur / 1000000000.0f; 76 | auto timeUniform = std::make_shared>("u_time", duration); 77 | // catch optimized-out uniforms -- this is for testing purposes only 78 | try 79 | { 80 | sp.addUniform(timeUniform); 81 | } 82 | catch (std::runtime_error& err) 83 | { 84 | std::cout << "Unused uniform" << '\n'; 85 | std::cout << err.what() << '\n'; 86 | } 87 | 88 | glm::vec4 clear_color(0.1f); 89 | 90 | Timer timer; 91 | 92 | glEnable(GL_CULL_FACE); 93 | glCullFace(GL_BACK); 94 | glEnable(GL_DEPTH_TEST); 95 | 96 | // render loop 97 | while (!glfwWindowShouldClose(window)) 98 | { 99 | timer.start(); 100 | 101 | glfwPollEvents(); 102 | ImGui_ImplGlfwGL3_NewFrame(); 103 | 104 | sp.showReloadShaderGUI({ vs, fs }); 105 | 106 | glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w); 107 | 108 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 109 | 110 | time2 = std::chrono::high_resolution_clock::now(); 111 | dur = (time2 - time).count(); 112 | duration = dur / 100000000.0f; 113 | timeUniform->setContent(duration); 114 | sp.updateUniforms(); 115 | 116 | glDrawArrays(GL_TRIANGLES, 0, static_cast(quadData.size())); 117 | 118 | timer.stop(); 119 | timer.drawGuiWindow(window); 120 | 121 | ImGui::Render(); 122 | ImGui_ImplGlfwGL3_RenderDrawData(ImGui::GetDrawData()); 123 | glfwSwapBuffers(window); 124 | } 125 | std::cout << std::endl; 126 | 127 | ImGui_ImplGlfwGL3_Shutdown(); 128 | 129 | // close window 130 | glfwDestroyWindow(window); 131 | } 132 | -------------------------------------------------------------------------------- /external/glshader/include/glsp/compiler.hpp: -------------------------------------------------------------------------------- 1 | /*******************************************************************************/ 2 | /* File compiler.hpp 3 | /* Author Johannes Braun 4 | /* Created 01.04.2018 5 | /* 6 | /* Wrapper for the proprietary binary format interface in OpenGL to 7 | /* cache binary versions of loaded shaders for shorter loading times. 8 | /*******************************************************************************/ 9 | 10 | #pragma once 11 | 12 | #include "glsp.hpp" 13 | 14 | namespace glshader::process 15 | { 16 | /* Pack a 4-byte char sequence into a uint32_t. Used in binary file section markers and format tags. */ 17 | constexpr uint32_t make_tag(const char name[4]) 18 | { 19 | return (name[0] << 0) | (name[1] << 8) | (name[2] << 16) | (name[3] << 24); 20 | } 21 | 22 | /* The base format of the binary source. */ 23 | enum class format : uint32_t 24 | { 25 | gl_binary = make_tag("GBIN"), /* Use system's proprietary vendor binary format. */ 26 | spirv = make_tag("SPRV") /* Use SPIR-V format. NOT SUPPORTED AT THE MOMENT! */ 27 | }; 28 | 29 | /* The resulting binary shader data. */ 30 | struct shader_binary 31 | { 32 | uint32_t format; /* The vendor binary format, used as binaryFormat parameter in glProgramBinary. */ 33 | std::vector data; /* The binary data. */ 34 | }; 35 | 36 | /* A wrapper class containing state information about compiling shaders. 37 | Derives from glsp::state and can therefore preprocess and compile shader files. 38 | Additionally to the state class, you can set file extensions for the cached binary files, 39 | which will be saved into the cache directory with their filename being their text-format-shader's source path's hash value. 40 | There is also the option to set a prefix and a postfix for OpenGL shaders. This might be useful if you wish for 41 | all shaders to have the same #version and #extension declarations, as well as layout(bindless_) uniform; declarations. */ 42 | class compiler : public glsp::state 43 | { 44 | public: 45 | /* A compiler constructed with this constructor will in it's unchanged state save binaries in the following path: 46 | /. 47 | If passed a file extension not starting with a '.', it will be prepended.*/ 48 | compiler(const std::string& extension, const glsp::files::path& cache_dir); 49 | 50 | /* Replace the file extension with which binaries will be saved. */ 51 | void set_extension(const std::string& ext); 52 | 53 | /* Set the directory in which compiled binaries will be saved and from where they will be loaded. */ 54 | void set_cache_dir(const glsp::files::path& dir); 55 | 56 | /* Set a common source code prefix for all compiled shaders. This will NOT be preprocessed! */ 57 | void set_default_prefix(const std::string& prefix); 58 | 59 | /* Set a common source code postfix for all compiled shaders. This will NOT be preprocessed! */ 60 | void set_default_postfix(const std::string& postfix); 61 | 62 | /* Preprocess, compile, save and return binary data of the given shader file. If force_reload is set to false, the binary file already exists 63 | and the internal time stamp matches the shader's last editing time, the binary file will be loaded and returned directly instead. 64 | The parameters "includes" and "definitions" can add special include paths and definitions for this one compilation process. */ 65 | shader_binary compile(const glsp::files::path& shader, format format, bool force_reload = false, std::vector includes ={}, std::vector definitions ={}); 66 | 67 | private: 68 | std::string _default_prefix; 69 | std::string _default_postfix; 70 | std::string _extension; 71 | glsp::files::path _cache_dir; 72 | }; 73 | } -------------------------------------------------------------------------------- /external/glshader/include/glsp/config.hpp: -------------------------------------------------------------------------------- 1 | /*******************************************************************************/ 2 | /* File config.hpp 3 | /* Author Johannes Braun 4 | /* Created 31.03.2018 5 | /* 6 | /* User space for own settings. 7 | /*******************************************************************************/ 8 | 9 | #pragma once 10 | 11 | // CUSTOM LOGGING: 12 | // If you want to use your own logger for error logs, you can define ERR_OUTPUT(x) with x being the logged string. 13 | // Example for a custom stream-style logger: 14 | // #define ERR_OUTPUT(x) my_logger("GLShader") << (x) 15 | 16 | // NAMESPACE: 17 | namespace glshader::process {} 18 | // Shorten base namespace. You can use your own namespace if you wish. 19 | namespace glsp = glshader::process; -------------------------------------------------------------------------------- /external/glshader/include/glsp/definition.hpp: -------------------------------------------------------------------------------- 1 | /*******************************************************************************/ 2 | /* File definition.hpp 3 | /* Author Johannes Braun 4 | /* Created 30.03.2018 5 | /* 6 | /* Wrapper for in-code #define directives. 7 | /*******************************************************************************/ 8 | 9 | #pragma once 10 | 11 | #include "config.hpp" 12 | #include 13 | #include 14 | 15 | namespace glshader::process 16 | { 17 | /* Holds all the needed information for resolving a definition. */ 18 | struct definition_info 19 | { 20 | definition_info() = default; 21 | /* Use the given string value as a macro replacement (no macro parameters). */ 22 | definition_info(std::string value); 23 | /* Use the given string value as a macro replacement (no macro parameters). */ 24 | definition_info(const char* value); 25 | /* Use the given value as a macro replacement (no macro parameters). Will be converted to a string via std::to_string.*/ 26 | template()))> 27 | definition_info(const T& value) : definition_info(std::to_string(value)) {} 28 | /* Full initialization with parameters and an according macro replacement. */ 29 | definition_info(std::vector parameters, std::string replacement); 30 | 31 | /* The string that will be inserted and resolved when expanding the macro. */ 32 | std::string replacement; 33 | /* The macro's parameters. */ 34 | std::vector parameters; 35 | }; 36 | 37 | struct definition 38 | { 39 | definition() = default; 40 | /* Parameterless and valueless definition with a name. */ 41 | definition(const std::string& name); 42 | /* Full initialization with name and info. */ 43 | definition(const std::string& name, const definition_info& info); 44 | 45 | /* Parse string and construct definition from it. 46 | Format: MACRO(p0, p1, ..., pn) replacement */ 47 | static definition from_format(const std::string& str); 48 | 49 | /* Macro name written in code. */ 50 | std::string name; 51 | /* Macro info like replacement and parameters. */ 52 | definition_info info; 53 | }; 54 | } 55 | 56 | /* Calls and returns glsp::definition::from_format({def, def+len}). */ 57 | glsp::definition operator"" _gdef(const char* def, size_t len); -------------------------------------------------------------------------------- /external/glshader/include/glsp/glsp.hpp: -------------------------------------------------------------------------------- 1 | /*******************************************************************************/ 2 | /* File glsp.hpp 3 | /* Author Johannes Braun 4 | /* Created 01.04.2018 5 | /* 6 | /* All library files included once. 7 | /*******************************************************************************/ 8 | 9 | #pragma once 10 | 11 | #include "config.hpp" 12 | #include "preprocess.hpp" 13 | #include "compiler.hpp" 14 | #include "definition.hpp" 15 | #include "huffman.hpp" -------------------------------------------------------------------------------- /external/glshader/include/glsp/huffman.hpp: -------------------------------------------------------------------------------- 1 | /*******************************************************************************/ 2 | /* File huffman.hpp 3 | /* Author Johannes Braun 4 | /* Created 31.03.2018 5 | /* 6 | /* Provides helper functionality for compressing and uncompressing data using 7 | /* huffman trees. 8 | /*******************************************************************************/ 9 | 10 | #pragma once 11 | 12 | #include "config.hpp" 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | namespace glshader::process::compress::huffman 19 | { 20 | /* Tests a type on whether it is a container type by checking for a value_type type, as well as a resize(size_t) function and 21 | overloads for std::size(...) and std::data(...). */ 22 | template>> 23 | using enable_if_container = std::void_t< 24 | typename BaseContainer::value_type, 25 | decltype(std::declval().resize(size_t(0))), 26 | decltype(std::size(std::declval())), 27 | decltype(std::data(std::declval())) 28 | >; 29 | 30 | /* Contains a byte stream used when de-/encoding. 31 | For simple std::basic_string conversion, call stream.stringstream.str(), otherwise you can convert it 32 | to any other STL contiguous-storage container using to_container(). */ 33 | struct stream { 34 | size_t stream_length; 35 | std::basic_stringstream stringstream; 36 | 37 | template> 38 | std::decay_t> to_container() 39 | { 40 | using BaseContainer = std::decay_t>; 41 | BaseContainer container; 42 | container.resize(stream_length / sizeof(typename BaseContainer::value_type)); 43 | stringstream.read(reinterpret_cast(std::data(container)), std::size(container) * sizeof(typename BaseContainer::value_type)); 44 | return container; 45 | } 46 | }; 47 | 48 | /*******************************/ 49 | /* STL container wrapper 50 | /*******************************/ 51 | 52 | /* Helper function calling encode(const uint8_t*, size_t) */ 53 | template> 54 | stream encode(const Container& in) { return encode(std::data(in), std::size(in)); } 55 | 56 | /* Helper function calling decode(const uint8_t*, size_t) */ 57 | template> 58 | stream decode(const Container& in) { return decode(std::data(in), std::size(in)); } 59 | 60 | /*******************************/ 61 | /* Base functions 62 | /*******************************/ 63 | 64 | /* Encode a given uncompressed input with a given length into a compressed stream form using the huffman algorithm. */ 65 | stream encode(const uint8_t* in, size_t in_length); 66 | 67 | /* Encode a given compressed input with a given length into an uncompressed stream form using the huffman algorithm. */ 68 | stream decode(const uint8_t* in, size_t in_length); 69 | } -------------------------------------------------------------------------------- /external/glshader/include/glsp/preprocess.hpp: -------------------------------------------------------------------------------- 1 | /*******************************************************************************/ 2 | /* File preprocess.hpp 3 | /* Author Johannes Braun 4 | /* Created 30.03.2018 5 | /*******************************************************************************/ 6 | 7 | #pragma once 8 | 9 | #include "definition.hpp" 10 | #include "config.hpp" 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #ifndef ERR_OUTPUT 17 | #include 18 | #define ERR_OUTPUT(x) std::runtime_error(x) 19 | #endif 20 | 21 | namespace glshader::process 22 | { 23 | namespace files = std::filesystem; 24 | 25 | /* Refers to in-shader version declaration profile, e.g. #version 450 core/compatibility */ 26 | enum class shader_profile 27 | { 28 | core = 0, 29 | compatibility 30 | }; 31 | 32 | /* Refers to in-shader extension declarations, e.g. #extension GL_ARB_some_extension : enable */ 33 | enum class ext_behavior { 34 | enable = 0, 35 | require, 36 | warn, 37 | disable 38 | }; 39 | 40 | /* The file data after processing. */ 41 | struct processed_file 42 | { 43 | uint32_t version{ 0 }; /* GLSL Shader version in integral form (e.g. 450) or 0 if no version tag is found. */ 44 | shader_profile profile{ shader_profile::core }; /* GLSL Shader profile (core or compatibility) or core if none specified. */ 45 | files::path file_path; /* The original path of the loaded file. */ 46 | std::set dependencies; /* All files included while loading the shader. */ 47 | std::map extensions; /* All explicitly enabled/required glsl extensions. */ 48 | std::map definitions; /* All definitions which have been defined in the shader without being undefined afterwards. */ 49 | std::string contents; /* The fully processed shader code string. */ 50 | }; 51 | 52 | /* Loads and processes a shader file. 53 | If being called while having a valid OpenGL context, all available extension names will be loaded and checked against when compiling. 54 | Otherwise, extension related #if statements will always be evaluated as false. 55 | file_path -- The source file to load. 56 | include_directories -- A list of include directories to search in when parsing includes. 57 | definitions -- A list of predefined definitions. */ 58 | processed_file preprocess_file(const files::path& file_path, const std::vector& include_directories, const std::vector& definitions); 59 | 60 | /* Customizable function which is called when a syntax error was detected. 61 | You can redefine ERR_OUTPUT(str) in config.h. */ 62 | inline void syntax_error(const files::path& file, const int line, const std::string& reason) 63 | { 64 | ERR_OUTPUT("Error in " + file.string() + ":" + std::to_string(line) + ": " + reason); 65 | } 66 | 67 | /* A preprocessor state holding include directories and definitions. 68 | Can be used as a global default for when processing shaders, or as a slightly more flexible way to add definitions and include directories. */ 69 | class state 70 | { 71 | public: 72 | /* Add a persistent definition. */ 73 | void add_definition(const definition& d); 74 | /* Remove a persistent definition by it's name (without parameters, ect.!). */ 75 | void remove_definition(const std::string& name); 76 | 77 | /* Add a persistent include directory. */ 78 | void add_include_dir(const files::path& dir); 79 | /* Remove a persistent include directory. */ 80 | void remove_include_dir(const files::path& dir); 81 | 82 | /* Stacks all persistent include directories and definitions onto the ones passed as parameters (Therefore the need to copy), 83 | and calls the global glsp::preprocess_file function. */ 84 | processed_file preprocess_file(const files::path& file_path, std::vector include_directories ={}, std::vector definitions ={}); 85 | 86 | protected: 87 | std::vector _include_directories; 88 | std::vector _definitions; 89 | }; 90 | } 91 | #undef ERR_OUTPUT -------------------------------------------------------------------------------- /external/glshader/src/definition.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "preprocessor/skip.hpp" 4 | #include "preprocessor/classify.hpp" 5 | 6 | namespace glshader::process 7 | { 8 | definition_info::definition_info(const char* value) 9 | : definition_info(std::string(value)) 10 | { 11 | 12 | } 13 | 14 | definition_info::definition_info(const std::string value) : replacement(std::move(value)) 15 | {} 16 | 17 | definition_info::definition_info(const std::vector parameters, const std::string replacement) : 18 | replacement(std::move(replacement)), parameters(std::move(parameters)) 19 | {} 20 | 21 | definition::definition(const std::string& name) 22 | : name(name) 23 | { 24 | 25 | } 26 | 27 | definition::definition(const std::string& name, const definition_info& info) 28 | : name(name), info(info) 29 | { 30 | 31 | } 32 | 33 | definition definition::from_format(const std::string& str) 34 | { 35 | namespace skip = impl::skip; 36 | namespace cls = impl::classify; 37 | 38 | const char* begin = impl::skip::space(str.data()); 39 | const char* c = begin; 40 | while (!cls::is_eof(c) && !cls::is_space(c) && *c != '(') 41 | ++c; 42 | const char* end_name = c; 43 | c = skip::space(c); 44 | if (cls::is_eof(c)) 45 | return { begin, end_name }; 46 | if (*c == '(') 47 | { 48 | definition_info info; 49 | do 50 | { 51 | const char* begin_param = c=skip::space(++c); 52 | while (!cls::is_eof(c) && !cls::is_space(c) && *c!=',' && *c != ')') 53 | ++c; 54 | const char* end_param = c; 55 | 56 | info.parameters.emplace_back(begin_param, end_param); 57 | 58 | c = skip::space(c); 59 | } while (!cls::is_eof(c) && *c != ')'); 60 | c = !cls::is_eof(c) ? skip::space(++c) : c; 61 | info.replacement = std::string{ c, begin + str.size() }; 62 | return definition({ begin, end_name }, info); 63 | } 64 | else 65 | { 66 | return definition({ begin, end_name }, std::string{ c, begin + str.size() }); 67 | } 68 | } 69 | } 70 | 71 | glsp::definition operator"" _gdef(const char* def, size_t len) 72 | { 73 | return glsp::definition::from_format({ def, def+len }); 74 | } -------------------------------------------------------------------------------- /external/glshader/src/opengl/loader.cpp: -------------------------------------------------------------------------------- 1 | #include "loader.hpp" 2 | 3 | #include 4 | 5 | #ifdef _WIN32 6 | #include 7 | #else 8 | #include 9 | #endif 10 | 11 | namespace glshader::process::impl::loader 12 | { 13 | class function_loader 14 | { 15 | public: 16 | function_loader() 17 | { 18 | for (size_t i = 0; i < std::size(libs); ++i) { 19 | #ifdef _WIN32 20 | hnd = LoadLibraryA(libs[i]); 21 | #else 22 | hnd = dlopen(libs[i], RTLD_LAZY | RTLD_GLOBAL); 23 | #endif 24 | if (hnd != nullptr) 25 | break; 26 | } 27 | } 28 | 29 | void load_getters() noexcept 30 | { 31 | #ifdef __APPLE__ 32 | get_fun = nullptr; 33 | get_ctx_fun = reinterpret_cast(get_handle(hnd, "CGLGetCurrentContext")); 34 | #elif defined _WIN32 35 | get_fun = reinterpret_cast(get_handle(hnd, "wglGetProcAddress")); 36 | get_ctx_fun = reinterpret_cast(get_handle(hnd, "wglGetCurrentContext")); 37 | #else 38 | get_fun = reinterpret_cast(get_handle(hnd, "glXGetProcAddressARB")); 39 | get_ctx_fun = reinterpret_cast(get_handle(hnd, "glXGetCurrentContext")); 40 | #endif 41 | ctx = get_ctx_fun(); 42 | } 43 | 44 | bool valid() const 45 | { 46 | return ctx && ctx == get_ctx_fun(); 47 | } 48 | 49 | ~function_loader() 50 | { 51 | #ifdef _WIN32 52 | FreeLibrary(HMODULE(hnd)); 53 | #else 54 | dlclose(hnd); 55 | #endif 56 | } 57 | 58 | void* get(const char* name) const 59 | { 60 | void* addr = get_fun ? get_fun(name) : nullptr; 61 | return addr ? addr : get_handle(hnd, name); 62 | } 63 | 64 | private: 65 | void *hnd; 66 | void* ctx; 67 | 68 | void* get_handle(void* handle, const char* name) const 69 | { 70 | #if defined _WIN32 71 | return static_cast(GetProcAddress(static_cast(handle), name)); 72 | #else 73 | return dlsym(handle, name); 74 | #endif 75 | } 76 | 77 | void* (*get_fun)(const char*) = nullptr; 78 | void* (*get_ctx_fun)() = nullptr; 79 | 80 | #ifdef __APPLE__ 81 | constexpr static std::array libs ={ 82 | "../Frameworks/OpenGL.framework/OpenGL", 83 | "/Library/Frameworks/OpenGL.framework/OpenGL", 84 | "/System/Library/Frameworks/OpenGL.framework/OpenGL", 85 | "/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL" 86 | }; 87 | #elif defined _WIN32 88 | constexpr static std::array libs ={ "opengl32.dll" }; 89 | #else 90 | #if defined __CYGWIN__ 91 | constexpr static std::array libs ={ 92 | "libGL-1.so", 93 | #else 94 | constexpr static std::array libs ={ 95 | #endif 96 | "libGL.so.1", 97 | "libGL.so" 98 | }; 99 | #endif 100 | }; 101 | 102 | function_loader& get_loader() 103 | { 104 | static function_loader l; 105 | return l; 106 | } 107 | 108 | bool valid() noexcept 109 | { 110 | return get_loader().valid(); 111 | } 112 | 113 | void reload() noexcept 114 | { 115 | get_loader().load_getters(); 116 | } 117 | 118 | void* load_function(const char* name) noexcept 119 | { 120 | return get_loader().get(name); 121 | } 122 | } -------------------------------------------------------------------------------- /external/glshader/src/opengl/loader.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace glshader::process::impl::loader 6 | { 7 | void* load_function(const char* name) noexcept; 8 | bool valid() noexcept; 9 | void reload() noexcept; 10 | } -------------------------------------------------------------------------------- /external/glshader/src/preprocessor/classify.cpp: -------------------------------------------------------------------------------- 1 | #include "classify.hpp" 2 | #include "skip.hpp" 3 | 4 | #include 5 | #include 6 | 7 | namespace glshader::process::impl::classify 8 | { 9 | bool is_eof(const char* c) 10 | { 11 | return *c=='\0'; 12 | } 13 | 14 | bool is_newline(const char* c) 15 | { 16 | return *c=='\n' || *c=='\r'; 17 | } 18 | 19 | bool is_comment(const char* c) 20 | { 21 | return strncmp(c, "//", 2) == 0 || strncmp(c, "/*", 2) == 0; 22 | } 23 | 24 | bool is_space(const char* c) 25 | { 26 | return *c==' ' || *c=='\t'; 27 | } 28 | 29 | bool is_name_char(const char* c) 30 | { 31 | return isalnum(*c) || *c=='_'; 32 | } 33 | 34 | bool is_directive(const char* c, bool check_before) 35 | { 36 | return *c=='#' && (!check_before || is_newline(skip::space_rev(c - 1))); 37 | } 38 | 39 | bool is_token_equal(const char* c, const char* token, int token_len, bool check_before, bool check_after) 40 | { 41 | return (!check_before || !isalpha(*(c - 1))) && 42 | (memcmp(c, token, token_len) == 0) && 43 | (!check_after || !is_name_char(c + token_len)); 44 | 45 | } 46 | } -------------------------------------------------------------------------------- /external/glshader/src/preprocessor/classify.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace glshader::process::impl::classify 4 | { 5 | bool is_eof (const char* c); 6 | bool is_newline (const char* c); 7 | bool is_comment (const char* c); 8 | bool is_space (const char* c); 9 | bool is_name_char (const char* c); 10 | bool is_directive (const char* c, bool check_before = true); 11 | bool is_token_equal (const char* c, const char* token, int token_len, bool check_before = true, bool check_after = true); 12 | } -------------------------------------------------------------------------------- /external/glshader/src/preprocessor/control.cpp: -------------------------------------------------------------------------------- 1 | #include "control.hpp" 2 | 3 | namespace glshader::process::impl::control 4 | { 5 | 6 | std::string line_directive(const files::path& file, int line) 7 | { 8 | return "\n#line " + std::to_string(line) + " \"" + file.filename().string() + "\"\n"; 9 | } 10 | 11 | void increment_line(int& current_line, processed_file& processed) 12 | { 13 | processed.definitions["__LINE__"] = ++current_line; 14 | } 15 | } -------------------------------------------------------------------------------- /external/glshader/src/preprocessor/control.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "files.hpp" 4 | #include 5 | 6 | namespace glshader::process::impl::control 7 | { 8 | std::string line_directive(const files::path& file, int line); 9 | void increment_line(int& current_line, processed_file& processed); 10 | } -------------------------------------------------------------------------------- /external/glshader/src/preprocessor/eval.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "files.hpp" 4 | 5 | namespace glshader::process::impl::operation 6 | { 7 | /*** 8 | Takes a const char* substring with a given length and tries to evaluate it's value. 9 | Evaluates arithmetical, logical and comparison operations on integral values. 10 | ***/ 11 | int eval(const char* x, int len, const files::path& current_file, const int current_line); 12 | } -------------------------------------------------------------------------------- /external/glshader/src/preprocessor/extensions.cpp: -------------------------------------------------------------------------------- 1 | #include "extensions.hpp" 2 | #include 3 | #include 4 | 5 | namespace glshader::process::impl::ext 6 | { 7 | std::set _extensions; 8 | void enable_extension(const char* extension) 9 | { 10 | _extensions.emplace(extension); 11 | } 12 | 13 | bool extension_available(const std::string& extension) 14 | { 15 | return _extensions.count(extension) != 0; 16 | } 17 | 18 | const std::set& extensions() noexcept 19 | { 20 | return _extensions; 21 | } 22 | } -------------------------------------------------------------------------------- /external/glshader/src/preprocessor/extensions.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace glshader::process::impl::ext 7 | { 8 | void enable_extension(const char* extension); 9 | bool extension_available(const std::string& extension); 10 | const std::set& extensions() noexcept; 11 | } -------------------------------------------------------------------------------- /external/glshader/src/preprocessor/files.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace glshader::process 6 | { 7 | namespace files = std::filesystem; 8 | } -------------------------------------------------------------------------------- /external/glshader/src/preprocessor/macro.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "files.hpp" 4 | #include 5 | 6 | namespace glshader::process::impl::macro 7 | { 8 | bool is_defined(const std::string& val, const processed_file& processed); 9 | bool is_macro(const char* text_ptr, processed_file& processed); 10 | std::string expand(const char* text_ptr, const char* & text_ptr_after, const files::path& current_file, int current_line, processed_file& processed); 11 | } -------------------------------------------------------------------------------- /external/glshader/src/preprocessor/skip.cpp: -------------------------------------------------------------------------------- 1 | #include "skip.hpp" 2 | 3 | #include "classify.hpp" 4 | #include "control.hpp" 5 | 6 | #include 7 | #include 8 | 9 | namespace glshader::process::impl::skip 10 | { 11 | const char* space(const char* c) 12 | { 13 | while (classify::is_space(c) && !classify::is_eof(c)) ++c; 14 | return c; 15 | } 16 | 17 | const char* space_rev(const char* c) 18 | { 19 | while (classify::is_space(c)) --c; 20 | return c; 21 | } 22 | 23 | const char* to_next_space(const char* c) 24 | { 25 | using namespace classify; 26 | while (!is_space(c) && !is_newline(c) && !is_eof(c)) 27 | ++c; 28 | return c; 29 | } 30 | 31 | const char* to_next_space(const char* c, char alt) 32 | { 33 | using namespace classify; 34 | while (!is_space(c) && !is_newline(c) && !is_eof(c) && *c != alt) 35 | ++c; 36 | return c; 37 | } 38 | 39 | const char* to_endline(const char* c) 40 | { 41 | using namespace classify; 42 | while (!is_newline(c) && !is_eof(c)) 43 | ++c; 44 | return c; 45 | } 46 | 47 | const char* to_next_token(const char* c) 48 | { 49 | return space(to_next_space(c)); 50 | } 51 | 52 | const char* over_comments(const char* text_ptr, const files::path& file, int& line, processed_file& processed, std::stringstream& result) 53 | { 54 | if (strncmp(text_ptr, "//", 2) == 0) 55 | { 56 | while (!classify::is_newline(text_ptr) && classify::is_eof(text_ptr)) 57 | ++text_ptr; 58 | } 59 | else if (strncmp(text_ptr, "/*", 2) == 0) 60 | { 61 | while (strncmp(text_ptr, "*/", 2) != 0) 62 | { 63 | if (classify::is_newline(text_ptr)) 64 | control::increment_line(line, processed); 65 | ++text_ptr; 66 | } 67 | 68 | text_ptr += 2; 69 | if (processed.version != -1) 70 | result << control::line_directive(file, line); 71 | } 72 | return text_ptr; 73 | } 74 | } -------------------------------------------------------------------------------- /external/glshader/src/preprocessor/skip.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "files.hpp" 4 | #include 5 | 6 | namespace glshader::process::impl::skip 7 | { 8 | const char* space (const char* c); 9 | const char* space_rev (const char* c); 10 | const char* to_next_space (const char* c); 11 | const char* to_next_space (const char* c, char alt); 12 | const char* to_endline (const char* c); 13 | const char* to_next_token (const char* c); 14 | const char* over_comments (const char* text_ptr, const files::path& file, int& line, processed_file& processed, std::stringstream& result); 15 | } -------------------------------------------------------------------------------- /external/glshader/src/strings.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace glshader::process 4 | { 5 | template 6 | std::string strfmt(const std::string& format, Args ... args) 7 | { 8 | size_t size = std::snprintf(nullptr, 0, format.c_str(), args...) + 1; 9 | std::string buf; 10 | buf.resize(size); 11 | std::snprintf(buf.data(), size, format.c_str(), args...); 12 | return buf; 13 | } 14 | 15 | namespace strings 16 | { 17 | constexpr const char* serr_unrecognized_profile = "Unrecognized #version profile: %s. Using core."; 18 | constexpr const char* serr_extension_all_behavior = "Cannot use #extension behavior \"%s\", must be \"warn\" or \"disable\"."; 19 | constexpr const char* serr_extension_behavior = "Unrecognized #extension behavior \"%s\", must be \"require\", \"enable\", \"warn\" or \"disable\"."; 20 | constexpr const char* serr_no_endif_else = "No closing #endif or #else found for if-expression in line %i."; 21 | constexpr const char* serr_no_endif = "No closing #endif found."; 22 | constexpr const char* serr_invalid_line = "Invalid line directive, did not find closing \"."; 23 | constexpr const char* serr_invalid_include = "Include must be in \"...\" or <...>."; 24 | constexpr const char* serr_file_not_found = "File not found: %s"; 25 | constexpr const char* serr_eval_end_of_brackets = "Unexpected end of brackets."; 26 | constexpr const char* serr_non_matching_argc = "Macro %s: non-matching argument count."; 27 | 28 | constexpr const char* serr_loader_failed = "Unable to load required OpenGL functions. Please check whether the current context is valid and supports GL_ARB_separate_shader_objects."; 29 | constexpr const char* serr_unsupported = "%s is currently not supported."; 30 | } 31 | } -------------------------------------------------------------------------------- /external/imgui/imconfig.h: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // COMPILE-TIME OPTIONS FOR DEAR IMGUI 3 | // Runtime options (clipboard callbacks, enabling various features, etc.) can generally be set via the ImGuiIO structure. 4 | // You can use ImGui::SetAllocatorFunctions() before calling ImGui::CreateContext() to rewire memory allocation functions. 5 | //----------------------------------------------------------------------------- 6 | // A) You may edit imconfig.h (and not overwrite it when updating imgui, or maintain a patch/branch with your modifications to imconfig.h) 7 | // B) or add configuration directives in your own file and compile with #define IMGUI_USER_CONFIG "myfilename.h" 8 | // C) Many compile-time options have an effect on data structures. They need defined consistently _everywhere_ imgui.h is included, 9 | // not only for the imgui*.cpp compilation units. Defining those options in imconfig.h will ensure they correctly get used everywhere. 10 | //----------------------------------------------------------------------------- 11 | 12 | #pragma once 13 | 14 | //---- Define assertion handler. Defaults to calling assert(). 15 | //#define IM_ASSERT(_EXPR) MyAssert(_EXPR) 16 | 17 | //---- Define attributes of all API symbols declarations, e.g. for DLL under Windows. 18 | //#define IMGUI_API __declspec( dllexport ) 19 | //#define IMGUI_API __declspec( dllimport ) 20 | 21 | //---- Don't define obsolete functions/enums names. Consider enabling from time to time after updating to avoid using soon-to-be obsolete function/names 22 | //#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS 23 | 24 | //---- Don't implement default handlers for Windows (so as not to link with certain functions) 25 | //#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // Don't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. 26 | //#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // Don't use and link with ImmGetContext/ImmSetCompositionWindow. 27 | 28 | //---- Don't implement demo windows functionality (ShowDemoWindow()/ShowStyleEditor()/ShowUserGuide() methods will be empty) 29 | //---- It is very strongly recommended to NOT disable the demo windows during development. Please read the comments in imgui_demo.cpp. 30 | //#define IMGUI_DISABLE_DEMO_WINDOWS 31 | 32 | //---- Don't implement ImFormatString(), ImFormatStringV() so you can reimplement them yourself. 33 | //#define IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS 34 | 35 | //---- Include imgui_user.h at the end of imgui.h as a convenience 36 | //#define IMGUI_INCLUDE_IMGUI_USER_H 37 | 38 | //---- Pack colors to BGRA8 instead of RGBA8 (if you needed to convert from one to another anyway) 39 | //#define IMGUI_USE_BGRA_PACKED_COLOR 40 | 41 | //---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version 42 | // By default the embedded implementations are declared static and not available outside of imgui cpp files. 43 | //#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h" 44 | //#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h" 45 | //#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION 46 | //#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION 47 | 48 | //---- Define constructor and implicit cast operators to convert back<>forth from your math types and ImVec2/ImVec4. 49 | // This will be inlined as part of ImVec2 and ImVec4 class declarations. 50 | /* 51 | #define IM_VEC2_CLASS_EXTRA \ 52 | ImVec2(const MyVec2& f) { x = f.x; y = f.y; } \ 53 | operator MyVec2() const { return MyVec2(x,y); } 54 | 55 | #define IM_VEC4_CLASS_EXTRA \ 56 | ImVec4(const MyVec4& f) { x = f.x; y = f.y; z = f.z; w = f.w; } \ 57 | operator MyVec4() const { return MyVec4(x,y,z,w); } 58 | */ 59 | 60 | //---- Use 32-bit vertex indices (default is 16-bit) to allow meshes with more than 64K vertices. Render function needs to support it. 61 | //#define ImDrawIdx unsigned int 62 | 63 | //---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files. 64 | /* 65 | namespace ImGui 66 | { 67 | void MyFunction(const char* name, const MyMatrix44& v); 68 | } 69 | */ 70 | -------------------------------------------------------------------------------- /external/imgui/imgui_impl_glfw_gl3.h: -------------------------------------------------------------------------------- 1 | // ImGui GLFW binding with OpenGL3 + shaders 2 | // (GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.) 3 | // (GL3W is a helper library to access OpenGL functions since there is no standard header to access modern OpenGL functions easily. Alternatives are GLEW, Glad, etc.) 4 | 5 | // Implemented features: 6 | // [X] User texture binding. Cast 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. 7 | // [X] Gamepad navigation mapping. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. 8 | 9 | // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. 10 | // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). 11 | // If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. 12 | // https://github.com/ocornut/imgui 13 | 14 | struct GLFWwindow; 15 | 16 | IMGUI_API bool ImGui_ImplGlfwGL3_Init(GLFWwindow* window, bool install_callbacks, const char* glsl_version = NULL); 17 | IMGUI_API void ImGui_ImplGlfwGL3_Shutdown(); 18 | IMGUI_API void ImGui_ImplGlfwGL3_NewFrame(); 19 | IMGUI_API void ImGui_ImplGlfwGL3_RenderDrawData(ImDrawData* draw_data); 20 | 21 | // Use if you want to reset your rendering device without losing ImGui state. 22 | IMGUI_API void ImGui_ImplGlfwGL3_InvalidateDeviceObjects(); 23 | IMGUI_API bool ImGui_ImplGlfwGL3_CreateDeviceObjects(); 24 | 25 | // GLFW callbacks (installed by default if you enable 'install_callbacks' during initialization) 26 | // Provided here if you want to chain callbacks. 27 | // You can also handle inputs yourself and use those as a reference. 28 | IMGUI_API void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods); 29 | IMGUI_API void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset); 30 | IMGUI_API void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods); 31 | IMGUI_API void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c); 32 | -------------------------------------------------------------------------------- /libraries/IO/ModelImporter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | #include "Rendering/Mesh.h" 12 | #include "Rendering/Texture.h" 13 | #include "Rendering/Uniform.h" 14 | #include "Rendering/Camera.h" 15 | #include "Rendering/ShaderProgram.h" 16 | 17 | class ShaderProgram; 18 | 19 | struct PhongGPUMaterial 20 | { 21 | uint64_t diffTexture = -1; 22 | uint64_t specTexture = -1; 23 | uint64_t opacityTexture = -1; 24 | float opacity = 1.0f; 25 | float Ns = -1.0f; 26 | glm::vec4 diffColor; 27 | glm::vec4 specColor; 28 | glm::vec4 emissiveColor; 29 | uint64_t bumpTexture = -1; 30 | int bumpType = 0; //0 = no bump, 1 = normal map, 2 = height map 31 | float pad1 = 0.f; 32 | }; 33 | 34 | struct Indirect 35 | { 36 | unsigned count; 37 | unsigned instanceCount; 38 | unsigned firstIndex; 39 | unsigned baseVertex; 40 | unsigned baseInstance; 41 | }; 42 | 43 | class ModelImporter 44 | { 45 | public: 46 | static std::vector> loadAllMeshesFromFile(const std::filesystem::path& filename); 47 | 48 | explicit ModelImporter(const std::filesystem::path& filename); 49 | 50 | std::vector> getMeshes() const; 51 | 52 | void bindGPUbuffers() const; 53 | 54 | void draw(const ShaderProgram& sp) const; 55 | void drawCulled(const ShaderProgram& sp, const glm::mat4& view, float angle, float ratio, float near, float far) const; 56 | 57 | void multiDraw(const ShaderProgram& sp) const; 58 | void multiDrawCulled(const ShaderProgram & sp, const glm::mat4 & viewProjection) const; 59 | 60 | void registerUniforms(ShaderProgram& sp) const; 61 | void resetIndirectDrawParams(); 62 | 63 | glm::mat2x4 getOuterBoundingBox() const; 64 | 65 | private: 66 | Assimp::Importer m_importer; 67 | const aiScene* m_scene; 68 | std::vector> m_meshes; 69 | std::unordered_map> m_texturemap; 70 | std::vector m_gpuMaterials; 71 | Buffer m_gpuMaterialBuffer; 72 | 73 | std::vector m_gpuMaterialIndices; 74 | Buffer m_gpuMaterialIndicesBuffer; 75 | 76 | std::vector m_modelMatrices; 77 | Buffer m_modelMatrixBuffer; 78 | 79 | std::shared_ptr> m_meshIndexUniform; 80 | std::shared_ptr> m_materialIndexUniform; 81 | 82 | // multi-draw buffers 83 | std::vector m_allTheIndices; 84 | std::vector m_allTheVertices; 85 | std::vector m_allTheNormals; 86 | std::vector m_allTheTexCoords; 87 | 88 | std::vector m_indirectDrawParams; 89 | Buffer m_indirectDrawBuffer; 90 | 91 | Buffer m_multiDrawIndexBuffer; 92 | Buffer m_multiDrawVertexBuffer; 93 | Buffer m_multiDrawNormalBuffer; 94 | Buffer m_multiDrawTexCoordBuffer; 95 | VertexArray m_multiDrawVao; 96 | 97 | glm::mat2x4 m_outerBoundingBox; 98 | 99 | // culling stuff 100 | std::vector m_boundingBoxes; 101 | Buffer m_boundingBoxBuffer; 102 | std::shared_ptr> m_viewProjUniform; 103 | ShaderProgram m_cullingProgram; 104 | }; 105 | -------------------------------------------------------------------------------- /libraries/Rendering/Binding.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "glsp/glsp.hpp" 4 | 5 | namespace BufferBindings 6 | { 7 | enum class Binding : int 8 | { 9 | cameraParameters = 7, 10 | lights = 8, 11 | materials = 9, 12 | modelMatrices = 10, 13 | materialIndices = 11 14 | }; 15 | 16 | enum class VertexAttributeLocation : int 17 | { 18 | vertices = 0, 19 | normals = 1, 20 | texCoords = 2 21 | }; 22 | 23 | enum class Subroutine : int 24 | { 25 | multiDraw = 0, 26 | normalDraw = 1 27 | }; 28 | 29 | inline std::vector g_definitions = { 30 | glsp::definition("CAMERA_BINDING", static_cast(Binding::cameraParameters)), 31 | glsp::definition("LIGHTS_BINDING", static_cast(Binding::lights)), 32 | glsp::definition("MATERIAL_BINDING", static_cast(Binding::materials)), 33 | glsp::definition("MODELMATRICES_BINDING", static_cast(Binding::modelMatrices)), 34 | glsp::definition("MATERIAL_INDICES_BINDING", static_cast(Binding::materialIndices)), 35 | 36 | 37 | glsp::definition("VERTEX_LAYOUT", static_cast(VertexAttributeLocation::vertices)), 38 | glsp::definition("NORMAL_LAYOUT", static_cast(VertexAttributeLocation::normals)), 39 | glsp::definition("TEXCOORD_LAYOUT", static_cast(VertexAttributeLocation::texCoords)) 40 | 41 | }; 42 | } 43 | 44 | -------------------------------------------------------------------------------- /libraries/Rendering/Buffer.cpp: -------------------------------------------------------------------------------- 1 | #include "Buffer.h" 2 | 3 | #include "Utils/UtilCollection.h" 4 | #include 5 | 6 | Buffer::Buffer(GLenum target) : m_target(target) 7 | { 8 | glCreateBuffers(1, &m_bufferHandle); 9 | } 10 | 11 | Buffer::~Buffer() 12 | { 13 | if (glfwGetCurrentContext() != nullptr) 14 | { 15 | glDeleteBuffers(1, &m_bufferHandle); 16 | } 17 | if constexpr (util::debugmode) 18 | { 19 | util::getGLerror(__LINE__, __FUNCTION__); 20 | std::cout << "buffer destructor called" << std::endl; 21 | } 22 | } 23 | 24 | GLuint Buffer::getHandle() const 25 | { 26 | return m_bufferHandle; 27 | } 28 | 29 | GLenum Buffer::getTarget() const 30 | { 31 | return m_target; 32 | } 33 | 34 | size_t Buffer::getTypeSize() const 35 | { 36 | return m_typeSize; 37 | } 38 | 39 | void Buffer::bindBase(unsigned int binding) const 40 | { 41 | glBindBufferBase(m_target, binding, m_bufferHandle); 42 | } 43 | 44 | void Buffer::bindBase(BufferBindings::Binding binding) const 45 | { 46 | glBindBufferBase(m_target, static_cast(binding), m_bufferHandle); 47 | } 48 | 49 | void Buffer::unmapBuffer() const 50 | { 51 | glUnmapNamedBuffer(m_bufferHandle); 52 | } 53 | -------------------------------------------------------------------------------- /libraries/Rendering/Camera.cpp: -------------------------------------------------------------------------------- 1 | #include "Camera.h" 2 | 3 | #include 4 | #include 5 | #include "imgui/imgui.h" 6 | 7 | Camera::Camera(int width, int height) : m_width(width), m_height(height) 8 | { 9 | m_sensitivity = 0.1f; 10 | 11 | Camera::reset(); 12 | } 13 | 14 | void Camera::reset() 15 | { 16 | m_pos = glm::vec3(0.0f); 17 | m_center = glm::vec3(0.0f); 18 | m_up = glm::vec3(0.0f, 1.0f, 0.0f); 19 | 20 | m_theta = glm::pi() / 2.0f; 21 | m_phi = 0.f; 22 | m_viewMatrix = lookAt(m_pos, m_center, m_up); 23 | m_oldX = m_width / 2.f; 24 | m_oldY = m_height / 2.f; 25 | } 26 | 27 | void Camera::update(GLFWwindow* window) 28 | { 29 | if (!ImGui::GetIO().WantCaptureMouse) 30 | { 31 | double x, y; 32 | glfwGetCursorPos(window, &x, &y); 33 | if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS) 34 | { 35 | const float changeX = (static_cast(x) - m_oldX) * 0.01f; 36 | const float changeY = (static_cast(y) - m_oldY) * 0.01f; 37 | 38 | m_theta -= changeY; 39 | if (m_theta < 0.01f) 40 | { 41 | m_theta = 0.01f; 42 | } 43 | else if (m_theta > glm::pi() - 0.01f) 44 | { 45 | m_theta = glm::pi() - 0.01f; 46 | } 47 | 48 | m_phi -= changeX; 49 | if (m_phi < 0) 50 | { 51 | m_phi += 2 * glm::pi(); 52 | } 53 | else if (m_phi > 2 * glm::pi()) 54 | { 55 | m_phi -= 2 * glm::pi(); 56 | } 57 | } 58 | 59 | m_oldX = static_cast(x); 60 | m_oldY = static_cast(y); 61 | } 62 | } 63 | 64 | const glm::mat4& Camera::getView() const 65 | { 66 | return m_viewMatrix; 67 | } 68 | 69 | glm::mat4& Camera::getView() 70 | { 71 | return m_viewMatrix; 72 | } 73 | 74 | glm::vec3 Camera::getPosition() const 75 | { 76 | return m_pos; 77 | } 78 | 79 | glm::vec3 Camera::getCenter() const 80 | { 81 | return m_center; 82 | } 83 | 84 | glm::vec3 Camera::getDirection() const 85 | { 86 | return glm::normalize(m_center - m_pos); 87 | } 88 | 89 | void Camera::setPosition(glm::vec3 pos) 90 | { 91 | m_pos = pos; 92 | } 93 | 94 | void Camera::setTheta(float theta) 95 | { 96 | m_theta = theta; 97 | } 98 | 99 | void Camera::setPhi(float phi) 100 | { 101 | m_phi = phi; 102 | } 103 | 104 | void Camera::setSensitivity(float sensitivity) 105 | { 106 | m_sensitivity = sensitivity; 107 | } 108 | 109 | void Camera::setSensitivityFromBBox(glm::mat2x4 bbox) 110 | { 111 | m_sensitivity = 0.001f * glm::length(bbox[1] - bbox[0]); 112 | } 113 | -------------------------------------------------------------------------------- /libraries/Rendering/Camera.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | using namespace gl; 5 | #include 6 | #include 7 | 8 | struct FrustumGeo 9 | { 10 | enum Plane 11 | { 12 | TOP = 0, BOTTOM = 1, LEFT = 2, 13 | RIGHT = 3, NEAR = 4, FAR = 5 14 | }; 15 | 16 | std::array normals; 17 | std::array points; 18 | 19 | // the function setNormalFromPoints assumes that the points 20 | // are given in counter clockwise order 21 | void setNormalFromPoints(Plane plane, glm::vec3 v1, glm::vec3 v2, glm::vec3 v3) 22 | { 23 | normals[plane] = glm::normalize(glm::cross(v3 - v2, v1 - v2)); 24 | } 25 | 26 | // gets the smallest distance from a point to a plane 27 | float distance(int plane, const glm::vec3& p) 28 | { 29 | return glm::dot(normals[plane], p - points[plane]); 30 | } 31 | }; 32 | 33 | class Camera 34 | { 35 | public: 36 | Camera(int width, int height); 37 | 38 | /** 39 | * \brief Updates the view matrix based on mouse input 40 | * \param window 41 | */ 42 | virtual void update(GLFWwindow* window) = 0; 43 | 44 | virtual void reset(); 45 | 46 | /** 47 | * \brief returns the view matrix (const) 48 | * \return 4x4 view matrix (const) 49 | */ 50 | const glm::mat4& getView() const; 51 | 52 | /** 53 | * \brief returns the view matrix (mutable) 54 | * \return 4x4 view matrix 55 | */ 56 | glm::mat4& getView(); 57 | 58 | virtual glm::vec3 getPosition() const; 59 | virtual glm::vec3 getCenter() const; 60 | virtual glm::vec3 getDirection() const; 61 | 62 | void setPosition(glm::vec3 pos); 63 | void setTheta(float theta); 64 | void setPhi(float phi); 65 | void setSensitivity(float sensitivity); 66 | void setSensitivityFromBBox(glm::mat2x4 bbox); 67 | 68 | virtual ~Camera() = default; 69 | 70 | protected: 71 | glm::mat4 m_viewMatrix; 72 | glm::vec3 m_center; 73 | glm::vec3 m_pos; 74 | glm::vec3 m_up; 75 | 76 | int m_width; 77 | int m_height; 78 | 79 | float m_sensitivity; 80 | float m_theta; 81 | float m_phi; 82 | float m_oldX; 83 | float m_oldY; 84 | }; 85 | -------------------------------------------------------------------------------- /libraries/Rendering/Cubemap.cpp: -------------------------------------------------------------------------------- 1 | #include "Cubemap.h" 2 | #include "stb/stb_image.h" 3 | #include 4 | 5 | Cubemap::Cubemap(GLenum minFilter, GLenum maxFilter) : Texture(GL_TEXTURE_CUBE_MAP, minFilter, maxFilter) 6 | { 7 | } 8 | 9 | void Cubemap::initWithoutData(int width, int height, GLenum internalFormat, GLenum format, GLenum type, int levels) // TODO fix unused params 10 | { 11 | glTextureStorage2D(m_name, levels, internalFormat, width, height); 12 | m_width = width; 13 | m_height = height; 14 | 15 | glTextureParameteri(m_name, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 16 | glTextureParameteri(m_name, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 17 | glTextureParameteri(m_name, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); 18 | glTextureParameteri(m_name, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 19 | glTextureParameteri(m_name, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 20 | 21 | //for (int face = 0; face < 6; face++) 22 | //{ 23 | // glTextureSubImage3D( 24 | // m_name, 25 | // 0, // only 1 level in example 26 | // 0, 27 | // 0, 28 | // face, // the offset to desired cubemap face, which offset goes to which face above 29 | // width, 30 | // height, 31 | // 1, // depth how many faces to set, if this was 3 we'd set 3 cubemap faces at once 32 | // format, 33 | // type, 34 | // nullptr); 35 | //} 36 | } 37 | 38 | TextureLoadInfo Cubemap::loadFromFile(const std::filesystem::path& texturePath, GLenum internalFormat, GLenum format, GLenum type, int desiredChannels) 39 | { 40 | // load the first image to get the width, height 41 | std::string path(texturePath.string()); 42 | path.insert(path.cbegin() + path.find_last_of('.'), 1, '0'); // image.png -> image1.png 43 | 44 | stbi_set_flip_vertically_on_load(false); 45 | int imageWidth, imageHeight, numChannels; 46 | auto imageData = stbi_load(path.c_str(), &imageWidth, &imageHeight, &numChannels, desiredChannels); 47 | 48 | if (!imageData) 49 | throw std::runtime_error("Cubemap Image couldn't be loaded"); 50 | 51 | m_width = imageWidth; 52 | m_height = imageHeight; 53 | 54 | const auto numLevels = static_cast(glm::ceil(glm::log2(static_cast(glm::max(imageWidth, imageHeight))))); 55 | glTextureStorage2D(m_name, numLevels, internalFormat, imageWidth, imageHeight); 56 | 57 | glTextureParameteri(m_name, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 58 | glTextureParameteri(m_name, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 59 | glTextureParameteri(m_name, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); 60 | 61 | // load the data for all faces 62 | for (int face = 0; face < 6; face++) 63 | { 64 | // face: 65 | // 0 = positive x face 66 | // 1 = negative x face 67 | // 2 = positive y face 68 | // 3 = negative y face 69 | // 4 = positive z face 70 | // 5 = negative z face 71 | 72 | path = texturePath.string(); 73 | path.insert(path.cbegin() + path.find_last_of('.'), 1, std::to_string(face).c_str()[0]); // image.png -> image1.png, image2.png, ... 74 | 75 | imageData = stbi_load(path.c_str(), &imageWidth, &imageHeight, &numChannels, 4); 76 | 77 | if (!imageData) 78 | { 79 | std::stringstream ss; 80 | ss << "Cubemap Image " << face << " couldn't be loaded"; 81 | throw std::runtime_error(ss.str()); 82 | } 83 | 84 | glTextureSubImage3D( 85 | m_name, 86 | 0, // only 1 level in example 87 | 0, 88 | 0, 89 | face, // the offset to desired cubemap face, which offset goes to which face above 90 | imageWidth, 91 | imageHeight, 92 | 1, // depth how many faces to set, if this was 3 we'd set 3 cubemap faces at once 93 | format, 94 | type, 95 | imageData); 96 | 97 | // let the cpu data of the image go 98 | stbi_image_free(imageData); 99 | } 100 | 101 | glGenerateTextureMipmap(m_name); 102 | 103 | m_textureLoadInfo = TextureLoadInfo::Other; 104 | return m_textureLoadInfo; 105 | } 106 | -------------------------------------------------------------------------------- /libraries/Rendering/Cubemap.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Texture.h" 4 | 5 | class Cubemap : public Texture 6 | { 7 | public: 8 | explicit Cubemap(GLenum minFilter = GL_LINEAR, GLenum maxFilter = GL_LINEAR); 9 | TextureLoadInfo loadFromFile(const std::filesystem::path& texturePath, GLenum internalFormat = GL_RGBA8, GLenum format = GL_RGBA, GLenum type = GL_UNSIGNED_BYTE, int desiredChannels = 4) override; 10 | void initWithoutData(int width, int height, GLenum internalFormat, GLenum format, GLenum type, int levels = 1); 11 | }; 12 | -------------------------------------------------------------------------------- /libraries/Rendering/FrameBuffer.cpp: -------------------------------------------------------------------------------- 1 | #include "FrameBuffer.h" 2 | #include 3 | #include "Utils/UtilCollection.h" 4 | 5 | FrameBuffer::FrameBuffer(const std::vector>& rendertargets, const bool useDepthStencil, const GLenum renderbufferFormat, int samples) 6 | { 7 | glCreateFramebuffers(1, &m_name); 8 | bind(); 9 | int attachmentNumber = 0; 10 | for (const auto& texture : rendertargets) 11 | { 12 | glNamedFramebufferTexture(m_name, GL_COLOR_ATTACHMENT0 + attachmentNumber, texture->getName(), 0); 13 | attachmentNumber++; 14 | } 15 | auto fboStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER); 16 | if (fboStatus != GL_FRAMEBUFFER_COMPLETE) 17 | throw std::runtime_error("Framebuffer is not complete!"); 18 | if (useDepthStencil && samples == 0) 19 | { 20 | attachDepthStencil(rendertargets.at(0)->getWidth(), rendertargets.at(0)->getHeight(), renderbufferFormat); 21 | } 22 | else if (useDepthStencil && samples > 0) 23 | { 24 | attachDepthStencilMultiSample(rendertargets.at(0)->getWidth(), rendertargets.at(0)->getHeight(), samples, renderbufferFormat); 25 | } 26 | fboStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER); 27 | if (fboStatus != GL_FRAMEBUFFER_COMPLETE) 28 | throw std::runtime_error("Framebuffer is not complete!"); 29 | unbind(); 30 | } 31 | 32 | FrameBuffer::FrameBuffer(GLenum attachmentType, const Texture& depthAttachment) 33 | { 34 | if (attachmentType != GL_DEPTH_ATTACHMENT) 35 | throw std::runtime_error("This constructor is for using depth textures only"); 36 | 37 | glCreateFramebuffers(1, &m_name); 38 | bind(); 39 | glNamedFramebufferTexture(m_name, GL_DEPTH_ATTACHMENT, depthAttachment.getName(), 0); 40 | glDrawBuffer(GL_NONE); 41 | glReadBuffer(GL_NONE); 42 | unbind(); 43 | } 44 | 45 | FrameBuffer::FrameBuffer(const int width, const int height, const bool useDepthStencil, const GLenum renderbufferFormat) 46 | { 47 | glCreateFramebuffers(1, &m_name); 48 | if (useDepthStencil) 49 | { 50 | attachDepthStencil(width, height, renderbufferFormat); 51 | } 52 | } 53 | 54 | FrameBuffer::~FrameBuffer() 55 | { 56 | if (glfwGetCurrentContext() != nullptr) 57 | { 58 | glDeleteFramebuffers(1, &m_name); 59 | } 60 | util::getGLerror(__LINE__, __FUNCTION__); 61 | } 62 | 63 | void FrameBuffer::bind() const 64 | { 65 | glBindFramebuffer(GL_FRAMEBUFFER, m_name); 66 | } 67 | 68 | void FrameBuffer::unbind() const 69 | { 70 | glBindFramebuffer(GL_FRAMEBUFFER, 0); 71 | } 72 | 73 | GLuint FrameBuffer::getName() const 74 | { 75 | return m_name; 76 | } 77 | 78 | void FrameBuffer::attachDepthStencil(const int width, const int height, const GLenum renderbufferFormat) 79 | { 80 | glCreateRenderbuffers(1, &m_rbo); 81 | glNamedRenderbufferStorage(m_rbo, renderbufferFormat, width, height); 82 | if (renderbufferFormat == GL_DEPTH_COMPONENT16 || renderbufferFormat == GL_DEPTH_COMPONENT24 || renderbufferFormat == GL_DEPTH_COMPONENT32) 83 | glNamedFramebufferRenderbuffer(m_name, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_rbo); 84 | else 85 | glNamedFramebufferRenderbuffer(m_name, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_rbo); 86 | } 87 | 88 | void FrameBuffer::attachDepthStencilMultiSample(const int width, const int height, const int samples, const GLenum renderbufferFormat) 89 | { 90 | glCreateRenderbuffers(1, &m_rbo); 91 | glNamedRenderbufferStorageMultisample(m_rbo, 4, renderbufferFormat, width, height); 92 | if (renderbufferFormat == GL_DEPTH_COMPONENT16 || renderbufferFormat == GL_DEPTH_COMPONENT24 || renderbufferFormat == GL_DEPTH_COMPONENT32) 93 | glNamedFramebufferRenderbuffer(m_name, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_rbo); 94 | else 95 | glNamedFramebufferRenderbuffer(m_name, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_rbo); 96 | } -------------------------------------------------------------------------------- /libraries/Rendering/FrameBuffer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Texture.h" 3 | 4 | class FrameBuffer 5 | { 6 | public: 7 | explicit FrameBuffer(const std::vector>& rendertargets, const bool useDepthStencil = true, const GLenum renderbufferFormat = GL_DEPTH24_STENCIL8, int samples = 0); 8 | 9 | // CAUTION: This constructor is only for rendering exclusively to a depth attachment 10 | FrameBuffer(GLenum attachmentType, const Texture& depthAttachment); 11 | 12 | FrameBuffer(const int width, const int height, const bool useDepthStencil = true, const GLenum renderbufferFormat = GL_DEPTH24_STENCIL8); 13 | ~FrameBuffer(); 14 | 15 | void bind() const; 16 | void unbind() const; 17 | 18 | GLuint getName() const; 19 | 20 | private: 21 | void attachDepthStencil(const int width, const int height, const GLenum renderbufferFormat); 22 | void attachDepthStencilMultiSample(int width, int height, int samples, GLenum renderbufferFormat); 23 | GLuint m_name; 24 | GLuint m_rbo; 25 | }; 26 | -------------------------------------------------------------------------------- /libraries/Rendering/IBLCubemapMaker.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "Cubemap.h" 4 | #include "SkyBoxCube.h" 5 | #include "Uniform.h" 6 | #include "ShaderProgram.h" 7 | 8 | class IBLCubemapMaker 9 | { 10 | public: 11 | explicit IBLCubemapMaker(const std::filesystem::path& filename); 12 | Cubemap getEnvironmentCubemap() const; 13 | Cubemap getIrradianceCubemap() const; 14 | Cubemap getSpecularCubemap() const; 15 | Texture getBRDFLUT() const; 16 | 17 | void draw(glm::mat4 view, glm::mat4 proj); 18 | 19 | private: 20 | Cubemap m_targetCubemap; 21 | Cubemap m_irradianceCubemap; 22 | Cubemap m_specularCubemap; 23 | 24 | Buffer m_iblSkyboxTextureBuffer; 25 | Buffer m_irrCalcTextureBuffer; 26 | 27 | Shader m_skyBoxVS; 28 | Shader m_skyBoxFS; 29 | 30 | ShaderProgram m_iblSkyboxSP; 31 | 32 | SkyBoxCube m_cube; 33 | std::shared_ptr> m_projUniform; 34 | std::shared_ptr> m_viewUniform; 35 | 36 | Texture m_brdfLUT; 37 | }; 38 | -------------------------------------------------------------------------------- /libraries/Rendering/Image.cpp: -------------------------------------------------------------------------------- 1 | #include "Image.h" 2 | #include 3 | 4 | Image::Image(GLenum target, GLenum minFilter, GLenum maxFilter) : Texture(target, minFilter, maxFilter) 5 | { 6 | 7 | } 8 | 9 | GLuint64 Image::generateImageHandle(GLenum format, GLboolean layered, int layer) 10 | { 11 | m_handle = glGetImageHandleARB(m_name, 0, layered, layer, format); 12 | if (m_handle == 0) 13 | throw std::runtime_error("image handle could not be returned"); 14 | glMakeImageHandleResidentARB(m_handle, GL_READ_WRITE); 15 | return m_handle; 16 | } 17 | 18 | GLuint64 Image::generateHandle() 19 | { 20 | std::cout << "WARNING: Generating texture handle for image! Consider calling generateImageHandle() instead. \n"; 21 | return Texture::generateHandle(); 22 | } 23 | -------------------------------------------------------------------------------- /libraries/Rendering/Image.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Texture.h" 4 | 5 | class Image : public Texture 6 | { 7 | public: 8 | explicit Image(GLenum target = GL_TEXTURE_2D, GLenum minFilter = GL_LINEAR, GLenum maxFilter = GL_LINEAR); 9 | GLuint64 generateImageHandle(GLenum format, GLboolean layered = GL_TRUE, int layer = 0); 10 | GLuint64 generateHandle() override; 11 | }; 12 | -------------------------------------------------------------------------------- /libraries/Rendering/Light.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include "Buffer.h" 7 | #include "Texture.h" 8 | #include "ShaderProgram.h" 9 | #include "Mesh.h" 10 | #include "FrameBuffer.h" 11 | 12 | 13 | class ModelImporter; 14 | using namespace gl; 15 | 16 | struct GPULight 17 | { 18 | glm::mat4 lightSpaceMatrix; 19 | glm::vec3 color; // all 20 | int type = -1; // 0 directional, 1 point light, 2 spot light 21 | glm::vec3 position; // spot, point 22 | float constant = -1.0f; // spot, point 23 | glm::vec3 direction; // dir, spot 24 | float linear = -1.0f; // spot, point 25 | uint64_t shadowMap; 26 | float quadratic = -1.0f; // spot, point 27 | float cutOff = -1.0f; // spot 28 | float outerCutOff = -1.0f; // spot 29 | int pcfKernelSize = 1; 30 | int32_t pad1, pad2; 31 | }; 32 | 33 | enum class LightType : int 34 | { 35 | directional = 0, 36 | point = 1, 37 | spot = 2 38 | }; 39 | 40 | class Light 41 | { 42 | public: 43 | 44 | Light(glm::vec3 color, glm::vec3 direction, float smFar = 3000.0f, glm::ivec2 shadowMapRes = glm::ivec2(4096, 4096)); // DIRECTIONAL 45 | Light(glm::vec3 color, glm::vec3 position, float constant, float linear, float quadratic, float smFar = 3000.0f, glm::ivec2 shadowMapRes = glm::ivec2(512, 512)); // POINT 46 | Light(glm::vec3 color, glm::vec3 position, glm::vec3 direction, float constant, float linear, float quadratic, float cutOff, float outerCutOff, float smFar = 3000.0f, glm::ivec2 shadowMapRes = glm::ivec2(4096, 4096)); // SPOT 47 | 48 | void renderShadowMap(const std::vector>& meshes); 49 | void renderShadowMap(const ModelImporter& mi); 50 | void renderShadowMapCulled(const ModelImporter& mi); 51 | 52 | const GPULight& getGpuLight() const; 53 | 54 | void recalculateLightSpaceMatrix(); 55 | 56 | bool showLightGUI(const std::string& name = "Light"); 57 | bool showLightGUIContent(const std::string& name = "Light"); 58 | 59 | // getters & setters 60 | void setColor(glm::vec3 col); 61 | glm::vec3 getColor() const; 62 | 63 | void setPosition(glm::vec3 pos); 64 | glm::vec3 getPosition() const; 65 | 66 | void setDirection(glm::vec3 dir); 67 | glm::vec3 getDirection() const; 68 | 69 | void setConstant(float constant); 70 | float getConstant() const; 71 | 72 | void setLinear(float linear); 73 | float getLinear() const; 74 | 75 | void setQuadratic(float quadratic); 76 | float getQuadratic() const; 77 | 78 | void setCutoff(float cutoff); 79 | float getCutoff() const; 80 | 81 | void setOuterCutoff(float cutOff); 82 | float getOuterCutoff() const; 83 | 84 | void setPCFKernelSize(int size); 85 | int getPCFKernelSize() const; 86 | 87 | LightType getType() const; 88 | 89 | void setOuterBoundingBox(const glm::mat2x4& outerBoundingBox); 90 | 91 | private: 92 | void checkParameters(); 93 | 94 | LightType m_type; 95 | 96 | bool m_hasShadowMap = true; 97 | glm::ivec2 m_shadowMapRes; 98 | float m_smFar; 99 | 100 | glm::mat4 m_lightProjection; 101 | glm::mat4 m_lightView; 102 | 103 | std::shared_ptr m_shadowTexture; 104 | FrameBuffer m_shadowMapFBO; 105 | ShaderProgram m_genShadowMapProgram; 106 | 107 | std::optional m_outerSceneBoundingBox; 108 | 109 | std::shared_ptr> m_modelUniform; 110 | std::shared_ptr> m_lightSpaceUniform; 111 | std::shared_ptr> m_lightPosUniform; 112 | 113 | GPULight m_gpuLight; 114 | }; -------------------------------------------------------------------------------- /libraries/Rendering/LightManager.cpp: -------------------------------------------------------------------------------- 1 | #include "LightManager.h" 2 | #include "imgui/imgui.h" 3 | #include 4 | 5 | // Light Manager 6 | LightManager::LightManager() 7 | { 8 | } 9 | 10 | LightManager::LightManager(std::vector> lights) 11 | { 12 | m_lightList = lights; 13 | } 14 | 15 | void LightManager::uploadLightsToGPU() 16 | { 17 | std::vector gpuLights; 18 | std::for_each(m_lightList.begin(), m_lightList.end(), [&gpuLights](auto& light) 19 | { 20 | light->recalculateLightSpaceMatrix(); 21 | gpuLights.push_back(light->getGpuLight()); 22 | }); 23 | 24 | m_lightsBuffer.setStorage(gpuLights, GL_DYNAMIC_STORAGE_BIT); 25 | m_lightsBuffer.bindBase(BufferBindings::Binding::lights); 26 | } 27 | 28 | void LightManager::bindLightBuffer() const 29 | { 30 | m_lightsBuffer.bindBase(BufferBindings::Binding::lights); 31 | } 32 | 33 | bool LightManager::showLightGUIs() 34 | { 35 | bool changed = false; 36 | int index = 0; 37 | std::for_each(m_lightList.begin(), m_lightList.end(), [this, &changed, &index](auto& light) 38 | { 39 | index++; 40 | if (light->showLightGUI(std::string("Light ") + std::to_string(index))) 41 | { 42 | updateLightParams(light); 43 | changed = true; 44 | } 45 | }); 46 | return changed; 47 | } 48 | 49 | bool LightManager::showLightGUIsContent() 50 | { 51 | bool changed = false; 52 | int index = 0; 53 | std::for_each(m_lightList.begin(), m_lightList.end(), [this, &changed, &index](auto& light) 54 | { 55 | index++; 56 | ImGui::Separator(); 57 | if (light->showLightGUIContent(std::string("Light ") + std::to_string(index))) 58 | { 59 | updateLightParams(light); 60 | changed = true; 61 | } 62 | }); 63 | return changed; 64 | } 65 | 66 | void LightManager::renderShadowMaps(const std::vector>& meshes) 67 | { 68 | std::for_each(m_lightList.begin(), m_lightList.end(), [&meshes](auto& light) 69 | { 70 | light->renderShadowMap(meshes); 71 | }); 72 | } 73 | 74 | void LightManager::renderShadowMaps(const ModelImporter& mi) 75 | { 76 | std::for_each(m_lightList.begin(), m_lightList.end(), [&mi](auto& light) 77 | { 78 | light->renderShadowMap(mi); 79 | }); 80 | } 81 | 82 | void LightManager::renderShadowMapsCulled(const ModelImporter& scene) 83 | { 84 | std::for_each(m_lightList.begin(), m_lightList.end(), [&scene](auto& light) 85 | { 86 | light->renderShadowMapCulled(scene); 87 | }); 88 | } 89 | 90 | void LightManager::updateLightParams() 91 | { 92 | std::vector gpuLights; 93 | std::for_each(m_lightList.begin(), m_lightList.end(), [&gpuLights](auto& light) 94 | { 95 | light->recalculateLightSpaceMatrix(); 96 | gpuLights.push_back(light->getGpuLight()); 97 | }); 98 | 99 | m_lightsBuffer.setContentSubData(gpuLights, 0); 100 | m_lightsBuffer.bindBase(BufferBindings::Binding::lights); 101 | } 102 | 103 | void LightManager::updateLightParams(std::shared_ptr light) 104 | { 105 | size_t index = std::distance(m_lightList.begin(), std::find(m_lightList.begin(), m_lightList.end(), light)); 106 | if (index < m_lightList.size()) 107 | { 108 | m_lightList[index]->recalculateLightSpaceMatrix(); 109 | m_lightsBuffer.setContentSubData(m_lightList[index]->getGpuLight(), index * sizeof(GPULight)); 110 | m_lightsBuffer.bindBase(BufferBindings::Binding::lights); 111 | } 112 | else 113 | { 114 | throw std::runtime_error("Tried to update a light that was not added to this LightManager!"); 115 | } 116 | } 117 | 118 | void LightManager::addLight(std::shared_ptr light) 119 | { 120 | m_lightList.push_back(light); 121 | } 122 | 123 | std::vector> LightManager::getLights() const 124 | { 125 | return m_lightList; 126 | } 127 | 128 | void LightManager::setOuterSceneBoundingBoxToAllLights(const glm::mat2x4& outerSceneBoundingBox) 129 | { 130 | std::for_each(std::execution::par, m_lightList.begin(), m_lightList.end(), 131 | [&outerSceneBoundingBox](auto& light) { light->setOuterBoundingBox(outerSceneBoundingBox); }); 132 | } -------------------------------------------------------------------------------- /libraries/Rendering/LightManager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | using namespace gl; 5 | 6 | #include 7 | #include 8 | #include "Mesh.h" 9 | #include "Light.h" 10 | 11 | class LightManager 12 | { 13 | public: 14 | 15 | LightManager(); 16 | explicit LightManager(std::vector> lights); 17 | 18 | void uploadLightsToGPU(); 19 | void bindLightBuffer() const; 20 | 21 | bool showLightGUIs(); 22 | 23 | bool showLightGUIsContent(); 24 | 25 | void renderShadowMaps(const std::vector>& meshes); 26 | void renderShadowMaps(const ModelImporter& mi); 27 | void renderShadowMapsCulled(const ModelImporter& scene); 28 | 29 | void updateLightParams(); 30 | void updateLightParams(std::shared_ptr light); 31 | 32 | void setOuterSceneBoundingBoxToAllLights(const glm::mat2x4& outerSceneBoundingBox); 33 | 34 | void addLight(std::shared_ptr light); 35 | 36 | std::vector> getLights() const; 37 | 38 | private: 39 | 40 | Buffer m_lightsBuffer{ GL_SHADER_STORAGE_BUFFER }; 41 | std::vector> m_lightList; 42 | int m_e = 0; 43 | 44 | }; -------------------------------------------------------------------------------- /libraries/Rendering/Mesh.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "Buffer.h" 8 | #include "VertexArray.h" 9 | 10 | class Mesh 11 | { 12 | public: 13 | Mesh(aiMesh* assimpMesh, bool useOwnBuffers = true); 14 | Mesh(std::vector& vertices, std::vector& normals, std::vector& indices); 15 | 16 | /** 17 | * \brief returns vertices as vector of vec3 18 | * \return vertices 19 | */ 20 | const std::vector& getVertices() const; 21 | 22 | /** 23 | * \brief returns normals as vector of vec3 24 | * \return normals 25 | */ 26 | const std::vector& getNormals() const; 27 | 28 | /** 29 | * \brief returns UV coords as vector of vec3 30 | * \return UV/texture coordinates 31 | */ 32 | const std::vector& getTexCoords() const; 33 | 34 | /** 35 | * \brief returns indices as vectors of uint 36 | * \return indices 37 | */ 38 | const std::vector& getIndices() const; 39 | 40 | /** 41 | * \brief returns the model matrix 42 | * \return 4x4 model matrix, initially identity matrix 43 | */ 44 | const glm::mat4& getModelMatrix() const; 45 | 46 | /** 47 | * \brief returns the material ID 48 | * \return material ID 49 | */ 50 | unsigned getMaterialID() const; 51 | unsigned getMaterialIndex() const; 52 | 53 | /** 54 | * \brief returns the previously calculated bounding box 55 | * \return bmin: getBoundingBox()[0], bmax: getBoundingBox()[1] 56 | */ 57 | const glm::mat2x3& getBoundingBox() const; 58 | 59 | /** 60 | * \brief re-calculates the bounding box and returns it 61 | * \return bmin: getBoundingBox()[0], bmax: getBoundingBox()[1] 62 | */ 63 | const glm::mat2x3& calculateBoundingBox(); 64 | 65 | /** 66 | * \brief calls forceDraw() if the mesh is enabled for rendering 67 | */ 68 | void draw() const; 69 | 70 | /** 71 | * \brief binds the vao & index buffer and uses glDrawArrays 72 | */ 73 | void forceDraw() const; 74 | 75 | /** 76 | * \brief sets the model matrix 77 | * \param modelMatrix model matrix for this mesh 78 | */ 79 | void setModelMatrix(const glm::mat4& modelMatrix); 80 | 81 | /** 82 | * \brief sets the material ID 83 | * \param materialID material ID for this mesh 84 | */ 85 | void setMaterialID(const unsigned materialID); 86 | 87 | void setEnabledForRendering(bool enable); 88 | bool isEnabledForRendering() const; 89 | 90 | private: 91 | std::vector m_vertices; 92 | std::vector m_normals; 93 | std::vector m_texCoords; 94 | std::vector m_indices; 95 | 96 | bool m_enabledForRendering = true; 97 | 98 | glm::mat2x3 m_boundingBox; 99 | 100 | glm::mat4 m_modelMatrix = glm::mat4(1.0f); 101 | 102 | unsigned m_materialID = 1U; 103 | 104 | Buffer m_vertexBuffer; 105 | Buffer m_normalBuffer; 106 | Buffer m_texCoordBuffer; 107 | Buffer m_indexBuffer; 108 | VertexArray m_vao; 109 | 110 | unsigned int m_materialIndex; 111 | }; 112 | -------------------------------------------------------------------------------- /libraries/Rendering/Parameters.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | struct ParameterFog 7 | { 8 | glm::vec3 albedo; 9 | float anisotropy; 10 | float scattering; 11 | float absorption; 12 | float density; 13 | }; 14 | 15 | struct PrarameterLight 16 | { 17 | glm::vec3 color; // all 18 | glm::vec3 position; // spot, point 19 | glm::vec3 direction; // dir, spot 20 | int pcfKernelSize = 1; 21 | float constant; // spot, point 22 | float linear; // spot, point 23 | float quadratic; // spot, point 24 | float cutOff; // spot 25 | float outerCutOff; // spot 26 | }; 27 | 28 | struct ParamterNoise 29 | { 30 | float densityFactor; 31 | float densityHeight; 32 | float scale; 33 | float speed; 34 | }; 35 | 36 | struct Parameters 37 | { 38 | std::vector lights; 39 | ParamterNoise noise; 40 | ParameterFog fog; 41 | float gamma; 42 | float exposure; 43 | float maxRange; //range of voxel grid 44 | glm::vec3 cameraPos; 45 | float phi, theta; //for camera direction 46 | 47 | }; 48 | 49 | /* E X A M P L E 50 | Parameters Scene{ 51 | LIGHTS 52 | { 53 | {color, position, direction, pcfKernelSize, constant, linear, quadratic, cutOff, outerCutoff}, 54 | ... 55 | }, 56 | NOISE 57 | {densityFactor, densityHeigt, scale, speed}, 58 | FOG 59 | {albedo, anisotropy, scattering, absorption, density}, 60 | HDR AND VOXEL SETTINGS 61 | gamma, exposure, maxRange, 62 | CAMERA PARAMETERS 63 | cameraPos, phi, theta 64 | }*/ 65 | 66 | const std::vector sceneParams = { 67 | 68 | // S P O N Z A 69 | Parameters{ 70 | { 71 | //global directional light 72 | {glm::vec3(10.0f), glm::vec3(0.0f, 2000.0f, 0.0f), glm::vec3(0.0f, -1.0f, -0.2f)}, 73 | //spotlight 1 74 | {glm::vec3(0.0f, 10.0f, 10.0f), glm::vec3(80.0f, 300.0f, 100.0f), glm::normalize(glm::vec3(0.0f) - glm::vec3(80.0f, 300.0f, 100.0f)), 1, 75 | 0.05f, 0.002f, 0.0f, glm::cos(glm::radians(30.0f)), glm::cos(glm::radians(35.0f))} 76 | }, 77 | //noise 78 | {0.015f, 1.03f, 0.003f, 0.15f}, 79 | //fog 80 | {glm::vec3(1.0f), 0.2f, 0.6f, 0.25f, 0.125f }, 81 | //hdr 82 | 2.2f, 0.25f, 83 | 3000.0f, 84 | //camera 85 | glm::vec3(-1000.0f, 222.2f, 0.0f), 1.7f, 1.7f 86 | }, 87 | 88 | // B R E A K F A S T R O O M 89 | Parameters{ 90 | { 91 | //global directional light 92 | { glm::vec3(4.0f), glm::vec3(12.0f, 10.0f, 0.0f), glm::vec3(-1.0f, -1.0f, -0.2f), 2 }, 93 | //lamp 1 94 | { glm::vec3(2.0f, 2.0f, 1.3f), glm::vec3(1.0f, 4.15f, -1.92f), glm::vec3(0.001f, -1.0f, 0.0f), 1, 95 | 0.025f, 0.01f, 0.0f, 1.055f, 0.72f }, 96 | //lamp 2 97 | { glm::vec3(2.0f, 2.0f, 1.3f), glm::vec3(-2.15f, 4.15f, -1.92f), glm::vec3(0.001f, -1.0f, 0.0f), 1, 98 | 0.025f, 0.01f, 0.0f, 1.055f, 0.72f }, 99 | //lamp 3 as sun 100 | { glm::vec3(10.0f), glm::vec3(15.0f, 10.0f, -1.0f), glm::vec3(-0.6f, -0.33f, 0.0f), 3, 101 | 0.025f, 0.01f, 0.0f, 1.0f, 0.92f }, 102 | }, 103 | //noise 104 | { 0.015f, 0.1f, 0.5f, 0.3f }, 105 | //fog 106 | { glm::vec3(1.0f), 0.35f, 0.1f, 0.1f, 0.15f }, 107 | //hdr 108 | 2.2f, 0.15f, 109 | 30.0f, 110 | //camera 111 | glm::vec3(2.6f, 4.8f, 7.0f), 3.8f, 1.25f 112 | }, 113 | 114 | // S A N M I G U E L 115 | Parameters{ 116 | { 117 | //global directional light 118 | { glm::vec3(20.0f, 20.0f, 18.0f), glm::vec3(0.0f, 25.0f, 0.0f), glm::vec3(0.6f, -1.0f, -0.6f), 3 }, 119 | //lamp 1 - lower floor above table 120 | //{ glm::vec3(10.0f, 10.0f, 9.0f), glm::vec3(11.2f, 2.9f, -1.75f), glm::vec3(0.001f, -1.0f, 0.0f), 1, 121 | //0.025f, 0.01f, 0.0f, 1.055f, 0.72f }, 122 | //lamp 2 - above scene through trees 123 | { glm::vec3(10.0f, 10.0f, 8.0f), glm::vec3(15.0f, 16.5f, 11.0f), glm::vec3(0.001f, -1.0f, 0.0f), 1, 124 | 0.025f, 0.01f, 0.0f, 0.85f, 0.55f }, 125 | //lamp 3 126 | //{ glm::vec3(10.0f), glm::vec3(15.0f, 10.0f, -1.0f), glm::vec3(-0.6f, -0.33f, 0.0f), 3, 127 | //0.025f, 0.01f, 0.0f, 1.0f, 0.92f }, 128 | }, 129 | //noise 130 | { 0.008f, 3.0f, 2.0f, 0.06f }, 131 | //fog 132 | { glm::vec3(1.0f), 0.35f, 0.3f, 0.025f, 0.15f }, 133 | //hdr 134 | 2.2f, 0.15f, 135 | 30.0f, 136 | //camera 137 | glm::vec3(18.9f, 1.2f, -2.1f), 3.8f, 1.25f 138 | } 139 | 140 | }; -------------------------------------------------------------------------------- /libraries/Rendering/Pilotview.cpp: -------------------------------------------------------------------------------- 1 | #include "Pilotview.h" 2 | 3 | #include 4 | #include 5 | #include "../Utils/UtilCollection.h" 6 | 7 | Pilotview::Pilotview(int width, int height) : Camera(width, height) 8 | { 9 | Pilotview::reset(); 10 | } 11 | 12 | void Pilotview::reset() 13 | { 14 | Camera::reset(); 15 | m_dir = glm::vec3(0.0f, 0.0f, -1.0f); 16 | m_pos = glm::vec3(0.0f); 17 | m_center = m_pos + m_dir; 18 | m_viewMatrix = lookAt(m_pos, m_center, m_up); 19 | m_phi = glm::pi(); 20 | } 21 | 22 | void Pilotview::setDirection(glm::vec3 dir) 23 | { 24 | m_dir = dir; 25 | } 26 | 27 | glm::vec3 Pilotview::getDirection() const 28 | { 29 | return m_dir; 30 | } 31 | 32 | void Pilotview::update(GLFWwindow* window) 33 | { 34 | Camera::update(window); 35 | 36 | m_dir.x = sin(m_theta) * sin(m_phi); 37 | m_dir.y = -cos(m_theta); 38 | m_dir.z = sin(m_theta) * cos(m_phi); 39 | m_dir = glm::normalize(m_dir); 40 | 41 | const float old_sensitivity = m_sensitivity; 42 | 43 | if (glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS) 44 | { 45 | m_sensitivity *= 10; // fast mode 46 | } 47 | 48 | if (glfwGetKey(window, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS) 49 | { 50 | m_sensitivity *= 0.1f; // slow mode 51 | } 52 | 53 | if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) 54 | { 55 | m_pos += m_dir * m_sensitivity; 56 | } 57 | if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) 58 | { 59 | m_pos -= m_dir * m_sensitivity; 60 | } 61 | 62 | if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) 63 | { 64 | m_pos += glm::normalize(glm::cross(m_up, m_dir)) * m_sensitivity; 65 | } 66 | if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) 67 | { 68 | m_pos -= glm::normalize(glm::cross(m_up, m_dir)) * m_sensitivity; 69 | } 70 | 71 | if (glfwGetKey(window, GLFW_KEY_Q) == GLFW_PRESS) 72 | { 73 | m_pos += glm::normalize(m_up) * m_sensitivity; 74 | } 75 | if (glfwGetKey(window, GLFW_KEY_E) == GLFW_PRESS) 76 | { 77 | m_pos -= glm::normalize(m_up) * m_sensitivity; 78 | } 79 | 80 | m_sensitivity = old_sensitivity; 81 | 82 | m_center = m_pos + m_dir; 83 | m_viewMatrix = lookAt(m_pos, m_center, m_up); 84 | 85 | if constexpr(util::debugmode) 86 | { 87 | // TODO implement proper "pilot view" Pilotview so the trackball doesn't overflow 88 | if (std::isnan(m_viewMatrix[0][0])) 89 | throw std::runtime_error("NaN in View Matrix"); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /libraries/Rendering/Pilotview.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Camera.h" 3 | 4 | class Pilotview : public Camera 5 | { 6 | public: 7 | Pilotview(int width, int height); 8 | 9 | /** 10 | * \brief Updates the view matrix based on mouse input 11 | * \param window 12 | */ 13 | void update(GLFWwindow* window) override; 14 | 15 | void reset() override; 16 | 17 | void setDirection(glm::vec3 dir); 18 | glm::vec3 getDirection() const override; 19 | 20 | private: 21 | glm::vec3 m_dir; 22 | }; 23 | -------------------------------------------------------------------------------- /libraries/Rendering/Quad.cpp: -------------------------------------------------------------------------------- 1 | #include "Quad.h" 2 | 3 | Quad::Quad() : m_quadBuffer(GL_ARRAY_BUFFER), m_texCoordBuffer(GL_ARRAY_BUFFER) 4 | { 5 | m_quadBuffer.setStorage(quadVertices, GL_DYNAMIC_STORAGE_BIT); 6 | 7 | m_texCoordBuffer.setStorage(quadTexCoords, GL_DYNAMIC_STORAGE_BIT); 8 | 9 | // TODO use proper bindings (definitions have to be used in the shader too) 10 | m_quadVAO.connectBuffer(m_quadBuffer, static_cast(0), 2, GL_FLOAT, GL_FALSE); 11 | m_quadVAO.connectBuffer(m_texCoordBuffer, static_cast(1), 2, GL_FLOAT, GL_FALSE); 12 | } 13 | 14 | void Quad::draw() const 15 | { 16 | m_quadVAO.bind(); 17 | glDrawArrays(GL_TRIANGLES, 0, static_cast(quadVertices.size())); 18 | } 19 | 20 | std::vector Quad::quadVertices = 21 | { 22 | {-1.0, -1.0}, 23 | {1.0, -1.0}, 24 | {-1.0, 1.0}, 25 | {-1.0, 1.0}, 26 | {1.0, -1.0}, 27 | {1.0, 1.0} 28 | }; 29 | 30 | std::vector Quad::quadTexCoords = 31 | { 32 | {0.0, 0.0}, 33 | {1.0, 0.0}, 34 | {0.0, 1.0}, 35 | {0.0, 1.0}, 36 | {1.0, 0.0}, 37 | {1.0, 1.0} 38 | }; 39 | -------------------------------------------------------------------------------- /libraries/Rendering/Quad.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Mesh.h" 4 | 5 | class Quad 6 | { 7 | public: 8 | Quad(); 9 | void draw() const; 10 | private: 11 | VertexArray m_quadVAO; 12 | Buffer m_quadBuffer; 13 | Buffer m_texCoordBuffer; 14 | 15 | static std::vector quadVertices; 16 | static std::vector quadTexCoords; 17 | }; 18 | -------------------------------------------------------------------------------- /libraries/Rendering/Shader.cpp: -------------------------------------------------------------------------------- 1 | #include "Shader.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "Utils/UtilCollection.h" 8 | #include "glbinding-aux/Meta.h" 9 | 10 | 11 | Shader::Shader(const std::filesystem::path& path, GLenum shaderType, const std::vector& definitions) : m_shaderType(shaderType), m_path(path), m_definitions(definitions) 12 | { 13 | // create shader and check for errors 14 | m_shaderHandle = glCreateShader(shaderType); 15 | if (0 == m_shaderHandle) 16 | { 17 | throw std::runtime_error("Error creating shader."); 18 | } 19 | init(); 20 | } 21 | 22 | void Shader::init() const 23 | { 24 | if (m_path.empty()) 25 | { 26 | throw std::runtime_error("No path given"); 27 | } 28 | // load shader file and use it 29 | auto shaderCode = loadShaderFile(std::filesystem::path(util::gs_shaderPath) / m_path); 30 | std::array codeArray{shaderCode.c_str()}; 31 | glShaderSource(m_shaderHandle, 1, codeArray.data(), nullptr); 32 | 33 | // compile shader 34 | glCompileShader(m_shaderHandle); 35 | 36 | // check of compilation was succesful, print log if not 37 | GLint result; 38 | glGetShaderiv(m_shaderHandle, GL_COMPILE_STATUS, &result); 39 | if (GL_FALSE == result) 40 | { 41 | GLint logLen; 42 | glGetShaderiv(m_shaderHandle, GL_INFO_LOG_LENGTH, &logLen); 43 | if (logLen > 0) 44 | { 45 | std::string log; 46 | log.resize(logLen); 47 | GLsizei written; 48 | glGetShaderInfoLog(m_shaderHandle, logLen, &written, &log[0]); 49 | std::cout << "Shader log: " << log << std::endl; 50 | } 51 | throw std::runtime_error("Shader compilation failed"); 52 | } 53 | util::getGLerror(__LINE__, __FUNCTION__); 54 | } 55 | 56 | GLuint Shader::getHandle() const 57 | { 58 | return m_shaderHandle; 59 | } 60 | 61 | GLenum Shader::getShaderType() const 62 | { 63 | return m_shaderType; 64 | } 65 | 66 | std::string Shader::loadShaderFile(const std::filesystem::path& fileName) const 67 | { 68 | auto file = glsp::preprocess_file(fileName, { util::gs_shaderPath }, m_definitions); 69 | std::cout << "Loaded " << glbinding::aux::Meta::getString(m_shaderType) << " from " << fileName << std::endl;; 70 | return file.contents; 71 | } 72 | -------------------------------------------------------------------------------- /libraries/Rendering/Shader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | using namespace gl; 8 | #include "glshader/include/glsp/glsp.hpp" 9 | 10 | class Shader 11 | { 12 | public: 13 | Shader(const std::filesystem::path& path, GLenum shaderType, const std::vector& definitions = {}); 14 | 15 | void init() const; 16 | 17 | /** 18 | * \brief returns the shader handle 19 | * \return shader handle 20 | */ 21 | GLuint getHandle() const; 22 | 23 | /** 24 | * \brief returns the shader type (vertex, fragment, ...) 25 | * \return shader type 26 | */ 27 | GLenum getShaderType() const; 28 | 29 | private: 30 | GLuint m_shaderHandle; 31 | GLenum m_shaderType; 32 | std::filesystem::path m_path; 33 | 34 | std::vector m_definitions; 35 | 36 | std::string loadShaderFile(const std::filesystem::path& fileName) const; 37 | }; 38 | -------------------------------------------------------------------------------- /libraries/Rendering/ShaderProgram.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | using namespace gl; 10 | 11 | #include "Shader.h" 12 | #include "Uniform.h" 13 | #include "Utils/UtilCollection.h" 14 | #include "glshader/include/glsp/glsp.hpp" 15 | 16 | 17 | class ShaderProgram 18 | { 19 | public: 20 | ShaderProgram(const std::filesystem::path& vspath, const std::filesystem::path& fspath, const std::vector& definitions = {}); 21 | ShaderProgram(const Shader& shader1, const Shader& shader2); 22 | ShaderProgram(const std::vector& shaders); 23 | ~ShaderProgram(); 24 | 25 | /** 26 | * \brief adds a shaderto the program 27 | * \param shader the shader that is to be added 28 | */ 29 | void addShader(const Shader& shader); 30 | 31 | /** 32 | * \brief creates a shader program with all shaders from the map 33 | */ 34 | void createProgram(); 35 | 36 | /** 37 | * \brief links the shader program 38 | */ 39 | void linkProgram() const; 40 | 41 | /** 42 | * \brief retruns the shader program handle 43 | * \return shader program handle 44 | */ 45 | GLuint getShaderProgramHandle() const; 46 | 47 | /** 48 | * \brief sets the shader program as the currently used shader program 49 | */ 50 | void use() const; 51 | 52 | /** 53 | * \brief swaps current shader of the same kind with the given shader 54 | * \param shader new shader to be used 55 | */ 56 | void changeShader(const Shader& shader); 57 | 58 | /** 59 | * \brief adds an unifrom to the container of uniforms 60 | * \tparam UniformType the type of the uniform to be added 61 | * \param uniform the uniform itself 62 | */ 63 | template 64 | void addUniform(std::shared_ptr> uniform); 65 | 66 | /** 67 | * \brief updates all uniforms depending on their flags 68 | */ 69 | void updateUniforms() const; 70 | 71 | /** 72 | * \brief shows a "reload vertex/fragment shader" gui window using imgui 73 | * \param vshader the vertex shader to be changed/reloaded 74 | * \param fshader the fragment shader to be changed/reloaded 75 | * \param name debug name in the GUI 76 | */ 77 | void showReloadShaderGUI(const std::vector& shaders, std::string_view name = "Generic Shaderprogram"); 78 | 79 | /** 80 | * \brief returns "reload vertex/fragment shader" gui content to use with imgui 81 | * \param vshader the vertex shader to be changed/reloaded 82 | * \param fshader the fragment shader to be changed/reloaded 83 | * \param name debug name in the GUI 84 | */ 85 | void showReloadShaderGUIContent(const std::vector& shaders, std::string_view name = "Generic Shaderprogram"); 86 | 87 | private: 88 | GLuint m_shaderProgramHandle; 89 | std::unordered_map m_shaderMap; 90 | bool m_initWithShaders = false; 91 | 92 | std::vector> m_anyUniforms; 93 | 94 | /** 95 | * \brief forces update of all uniforms (ignores flag) 96 | */ 97 | void forceUpdateUniforms(); 98 | }; 99 | 100 | template 101 | void ShaderProgram::addUniform(std::shared_ptr> uniform) 102 | { 103 | GLint location = glGetUniformLocation(m_shaderProgramHandle, uniform->getName().c_str()); 104 | if (location < 0) 105 | throw std::runtime_error("Uniform " + uniform->getName() + " does not exist"); 106 | uniform->registerUniformWithShaderProgram(m_shaderProgramHandle); 107 | m_anyUniforms.push_back(std::make_pair(std::make_any>>(uniform), location)); 108 | } 109 | -------------------------------------------------------------------------------- /libraries/Rendering/SimplexNoise.cpp: -------------------------------------------------------------------------------- 1 | #include "SimplexNoise.h" 2 | #include "imgui/imgui.h" 3 | 4 | SimplexNoise::SimplexNoise(float scale, float speed, float densityFactor, float densityHeight) : 5 | m_noiseScale(scale), m_noiseSpeed(speed), m_densityFactor(densityFactor), m_densityHeight(densityHeight) 6 | { 7 | m_time = static_cast(glfwGetTime()); 8 | 9 | { 10 | std::array pixels; 11 | for (int i = 0; i<256; i++) 12 | for (int j = 0; j<256; j++) 13 | { 14 | int offset = (i * 256 + j) * 4; 15 | char value = m_perm[(j + m_perm[i]) & 0xFF]; 16 | pixels[offset] = m_gradient4[2 * (value & 0x0F)][0] * 64 + 64; // Gradient x 17 | pixels[offset + 1] = m_gradient4[2 * (value & 0x0F)][1] * 64 + 64; // Gradient y 18 | pixels[offset + 2] = m_gradient4[2 * (value & 0x0F)][2] * 64 + 64; // Gradient z 19 | pixels[offset + 3] = value; // Permuted index 20 | } 21 | 22 | m_permTexture.initWithData2D(pixels, 256, 256); 23 | } 24 | 25 | m_simplexTexture.initWithData1D(m_simplex4, 64); 26 | 27 | { 28 | std::array pixels; 29 | for (int i = 0; i<256; i++) 30 | for (int j = 0; j<256; j++) 31 | { 32 | int offset = (i * 256 + j) * 4; 33 | char value = m_perm[(j + m_perm[i]) & 0xFF]; 34 | pixels[offset] = m_gradient4[value & 0x1F][0] * 64 + 64; // Gradient x 35 | pixels[offset + 1] = m_gradient4[value & 0x1F][1] * 64 + 64; // Gradient y 36 | pixels[offset + 2] = m_gradient4[value & 0x1F][2] * 64 + 64; // Gradient z 37 | pixels[offset + 3] = m_gradient4[value & 0x1F][3] * 64 + 64; // Gradient z 38 | } 39 | 40 | m_gradientTexture.initWithData2D(pixels, 256, 256); 41 | } 42 | 43 | m_noiseSSBO.setStorage(std::array{ {m_permTexture.generateHandle(), m_simplexTexture.generateHandle(), m_gradientTexture.generateHandle(), m_time, m_densityFactor, m_densityHeight, m_noiseScale, m_noiseSpeed}}, GL_DYNAMIC_STORAGE_BIT); 44 | } 45 | 46 | void SimplexNoise::bindNoiseBuffer(BufferBindings::Binding binding) const 47 | { 48 | m_noiseSSBO.bindBase(binding); 49 | } 50 | 51 | Buffer& SimplexNoise::getNoiseBuffer() 52 | { 53 | return m_noiseSSBO; 54 | } 55 | 56 | bool SimplexNoise::showNoiseGUI() 57 | { 58 | ImGui::Begin("Noise GUI"); 59 | const bool noiseChanged = showNoiseGUIContent(); 60 | ImGui::End(); 61 | 62 | return noiseChanged; 63 | } 64 | 65 | bool SimplexNoise::showNoiseGUIContent() 66 | { 67 | bool res = false; 68 | ImGui::Text("Density and Noise Settings"); 69 | ImGui::Separator(); 70 | if (ImGui::SliderFloat("Noise Scale", &m_noiseScale, 0.0f, 0.1f)) 71 | { 72 | getNoiseBuffer().setContentSubData(m_noiseScale, offsetof(GpuNoiseInfo, noiseScale)); 73 | res = true; 74 | } 75 | if (ImGui::SliderFloat("Noise Speed", &m_noiseSpeed, 0.0f, 1.0f)) 76 | { 77 | getNoiseBuffer().setContentSubData(m_noiseSpeed, offsetof(GpuNoiseInfo, noiseSpeed)); 78 | res = true; 79 | } 80 | if (ImGui::SliderFloat("Density Factor", &m_densityFactor, 0.0f, 0.2f)) 81 | { 82 | getNoiseBuffer().setContentSubData(m_densityFactor, offsetof(GpuNoiseInfo, heightDensityFactor)); 83 | res = true; 84 | } 85 | if (ImGui::SliderFloat("Density Height", &m_densityHeight, 0.0f, 4.0f)) 86 | { 87 | getNoiseBuffer().setContentSubData(glm::log(m_densityHeight), offsetof(GpuNoiseInfo, heightDensityStart)); 88 | res = true; 89 | } 90 | return res; 91 | } 92 | -------------------------------------------------------------------------------- /libraries/Rendering/SimplexNoise.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "Texture.h" 4 | #include 5 | #include "Buffer.h" 6 | using namespace gl; 7 | 8 | struct GpuNoiseInfo 9 | { 10 | GLuint64 permTexture; 11 | GLuint64 simplexTexture; 12 | GLuint64 gradientTexture; 13 | float time; 14 | float heightDensityFactor; 15 | float heightDensityStart; 16 | float noiseScale; 17 | float noiseSpeed; 18 | }; 19 | 20 | class SimplexNoise 21 | { 22 | public: 23 | SimplexNoise(float scale = 0.003f, float speed = 0.15f, float densityFactor = 0.015f, float densityHeight = 0.85f); 24 | 25 | float m_time = 0.0f; 26 | float m_densityFactor; 27 | float m_densityHeight; 28 | float m_noiseScale; 29 | float m_noiseSpeed; 30 | 31 | void bindNoiseBuffer(BufferBindings::Binding binding) const; 32 | Buffer& getNoiseBuffer(); 33 | 34 | bool showNoiseGUI(); 35 | bool showNoiseGUIContent(); 36 | 37 | private: 38 | Texture m_permTexture{ GL_TEXTURE_2D, GL_NEAREST, GL_NEAREST }; 39 | Texture m_simplexTexture{ GL_TEXTURE_1D, GL_NEAREST, GL_NEAREST }; 40 | Texture m_gradientTexture{ GL_TEXTURE_2D, GL_NEAREST, GL_NEAREST }; 41 | 42 | Buffer m_noiseSSBO{ GL_SHADER_STORAGE_BUFFER }; 43 | 44 | const std::array m_perm{ 151,160,137,91,90,15, 45 | 131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23, 46 | 190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33, 47 | 88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166, 48 | 77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244, 49 | 102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196, 50 | 135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123, 51 | 5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42, 52 | 223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9, 53 | 129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228, 54 | 251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107, 55 | 49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254, 56 | 138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180 }; 57 | //gradients for 4d noise, midpoints of each edge of a tesseract 58 | const std::array, 32> m_gradient4{ { { 0,1,1,1 },{ 0,1,1,-1 },{ 0,1,-1,1 },{ 0,1,-1,-1 }, // 32 tesseract edges 59 | { 0,-1,1,1 },{ 0,-1,1,-1 },{ 0,-1,-1,1 },{ 0,-1,-1,-1 }, 60 | { 1,0,1,1 },{ 1,0,1,-1 },{ 1,0,-1,1 },{ 1,0,-1,-1 }, 61 | { -1,0,1,1 },{ -1,0,1,-1 },{ -1,0,-1,1 },{ -1,0,-1,-1 }, 62 | { 1,1,0,1 },{ 1,1,0,-1 },{ 1,-1,0,1 },{ 1,-1,0,-1 }, 63 | { -1,1,0,1 },{ -1,1,0,-1 },{ -1,-1,0,1 },{ -1,-1,0,-1 }, 64 | { 1,1,1,0 },{ 1,1,-1,0 },{ 1,-1,1,0 },{ 1,-1,-1,0 }, 65 | { -1,1,1,0 },{ -1,1,-1,0 },{ -1,-1,1,0 },{ -1,-1,-1,0 } } }; 66 | //simplex lookup table 67 | const std::array, 64> m_simplex4{ { { 0,64,128,192 },{ 0,64,192,128 },{ 0,0,0,0 }, 68 | { 0,128,192,64 },{ 0,0,0,0 },{ 0,0,0,0 },{ 0,0,0,0 },{ 64,128,192,0 }, 69 | { 0,128,64,192 },{ 0,0,0,0 },{ 0,192,64,128 },{ 0,192,128,64 }, 70 | { 0,0,0,0 },{ 0,0,0,0 },{ 0,0,0,0 },{ 64,192,128,0 }, 71 | { 0,0,0,0 },{ 0,0,0,0 },{ 0,0,0,0 },{ 0,0,0,0 }, 72 | { 0,0,0,0 },{ 0,0,0,0 },{ 0,0,0,0 },{ 0,0,0,0 }, 73 | { 64,128,0,192 },{ 0,0,0,0 },{ 64,192,0,128 },{ 0,0,0,0 }, 74 | { 0,0,0,0 },{ 0,0,0,0 },{ 128,192,0,64 },{ 128,192,64,0 }, 75 | { 64,0,128,192 },{ 64,0,192,128 },{ 0,0,0,0 },{ 0,0,0,0 }, 76 | { 0,0,0,0 },{ 128,0,192,64 },{ 0,0,0,0 },{ 128,64,192,0 }, 77 | { 0,0,0,0 },{ 0,0,0,0 },{ 0,0,0,0 },{ 0,0,0,0 }, 78 | { 0,0,0,0 },{ 0,0,0,0 },{ 0,0,0,0 },{ 0,0,0,0 }, 79 | { 128,0,64,192 },{ 0,0,0,0 },{ 0,0,0,0 },{ 0,0,0,0 }, 80 | { 192,0,64,128 },{ 192,0,128,64 },{ 0,0,0,0 },{ 192,64,128,0 }, 81 | { 128,64,0,192 },{ 0,0,0,0 },{ 0,0,0,0 },{ 0,0,0,0 }, 82 | { 192,64,0,128 },{ 0,0,0,0 },{ 192,128,0,64 },{ 192,128,64,0 } } }; 83 | }; -------------------------------------------------------------------------------- /libraries/Rendering/SkyBoxCube.cpp: -------------------------------------------------------------------------------- 1 | #include "SkyBoxCube.h" 2 | 3 | SkyBoxCube::SkyBoxCube() : Mesh(cubeVertices, noNormals, cubeIndices) 4 | { 5 | // this constructor initlializes the Mesh with the pre-defined vertices and indices, and with empty normals 6 | } 7 | 8 | std::vector SkyBoxCube::cubeVertices = 9 | { 10 | // front 11 | {-1.0, -1.0, 1.0}, 12 | {1.0, -1.0, 1.0}, 13 | {1.0, 1.0, 1.0}, 14 | {-1.0, 1.0, 1.0}, 15 | // back 16 | {-1.0, -1.0, -1.0}, 17 | {1.0, -1.0, -1.0}, 18 | {1.0, 1.0, -1.0}, 19 | {-1.0, 1.0, -1.0}, 20 | }; 21 | 22 | std::vector SkyBoxCube::cubeIndices = 23 | { 24 | // front 25 | 0, 1, 2, 26 | 2, 3, 0, 27 | // top 28 | 1, 5, 6, 29 | 6, 2, 1, 30 | // back 31 | 7, 6, 5, 32 | 5, 4, 7, 33 | // bottom 34 | 4, 0, 3, 35 | 3, 7, 4, 36 | // left 37 | 4, 5, 1, 38 | 1, 0, 4, 39 | // right 40 | 3, 2, 6, 41 | 6, 7, 3, 42 | }; 43 | 44 | std::vector SkyBoxCube::noNormals = 45 | { 46 | {0.0, 0.0, 0.0}, 47 | }; 48 | -------------------------------------------------------------------------------- /libraries/Rendering/SkyBoxCube.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Mesh.h" 4 | 5 | class SkyBoxCube : public Mesh 6 | { 7 | public: 8 | SkyBoxCube(); 9 | private: 10 | static std::vector cubeVertices; 11 | static std::vector cubeIndices; 12 | static std::vector noNormals; 13 | }; 14 | -------------------------------------------------------------------------------- /libraries/Rendering/SparseVoxelOctree.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | using namespace gl; 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include "Mesh.h" 11 | #include "ShaderProgram.h" 12 | 13 | class SparseVoxelOctree 14 | { 15 | public: 16 | SparseVoxelOctree(const std::vector>& scene, const size_t depth); 17 | 18 | void bind() const; 19 | 20 | void update(); 21 | 22 | glm::vec3 getBMin() const; 23 | glm::vec3 getBMax() const; 24 | 25 | protected: 26 | 27 | ShaderProgram m_voxelGenShader{ { 28 | Shader{ "SparseVoxelOctree/VoxelGen.vert", GL_VERTEX_SHADER}, 29 | Shader{ "SparseVoxelOctree/VoxelGen.geom", GL_GEOMETRY_SHADER}, 30 | Shader{ "SparseVoxelOctree/VoxelGen.frag", GL_FRAGMENT_SHADER} 31 | } }; 32 | 33 | ShaderProgram m_flagShader{ { 34 | Shader{ "SparseVoxelOctree/FlagNodes.comp", GL_COMPUTE_SHADER } 35 | } }; 36 | 37 | ShaderProgram m_nodeCreationShader{ { 38 | Shader{ "SparseVoxelOctree/CreateNodes.comp", GL_COMPUTE_SHADER } 39 | } }; 40 | 41 | ShaderProgram m_leafInitShader{ { 42 | Shader{ "SparseVoxelOctree/InitLeafNodes.comp", GL_COMPUTE_SHADER } 43 | } }; 44 | 45 | ShaderProgram m_mipMapShader{ { 46 | Shader{ "SparseVoxelOctree/MipMapNodes.comp", GL_COMPUTE_SHADER } 47 | } }; 48 | 49 | Buffer m_voxelFragmentList{GL_SHADER_STORAGE_BUFFER}; // vec4 50 | Buffer m_voxelCounter{GL_ATOMIC_COUNTER_BUFFER}; // uint32 51 | Buffer m_voxelFragmentColor{GL_SHADER_STORAGE_BUFFER}; // vec4 52 | 53 | Buffer m_nodePool{GL_SHADER_STORAGE_BUFFER}; // int32 54 | Buffer m_nodeCounter{GL_ATOMIC_COUNTER_BUFFER}; // uint32 55 | Buffer m_nodeColor{GL_SHADER_STORAGE_BUFFER}; // vec4 56 | 57 | std::shared_ptr> m_startIndexUniform; 58 | std::shared_ptr> m_modelMatrixUniform; 59 | 60 | int64_t m_N; 61 | int64_t m_depth; 62 | const std::vector>& m_scene; 63 | 64 | glm::vec3 m_bmin; 65 | glm::vec3 m_bmax; 66 | }; 67 | -------------------------------------------------------------------------------- /libraries/Rendering/Texture.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | using namespace gl; 4 | #include 5 | #include 6 | 7 | enum class TextureLoadInfo 8 | { 9 | None, 10 | Transparent, 11 | Opaque, 12 | Other 13 | }; 14 | 15 | class Texture 16 | { 17 | public: 18 | explicit Texture(GLenum target = GL_TEXTURE_2D, GLenum minFilter = GL_LINEAR_MIPMAP_LINEAR, GLenum maxFilter = GL_LINEAR); 19 | virtual ~Texture(); 20 | virtual TextureLoadInfo loadFromFile(const std::filesystem::path& texturePath, GLenum internalFormat = GL_RGBA8, GLenum format = GL_RGBA, GLenum type = GL_UNSIGNED_BYTE, int desiredChannels = 4); 21 | virtual GLuint64 generateHandle(); 22 | 23 | template()))> 24 | void initWithData1D(const T& container, GLint width, GLenum internalFormat = GL_RGBA8, GLenum format = GL_RGBA, GLenum type = GL_UNSIGNED_BYTE); 25 | 26 | template()))> 27 | void initWithData2D(const T& container, GLint width, GLint height, GLenum internalFormat = GL_RGBA8, GLenum format = GL_RGBA, GLenum type = GL_UNSIGNED_BYTE); 28 | 29 | template()))> 30 | void initWithData3D(const T& container, GLint width, GLint height, GLint depth, GLenum internalFormat = GL_RGBA8, GLenum format = GL_RGBA, GLenum type = GL_UNSIGNED_BYTE); 31 | 32 | virtual void initWithoutData(int width, int height, GLenum internalFormat); 33 | virtual void initWithoutDataMultiSample(int width, int height, GLenum internalFormat, GLsizei samples, GLboolean fixedSampleLocations); 34 | virtual void initWithoutData3D(int width, int height, int depth, GLenum internalFormat); 35 | 36 | void setWrap(GLenum wrapS, GLenum wrapT) const; 37 | void setWrap(GLenum wrapS, GLenum wrapT, GLenum wrapR) const; 38 | void setMinMagFilter(GLenum minFilter, GLenum magFilter) const; 39 | void generateMipmap() const; 40 | 41 | template 42 | void clearTexture(GLenum format, GLenum type, T data, GLint level = 0) const 43 | { 44 | glClearTexImage(m_name, level, format, type, &data); 45 | } 46 | 47 | TextureLoadInfo getTextureLoadInfo() const; 48 | 49 | GLuint64 getHandle() const; 50 | GLuint getName() const; 51 | 52 | int getWidth() const; 53 | int getHeight() const; 54 | 55 | protected: 56 | GLuint m_name; 57 | GLuint64 m_handle = 0; 58 | int m_width = 0; 59 | int m_height = 0; 60 | int m_depth = 0; 61 | 62 | TextureLoadInfo m_textureLoadInfo = TextureLoadInfo::None; 63 | }; 64 | 65 | template 66 | void Texture::initWithData1D(const T& container, GLint width, GLenum internalFormat, GLenum format, GLenum type) 67 | { 68 | glEnable(GL_TEXTURE_1D); 69 | const auto numLevels = static_cast(glm::ceil(glm::log2(static_cast(width)))); 70 | glTextureStorage1D(m_name, numLevels, internalFormat, width); 71 | glTextureSubImage1D(m_name, 0, 0, width, format, type, container.data()); 72 | generateMipmap(); 73 | m_width = width; 74 | } 75 | 76 | template 77 | void Texture::initWithData2D(const T& container, GLint width, GLint height, GLenum internalFormat, GLenum format, GLenum type) 78 | { 79 | glEnable(GL_TEXTURE_2D); 80 | const auto numLevels = static_cast(glm::ceil(glm::log2(static_cast(glm::max(width, height))))); 81 | glTextureStorage2D(m_name, numLevels, internalFormat, width, height); 82 | glTextureSubImage2D(m_name, 0, 0, 0, width, height, format, type, container.data()); 83 | generateMipmap(); 84 | m_width = width; 85 | m_height = height; 86 | } 87 | 88 | template 89 | void Texture::initWithData3D(const T& container, GLint width, GLint height, GLint depth, GLenum internalFormat, GLenum format, GLenum type) 90 | { 91 | glEnable(GL_TEXTURE_3D); 92 | const auto numLevels = static_cast(glm::ceil(glm::log2(glm::max(glm::max(width, height), depth)))); 93 | glTextureStorage3D(m_name, numLevels, internalFormat, width, height, depth); 94 | glTextureSubImage3D(m_name, 0, 0, 0, 0, width, height, depth, format, type, container.data()); 95 | generateMipmap(); 96 | m_width = width; 97 | m_height = height; 98 | m_depth = depth; 99 | } 100 | -------------------------------------------------------------------------------- /libraries/Rendering/Trackball.cpp: -------------------------------------------------------------------------------- 1 | #include "Trackball.h" 2 | 3 | #include 4 | #include 5 | #include "../Utils/UtilCollection.h" 6 | 7 | Trackball::Trackball(int width, int height, float radius) : Camera(width, height), m_radius(radius) 8 | { 9 | Trackball::reset(); 10 | } 11 | 12 | void Trackball::reset() 13 | { 14 | Camera::reset(); 15 | m_pos = glm::vec3(0.0f, 0.0f, m_radius); 16 | m_viewMatrix = lookAt(m_center + m_pos, m_center, m_up); 17 | } 18 | 19 | void Trackball::setCenter(glm::vec3 center) 20 | { 21 | m_center = center; 22 | } 23 | 24 | void Trackball::update(GLFWwindow* window) 25 | { 26 | Camera::update(window); 27 | 28 | if (glfwGetKey(window, GLFW_KEY_UP) == GLFW_PRESS) 29 | { 30 | m_radius -= m_sensitivity; 31 | } 32 | if (glfwGetKey(window, GLFW_KEY_DOWN) == GLFW_PRESS) 33 | { 34 | m_radius += m_sensitivity; 35 | } 36 | if (m_radius < 0.1f) 37 | { 38 | m_radius = 0.1f; 39 | } 40 | 41 | m_pos.x = m_center.x + m_radius * sin(m_theta) * sin(m_phi); 42 | m_pos.y = m_center.y + m_radius * cos(m_theta); 43 | m_pos.z = m_center.z + m_radius * sin(m_theta) * cos(m_phi); 44 | 45 | m_viewMatrix = lookAt(m_pos, m_center, m_up); 46 | 47 | if constexpr(util::debugmode) 48 | { 49 | // TODO implement proper "pilot view" Trackball so the trackball doesn't overflow 50 | if (std::isnan(m_viewMatrix[0][0])) 51 | throw std::runtime_error("NaN in View Matrix"); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /libraries/Rendering/Trackball.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Camera.h" 4 | 5 | class Trackball : public Camera 6 | { 7 | public: 8 | Trackball(int width, int height, float radius); 9 | 10 | /** 11 | * \brief Updates the view matrix based on mouse input 12 | * \param window 13 | */ 14 | void update(GLFWwindow* window) override; 15 | 16 | void reset() override; 17 | 18 | void setCenter(glm::vec3 center); 19 | 20 | private: 21 | 22 | float m_radius; 23 | }; 24 | -------------------------------------------------------------------------------- /libraries/Rendering/Uniform.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | using namespace gl; 6 | #include 7 | 8 | template 9 | class Uniform 10 | { 11 | public: 12 | Uniform(const std::string& name, T content) : 13 | m_name(name), m_content(content) 14 | { 15 | }; 16 | 17 | void registerUniformWithShaderProgram(GLuint); 18 | 19 | /** 20 | * \brief returns the uniform name 21 | * \return uniform name 22 | */ 23 | const std::string& getName() const; 24 | 25 | /** 26 | * \brief returns the current content 27 | * \return current content 28 | */ 29 | T getContent() const; 30 | 31 | /** 32 | * \brief returns a reference to the current content 33 | * \return current content 34 | */ 35 | T& getContentRef(); 36 | 37 | /** 38 | * \brief returns the 'content-has-been-changed'-flag 39 | * \return change flag 40 | */ 41 | bool getChangeFlag(GLuint shaderProgramHandle) const; 42 | 43 | /** 44 | * \brief sets the (cpu-sided) content and the change flag 45 | * \param content 46 | */ 47 | void setContent(const T& content); 48 | 49 | /** 50 | * \brief resets all change flags 51 | */ 52 | void hasBeenUpdated(GLuint shaderProgramHandle); 53 | 54 | private: 55 | std::string m_name; 56 | T m_content; 57 | 58 | // holds the shader program handles and the flag if the uniform is up-to-date in the corresponding shaderprogram 59 | std::unordered_map m_associatedShaderProgramUpdatedFlags; 60 | }; 61 | 62 | template 63 | void Uniform::registerUniformWithShaderProgram(const GLuint shaderProgramHandle) 64 | { 65 | m_associatedShaderProgramUpdatedFlags.insert({shaderProgramHandle, true}); 66 | } 67 | 68 | template 69 | bool Uniform::getChangeFlag(const GLuint shaderProgramHandle) const 70 | { 71 | return m_associatedShaderProgramUpdatedFlags.at(shaderProgramHandle); 72 | } 73 | 74 | template 75 | const std::string& Uniform::getName() const 76 | { 77 | return m_name; 78 | } 79 | 80 | template 81 | void Uniform::hasBeenUpdated(const GLuint shaderProgramHandle) 82 | { 83 | m_associatedShaderProgramUpdatedFlags.at(shaderProgramHandle) = false; 84 | } 85 | 86 | template 87 | T Uniform::getContent() const 88 | { 89 | return m_content; 90 | } 91 | 92 | template 93 | T& Uniform::getContentRef() 94 | { 95 | for (auto& flags : m_associatedShaderProgramUpdatedFlags) 96 | flags.second = true; 97 | return m_content; 98 | } 99 | 100 | template 101 | void Uniform::setContent(const T& content) 102 | { 103 | for (auto& flags : m_associatedShaderProgramUpdatedFlags) 104 | flags.second = true; 105 | m_content = content; 106 | } 107 | -------------------------------------------------------------------------------- /libraries/Rendering/VertexArray.cpp: -------------------------------------------------------------------------------- 1 | #include "VertexArray.h" 2 | #include "Utils/UtilCollection.h" 3 | 4 | VertexArray::VertexArray() 5 | { 6 | glCreateVertexArrays(1, &m_vaoHandle); 7 | } 8 | 9 | VertexArray::~VertexArray() 10 | { 11 | if (glfwGetCurrentContext() != nullptr) 12 | { 13 | glDeleteVertexArrays(1, &m_vaoHandle); 14 | } 15 | util::getGLerror(__LINE__, __FUNCTION__); 16 | } 17 | 18 | void VertexArray::bind() const 19 | { 20 | glBindVertexArray(m_vaoHandle); 21 | } 22 | 23 | void VertexArray::connectIndexBuffer(Buffer& buffer) const 24 | { 25 | if (buffer.getTarget() != GL_ELEMENT_ARRAY_BUFFER) 26 | throw std::runtime_error("Only index buffers can be conntected using connectIndexBuffer"); 27 | glVertexArrayElementBuffer(m_vaoHandle, buffer.getHandle()); 28 | } 29 | 30 | void VertexArray::connectBuffer(const Buffer& buffer, BufferBindings::VertexAttributeLocation location, GLuint size, GLenum type, GLboolean normalized) const 31 | { 32 | int index = static_cast(location); 33 | glEnableVertexArrayAttrib(m_vaoHandle, index); 34 | // only works for non-integer, non-long/double types 35 | // use the overloaded function below for custom strides/offsets 36 | 37 | // stupid GLsizei workaround stuff: 38 | auto actualSize = buffer.getTypeSize(); 39 | if (actualSize > std::numeric_limits::max()) 40 | throw std::runtime_error("Buffer size too large"); 41 | 42 | glVertexArrayVertexBuffer(m_vaoHandle, index, buffer.getHandle(), 0, static_cast(buffer.getTypeSize())); 43 | glVertexArrayAttribFormat(m_vaoHandle, index, size, type, normalized, 0); 44 | glVertexArrayAttribBinding(m_vaoHandle, index, index); 45 | } 46 | 47 | void VertexArray::connectBuffer(const Buffer& buffer, GLuint index, GLuint size, GLenum type, GLboolean normalized, GLuint stride, GLuint offset, GLuint relativeOffset) const 48 | { 49 | glEnableVertexArrayAttrib(m_vaoHandle, index); 50 | glVertexArrayVertexBuffer(m_vaoHandle, index, buffer.getHandle(), offset, stride); 51 | glVertexArrayAttribFormat(m_vaoHandle, index, size, type, normalized, relativeOffset); 52 | glVertexArrayAttribBinding(m_vaoHandle, index, index); 53 | } 54 | -------------------------------------------------------------------------------- /libraries/Rendering/VertexArray.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Buffer.h" 4 | #include "Binding.h" 5 | 6 | class VertexArray 7 | { 8 | public: 9 | VertexArray(); 10 | ~VertexArray(); 11 | 12 | /** 13 | * \brief connects an index buffer (GL_ELEMENT_ARRAY_BUFFER) to the vao 14 | * \param buffer the index buffer to be connected 15 | */ 16 | void connectIndexBuffer(Buffer& buffer) const; 17 | 18 | /** 19 | * \brief binds the VAO 20 | */ 21 | void bind() const; 22 | 23 | /** 24 | * \brief connects a buffer to this vao, assumes stride/pointer = 0 25 | * \param buffer buffer to connect to this vao 26 | * \param index location to be used 27 | * \param size elements per buffer primitive 28 | * \param type GL data type 29 | * \param normalized specifies if fixed point attributes should be normalized 30 | * \warning only works for 32 bit (because of stride) floating point (because of missing I or L) types for now. 31 | */ 32 | void connectBuffer(const Buffer& buffer, BufferBindings::VertexAttributeLocation location, GLuint size, GLenum type, GLboolean normalized) const; 33 | 34 | /** 35 | * \brief connects a buffer to this vao 36 | * \param buffer buffer to connect to this vao 37 | * \param index location to be used 38 | * \param size elements per buffer primitive 39 | * \param type GL data type 40 | * \param normalized specifies if fixed point attributes should be normalized 41 | * \param stride byte offset between vertex attributes 42 | * \param offset offset of the first element of the buffer 43 | * \param relativeOffset distance between elements within the buffer 44 | */ 45 | void connectBuffer(const Buffer& buffer, GLuint index, GLuint size, GLenum type, GLboolean normalized, GLuint stride, GLuint offset, GLuint relativeOffset) const; 46 | private: 47 | GLuint m_vaoHandle; 48 | }; 49 | -------------------------------------------------------------------------------- /libraries/Rendering/VoxelDebugRenderer.cpp: -------------------------------------------------------------------------------- 1 | #include "VoxelDebugRenderer.h" 2 | #include "Shader.h" 3 | #include "ShaderProgram.h" 4 | #include "Camera.h" 5 | #include "glm/glm.hpp" 6 | #include "glm/gtc/matrix_transform.hpp" 7 | #include "imgui/imgui.h" 8 | 9 | VoxelDebugRenderer::VoxelDebugRenderer(const glm::ivec3 gridDim, const ScreenInfo screenInfo) 10 | : m_gridDim(gridDim), m_screenInfo(screenInfo), m_camera(m_screenInfo.width, m_screenInfo.height), 11 | m_shaders{ Shader{ "voxeldebug.vert", GL_VERTEX_SHADER }, Shader{ "voxeldebug.geom", GL_GEOMETRY_SHADER }, Shader{ "voxeldebug.frag", GL_FRAGMENT_SHADER } }, 12 | m_sp(m_shaders) 13 | { 14 | m_numVoxels = gridDim.x * gridDim.y * gridDim.z; 15 | m_projMat = glm::perspective(glm::radians(60.0f), m_screenInfo.width / static_cast(m_screenInfo.height), m_screenInfo.near, m_screenInfo.far); 16 | glm::mat4 view = m_camera.getView(); 17 | m_viewUniform = std::make_shared>("dViewMat", view); 18 | const auto projUniform = std::make_shared>("dProjMat", m_projMat); 19 | const auto gridDimUniform = std::make_shared>("gridDim", gridDim); 20 | m_voxelSizeUniform = std::make_shared>("voxelSize", m_voxelSize); 21 | m_positionSourceUniform = std::make_shared>("positionSource", 0); 22 | m_dataModeUniform = std::make_shared>("dataMode", 0); 23 | m_sp.addUniform(gridDimUniform); 24 | m_sp.addUniform(m_viewUniform); 25 | m_sp.addUniform(projUniform); 26 | m_sp.addUniform(m_voxelSizeUniform); 27 | m_sp.addUniform(m_positionSourceUniform); 28 | m_sp.addUniform(m_dataModeUniform); 29 | } 30 | 31 | void VoxelDebugRenderer::updateCamera(GLFWwindow* window) 32 | { 33 | m_camera.update(window); 34 | m_viewUniform->setContent(m_camera.getView()); 35 | } 36 | 37 | void VoxelDebugRenderer::draw() const 38 | { 39 | m_sp.use(); 40 | m_sp.updateUniforms(); 41 | 42 | m_emptyVao.bind(); 43 | glDrawArrays(GL_POINTS, 0, m_numVoxels); 44 | glBindVertexArray(0); 45 | } 46 | 47 | void VoxelDebugRenderer::drawGuiContent() 48 | { 49 | ImGui::Text("Voxel Debug Renderer Settings"); 50 | ImGui::Separator(); 51 | if (ImGui::DragFloat("Voxel Size", &m_voxelSize, 0.0001f, 0.0f, 0.05f, "%.6f")) 52 | { 53 | m_voxelSizeUniform->setContent(m_voxelSize); 54 | } 55 | ImGui::Checkbox("Render Wireframe", &m_wireframe); 56 | if (m_wireframe) 57 | { 58 | glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 59 | } 60 | else 61 | { 62 | glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 63 | } 64 | ImGui::Text("Voxel position source"); 65 | ImGui::RadioButton("Pos = Image.xyz", &m_positionSourceUniform->getContentRef(), 0); ImGui::SameLine(); 66 | ImGui::RadioButton("Pos = Grid coords", &m_positionSourceUniform->getContentRef(), 1); 67 | 68 | ImGui::Text("Voxel color source"); 69 | ImGui::RadioButton("Col = Image.xyz", &m_dataModeUniform->getContentRef(), 0); ImGui::SameLine(); 70 | ImGui::RadioButton("Col = Image.w", &m_dataModeUniform->getContentRef(), 1); ImGui::SameLine(); 71 | ImGui::RadioButton("Col = Grid coords", &m_dataModeUniform->getContentRef(), 2); 72 | ImGui::Separator(); 73 | ImGui::Text("Reload Shaders"); 74 | m_sp.showReloadShaderGUIContent(m_shaders, "DebugRenderer Shaderprogram"); 75 | } 76 | 77 | void VoxelDebugRenderer::drawCameraGuiContent() 78 | { 79 | if (ImGui::Button("Reset Camera")) 80 | { 81 | m_camera.reset(); 82 | m_viewUniform->setContent(m_camera.getView()); 83 | } 84 | } -------------------------------------------------------------------------------- /libraries/Rendering/VoxelDebugRenderer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "Uniform.h" 5 | #include "ShaderProgram.h" 6 | #include "glm/glm.hpp" 7 | #include "VertexArray.h" 8 | #include "Trackball.h" 9 | #include "Pilotview.h" 10 | 11 | struct ScreenInfo 12 | { 13 | int width; 14 | int height; 15 | float near; 16 | float far; 17 | }; 18 | 19 | class Shader; 20 | class Camera; 21 | class VoxelDebugRenderer 22 | { 23 | public: 24 | VoxelDebugRenderer(const glm::ivec3 gridDim, const ScreenInfo screenInfo); 25 | void updateCamera(GLFWwindow* window); 26 | void draw() const; 27 | void drawGuiContent(); 28 | void drawCameraGuiContent(); 29 | 30 | private: 31 | glm::ivec3 m_gridDim; 32 | ScreenInfo m_screenInfo; 33 | Pilotview m_camera; 34 | std::vector m_shaders; 35 | ShaderProgram m_sp; 36 | int m_numVoxels; 37 | float m_voxelSize = 0.004f; 38 | std::shared_ptr> m_voxelSizeUniform; 39 | std::shared_ptr> m_positionSourceUniform; 40 | std::shared_ptr> m_dataModeUniform; 41 | glm::mat4 m_projMat; 42 | std::shared_ptr> m_viewUniform; 43 | bool m_wireframe = false; 44 | VertexArray m_emptyVao; 45 | }; -------------------------------------------------------------------------------- /libraries/Utils/Timer.cpp: -------------------------------------------------------------------------------- 1 | #include "Timer.h" 2 | #include "imgui/imgui.h" 3 | 4 | Timer::Timer() 5 | { 6 | glCreateQueries(GL_TIME_ELAPSED, 1, &m_query); 7 | } 8 | 9 | Timer::~Timer() 10 | { 11 | if (glfwGetCurrentContext() != nullptr) 12 | { 13 | glDeleteQueries(1, &m_query); 14 | } 15 | util::getGLerror(__LINE__, __FUNCTION__); 16 | } 17 | 18 | void Timer::start() const 19 | { 20 | glBeginQuery(GL_TIME_ELAPSED, m_query); 21 | } 22 | 23 | void Timer::stop() 24 | { 25 | glEndQuery(GL_TIME_ELAPSED); 26 | while (!m_done) 27 | { 28 | glGetQueryObjectiv(m_query, GL_QUERY_RESULT_AVAILABLE, &m_done); 29 | } 30 | glGetQueryObjectuiv(m_query, GL_QUERY_RESULT, &m_elapsedTime); 31 | m_ftimes.push_back(m_elapsedTime / 1000000.f); 32 | if (m_ftimes.size() > 1000) 33 | { 34 | m_ftimes.erase(m_ftimes.begin()); 35 | } 36 | util::getGLerror(__LINE__, __FUNCTION__); 37 | } 38 | 39 | void Timer::drawGuiWindow(GLFWwindow* window) 40 | { 41 | ImGui::SetNextWindowSize(ImVec2(300, 100), ImGuiSetCond_FirstUseEver); 42 | ImGui::Begin("Performance"); 43 | drawGuiContent(window); 44 | ImGui::End(); 45 | } 46 | 47 | void Timer::drawGuiContent(GLFWwindow* window, bool compact) 48 | { 49 | auto flaccTime = 0.0f; 50 | if (m_ftimes.size() > 21) 51 | { 52 | for (auto i = m_ftimes.size() - 21; i < m_ftimes.size(); ++i) 53 | { 54 | flaccTime += m_ftimes.at(i); 55 | } 56 | flaccTime /= 20.0f; 57 | } 58 | //show everything in one line 59 | if (compact) 60 | { 61 | const float availableWidth = ImGui::GetContentRegionAvailWidth(); 62 | if (availableWidth >= 300) 63 | ImGui::SameLine(ImGui::GetWindowContentRegionWidth() - 300); 64 | else if (availableWidth >= 70) 65 | ImGui::SameLine(ImGui::GetWindowContentRegionWidth() - 70); 66 | 67 | ImGui::PushItemWidth(70); 68 | ImGui::Text("%.3f ms", flaccTime); 69 | if (ImGui::IsItemClicked()) util::saveFBOtoFile("demo1", window); 70 | if (ImGui::IsItemHovered()) 71 | { 72 | ImGui::BeginTooltip(); 73 | ImGui::Text("Click to save FBO"); 74 | ImGui::EndTooltip(); 75 | } 76 | //don't show plot if not enough space 77 | if (availableWidth >= 300) 78 | { 79 | ImGui::SameLine(ImGui::GetWindowContentRegionWidth() - 230); 80 | ImGui::PushItemWidth(240); 81 | const auto offset = static_cast(m_ftimes.size() <= 240 ? m_ftimes.size() - 1 : 240); 82 | ImGui::PlotLines("", &m_ftimes.back() - offset, offset, 0, nullptr, 0.0f, std::numeric_limits::max()); 83 | } 84 | } 85 | else 86 | { 87 | ImGui::PlotLines("Frametime", m_ftimes.data(), static_cast(m_ftimes.size()), 0, nullptr, 0.0f, std::numeric_limits::max()); 88 | if (ImGui::Button("Save FBO")) 89 | { 90 | util::saveFBOtoFile("demo1", window); 91 | } 92 | ImGui::SameLine(); 93 | ImGui::Value("Frametime (milliseconds)", flaccTime); 94 | } 95 | } -------------------------------------------------------------------------------- /libraries/Utils/Timer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | using namespace gl; 6 | 7 | #include "Utils/UtilCollection.h" 8 | 9 | class Timer 10 | { 11 | public: 12 | Timer(); 13 | ~Timer(); 14 | 15 | /** 16 | * \brief starts the GPU timer 17 | */ 18 | void start() const; 19 | 20 | /** 21 | * \brief stops the GPU timer 22 | */ 23 | void stop(); 24 | 25 | /** 26 | * \brief draws an imgui window with the frametime and a graph 27 | * \param window 28 | */ 29 | void drawGuiWindow(GLFWwindow* window); 30 | 31 | /** 32 | * \brief returns conent for imgui with the frametime and a graph 33 | * \param window 34 | * \param compact show compact gui in one line 35 | */ 36 | void drawGuiContent(GLFWwindow* window, bool compact = false); 37 | 38 | private: 39 | std::vector m_ftimes; 40 | GLuint m_query; 41 | GLuint m_elapsedTime = 0U; 42 | int m_done = false; 43 | }; 44 | -------------------------------------------------------------------------------- /libraries/Utils/UtilCollection.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | using namespace gl; 9 | #include 10 | 11 | namespace util 12 | { 13 | /** 14 | * \brief converts a GLubyte* 'char array' to a std::string 15 | * \param content input GLubyte* 'char array' 16 | * \return std::string with same text as input 17 | */ 18 | std::string convertGLubyteToString(const GLubyte* content); 19 | 20 | /** 21 | * \brief prints the OpenGL driver/vendor info to the console 22 | */ 23 | void printOpenGLInfo(); 24 | 25 | /** 26 | * \brief sets up a GLFW window/context 27 | * \param width window width in pixels 28 | * \param height window height in pixels 29 | * \param name window name 30 | * \return window pointer for later use by glfw functions 31 | */ 32 | GLFWwindow* setupGLFWwindow(unsigned int width, unsigned int height, std::string name); 33 | 34 | /** 35 | * \brief inits the graphics API 36 | */ 37 | void initGL(); 38 | 39 | /** 40 | * \brief queries all available OpenGL extensions 41 | * \return vector of extensions as strings 42 | */ 43 | std::vector getGLExtenstions(); 44 | 45 | /** 46 | * \brief checks the OpenGL error stack (old way of getting errors) 47 | * \param line use __LINE__ 48 | * \param function use __FUNCTION__ 49 | */ 50 | void getGLerror(int line, std::string function); 51 | 52 | /** 53 | * \brief saves the FBO content to a PNG file (starts a new thread) 54 | * \param name output filename 55 | * \param window glfw window 56 | */ 57 | void saveFBOtoFile(std::string name, GLFWwindow* window); 58 | 59 | /** 60 | * \brief enabled OpenGL debug callback (new way of getting errors) 61 | */ 62 | void enableDebugCallback(); 63 | 64 | /** 65 | * \brief Calls the provided function and returns the number of milliseconds 66 | * that it takes to call that function. 67 | * \param f function to call 68 | */ 69 | template 70 | double timeCall(Function&& f) 71 | { 72 | auto begin = glfwGetTime(); 73 | f(); 74 | glFinish(); 75 | return (glfwGetTime() - begin) * 1000; 76 | } 77 | 78 | /** 79 | * \brief Container for overloaded functions/lambdas 80 | */ 81 | template 82 | struct overload : Ts... { using Ts::operator()...; }; 83 | 84 | /** 85 | * \brief Makes an overloaded function/lambda object 86 | * \param fs The functions to be overloaded 87 | */ 88 | template 89 | overload(Ts...)->overload; 90 | 91 | 92 | static const std::filesystem::path gs_shaderPath = std::filesystem::current_path().parent_path().parent_path().append("shaders"); 93 | static const std::filesystem::path gs_resourcesPath = std::filesystem::current_path().parent_path().parent_path().append("resources"); 94 | 95 | #ifdef _DEBUG 96 | static constexpr bool debugmode = true; 97 | #else 98 | static constexpr bool debugmode = false; 99 | #endif 100 | 101 | } 102 | -------------------------------------------------------------------------------- /resources/Newport_Loft/Newport_Loft.ibl: -------------------------------------------------------------------------------- 1 | [Header] 2 | ICOfile = "Newport_Loft_Thumb.jpg" 3 | PREVIEWfile = "Newport_Loft_preview.jpg" 4 | Name = "Newport Loft" 5 | Author = "Blochi" 6 | Location = "Los Angeles" 7 | Comment = "Indoor, bright upscale loft, indirect sunlight" 8 | GEOlat = 33.6196449484317 9 | GEOlong = -117.92401134967804 10 | Link = "http://www.hdrlabs.com/sibl/archive.html" 11 | Date = "2007:10:08" 12 | Time = "10:44:00" 13 | Height = 1.5 14 | North = 0.48 15 | 16 | [Background] 17 | BGfile = "Newport_Loft_8k.jpg" 18 | BGmap = 1 19 | BGu = 0.000000 20 | BGv = 0.000000 21 | BGheight = 4000 22 | 23 | [Enviroment] 24 | EVfile = "Newport_Loft_Env.hdr" 25 | EVmap = 1 26 | EVu = 0.000000 27 | EVv = 0.000000 28 | EVheight = 180 29 | EVmulti = 1.000000 30 | EVgamma = 1.700000 31 | 32 | [Reflection] 33 | REFfile = "Newport_Loft_Ref.hdr" 34 | REFmap = 1 35 | REFu = 0.000000 36 | REFv = 0.000000 37 | REFheight = 800 38 | REFmulti = 1.000000 39 | REFgamma = 1.700000 40 | 41 | 42 | -------------------------------------------------------------------------------- /resources/Newport_Loft/Newport_Loft_8k.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Max1412/Graphics2/7bc33b4f8472f94a91d1f589ba061487498bc50e/resources/Newport_Loft/Newport_Loft_8k.jpg -------------------------------------------------------------------------------- /resources/Newport_Loft/Newport_Loft_Env.hdr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Max1412/Graphics2/7bc33b4f8472f94a91d1f589ba061487498bc50e/resources/Newport_Loft/Newport_Loft_Env.hdr -------------------------------------------------------------------------------- /resources/Newport_Loft/Newport_Loft_Ref.hdr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Max1412/Graphics2/7bc33b4f8472f94a91d1f589ba061487498bc50e/resources/Newport_Loft/Newport_Loft_Ref.hdr -------------------------------------------------------------------------------- /resources/Newport_Loft/Newport_Loft_Thumb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Max1412/Graphics2/7bc33b4f8472f94a91d1f589ba061487498bc50e/resources/Newport_Loft/Newport_Loft_Thumb.jpg -------------------------------------------------------------------------------- /resources/Newport_Loft/Newport_Loft_preview.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Max1412/Graphics2/7bc33b4f8472f94a91d1f589ba061487498bc50e/resources/Newport_Loft/Newport_Loft_preview.jpg -------------------------------------------------------------------------------- /resources/cover2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Max1412/Graphics2/7bc33b4f8472f94a91d1f589ba061487498bc50e/resources/cover2.png -------------------------------------------------------------------------------- /resources/screenshots/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Max1412/Graphics2/7bc33b4f8472f94a91d1f589ba061487498bc50e/resources/screenshots/1.png -------------------------------------------------------------------------------- /resources/skybox/skybox0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Max1412/Graphics2/7bc33b4f8472f94a91d1f589ba061487498bc50e/resources/skybox/skybox0.jpg -------------------------------------------------------------------------------- /resources/skybox/skybox1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Max1412/Graphics2/7bc33b4f8472f94a91d1f589ba061487498bc50e/resources/skybox/skybox1.jpg -------------------------------------------------------------------------------- /resources/skybox/skybox2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Max1412/Graphics2/7bc33b4f8472f94a91d1f589ba061487498bc50e/resources/skybox/skybox2.jpg -------------------------------------------------------------------------------- /resources/skybox/skybox3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Max1412/Graphics2/7bc33b4f8472f94a91d1f589ba061487498bc50e/resources/skybox/skybox3.jpg -------------------------------------------------------------------------------- /resources/skybox/skybox4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Max1412/Graphics2/7bc33b4f8472f94a91d1f589ba061487498bc50e/resources/skybox/skybox4.jpg -------------------------------------------------------------------------------- /resources/skybox/skybox5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Max1412/Graphics2/7bc33b4f8472f94a91d1f589ba061487498bc50e/resources/skybox/skybox5.jpg -------------------------------------------------------------------------------- /set_vcpkg_path.ps1: -------------------------------------------------------------------------------- 1 | Function Get-FileName 2 | { 3 | [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null 4 | 5 | $OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog 6 | $OpenFileDialog.initialDirectory = $(get-location).Path 7 | $OpenFileDialog.filter = "CMake (*.cmake)| *.cmake" 8 | $OpenFileDialog.title = "Select vcpkg.cmake" 9 | $OpenFileDialog.ShowDialog() | Out-Null 10 | $OpenFileDialog.filename 11 | } 12 | 13 | [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null 14 | [System.Windows.Forms.MessageBox]::Show("Please select the vcpkg.cmake file in the next dialog. 15 | It is usually located in [vcpkg-root]/scripts/buildsystems/","Graphics2",0) 16 | 17 | $vcpkgpath = Get-FileName 18 | if($vcpkgpath -eq ""){ 19 | [System.Windows.Forms.MessageBox]::Show("Error setting the path.","Graphics2",0) 20 | Exit 21 | } 22 | 23 | $cmakesettingspath = "./CMakeSettings.json" 24 | 25 | $a = Get-Content $cmakesettingspath -raw | ConvertFrom-Json 26 | $a.configurations.variables | % {if($_.name -eq 'CMAKE_TOOLCHAIN_FILE'){$_.value=$vcpkgpath}} 27 | $a | ConvertTo-Json -Depth 20 | set-content $cmakesettingspath 28 | 29 | [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null 30 | [System.Windows.Forms.MessageBox]::Show("Finished setting vcpkg path in CMakeSettings.json","Graphics2",0) 31 | -------------------------------------------------------------------------------- /shaders/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(SHADERS) 2 | 3 | file(GLOB_RECURSE GLSL *.glsl) 4 | file(GLOB_RECURSE VERT *.vert *.vertex *.vs) 5 | file(GLOB_RECURSE TCS *.tcs *.cont *.t_cont) 6 | file(GLOB_RECURSE TES *.tes *.eval *.t_eval) 7 | file(GLOB_RECURSE GEOM *.geom *.geo *.geometry *.gs) 8 | file(GLOB_RECURSE FRAG *.frag *.fragment *.fs *.ps) 9 | file(GLOB_RECURSE COMP *.comp *.compute *.cs) 10 | 11 | SOURCE_GROUP(Vertex-Shaders FILES ${VERT}) 12 | SOURCE_GROUP(Tessellation-Control-Shaders FILES ${TCS}) 13 | SOURCE_GROUP(Tessellation-Evaluation-Shaders FILES ${TES}) 14 | SOURCE_GROUP(Geometry-Shaders FILES ${GEOM}) 15 | SOURCE_GROUP(Fragment-Shaders FILES ${FRAG}) 16 | SOURCE_GROUP(Compute-Shaders FILES ${COMP}) 17 | 18 | add_custom_target(SHADERS SOURCES ${GLSL} ${VERT} ${TCS} ${TES} ${GEOM} ${FRAG} ${COMP}) -------------------------------------------------------------------------------- /shaders/HDRtoLDR.frag: -------------------------------------------------------------------------------- 1 | #version 430 2 | #extension GL_ARB_bindless_texture : require 3 | 4 | in vec2 passTexCoord; 5 | 6 | out vec4 fragColor; 7 | 8 | uniform float exposure; 9 | uniform float gamma; 10 | 11 | layout(bindless_sampler) uniform sampler2DMS inputTexture; 12 | 13 | float A = 0.15; 14 | float B = 0.50; 15 | float C = 0.10; 16 | float D = 0.20; 17 | float E = 0.02; 18 | float F = 0.30; 19 | float W = 11.2; 20 | 21 | vec3 Uncharted2Tonemap(vec3 x) 22 | { 23 | return ((x*(A*x+C*B)+D*E)/(x*(A*x+B)+D*F))-E/F; 24 | } 25 | 26 | void main() 27 | { 28 | vec3 hdrColor = vec3(0.0f); 29 | 30 | for (int i = 0; i < SAMPLE_COUNT; i++) 31 | hdrColor += texelFetch(inputTexture, ivec2(gl_FragCoord.xy), i).rgb; 32 | 33 | hdrColor /= SAMPLE_COUNT; 34 | 35 | // R E I N H A R D 36 | // Exposure tone mapping 37 | vec3 mapped = vec3(1.0) - exp(-hdrColor * exposure); 38 | // Gamma correction 39 | mapped = pow(mapped, vec3(1.0 / gamma)); 40 | 41 | fragColor = vec4(mapped, 1.0f); 42 | //fragColor = vec4(hdrColor, 1.0+exposure+gamma); 43 | 44 | // U N C H A R T E D 2 45 | // vec3 curr = Uncharted2Tonemap(exposure * hdrColor); 46 | 47 | // vec3 whiteScale = 1.0f/Uncharted2Tonemap(vec3(W)); 48 | // vec3 color = curr * whiteScale; 49 | 50 | // fragColor = vec4(pow(color, vec3(1.0/gamma)), 1.0f); 51 | } -------------------------------------------------------------------------------- /shaders/IBLtoCube.frag: -------------------------------------------------------------------------------- 1 | #version 430 2 | #extension GL_ARB_bindless_texture : require 3 | 4 | out vec4 fragColor; 5 | 6 | in vec3 localPos; 7 | 8 | layout(binding = 5, std430) buffer textureBuffer 9 | { 10 | sampler2D equirectangularMap; 11 | }; 12 | 13 | const vec2 invAtan = vec2(0.1591, 0.3183); 14 | vec2 SampleSphericalMap(vec3 v) 15 | { 16 | vec2 uv = vec2(atan(v.z, v.x), asin(v.y)); 17 | uv *= invAtan; 18 | uv += 0.5; 19 | return uv; 20 | } 21 | 22 | void main() 23 | { 24 | vec2 uv = SampleSphericalMap(normalize(localPos)); // make sure to normalize localPos 25 | vec3 color = texture(equirectangularMap, uv).rgb; 26 | 27 | fragColor = vec4(color, 1.0); 28 | } -------------------------------------------------------------------------------- /shaders/IBLtoCube.vert: -------------------------------------------------------------------------------- 1 | #version 430 2 | 3 | layout (location = 0) in vec3 vertexPosition; 4 | 5 | out vec3 localPos; 6 | 7 | uniform mat4 projection; 8 | uniform mat4 view; 9 | 10 | void main() 11 | { 12 | localPos = vertexPosition; 13 | gl_Position = projection * view * vec4(localPos, 1.0); 14 | } -------------------------------------------------------------------------------- /shaders/SparseVoxelOctree/CreateNodes.comp: -------------------------------------------------------------------------------- 1 | #version 450 core 2 | 3 | layout (local_size_x = 8, local_size_y = 1, local_size_z = 1) in; 4 | 5 | layout(binding = 2, std430) buffer nodePool_buffer 6 | { 7 | int nodePool[]; 8 | }; 9 | 10 | layout (binding = 1, offset = 0) uniform atomic_uint nodeCounter; 11 | 12 | uniform int startIndex; 13 | 14 | void main() 15 | { 16 | uint index = startIndex + gl_WorkGroupID.x * gl_WorkGroupSize.x + gl_LocalInvocationID.x; 17 | if(nodePool[index] == 0) //node flagged 18 | nodePool[index] = int(atomicCounterIncrement(nodeCounter)+1) * 8; 19 | } 20 | -------------------------------------------------------------------------------- /shaders/SparseVoxelOctree/FlagNodes.comp: -------------------------------------------------------------------------------- 1 | #version 450 core 2 | 3 | layout (local_size_x = 64, local_size_y = 1, local_size_z = 1) in; 4 | 5 | layout(binding = 0, std430) buffer voxelFragmentList_buffer 6 | { 7 | vec4 voxelFragmentList[]; 8 | }; 9 | 10 | layout(binding = 2, std430) buffer nodePool_buffer 11 | { 12 | int nodePool[]; 13 | }; 14 | 15 | void traverseOctree(in vec3 voxelPos) 16 | { 17 | vec3 nodePos = vec3(0.f); 18 | vec3 nodeSize = vec3(1.f); 19 | int bufferIndex = 0; 20 | 21 | bool loop = true; 22 | while(loop) 23 | { 24 | ivec3 octant = ivec3(greaterThanEqual(voxelPos, nodePos + 0.5f * nodeSize)); 25 | int tileIndex = octant.z * 4 + octant.y * 2 + octant.x; 26 | bufferIndex = nodePool[bufferIndex] + tileIndex; 27 | 28 | if(nodePool[bufferIndex] > 0) //has subnode --> step into 29 | { 30 | nodeSize *= 0.5f; 31 | nodePos += octant * nodeSize; 32 | } 33 | else //current node is leaf --> flag node 34 | { 35 | nodePool[bufferIndex] = 0; 36 | return; 37 | } 38 | } 39 | } 40 | 41 | void main() 42 | { 43 | uint index = gl_WorkGroupID.x * gl_WorkGroupSize.x + gl_LocalInvocationID.x; 44 | vec4 voxelPos = voxelFragmentList[index]; 45 | 46 | if(voxelPos.w > 0.f) traverseOctree(voxelPos.xyz); 47 | } 48 | -------------------------------------------------------------------------------- /shaders/SparseVoxelOctree/InitLeafNodes.comp: -------------------------------------------------------------------------------- 1 | #version 450 core 2 | 3 | layout (local_size_x = 64, local_size_y = 1, local_size_z = 1) in; 4 | 5 | layout(binding = 0, std430) buffer voxelFragmentList_buffer 6 | { 7 | vec4 voxelFragmentList[]; 8 | }; 9 | 10 | layout(binding = 1, std430) buffer voxelFragmentColor_buffer 11 | { 12 | vec4 voxelFragmentColor[]; 13 | }; 14 | 15 | layout(binding = 2, std430) buffer nodePool_buffer 16 | { 17 | int nodePool[]; 18 | }; 19 | 20 | layout(binding = 3, std430) buffer nodeColor_buffer 21 | { 22 | vec4 nodeColor[]; 23 | }; 24 | 25 | void traverseOctree(in vec3 voxelPos, in vec4 voxelColor) 26 | { 27 | vec3 nodePos = vec3(0.f); 28 | vec3 nodeSize = vec3(1.f); 29 | int bufferIndex = 0; 30 | 31 | bool loop = true; 32 | while(loop) 33 | { 34 | ivec3 octant = ivec3(greaterThanEqual(voxelPos, nodePos + 0.5f * nodeSize)); 35 | int tileIndex = octant.z * 4 + octant.y * 2 + octant.x; 36 | bufferIndex = nodePool[bufferIndex] + tileIndex; 37 | 38 | if(nodePool[bufferIndex] > 0) //has subnode --> step into 39 | { 40 | nodeSize *= 0.5f; 41 | nodePos += octant * nodeSize; 42 | } 43 | else //current node is leaf --> fill data 44 | { 45 | nodeColor[bufferIndex] = vec4(voxelColor.xyz, 1.0f); //TODO: mix colors! 46 | return; 47 | } 48 | } 49 | } 50 | 51 | void main() 52 | { 53 | uint index = gl_WorkGroupID.x * gl_WorkGroupSize.x + gl_LocalInvocationID.x; 54 | vec4 voxelPos = voxelFragmentList[index]; 55 | 56 | if(voxelPos.w > 0.f) traverseOctree(voxelPos.xyz, voxelFragmentColor[index]); 57 | } 58 | -------------------------------------------------------------------------------- /shaders/SparseVoxelOctree/MipMapNodes.comp: -------------------------------------------------------------------------------- 1 | #version 450 core 2 | 3 | layout (local_size_x = 8, local_size_y = 1, local_size_z = 1) in; 4 | 5 | layout(binding = 2, std430) buffer nodePool_buffer 6 | { 7 | int nodePool[]; 8 | }; 9 | 10 | layout(binding = 3, std430) buffer nodeColor_buffer 11 | { 12 | vec4 nodeColor[][8]; 13 | }; 14 | 15 | uniform int startIndex; 16 | 17 | void main() 18 | { 19 | uint index = startIndex + gl_WorkGroupID.x * gl_WorkGroupSize.x + gl_LocalInvocationID.x; 20 | uint childrenStartIndex = nodePool[index]; 21 | if(childrenStartIndex > 0) //node has children 22 | { 23 | vec4 sub_colors[8] = nodeColor[childrenStartIndex>>3]; 24 | 25 | vec4 avgColor = vec4(0.f); 26 | 27 | for(int i = 0; i < 8; ++i) 28 | { 29 | avgColor += sub_colors[i]; 30 | } 31 | 32 | if (avgColor.w != 0.0f) 33 | { 34 | avgColor.xyz *= 1.0f / avgColor.w; //color is not affected by empty nodes 35 | avgColor.w = 1.0f; 36 | } 37 | 38 | nodeColor[index>>3][index&0x7] = avgColor; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /shaders/SparseVoxelOctree/VoxelGen.geom: -------------------------------------------------------------------------------- 1 | #version 450 core 2 | 3 | layout (triangles) in; 4 | layout (triangle_strip, max_vertices = 3) out; 5 | 6 | uniform mat4 projectionMatrix; 7 | uniform uvec3 res; 8 | 9 | flat out vec3 vertex0, vertex1, vertex2; 10 | 11 | flat out int axis; 12 | flat out vec3 face_normal; 13 | flat out vec3 diag; 14 | 15 | void main(void) 16 | { 17 | gl_PrimitiveID = gl_PrimitiveIDIn; 18 | 19 | vec4 pos[3] = 20 | { 21 | projectionMatrix * gl_in[0].gl_Position, 22 | projectionMatrix * gl_in[1].gl_Position, 23 | projectionMatrix * gl_in[2].gl_Position 24 | }; 25 | 26 | face_normal = normalize(cross((pos[2] - pos[1]).xyz, (pos[1] - pos[0]).xyz)); 27 | vec3 n = abs(face_normal); 28 | diag = vec3(res.xyz); 29 | axis = 3; 30 | 31 | //Find the axis that maximize the projected area of this triangle 32 | if(n.x > n.y && n.x > n.z) 33 | { 34 | pos[0] = pos[0].yzxw; 35 | pos[1] = pos[1].yzxw; 36 | pos[2] = pos[2].yzxw; 37 | diag = diag.yzx; 38 | face_normal = face_normal.yzx; 39 | axis = 1; 40 | } 41 | else if(n.y > n.x && n.y > n.z) 42 | { 43 | pos[0] = pos[0].zxyw; 44 | pos[1] = pos[1].zxyw; 45 | pos[2] = pos[2].zxyw; 46 | diag = diag.zxy; 47 | face_normal = face_normal.zxy; 48 | axis = 2; 49 | } 50 | 51 | diag = 1.0f / diag; 52 | 53 | vertex0 = pos[0].xyz; 54 | vertex1 = pos[1].xyz; 55 | vertex2 = pos[2].xyz; 56 | 57 | gl_ViewportIndex = axis; 58 | 59 | gl_Position = pos[0]; 60 | EmitVertex(); 61 | 62 | gl_Position = pos[1]; 63 | EmitVertex(); 64 | 65 | gl_Position = pos[2]; 66 | EmitVertex(); 67 | 68 | EndPrimitive(); 69 | } 70 | -------------------------------------------------------------------------------- /shaders/SparseVoxelOctree/VoxelGen.vert: -------------------------------------------------------------------------------- 1 | #version 450 core 2 | 3 | layout (location = 0) in vec3 VertexPosition; 4 | 5 | uniform mat4 modelMatrix; 6 | 7 | void main() 8 | { 9 | gl_Position = modelMatrix * vec4(VertexPosition, 1.0f); 10 | } 11 | -------------------------------------------------------------------------------- /shaders/SparseVoxelOctree/sfq_rayDir.vert: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | layout (location = 0) in vec4 position; 4 | 5 | uniform mat4 viewMatrix; 6 | uniform mat4 projectionMatrix; 7 | 8 | out vec3 passDir; 9 | 10 | void main() 11 | { 12 | gl_Position = position; 13 | 14 | mat4 inverseView = inverse(viewMatrix); 15 | mat4 inverseProjection = inverse(projectionMatrix); 16 | 17 | vec4 origin = inverseView * vec4(0,0,0,1); 18 | vec4 originPlusDir = (inverseView * inverseProjection) * vec4(position.xy, 0, 1); 19 | originPlusDir.xyz /= originPlusDir.w; 20 | passDir = normalize(vec3(originPlusDir - origin)); 21 | } -------------------------------------------------------------------------------- /shaders/accumulateVoxels.comp: -------------------------------------------------------------------------------- 1 | #version 430 2 | #extension GL_ARB_bindless_texture : require 3 | //#extension GL_ARB_compute_variable_group_size : require 4 | 5 | uniform ivec3 gridDim; 6 | 7 | layout(bindless_image, rgba32f) uniform image3D voxelGrid; 8 | 9 | //layout(local_size_variable) in; 10 | layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; 11 | 12 | vec4 accumulateScattering(in vec4 front, in vec4 back) 13 | { 14 | vec3 light = front.rgb + clamp(exp(-front.a), 0.0f, 1.0f) * back.rgb; 15 | //vec3 light = front.rgb + front.a * back.rgb; 16 | return vec4(light, front.a + back.a); 17 | } 18 | 19 | void writeOutputExponential(in ivec3 pos, in vec4 data) 20 | { 21 | data.a = exp(-data.a); 22 | imageStore(voxelGrid, pos, data); 23 | } 24 | 25 | void main() 26 | { 27 | ivec3 g_ID = ivec3(gl_GlobalInvocationID); 28 | 29 | if(g_ID.x < gridDim.x && g_ID.y < gridDim.y) 30 | { 31 | vec4 accum = imageLoad(voxelGrid, g_ID); 32 | // TODO not sure if we need exponential data when usign non-exp. grids & shadow maps 33 | writeOutputExponential(g_ID, accum); 34 | for (g_ID.z = 1; g_ID.z < gridDim.z; ++g_ID.z) 35 | { 36 | vec4 nextVal = imageLoad(voxelGrid, g_ID); 37 | accum = accumulateScattering(accum, nextVal); 38 | writeOutputExponential(g_ID, accum); 39 | /*accum += nextVal; 40 | imageStore(voxelGrid, g_ID, accum);*/ 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /shaders/accumulateVoxelsSM.comp: -------------------------------------------------------------------------------- 1 | #version 430 2 | #extension GL_ARB_bindless_texture : require 3 | //#extension GL_ARB_compute_variable_group_size : require 4 | 5 | #define Z_DIM 256 6 | 7 | uniform ivec3 gridDim; 8 | 9 | layout(bindless_image, rgba32f) uniform image3D voxelGrid; 10 | 11 | //layout(local_size_variable) in; 12 | layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; 13 | 14 | vec4 accumulateScattering(in vec4 front, in vec4 back) 15 | { 16 | vec3 light = front.rgb + clamp(exp(-front.a), 0.0f, 1.0f) * back.rgb; 17 | //vec3 light = front.rgb + front.a * back.rgb; 18 | return vec4(light, front.a + back.a); 19 | } 20 | 21 | void writeOutputExponential(in ivec3 pos, in vec4 data) 22 | { 23 | data.a = exp(-data.a); 24 | imageStore(voxelGrid, pos, data); 25 | } 26 | 27 | // idea: each local group loads all z values of an x,y coordinate into shared memory 28 | // the first thread of that local group accumulates the values (all in shared memory) 29 | // then, each thread i the local group writes to the image 30 | 31 | shared vec4 SMvalues[Z_DIM]; 32 | 33 | void main() 34 | { 35 | ivec3 g_ID = ivec3(gl_GlobalInvocationID); 36 | 37 | ivec3 voxelGridPos = ivec3(gl_WorkGroupID.x, gl_WorkGroupID.y, gl_LocalInvocationIndex); 38 | 39 | if (voxelGridPos.x < gridDim.x && voxelGridPos.y < gridDim.y) 40 | { 41 | SMvalues[gl_LocalInvocationIndex] = imageLoad(voxelGrid, voxelGridPos); 42 | //memoryBarrierShared(); 43 | barrier(); 44 | 45 | if (gl_LocalInvocationIndex == 0) 46 | { 47 | for (int i = 1; i < Z_DIM; i++) 48 | { 49 | vec4 nextVal = SMvalues[i]; 50 | SMvalues[i] = accumulateScattering(SMvalues[i-1], nextVal); 51 | } 52 | } 53 | //memoryBarrierShared(); 54 | barrier(); 55 | 56 | writeOutputExponential(voxelGridPos, SMvalues[gl_LocalInvocationIndex]); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /shaders/brdfLUT.frag: -------------------------------------------------------------------------------- 1 | #version 430 2 | 3 | in vec2 passTexCoord; 4 | out vec2 fragColorRG; 5 | 6 | const float PI = 3.14159265359; 7 | 8 | float GeometrySchlickGGX(float NdotV, float roughness) 9 | { 10 | float a = roughness; 11 | float k = (a * a) / 2.0; 12 | 13 | float nom = NdotV; 14 | float denom = NdotV * (1.0 - k) + k; 15 | 16 | return nom / denom; 17 | } 18 | // ---------------------------------------------------------------------------- 19 | float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness) 20 | { 21 | float NdotV = max(dot(N, V), 0.0); 22 | float NdotL = max(dot(N, L), 0.0); 23 | float ggx2 = GeometrySchlickGGX(NdotV, roughness); 24 | float ggx1 = GeometrySchlickGGX(NdotL, roughness); 25 | 26 | return ggx1 * ggx2; 27 | } 28 | 29 | // radical inverse function 30 | float RadicalInverse(uint bits) 31 | { 32 | bits = (bits << 16u) | (bits >> 16u); 33 | bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); 34 | bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); 35 | bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); 36 | bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); 37 | return float(bits) * 2.3283064365386963e-10; // / 0x100000000 38 | } 39 | 40 | // generate hammersley sequence using RIF 41 | vec2 Hammersley(uint i, uint N) 42 | { 43 | return vec2(float(i)/float(N), RadicalInverse(i)); 44 | } 45 | 46 | vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness) 47 | { 48 | float a = roughness*roughness; 49 | 50 | float phi = 2.0 * PI * Xi.x; 51 | float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a*a - 1.0) * Xi.y)); 52 | float sinTheta = sqrt(1.0 - cosTheta*cosTheta); 53 | 54 | // from spherical coordinates to cartesian coordinates 55 | vec3 H; 56 | H.x = cos(phi) * sinTheta; 57 | H.y = sin(phi) * sinTheta; 58 | H.z = cosTheta; 59 | 60 | // from tangent-space vector to world-space sample vector 61 | vec3 up = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); 62 | vec3 tangent = normalize(cross(up, N)); 63 | vec3 bitangent = cross(N, tangent); 64 | 65 | vec3 sampleVec = tangent * H.x + bitangent * H.y + N * H.z; 66 | return normalize(sampleVec); 67 | } 68 | 69 | 70 | vec2 IntegrateBRDF(float NdotV, float roughness) 71 | { 72 | vec3 V; 73 | V.x = sqrt(1.0 - NdotV*NdotV); 74 | V.y = 0.0; 75 | V.z = NdotV; 76 | 77 | float A = 0.0; 78 | float B = 0.0; 79 | 80 | vec3 N = vec3(0.0, 0.0, 1.0); 81 | 82 | const uint SAMPLE_COUNT = 1024u; 83 | for(uint i = 0u; i < SAMPLE_COUNT; ++i) 84 | { 85 | vec2 Xi = Hammersley(i, SAMPLE_COUNT); 86 | vec3 H = ImportanceSampleGGX(Xi, N, roughness); 87 | vec3 L = normalize(2.0 * dot(V, H) * H - V); 88 | 89 | float NdotL = max(L.z, 0.0); 90 | float NdotH = max(H.z, 0.0); 91 | float VdotH = max(dot(V, H), 0.0); 92 | 93 | if(NdotL > 0.0) 94 | { 95 | float G = GeometrySmith(N, V, L, roughness); 96 | float G_Vis = (G * VdotH) / (NdotH * NdotV); 97 | float Fc = pow(1.0 - VdotH, 5.0); 98 | 99 | A += (1.0 - Fc) * G_Vis; 100 | B += Fc * G_Vis; 101 | } 102 | } 103 | A /= float(SAMPLE_COUNT); 104 | B /= float(SAMPLE_COUNT); 105 | return vec2(A, B); 106 | } 107 | // ---------------------------------------------------------------------------- 108 | void main() 109 | { 110 | vec2 integratedBRDF = IntegrateBRDF(passTexCoord.x, passTexCoord.y); 111 | fragColorRG = integratedBRDF; 112 | } -------------------------------------------------------------------------------- /shaders/common/light.glsl: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct Light 4 | { 5 | mat4 lightSpaceMatrix; 6 | vec3 color; // all 7 | int type; // 0 directional, 1 point light, 2 spot light 8 | vec3 position; // spot, point 9 | float constant; // spot, point 10 | vec3 direction; // dir, spot 11 | float linear; // spot, point 12 | uvec2 shadowMap; // can be sampler2D or samplerCube 13 | float quadratic; // spot, point 14 | float cutOff; // spot 15 | float outerCutOff; // spot 16 | int pcfKernelSize; 17 | }; 18 | 19 | layout(std430, binding = LIGHTS_BINDING) readonly buffer LightBuffer 20 | { 21 | Light lights[]; 22 | }; 23 | 24 | uniform vec3 ambient = vec3(0.3f); 25 | 26 | struct LightResult 27 | { 28 | vec3 diffuse; 29 | vec3 specular; 30 | vec3 direction; 31 | }; 32 | 33 | LightResult getLight(int lightIndex, vec3 worldPos, vec3 viewDir, vec3 normal, float specExponent) 34 | { 35 | LightResult result; 36 | 37 | Light currentLight = lights[lightIndex]; 38 | if (currentLight.type == 0) // D I R E C T I O N A L 39 | { 40 | vec3 lightDir = normalize(-currentLight.direction); 41 | normal = normal == vec3(0.0f) ? lightDir : normal; 42 | 43 | // diffuse shading 44 | float diff = max(dot(normal, lightDir), 0.0); 45 | 46 | // specular shading 47 | vec3 halfwayDir = normalize(lightDir + viewDir); 48 | float spec = pow(max(dot(normal, halfwayDir), 0.0), specExponent); 49 | 50 | // combine results 51 | result.diffuse = currentLight.color * diff; 52 | result.specular = currentLight.color * spec; 53 | result.direction = lightDir; 54 | } 55 | if (currentLight.type == 1) // P O I N T 56 | { 57 | vec3 lightDir = normalize(currentLight.position - worldPos); 58 | normal = normal == vec3(0.0f) ? lightDir : normal; 59 | 60 | // diffuse shading 61 | float diff = max(dot(normal, lightDir), 0.0); 62 | 63 | // specular shading 64 | vec3 halfwayDir = normalize(lightDir + viewDir); 65 | float spec = pow(max(dot(normal, halfwayDir), 0.0), specExponent); 66 | 67 | // attenuation 68 | float distance = length(currentLight.position - worldPos); 69 | float attenuation = 1.0 / max(0.001f, (currentLight.constant + currentLight.linear * distance + currentLight.quadratic * (distance * distance))); 70 | 71 | // combine results 72 | result.diffuse = currentLight.color * diff * attenuation; 73 | result.specular = currentLight.color * spec * attenuation; 74 | result.direction = lightDir; 75 | } 76 | if (currentLight.type == 2) // S P O T 77 | { 78 | vec3 lightDir = normalize(currentLight.position - worldPos); 79 | normal = normal == vec3(0.0f) ? lightDir : normal; 80 | 81 | // diffuse shading 82 | float diff = max(dot(normal, lightDir), 0.0); 83 | 84 | // specular shading 85 | vec3 halfwayDir = normalize(lightDir + viewDir); 86 | float spec = pow(max(dot(normal, halfwayDir), 0.0), specExponent); 87 | 88 | // attenuation 89 | float distance = length(currentLight.position - worldPos); 90 | float attenuation = 1.0 / max(0.001f, (currentLight.constant + currentLight.linear * distance + currentLight.quadratic * (distance * distance))); 91 | 92 | // spotlight intensity 93 | float theta = dot(lightDir, normalize(-currentLight.direction)); 94 | float epsilon = currentLight.cutOff - currentLight.outerCutOff; 95 | float intensity = clamp((theta - currentLight.outerCutOff) / epsilon, 0.0, 1.0); 96 | 97 | // combine results 98 | result.diffuse = currentLight.color * diff * attenuation * intensity; 99 | result.specular = currentLight.color * spec * attenuation * intensity; 100 | result.direction = lightDir; 101 | } 102 | return result; 103 | } 104 | -------------------------------------------------------------------------------- /shaders/common/material.glsl: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct Material 4 | { 5 | sampler2D diffTexture; 6 | sampler2D specTexture; 7 | sampler2D opacityTexture; 8 | float opacity; 9 | float Ns; 10 | vec4 diffColor; 11 | vec4 specColor; 12 | vec4 emissiveColor; 13 | sampler2D bumpTexture; 14 | int bumpType; //0 = no bump, 1 = normal map, 2 = height map 15 | }; 16 | 17 | layout(std430, binding = MATERIAL_BINDING) readonly buffer MaterialBuffer 18 | { 19 | Material materials[]; 20 | }; 21 | 22 | layout(std430, binding = MATERIAL_INDICES_BINDING) readonly buffer MaterialIndexBuffer 23 | { 24 | uint materialIndices[]; 25 | }; 26 | 27 | vec3 getDiffColor(int materialIndex) 28 | { 29 | Material currentMaterial = materials[materialIndex]; 30 | // diffuse color or texture 31 | if (currentMaterial.diffColor.a != 0.0f) 32 | return texture(currentMaterial.diffTexture, passTexCoord.rg).rgb; 33 | else 34 | return currentMaterial.diffColor.rgb; 35 | } 36 | 37 | vec3 getSpecColor(int materialIndex) 38 | { 39 | Material currentMaterial = materials[materialIndex]; 40 | // specular color or texture TODO USE THIS 41 | if (currentMaterial.specColor.a != 0.0f) 42 | return texture(currentMaterial.specTexture, passTexCoord.rg).rgb; 43 | else 44 | return currentMaterial.specColor.rgb; 45 | } 46 | 47 | float getDiffTextureAlpha(int materialIndex) 48 | { 49 | Material currentMaterial = materials[materialIndex]; 50 | return texture(currentMaterial.diffTexture, passTexCoord.rg).a; 51 | } -------------------------------------------------------------------------------- /shaders/common/shadowMapping.glsl: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "light.glsl" 4 | 5 | // cube maps do not work at the moment 6 | float calculateCubeShadow(in int lightIndex, in vec3 worldPos, in vec3 lightDir) 7 | { 8 | Light currentLight = lights[lightIndex]; 9 | vec3 fragToLight = worldPos - currentLight.position; 10 | float shadowDepth = texture(samplerCube(currentLight.shadowMap), fragToLight).r; 11 | shadowDepth *= 1000.0f; 12 | float currentDepth = length(fragToLight); 13 | float bias = 0.05f; 14 | float shadow = currentDepth - bias > shadowDepth ? 1.0f : 0.0f; 15 | 16 | return shadow; 17 | } 18 | 19 | float calculateShadowPCF(in int lightIndex, in vec3 worldPos, in vec3 worldNormal, in vec3 lightDir) 20 | { 21 | Light l = lights[lightIndex]; 22 | 23 | //transform position to light space 24 | vec4 worldPosLightSpace = l.lightSpaceMatrix * vec4(worldPos, 1.0f); 25 | worldPosLightSpace = worldPosLightSpace * 0.5f + 0.5f * worldPosLightSpace.w; // transform to [0,w] range 26 | 27 | //calculate bias 28 | float cos_phi = max(dot(normalize(worldNormal), normalize(lightDir)), 0.0f); 29 | float bias = -0.00001f * tan(acos(cos_phi)); 30 | 31 | worldPosLightSpace.z -= bias * worldPosLightSpace.w; 32 | 33 | float shadow = 0.0f; 34 | 35 | //gaussian stuff 36 | float twoSigmaSq = max(1.0f, l.pcfKernelSize) * 2.0f; 37 | float preFactor = 1.0f / (3.14159265f * twoSigmaSq); 38 | float kernelSum = 0.0f; 39 | 40 | sampler2DShadow sm = sampler2DShadow(l.shadowMap); 41 | vec2 texelSize = 1.0f / textureSize(sm, 0); 42 | int kernelSize = l.pcfKernelSize * 2 + 1; 43 | int go = l.pcfKernelSize; 44 | for (int x = -go; x <= go; ++x) 45 | { 46 | for (int y = -go; y <= go; ++y) 47 | { 48 | vec4 tcOffset = vec4(vec2(x, y) * texelSize * worldPosLightSpace.w, 0.f, 0.f); 49 | float weight = preFactor * exp(-((x * x + y * y) / twoSigmaSq)); 50 | shadow += weight * textureProj(sm, worldPosLightSpace + tcOffset); 51 | kernelSum += weight; 52 | } 53 | } 54 | shadow /= kernelSum; 55 | 56 | return shadow; 57 | } 58 | 59 | float calculateShadowBias(in int lightIndex, in vec3 worldPos, in vec3 worldNormal, in vec3 lightDir) 60 | { 61 | Light l = lights[lightIndex]; 62 | 63 | //transform position to light space 64 | vec4 worldPosLightSpace = l.lightSpaceMatrix * vec4(worldPos, 1.0f); 65 | worldPosLightSpace = worldPosLightSpace * 0.5f + 0.5f * worldPosLightSpace.w; // transform to [0,w] range 66 | 67 | //calculate bias 68 | float cos_phi = max(dot(normalize(worldNormal), normalize(lightDir)), 0.0f); 69 | float bias = -0.00001f * tan(acos(cos_phi)); 70 | 71 | worldPosLightSpace.z -= bias * worldPosLightSpace.w; 72 | 73 | float shadow = textureProj(sampler2DShadow(l.shadowMap), worldPosLightSpace); 74 | 75 | return shadow; 76 | } 77 | 78 | float calculateShadow(in int lightIndex, in vec3 worldPos) 79 | { 80 | Light l = lights[lightIndex]; 81 | 82 | //transform position to light space 83 | vec4 worldPosLightSpace = l.lightSpaceMatrix * vec4(worldPos, 1.0f); 84 | worldPosLightSpace = worldPosLightSpace * 0.5f + 0.5f * worldPosLightSpace.w; // transform to [0,w] range 85 | 86 | float shadow = textureProj(sampler2DShadow(l.shadowMap), worldPosLightSpace); 87 | 88 | return shadow; 89 | } 90 | -------------------------------------------------------------------------------- /shaders/common/volumetricLighting.glsl: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "light.glsl" 4 | 5 | layout(bindless_sampler) uniform sampler3D voxelGrid; 6 | uniform float maxRange; 7 | uniform vec2 screenRes; 8 | 9 | vec3 applyVolumetricLightingManual(in vec3 colorWithoutVolumetric, in float viewZ) 10 | { 11 | float zDist = -viewZ / maxRange; 12 | zDist /= exp(-1.f+zDist); //use exponential depth 13 | vec3 texCoord = vec3(gl_FragCoord.xy / screenRes, zDist); 14 | vec4 texEntry = texture(voxelGrid, texCoord); 15 | return colorWithoutVolumetric * texEntry.w + texEntry.xyz; 16 | } 17 | 18 | // CAUTION: to use this you have to enable blending with glBlendFunc(GL_ONE, GL_SRC_ALPHA) 19 | vec4 getVolumetricLighting(in float viewZ) 20 | { 21 | float zDist = -viewZ / maxRange; 22 | zDist /= exp(-1.f + zDist); //use exponential depth 23 | vec3 texCoord = vec3(gl_FragCoord.xy / screenRes, zDist); 24 | return texture(voxelGrid, texCoord); 25 | } 26 | -------------------------------------------------------------------------------- /shaders/cubemap.frag: -------------------------------------------------------------------------------- 1 | #version 430 2 | #extension GL_ARB_bindless_texture : require 3 | 4 | in vec3 texCoords; 5 | 6 | out vec4 fragColor; 7 | 8 | layout(binding = 3, std430) buffer textureBuffer 9 | { 10 | samplerCube skybox; 11 | }; 12 | 13 | void main() 14 | { 15 | fragColor = texture(skybox, texCoords); 16 | } -------------------------------------------------------------------------------- /shaders/cubemap.vert: -------------------------------------------------------------------------------- 1 | #version 430 2 | layout (location = 0) in vec3 vertexPosition; 3 | 4 | out vec3 texCoords; 5 | 6 | uniform mat4 ProjectionMatrix; 7 | uniform mat4 ViewMatrix; 8 | 9 | void main() 10 | { 11 | texCoords = vertexPosition; 12 | vec4 pos = ProjectionMatrix * mat4(mat3(ViewMatrix)) * vec4(vertexPosition, 1.0f); 13 | gl_Position = pos.xyww; 14 | } -------------------------------------------------------------------------------- /shaders/cubemap2.frag: -------------------------------------------------------------------------------- 1 | #version 430 2 | #extension GL_ARB_bindless_texture : require 3 | 4 | #include "common/volumetricLighting.glsl" 5 | 6 | in vec3 texCoords; 7 | 8 | out vec4 fragColor; 9 | 10 | layout(bindless_sampler) uniform samplerCube skybox; 11 | 12 | void main() 13 | { 14 | fragColor = texture(skybox, texCoords); 15 | fragColor.xyz = applyVolumetricLightingManual(fragColor.xyz, -maxRange); 16 | 17 | } -------------------------------------------------------------------------------- /shaders/cubemap2.vert: -------------------------------------------------------------------------------- 1 | #version 430 2 | layout (location = 0) in vec3 vertexPosition; 3 | 4 | out vec3 texCoords; 5 | 6 | layout(binding = CAMERA_BINDING, std430) buffer cameraBuffer 7 | { 8 | mat4 ViewMatrix; 9 | mat4 ProjectionMatrix; 10 | vec3 camPos; 11 | }; 12 | 13 | void main() 14 | { 15 | texCoords = vertexPosition; 16 | vec4 pos = ProjectionMatrix * mat4(mat3(ViewMatrix)) * vec4(vertexPosition, 1.0f); 17 | gl_Position = pos.xyww; 18 | } -------------------------------------------------------------------------------- /shaders/demo1.vert: -------------------------------------------------------------------------------- 1 | #version 430 2 | 3 | layout (location = 0) in vec3 VertexPosition; 4 | layout (location = 1) in vec3 VertexNormal; 5 | 6 | out vec3 passPosition; 7 | out vec3 interpNormal; 8 | flat out vec3 flatNormal; 9 | out vec3 modelNormal; 10 | out vec3 Position; 11 | 12 | 13 | uniform mat4 ModelMatrix; 14 | uniform mat4 ViewMatrix; 15 | uniform mat4 ProjectionMatrix; 16 | 17 | void main() 18 | { 19 | mat4 ModelViewMatrix = ViewMatrix * ModelMatrix; 20 | mat3 NormalMatrix = mat3(transpose(inverse(ModelViewMatrix))); 21 | 22 | vec3 Normal = normalize( NormalMatrix * VertexNormal); 23 | interpNormal = Normal; 24 | flatNormal = Normal; 25 | passPosition = vec3( ModelViewMatrix * vec4(VertexPosition, 1.0)); 26 | 27 | modelNormal = mat3(transpose(inverse(ModelMatrix))) * VertexNormal; 28 | Position = vec3(ModelMatrix * vec4(VertexPosition, 1.0)); 29 | 30 | gl_Position = ProjectionMatrix * ModelViewMatrix * vec4(VertexPosition, 1.0); 31 | } -------------------------------------------------------------------------------- /shaders/drawIBLskybox.frag: -------------------------------------------------------------------------------- 1 | #version 430 2 | #extension GL_ARB_bindless_texture : require 3 | 4 | out vec4 FragColor; 5 | 6 | in vec3 localPos; 7 | 8 | layout(binding = 6, std430) buffer skyboxBuffer 9 | { 10 | samplerCube environmentMap; 11 | }; 12 | 13 | void main() 14 | { 15 | vec3 envColor = texture(environmentMap, localPos).rgb; 16 | //vec3 envColor = textureLod(environmentMap, localPos, 1.2).rgb; 17 | 18 | 19 | envColor = envColor / (envColor + vec3(1.0)); 20 | envColor = pow(envColor, vec3(1.0/2.2)); 21 | 22 | FragColor = vec4(envColor, 1.0); 23 | } -------------------------------------------------------------------------------- /shaders/drawIBLskybox.vert: -------------------------------------------------------------------------------- 1 | #version 430 2 | 3 | layout (location = 0) in vec3 aPos; 4 | 5 | uniform mat4 projection; 6 | uniform mat4 view; 7 | 8 | out vec3 localPos; 9 | 10 | void main() 11 | { 12 | localPos = aPos; 13 | 14 | mat4 rotView = mat4(mat3(view)); // remove translation from the view matrix 15 | vec4 clipPos = projection * rotView * vec4(localPos, 1.0); 16 | 17 | gl_Position = clipPos.xyww; 18 | } -------------------------------------------------------------------------------- /shaders/fbo.frag: -------------------------------------------------------------------------------- 1 | #version 430 2 | #extension GL_ARB_bindless_texture : require 3 | 4 | in vec2 passTexCoord; 5 | 6 | out vec4 fragColor; 7 | 8 | layout(binding = 6, std430) buffer textureBuffer 9 | { 10 | sampler2D inputTexture; 11 | }; 12 | 13 | void main() 14 | { 15 | vec4 inputTexPixel = texture(inputTexture, passTexCoord); 16 | fragColor = inputTexPixel; 17 | } -------------------------------------------------------------------------------- /shaders/frustumCulling.comp: -------------------------------------------------------------------------------- 1 | #version 430 2 | 3 | layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in; 4 | 5 | struct Indirect 6 | { 7 | uint count; 8 | uint instanceCount; 9 | uint firstIndex; 10 | uint baseVertex; 11 | uint baseInstance; 12 | }; 13 | 14 | layout(binding = 5, std430) buffer indirectDrawBuffer 15 | { 16 | Indirect indirect[]; 17 | }; 18 | 19 | layout(std430, binding = MODELMATRICES_BINDING) buffer modelMatrixBuffer 20 | { 21 | mat4 modelMatrices[]; 22 | }; 23 | 24 | layout(std430, binding = 6) buffer boundingBoxBuffer 25 | { 26 | mat2x4 bbox[]; 27 | }; 28 | 29 | uniform mat4 viewProjMatrix; 30 | 31 | void main() 32 | { 33 | uint index = gl_GlobalInvocationID.x; 34 | if (index >= indirect.length()) 35 | return; 36 | 37 | mat2x4 currentBBox = bbox[index]; 38 | vec3 bmin = currentBBox[0].xyz; 39 | vec3 bmax = currentBBox[1].xyz; 40 | 41 | mat4 mvp = viewProjMatrix * modelMatrices[index]; 42 | 43 | vec4 vertices[8] = 44 | { 45 | mvp * vec4(bmin.x, bmin.y, bmin.z, 1.0f), 46 | mvp * vec4(bmax.x, bmin.y, bmin.z, 1.0f), 47 | mvp * vec4(bmin.x, bmax.y, bmin.z, 1.0f), 48 | mvp * vec4(bmax.x, bmax.y, bmin.z, 1.0f), 49 | mvp * vec4(bmin.x, bmin.y, bmax.z, 1.0f), 50 | mvp * vec4(bmax.x, bmin.y, bmax.z, 1.0f), 51 | mvp * vec4(bmin.x, bmax.y, bmax.z, 1.0f), 52 | mvp * vec4(bmax.x, bmax.y, bmax.z, 1.0f) 53 | }; 54 | 55 | // clip bounding box vertices on frustum planes 56 | for (int direction = -1; direction < 2; direction += 2) 57 | for (int axis = 0; axis < 3; ++axis) 58 | { 59 | bool outside = true; 60 | 61 | for (int vertex = 0; vertex < 8; ++vertex) 62 | outside = outside && (direction * vertices[vertex][axis] > vertices[vertex].w); 63 | 64 | if (outside) 65 | { 66 | indirect[index].instanceCount = 0; 67 | return; 68 | } 69 | } 70 | 71 | indirect[index].instanceCount = 1; 72 | } 73 | -------------------------------------------------------------------------------- /shaders/irradianceMapCalc.frag: -------------------------------------------------------------------------------- 1 | #version 430 2 | 3 | #extension GL_ARB_bindless_texture : require 4 | 5 | out vec4 fragColor; 6 | in vec3 localPos; 7 | 8 | layout(binding = 6, std430) buffer textureBuffer 9 | { 10 | samplerCube environmentMap; 11 | }; 12 | 13 | const float PI = 3.14159265359; 14 | 15 | void main() 16 | { 17 | // the sample direction equals the hemisphere's orientation 18 | vec3 normal = normalize(localPos); 19 | 20 | vec3 irradiance = vec3(0.0); 21 | 22 | vec3 up = vec3(0.0, 1.0, 0.0); 23 | vec3 right = cross(up, normal); 24 | up = cross(normal, right); 25 | 26 | float sampleDelta = 0.025; 27 | float nrSamples = 0.0; 28 | for(float phi = 0.0; phi < 2.0 * PI; phi += sampleDelta) 29 | { 30 | for(float theta = 0.0; theta < 0.5 * PI; theta += sampleDelta) 31 | { 32 | // spherical to cartesian (in tangent space) 33 | vec3 tangentSample = vec3(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta)); 34 | // tangent space to world 35 | vec3 sampleVec = tangentSample.x * right + tangentSample.y * up + tangentSample.z * normal; 36 | 37 | irradiance += texture(environmentMap, sampleVec).rgb * cos(theta) * sin(theta); 38 | nrSamples++; 39 | } 40 | } 41 | irradiance = PI * irradiance * (1.0 / float(nrSamples)); 42 | 43 | fragColor = vec4(irradiance, 1.0); 44 | } -------------------------------------------------------------------------------- /shaders/lightDebug.vert: -------------------------------------------------------------------------------- 1 | #version 430 2 | 3 | #include "common/light.glsl" 4 | 5 | out vec3 posColor; 6 | out int vertexID; 7 | 8 | void main() 9 | { 10 | Light currentLight = lights[gl_VertexID]; 11 | gl_Position = vec4(currentLight.position, 1.0f); 12 | posColor = currentLight.color; 13 | vertexID = gl_VertexID; 14 | } -------------------------------------------------------------------------------- /shaders/lightTransform.vert: -------------------------------------------------------------------------------- 1 | #version 460 2 | layout (location = VERTEX_LAYOUT) in vec3 vertexPosition; 3 | layout (location = TEXCOORD_LAYOUT) in vec3 vertexTexCoord; 4 | 5 | uniform mat4 lightSpaceMatrix; 6 | uniform mat4 ModelMatrix = mat4(1.0f); 7 | 8 | flat out uint passDrawID; 9 | out vec3 passTexCoord; 10 | 11 | layout(std430, binding = MODELMATRICES_BINDING) buffer ModelMatrixBuffer 12 | { 13 | mat4 modelMatrices[]; 14 | }; 15 | 16 | subroutine mat4 getModelMatrix(); 17 | 18 | layout(index = 0) subroutine(getModelMatrix) mat4 bufferModelMatrix() 19 | { 20 | return modelMatrices[gl_DrawID]; 21 | } 22 | 23 | layout(index = 1) subroutine(getModelMatrix) mat4 uniformModelMatrix() 24 | { 25 | return ModelMatrix; 26 | } 27 | 28 | layout(location = 0) subroutine uniform getModelMatrix drawMode; 29 | 30 | void main() 31 | { 32 | mat4 modelMatrix = drawMode(); 33 | gl_Position = lightSpaceMatrix * modelMatrix * vec4(vertexPosition, 1.0); 34 | passDrawID = gl_DrawID; 35 | passTexCoord = vertexTexCoord; 36 | } -------------------------------------------------------------------------------- /shaders/modelFragVolumetric.frag: -------------------------------------------------------------------------------- 1 | #version 430 2 | #extension GL_ARB_bindless_texture : require 3 | //#extension GL_ARB_gpu_shader_int64 : require 4 | 5 | uniform int materialIndex; 6 | 7 | layout(binding = CAMERA_BINDING, std430) buffer cameraBuffer 8 | { 9 | mat4 viewMatrix; 10 | mat4 projectionMatrix; 11 | vec3 camPos; 12 | }; 13 | 14 | in vec3 passNormal; 15 | in vec3 passTexCoord; 16 | in vec3 passWorldPos; 17 | in vec3 passViewPos; 18 | 19 | #include "common/light.glsl" 20 | #include "common/material.glsl" 21 | #include "common/shadowMapping.glsl" 22 | #include "common/volumetricLighting.glsl" 23 | 24 | out vec4 fragColor; 25 | 26 | void main() 27 | { 28 | Material currentMaterial = materials[materialIndex]; 29 | 30 | vec3 diffCol = getDiffColor(materialIndex); 31 | vec3 specCol = getSpecColor(materialIndex); 32 | 33 | vec3 normal = normalize(passNormal); 34 | vec3 viewDir = normalize(camPos - passWorldPos); 35 | 36 | vec3 lightingColor = ambient; 37 | 38 | for (int i = 0; i < lights.length(); i++) 39 | { 40 | LightResult lRes = getLight(i, passWorldPos, viewDir, normal, currentMaterial.Ns); 41 | float shadowFactor = calculateShadowPCF(i, passWorldPos, normal, lRes.direction); 42 | lightingColor += shadowFactor * (diffCol * lRes.diffuse + specCol * lRes.specular); 43 | } 44 | lightingColor = applyVolumetricLightingManual(lightingColor, passViewPos.z); 45 | vec4 col = vec4(lightingColor, 1.0); 46 | 47 | if (currentMaterial.opacity == -1.0f) // has opacity texture instead of opacity 48 | col.a = texture(currentMaterial.opacityTexture, passTexCoord.rg).r; 49 | else 50 | col.a = currentMaterial.opacity; 51 | 52 | // SPONZA HACK 53 | if (col.a <= 0.9f) 54 | discard; 55 | 56 | fragColor = col; 57 | } -------------------------------------------------------------------------------- /shaders/modelFragVolumetricMD.frag: -------------------------------------------------------------------------------- 1 | #version 430 2 | #extension GL_ARB_bindless_texture : require 3 | //#extension GL_ARB_gpu_shader_int64 : require 4 | layout(early_fragment_tests) in; 5 | 6 | layout(binding = CAMERA_BINDING, std430) buffer cameraBuffer 7 | { 8 | mat4 viewMatrix; 9 | mat4 projectionMatrix; 10 | vec3 camPos; 11 | }; 12 | 13 | layout(location = 0) in vec3 passWorldPos; 14 | layout(location = 1) in vec3 passTexCoord; 15 | layout(location = 2) in vec3 passNormal; 16 | layout(location = 3) in vec3 passViewPos; 17 | layout(location = 4) flat in uint passDrawID; 18 | 19 | #include "common/light.glsl" 20 | #include "common/material.glsl" 21 | #include "common/shadowMapping.glsl" 22 | #include "common/volumetricLighting.glsl" 23 | 24 | out vec4 fragColor; 25 | 26 | void main() 27 | { 28 | int materialIndex = int(materialIndices[passDrawID]); 29 | Material currentMaterial = materials[materialIndex]; 30 | 31 | vec3 diffCol = getDiffColor(materialIndex); 32 | vec3 specCol = getSpecColor(materialIndex); 33 | 34 | vec3 normal = normalize(passNormal); 35 | vec3 viewDir = normalize(camPos - passWorldPos); 36 | 37 | vec3 lightingColor = ambient; 38 | 39 | for (int i = 0; i < lights.length(); i++) 40 | { 41 | LightResult lRes = getLight(i, passWorldPos, viewDir, normal, currentMaterial.Ns); 42 | float shadowFactor = calculateShadowPCF(i, passWorldPos, normal, lRes.direction); 43 | lightingColor += shadowFactor * (diffCol * lRes.diffuse + specCol * lRes.specular); 44 | } 45 | lightingColor = applyVolumetricLightingManual(lightingColor, passViewPos.z); 46 | vec4 col = vec4(lightingColor, 1.0); 47 | 48 | if (currentMaterial.opacity == -1.0f) // has opacity texture instead of opacity 49 | col.a = texture(currentMaterial.opacityTexture, passTexCoord.rg).r; 50 | else if (currentMaterial.opacity == -2.0f) 51 | col.a = getDiffTextureAlpha(materialIndex); 52 | else 53 | col.a = currentMaterial.opacity; 54 | 55 | fragColor = col; 56 | } -------------------------------------------------------------------------------- /shaders/modelFragVolumetricMDBump.frag: -------------------------------------------------------------------------------- 1 | #version 430 2 | #extension GL_ARB_bindless_texture : require 3 | //#extension GL_ARB_gpu_shader_int64 : require 4 | layout(early_fragment_tests) in; 5 | 6 | layout(binding = CAMERA_BINDING, std430) buffer cameraBuffer 7 | { 8 | mat4 viewMatrix; 9 | mat4 projectionMatrix; 10 | vec3 camPos; 11 | }; 12 | 13 | layout(location = 0) in vec3 passWorldPos; 14 | layout(location = 1) in vec3 passTexCoord; 15 | layout(location = 2) in vec3 passNormal; 16 | layout(location = 3) in vec3 passViewPos; 17 | layout(location = 4) flat in uint passDrawID; 18 | layout(location = 5) in vec3 tangent; 19 | layout(location = 6) in vec3 bitangent; 20 | 21 | #include "common/light.glsl" 22 | #include "common/material.glsl" 23 | #include "common/shadowMapping.glsl" 24 | #include "common/volumetricLighting.glsl" 25 | 26 | layout(bindless_sampler) uniform samplerCube skybox; 27 | 28 | out vec4 fragColor; 29 | 30 | void main() 31 | { 32 | int materialIndex = int(materialIndices[passDrawID]); 33 | Material currentMaterial = materials[materialIndex]; 34 | 35 | vec3 diffCol = getDiffColor(materialIndex); 36 | vec3 specCol = getSpecColor(materialIndex); 37 | 38 | vec3 viewDir = normalize(camPos - passWorldPos); 39 | 40 | vec3 normal; 41 | if(currentMaterial.bumpType == 1) 42 | { 43 | mat3 TBN = mat3(tangent, bitangent, passNormal); 44 | normal = texture(currentMaterial.bumpTexture, passTexCoord.rg).rgb; 45 | normal = normalize(normal * 2.0 - 1.0); 46 | normal = normalize(TBN * normal); 47 | } 48 | else if(currentMaterial.bumpType == 2) 49 | { 50 | vec2 size = vec2(0.5,0.0); //"strength" of bump-mapping 51 | ivec3 off = ivec3(-1,0,1); 52 | 53 | float s01 = textureOffset(currentMaterial.bumpTexture, passTexCoord.rg, off.xy).x; 54 | float s21 = textureOffset(currentMaterial.bumpTexture, passTexCoord.rg, off.zy).x; 55 | float s10 = textureOffset(currentMaterial.bumpTexture, passTexCoord.rg, off.yx).x; 56 | float s12 = textureOffset(currentMaterial.bumpTexture, passTexCoord.rg, off.yz).x; 57 | vec3 va = normalize(vec3(size.xy,s21-s01)); 58 | vec3 vb = normalize(vec3(size.yx,s12-s10)); 59 | vec3 tanSpaceNormal = cross(va,vb); 60 | 61 | mat3 TBN = mat3(tangent, bitangent, passNormal); 62 | normal = normalize(TBN * tanSpaceNormal); 63 | } 64 | else 65 | { 66 | normal = normalize(passNormal); 67 | } 68 | 69 | vec3 lightingColor = ambient * diffCol; 70 | vec3 reflection = 2.0f * textureLod(skybox, reflect(-viewDir, normal), 5).rgb; 71 | 72 | for (int i = 0; i < lights.length(); i++) 73 | { 74 | LightResult lRes = getLight(i, passWorldPos, viewDir, normal, currentMaterial.Ns); 75 | float shadowFactor = calculateShadowPCF(i, passWorldPos, normal, lRes.direction); 76 | lightingColor += shadowFactor * (diffCol * lRes.diffuse + specCol * lRes.specular); 77 | } 78 | if(dot(diffCol, diffCol) < 0.1f && currentMaterial.Ns > 50.0f) 79 | lightingColor = mix(lightingColor, reflection, clamp(currentMaterial.Ns / 100.0f, 0.0f, 1.0f)); 80 | lightingColor = applyVolumetricLightingManual(lightingColor, passViewPos.z); 81 | vec4 col = vec4(lightingColor, 1.0); 82 | 83 | if (currentMaterial.opacity == -1.0f) // has opacity texture instead of opacity 84 | col.a = texture(currentMaterial.opacityTexture, passTexCoord.rg).r; 85 | else if (currentMaterial.opacity == -2.0f) 86 | col.a = getDiffTextureAlpha(materialIndex); 87 | else 88 | col.a = currentMaterial.opacity; 89 | 90 | fragColor = col; 91 | } -------------------------------------------------------------------------------- /shaders/modelVert.vert: -------------------------------------------------------------------------------- 1 | #version 430 2 | 3 | layout (location = VERTEX_LAYOUT) in vec3 vertexPosition; 4 | layout (location = NORMAL_LAYOUT) in vec3 vertexNormal; 5 | layout (location = TEXCOORD_LAYOUT) in vec3 vertexTexCoord; 6 | 7 | uniform mat4 projectionMatrix; 8 | uniform mat4 viewMatrix; 9 | 10 | uniform int meshIndex; 11 | 12 | out vec3 passNormal; 13 | out vec3 passTexCoord; 14 | out vec3 passFragPos; 15 | 16 | layout (std430, binding = MODELMATRICES_BINDING) buffer ModelMatrixBuffer 17 | { 18 | mat4 modelMatrices[]; 19 | }; 20 | 21 | void main() 22 | { 23 | mat4 modelMatrix = modelMatrices[meshIndex]; 24 | mat4 mvp = projectionMatrix * viewMatrix * modelMatrix; 25 | gl_Position = mvp * vec4(vertexPosition, 1.0f); 26 | passNormal = mat3(transpose(inverse(modelMatrix))) * vertexNormal; 27 | passTexCoord = vertexTexCoord; 28 | passFragPos = vec3(modelMatrix * vec4(vertexPosition, 1.0f)); 29 | } -------------------------------------------------------------------------------- /shaders/modelVertMultiDraw.vert: -------------------------------------------------------------------------------- 1 | #version 460 2 | 3 | layout (location = VERTEX_LAYOUT) in vec3 vertexPosition; 4 | layout (location = NORMAL_LAYOUT) in vec3 vertexNormal; 5 | layout (location = TEXCOORD_LAYOUT) in vec3 vertexTexCoord; 6 | 7 | uniform mat4 projectionMatrix; 8 | uniform mat4 viewMatrix; 9 | 10 | layout(location = 0) out vec3 passFragPos; 11 | layout(location = 1) out vec3 passNormal; 12 | layout(location = 2) out vec3 passTexCoord; 13 | layout(location = 3) flat out uint passDrawID; 14 | 15 | layout (std430, binding = MODELMATRICES_BINDING) buffer ModelMatrixBuffer 16 | { 17 | mat4 modelMatrices[]; 18 | }; 19 | 20 | void main() 21 | { 22 | mat4 modelMatrix = modelMatrices[gl_DrawID]; 23 | passDrawID = gl_DrawID; 24 | mat4 mvp = projectionMatrix * viewMatrix * modelMatrix; 25 | gl_Position = mvp * vec4(vertexPosition, 1.0f); 26 | passNormal = mat3(transpose(inverse(modelMatrix))) * vertexNormal; 27 | passTexCoord = vertexTexCoord; 28 | passFragPos = vec3(modelMatrix * vec4(vertexPosition, 1.0f)); 29 | } -------------------------------------------------------------------------------- /shaders/modelVertVolumetric.vert: -------------------------------------------------------------------------------- 1 | #version 430 2 | 3 | layout (location = VERTEX_LAYOUT) in vec3 vertexPosition; 4 | layout (location = NORMAL_LAYOUT) in vec3 vertexNormal; 5 | layout (location = TEXCOORD_LAYOUT) in vec3 vertexTexCoord; 6 | 7 | layout(binding = CAMERA_BINDING, std430) buffer cameraBuffer 8 | { 9 | mat4 viewMatrix; 10 | mat4 projectionMatrix; 11 | vec3 camPos; 12 | }; 13 | 14 | uniform int meshIndex; 15 | 16 | out vec3 passNormal; 17 | out vec3 passTexCoord; 18 | out vec3 passWorldPos; 19 | out vec3 passViewPos; 20 | 21 | layout (std430, binding = MODELMATRICES_BINDING) buffer ModelMatrixBuffer 22 | { 23 | mat4 modelMatrices[]; 24 | }; 25 | 26 | void main() 27 | { 28 | mat4 modelMatrix = modelMatrices[meshIndex]; 29 | 30 | vec4 worldPos = modelMatrix * vec4(vertexPosition, 1.0f); 31 | passWorldPos = worldPos.xyz; 32 | 33 | vec4 viewPos = viewMatrix * worldPos; 34 | passViewPos = viewPos.xyz; 35 | 36 | vec4 projPos = projectionMatrix * viewPos; 37 | gl_Position = projPos; 38 | 39 | passNormal = mat3(transpose(inverse(modelMatrix))) * vertexNormal; 40 | passTexCoord = vertexTexCoord; 41 | } -------------------------------------------------------------------------------- /shaders/modelVertVolumetricMD.vert: -------------------------------------------------------------------------------- 1 | #version 460 2 | 3 | layout (location = VERTEX_LAYOUT) in vec3 vertexPosition; 4 | layout (location = NORMAL_LAYOUT) in vec3 vertexNormal; 5 | layout (location = TEXCOORD_LAYOUT) in vec3 vertexTexCoord; 6 | 7 | layout(binding = CAMERA_BINDING, std430) buffer cameraBuffer 8 | { 9 | mat4 viewMatrix; 10 | mat4 projectionMatrix; 11 | vec3 camPos; 12 | }; 13 | 14 | layout(location = 0) out vec3 passFragPos; 15 | layout(location = 1) out vec3 passTexCoord; 16 | layout(location = 2) out vec3 passNormal; 17 | layout(location = 3) out vec3 passViewPos; 18 | layout(location = 4) flat out uint passDrawID; 19 | 20 | layout (std430, binding = MODELMATRICES_BINDING) buffer ModelMatrixBuffer 21 | { 22 | mat4 modelMatrices[]; 23 | }; 24 | 25 | void main() 26 | { 27 | mat4 modelMatrix = modelMatrices[gl_DrawID]; 28 | passDrawID = gl_DrawID; 29 | 30 | vec4 worldPos = modelMatrix * vec4(vertexPosition, 1.0f); 31 | passFragPos = worldPos.xyz; 32 | 33 | vec4 viewPos = viewMatrix * worldPos; 34 | passViewPos = viewPos.xyz; 35 | 36 | vec4 projPos = projectionMatrix * viewPos; 37 | gl_Position = projPos; 38 | 39 | passNormal = mat3(transpose(inverse(modelMatrix))) * vertexNormal; 40 | passTexCoord = vertexTexCoord; 41 | } -------------------------------------------------------------------------------- /shaders/mondrian.frag: -------------------------------------------------------------------------------- 1 | // Mondrian Image 2 | uniform vec2 u_resolution; 3 | 4 | vec3 smoothBorder(in vec2 st, in float start, in float end) 5 | { 6 | float left = smoothstep(start, end, st.x); 7 | float bottom = smoothstep(start, end,st.y); 8 | float right = smoothstep(start, end, 1.0-st.x); 9 | float top = smoothstep(start, end, 1.0-st.y); 10 | return vec3(left * bottom * right * top); 11 | } 12 | 13 | vec3 solidBorder(in vec2 st, in float borderWidth) 14 | { 15 | float left = step(borderWidth, st.x); 16 | float bottom = step(borderWidth, st.y); 17 | float right = step(borderWidth, 1.0-st.x); 18 | float top = step(borderWidth, 1.0-st.y); 19 | return vec3(left * bottom * right * top); 20 | } 21 | 22 | vec3 positionedRectangle(in vec2 st, in float borderWidth, in vec4 borderPositions) 23 | { 24 | float left = 1.0; 25 | float bottom = 1.0; 26 | float right = 1.0; 27 | float top = 1.0; 28 | if(st.x < borderPositions.y && st.x > borderPositions.x 29 | && st.y < borderPositions.w && st.y > borderPositions.z) 30 | { 31 | left = step(borderPositions.x + borderWidth, st.x); 32 | right = step(borderWidth, borderPositions.y - st.x); 33 | bottom = step(borderPositions.z + borderWidth, st.y); 34 | top = step(borderWidth, borderPositions.w-st.y); 35 | } 36 | return vec3(left * bottom * right * top); 37 | } 38 | 39 | vec3 positionedSmoothRectangle(in vec2 st, in float start, in float end, in vec4 borderPositions) 40 | { 41 | float left = 1.0; 42 | float bottom = 1.0; 43 | float right = 1.0; 44 | float top = 1.0; 45 | if(st.x < borderPositions.y && st.x > borderPositions.x 46 | && st.y < borderPositions.w && st.y > borderPositions.z) 47 | { 48 | left = smoothstep(borderPositions.x + start, borderPositions.x + end, st.x); 49 | right = smoothstep(start, end, borderPositions.y - st.x); 50 | bottom = smoothstep(borderPositions.z + start, borderPositions.z + end, st.y); 51 | top = smoothstep(start, end, borderPositions.w-st.y); 52 | } 53 | return vec3(left * bottom * right * top); 54 | } 55 | 56 | vec3 TDline(in vec2 st, in float width, in float xpos) 57 | { 58 | float line = 1.0; 59 | if(st.x < xpos && st.x > xpos - width) 60 | { 61 | line = step(xpos + width, st.x); 62 | } 63 | return vec3(line); 64 | } 65 | 66 | vec3 RLline(in vec2 st, in float width, in float ypos) 67 | { 68 | float line = 1.0; 69 | if(st.y < ypos && st.y > ypos - width) 70 | { 71 | line = step(width, ypos - st.y); 72 | } 73 | return vec3(line); 74 | } 75 | 76 | vec3 ClampedRLline(in vec2 st, in float width, in float ypos, in float minX, in float maxX) 77 | { 78 | float line = 1.0; 79 | if(st.y < ypos && st.y > ypos - width 80 | && st.x > minX && st.x < maxX) 81 | { 82 | line = step(width, ypos - st.y); 83 | } 84 | return vec3(line); 85 | } 86 | 87 | vec3 ClampedTDline(in vec2 st, in float width, in float xpos, in float minY, in float maxY) 88 | { 89 | float line = 1.0; 90 | if(st.x < xpos && st.x > xpos - width 91 | && st.y > minY && st.y < maxY) 92 | { 93 | line = step(xpos + width, st.x); 94 | } 95 | return vec3(line); 96 | } 97 | 98 | void main() 99 | { 100 | vec2 st = gl_FragCoord.xy/u_resolution.xy; 101 | vec3 color = vec3(0.9, 0.9, 0.8); 102 | 103 | vec4 borderPos1 = vec4(0.2, 0.4, 0.2, 0.4); 104 | vec4 borderPos2 = vec4(0.3, 0.5, 0.3, 0.5); 105 | 106 | if(st.x < 0.2 && st.y < 1.0 && st.y > 0.7) 107 | { 108 | color = vec3(0.8, 0.2, 0.2); 109 | } 110 | 111 | if(st.x > 0.95 && st.y > 0.7) 112 | { 113 | color = vec3(1.0, 0.8, 0.2); 114 | } 115 | 116 | if(st.x > 0.8 && st.y < 0.1) 117 | { 118 | color = vec3(0.2, 0.2, 1.0); 119 | } 120 | 121 | //color = smoothRectangle(st, 0.01, 0.05); 122 | //color *= positionedRectangle(st, 0.02, borderPos1); 123 | //color *= positionedRectangle(st, 0.02, borderPos2); 124 | 125 | color *= TDline(st, 0.02, 0.2); 126 | color *= TDline(st, 0.02, 0.8); 127 | color *= TDline(st, 0.02, 0.95); 128 | 129 | color *= RLline(st, 0.02, 0.85); 130 | color *= RLline(st, 0.02, 0.7); 131 | color *= ClampedRLline(st, 0.02, 0.1, 0.2, 1.0); 132 | color *= ClampedTDline(st, 0.02, 0.07, 0.7, 1.0); 133 | 134 | 135 | gl_FragColor = vec4(color,1.0); 136 | } -------------------------------------------------------------------------------- /shaders/nothing.frag: -------------------------------------------------------------------------------- 1 | #version 430 2 | layout(early_fragment_tests) in; 3 | 4 | // "empty" fragment shader, used to only fill the depth buffer 5 | 6 | void main() 7 | { 8 | // gl_FragDepth = gl_FragCoord.z; 9 | } -------------------------------------------------------------------------------- /shaders/omnidirectional.frag: -------------------------------------------------------------------------------- 1 | #version 430 2 | 3 | in vec4 FragPos; 4 | 5 | uniform vec3 lightPos; 6 | 7 | float far = 1000; 8 | 9 | void main() 10 | { 11 | // get distance between fragment and light source 12 | float lightDistance = length(FragPos.xyz - lightPos); 13 | 14 | // map to [0;1] range by dividing by far_plane 15 | lightDistance = lightDistance / far; 16 | 17 | // write this as modified depth 18 | gl_FragDepth = lightDistance; 19 | } -------------------------------------------------------------------------------- /shaders/omnidirectional.geom: -------------------------------------------------------------------------------- 1 | #version 430 2 | layout (triangles) in; 3 | layout (triangle_strip, max_vertices=18) out; 4 | 5 | uniform mat4 lightSpaceMatrix; 6 | uniform vec3 lightPos; 7 | 8 | mat4 shadowMatrices[6] = { 9 | mat4(vec4(0, 0, -1, 0), vec4(0, -1, 0, 0), vec4(-1, 0, 0, 0), vec4(0, 0, 0, 1)), 10 | mat4(vec4(0, 0, 1, 0), vec4(0, -1, 0, 0), vec4( 1, 0, 0, 0), vec4(0, 0, 0, 1)), 11 | mat4(vec4( 1, 0, 0, 0), vec4(0, 0, -1, 0), vec4(0, 1, 0, 0), vec4(0, 0, 0, 1)), 12 | mat4(vec4( 1, 0, 0, 0), vec4(0, 0, 1, 0), vec4(0, -1, 0, 0), vec4(0, 0, 0, 1)), 13 | mat4(vec4( 1, 0, 0, 0), vec4(0, -1, 0, 0), vec4(0, 0, -1, 0), vec4(0, 0, 0, 1)), 14 | mat4(vec4(-1, 0, 0, 0), vec4(0, -1, 0, 0), vec4(0, 0, 1, 0), vec4(0, 0, 0, 1)) 15 | }; 16 | 17 | out vec4 FragPos; // FragPos from GS (output per emitvertex) 18 | 19 | void main() 20 | { 21 | for(int face = 0; face < 6; ++face) 22 | { 23 | gl_Layer = face; // built-in variable that specifies to which face we render. 24 | for(int i = 0; i < 3; ++i) // for each triangle's vertices 25 | { 26 | FragPos = gl_in[i].gl_Position; 27 | mat4 view = shadowMatrices[face]; 28 | view[3] = vec4(lightPos, 1); 29 | gl_Position = lightSpaceMatrix * view * FragPos; 30 | EmitVertex(); 31 | } 32 | EndPrimitive(); 33 | } 34 | } -------------------------------------------------------------------------------- /shaders/pbr1.vert: -------------------------------------------------------------------------------- 1 | #version 430 2 | 3 | layout (location = 0) in vec3 VertexPosition; 4 | layout (location = 1) in vec3 VertexNormal; 5 | 6 | out vec3 passPosition; 7 | out vec3 Normal; 8 | 9 | uniform mat4 ModelMatrix; 10 | uniform mat4 ViewMatrix; 11 | uniform mat4 ProjectionMatrix; 12 | 13 | void main() 14 | { 15 | Normal = mat3(ModelMatrix) * VertexNormal; 16 | passPosition = vec3( ModelMatrix * vec4(VertexPosition, 1.0)); 17 | 18 | gl_Position = ProjectionMatrix * ViewMatrix * ModelMatrix * vec4(VertexPosition, 1.0); 19 | } -------------------------------------------------------------------------------- /shaders/postProcess.frag: -------------------------------------------------------------------------------- 1 | #version 430 2 | #extension GL_ARB_bindless_texture : require 3 | 4 | in vec2 passTexCoord; 5 | 6 | out vec4 fragColor; 7 | 8 | uniform vec2 dimensions; 9 | 10 | uniform int useGrayscale; 11 | uniform int useBlur; 12 | uniform int useSharpen; 13 | 14 | 15 | layout(binding = 6, std430) buffer textureBuffer 16 | { 17 | sampler2D inputTexture; 18 | }; 19 | 20 | vec4 computeGreyscale(in vec4 color) 21 | { 22 | float grey = 0.21 * color.r + 0.72 * color.g + 0.07 * color.b; 23 | return vec4(grey, grey, grey, color.a); 24 | } 25 | 26 | vec3 applyKernel3x3(in float kernel[9], in float factor) 27 | { 28 | vec2 offset = vec2(1.0) / dimensions; 29 | vec2 imageOffsets[9] = vec2[]( 30 | vec2(-offset.x, offset.y), // top-left 31 | vec2( 0.0f, offset.y), // top-center 32 | vec2( offset.x, offset.y), // top-right 33 | vec2(-offset.x, 0.0f), // center-left 34 | vec2( 0.0f, 0.0f), // center-center 35 | vec2( offset.x, 0.0f), // center-right 36 | vec2(-offset.x, -offset.y), // bottom-left 37 | vec2( 0.0f, -offset.y), // bottom-center 38 | vec2( offset.x, -offset.y) // bottom-right 39 | ); 40 | vec3 col = vec3(0.0); 41 | for(int i = 0; i < 9; i++) 42 | { 43 | col += factor * kernel[i] * vec3(texture(inputTexture, passTexCoord + imageOffsets[i])); 44 | } 45 | return col; 46 | } 47 | 48 | void main() 49 | { 50 | vec4 currentColor = texture(inputTexture, passTexCoord); 51 | 52 | if(useSharpen == 1) 53 | { 54 | float kernel[9] = float[]( 55 | -1, -1, -1, 56 | -1, 9, -1, 57 | -1, -1, -1 58 | ); 59 | currentColor.rgb = applyKernel3x3(kernel, 1.0); 60 | } 61 | 62 | if(useBlur == 1) 63 | { 64 | float kernel[9] = float[]( 65 | 1, 2, 1, 66 | 2, 4, 2, 67 | 1, 2, 1 68 | ); 69 | currentColor.rgb = applyKernel3x3(kernel, 1.0 / 16.0); 70 | } 71 | 72 | if(useGrayscale == 1) 73 | { 74 | currentColor = computeGreyscale(currentColor); 75 | } 76 | 77 | fragColor = currentColor; 78 | } -------------------------------------------------------------------------------- /shaders/prefilterEnvMap.frag: -------------------------------------------------------------------------------- 1 | #version 430 2 | #extension GL_ARB_bindless_texture : require 3 | 4 | out vec4 fragColor; 5 | in vec3 localPos; 6 | 7 | layout(binding = 6, std430) buffer textureBuffer 8 | { 9 | samplerCube environmentMap; 10 | }; 11 | 12 | uniform float roughness; 13 | 14 | const float PI = 3.14159265359; 15 | 16 | // radical inverse function 17 | float RadicalInverse(uint bits) 18 | { 19 | bits = (bits << 16u) | (bits >> 16u); 20 | bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); 21 | bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); 22 | bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); 23 | bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); 24 | return float(bits) * 2.3283064365386963e-10; // / 0x100000000 25 | } 26 | 27 | // generate hammersley sequence using RIF 28 | vec2 Hammersley(uint i, uint N) 29 | { 30 | return vec2(float(i)/float(N), RadicalInverse(i)); 31 | } 32 | 33 | vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness) 34 | { 35 | float a = roughness*roughness; 36 | 37 | float phi = 2.0 * PI * Xi.x; 38 | float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a*a - 1.0) * Xi.y)); 39 | float sinTheta = sqrt(1.0 - cosTheta*cosTheta); 40 | 41 | // from spherical coordinates to cartesian coordinates 42 | vec3 H; 43 | H.x = cos(phi) * sinTheta; 44 | H.y = sin(phi) * sinTheta; 45 | H.z = cosTheta; 46 | 47 | // from tangent-space vector to world-space sample vector 48 | vec3 up = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); 49 | vec3 tangent = normalize(cross(up, N)); 50 | vec3 bitangent = cross(N, tangent); 51 | 52 | vec3 sampleVec = tangent * H.x + bitangent * H.y + N * H.z; 53 | return normalize(sampleVec); 54 | } 55 | 56 | void main() 57 | { 58 | vec3 N = normalize(localPos); 59 | vec3 R = N; 60 | vec3 V = R; 61 | 62 | const uint SAMPLE_COUNT = 4096u; 63 | float totalWeight = 0.0; 64 | vec3 prefilteredColor = vec3(0.0); 65 | for(uint i = 0u; i < SAMPLE_COUNT; ++i) 66 | { 67 | vec2 Xi = Hammersley(i, SAMPLE_COUNT); 68 | vec3 H = ImportanceSampleGGX(Xi, N, roughness); 69 | vec3 L = normalize(2.0 * dot(V, H) * H - V); 70 | 71 | float NdotL = max(dot(N, L), 0.0); 72 | if(NdotL > 0.0) 73 | { 74 | prefilteredColor += texture(environmentMap, L).rgb * NdotL; 75 | totalWeight += NdotL; 76 | } 77 | } 78 | prefilteredColor = prefilteredColor / totalWeight; 79 | 80 | fragColor = vec4(prefilteredColor, 1.0); 81 | } -------------------------------------------------------------------------------- /shaders/quadSDF.vert: -------------------------------------------------------------------------------- 1 | #version 430 2 | 3 | layout (location = 0) in vec4 position; 4 | 5 | out vec2 pixelPos; 6 | 7 | void main() 8 | { 9 | gl_Position = position; 10 | pixelPos = position.xy; 11 | } -------------------------------------------------------------------------------- /shaders/sfq.vert: -------------------------------------------------------------------------------- 1 | #version 430 2 | 3 | layout (location = 0) in vec4 position; 4 | 5 | void main() 6 | { 7 | gl_Position = position; 8 | } -------------------------------------------------------------------------------- /shaders/sfq1.frag: -------------------------------------------------------------------------------- 1 | // time colors 2 | 3 | uniform vec2 u_resolution; 4 | uniform float u_time; 5 | 6 | // Plot a line on Y using a value between 0.0-1.0 7 | float plot(vec2 st, float pct) 8 | { 9 | return smoothstep( pct-0.02, pct, st.y) - 10 | smoothstep( pct, pct+0.02, st.y); 11 | } 12 | 13 | void main() 14 | { 15 | vec2 st = gl_FragCoord.xy/u_resolution; 16 | gl_FragColor = vec4(abs(sin(u_time)), st.x, st.y, 1.0); 17 | } -------------------------------------------------------------------------------- /shaders/shadowmapping.frag: -------------------------------------------------------------------------------- 1 | #version 430 2 | #extension GL_ARB_bindless_texture : require 3 | 4 | in vec3 passPositionView; 5 | in vec3 passPositionWorld; 6 | in vec3 interpNormal; 7 | 8 | #include "common/light.glsl" 9 | #include "common/shadowMapping.glsl" 10 | 11 | struct Material 12 | { 13 | vec3 diffColor; 14 | float kd; 15 | vec3 specColor; 16 | float ks; 17 | float shininess; 18 | float kt; 19 | int reflective; 20 | }; 21 | 22 | layout (std430, binding = MATERIAL_BINDING) restrict readonly buffer MaterialBuffer 23 | { 24 | Material material[]; 25 | }; 26 | 27 | uniform mat4 ModelMatrix; 28 | uniform mat4 ViewMatrix; 29 | uniform vec3 lightAmbient; 30 | uniform int matIndex; 31 | 32 | uniform vec3 camPos; 33 | 34 | layout( location = 0 ) out vec4 fragmentColor; 35 | 36 | void main() 37 | { 38 | vec3 passNormal = normalize(interpNormal); 39 | Material mat = material[ matIndex]; 40 | vec3 diffuse_color = mat.diffColor; 41 | float diffuse_alpha = 1.f - mat.kt; 42 | 43 | vec3 viewDir = normalize(camPos - passPositionWorld); 44 | 45 | fragmentColor.rgb = mat.kd*diffuse_color*lightAmbient; 46 | 47 | float ambient = 0.15; 48 | 49 | for (int i = 0; i < lights.length(); i++) 50 | { 51 | LightResult lRes = getLight(i, passPositionWorld, viewDir, passNormal, mat.shininess); 52 | float shadowFactor = calculateShadowPCF(i, passPositionWorld, passNormal, lRes.direction); 53 | fragmentColor.rgb += shadowFactor * (diffuse_color * lRes.diffuse + mat.specColor * lRes.specular); 54 | } 55 | 56 | fragmentColor.a = diffuse_alpha; 57 | } -------------------------------------------------------------------------------- /shaders/shadowmapping.vert: -------------------------------------------------------------------------------- 1 | #version 430 2 | 3 | layout (location = 0) in vec3 VertexPosition; 4 | layout (location = 1) in vec3 VertexNormal; 5 | 6 | out vec3 passPositionView; 7 | out vec3 passPositionWorld; 8 | out vec3 interpNormal; 9 | 10 | uniform mat4 ModelMatrix; 11 | uniform mat4 ViewMatrix; 12 | uniform mat4 ProjectionMatrix; 13 | 14 | void main() 15 | { 16 | mat4 ModelViewMatrix = ViewMatrix * ModelMatrix; 17 | mat3 NormalMatrix = mat3(transpose(inverse(ModelViewMatrix))); 18 | 19 | interpNormal = normalize( NormalMatrix * VertexNormal); 20 | passPositionView = vec3( ModelViewMatrix * vec4(VertexPosition, 1.0)); 21 | passPositionWorld = vec3(ModelMatrix * vec4(VertexPosition, 1.0)); 22 | gl_Position = ProjectionMatrix * ModelViewMatrix * vec4(VertexPosition, 1.0); 23 | } 24 | -------------------------------------------------------------------------------- /shaders/smAlpha.frag: -------------------------------------------------------------------------------- 1 | #version 430 2 | #extension GL_ARB_bindless_texture : require 3 | 4 | flat in uint passDrawID; 5 | in vec3 passTexCoord; 6 | 7 | #include "common/material.glsl" 8 | 9 | void main() 10 | { 11 | int materialIndex = int(materialIndices[passDrawID]); 12 | Material currentMaterial = materials[materialIndex]; 13 | 14 | float alpha = 1.0f; 15 | 16 | if (currentMaterial.opacity == -1.0f) // has opacity texture instead of opacity 17 | alpha = texture(currentMaterial.opacityTexture, passTexCoord.rg).r; 18 | else if (currentMaterial.opacity == -2.0f) 19 | alpha = getDiffTextureAlpha(materialIndex); 20 | else 21 | alpha = currentMaterial.opacity; 22 | 23 | if(alpha <= 0.8f) 24 | discard; 25 | } -------------------------------------------------------------------------------- /shaders/smfbo.frag: -------------------------------------------------------------------------------- 1 | #version 430 2 | #extension GL_ARB_bindless_texture : require 3 | 4 | in vec2 passTexCoord; 5 | 6 | out vec4 fragColor; 7 | 8 | layout(binding = 7, std430) buffer textureBuffer 9 | { 10 | sampler2D inputTexture; 11 | }; 12 | 13 | void main() 14 | { 15 | float depthValue = texture(inputTexture, passTexCoord).r; 16 | fragColor = vec4(vec3(depthValue), 1.0); 17 | } -------------------------------------------------------------------------------- /shaders/tangentSpace.geom: -------------------------------------------------------------------------------- 1 | #version 430 2 | 3 | layout (triangles) in; 4 | layout (triangle_strip, max_vertices = 3) out; 5 | 6 | layout(location = 0) in vec3 passFragPos[]; 7 | layout(location = 1) in vec3 passNormal[]; 8 | layout(location = 2) in vec3 passTexCoord[]; 9 | layout(location = 3) flat in uint passDrawID[]; 10 | 11 | layout(location = 0) out vec3 pos; 12 | layout(location = 1) out vec3 texCoord; 13 | layout(location = 2) out vec3 normal; 14 | layout(location = 3) flat out uint drawID; 15 | layout(location = 4) out vec3 tangent; 16 | layout(location = 5) out vec3 bitangent; 17 | 18 | void main() { 19 | 20 | vec3 edge1 = passFragPos[1] - passFragPos[0]; 21 | vec3 edge2 = passFragPos[2] - passFragPos[0]; 22 | vec2 deltaUV1 = passTexCoord[1].xy - passTexCoord[0].xy; 23 | vec2 deltaUV2 = passTexCoord[2].xy - passTexCoord[0].xy; 24 | 25 | float f = 1.0f / (deltaUV1.x * deltaUV2.y - deltaUV2.x * deltaUV1.y); 26 | 27 | tangent.x = f * (deltaUV2.y * edge1.x - deltaUV1.y * edge2.x); 28 | tangent.y = f * (deltaUV2.y * edge1.y - deltaUV1.y * edge2.y); 29 | tangent.z = f * (deltaUV2.y * edge1.z - deltaUV1.y * edge2.z); 30 | tangent = normalize(tangent); 31 | 32 | bitangent.x = f * (-deltaUV2.x * edge1.x + deltaUV1.x * edge2.x); 33 | bitangent.y = f * (-deltaUV2.x * edge1.y + deltaUV1.x * edge2.y); 34 | bitangent.z = f * (-deltaUV2.x * edge1.z + deltaUV1.x * edge2.z); 35 | bitangent = normalize(bitangent); 36 | 37 | drawID = passDrawID[0]; 38 | 39 | for (int i = 0; i < 3; i++) { 40 | gl_Position = gl_in[i].gl_Position; 41 | texCoord = passTexCoord[i]; 42 | pos = passFragPos[i]; 43 | normal = normalize(passNormal[i]); 44 | EmitVertex(); 45 | } 46 | EndPrimitive(); 47 | } 48 | 49 | -------------------------------------------------------------------------------- /shaders/tangentSpace2.geom: -------------------------------------------------------------------------------- 1 | #version 430 2 | 3 | layout (triangles) in; 4 | layout (triangle_strip, max_vertices = 3) out; 5 | 6 | layout(location = 0) in vec3 passFragPos[]; 7 | layout(location = 1) in vec3 passTexCoord[]; 8 | layout(location = 2) in vec3 passNormal[]; 9 | layout(location = 3) in vec3 passViewPos[]; 10 | layout(location = 4) flat in uint passDrawID[]; 11 | 12 | layout(location = 0) out vec3 pos; 13 | layout(location = 1) out vec3 texCoord; 14 | layout(location = 2) out vec3 normal; 15 | layout(location = 3) out vec3 viewPos; 16 | layout(location = 4) flat out uint drawID; 17 | layout(location = 5) out vec3 tangent; 18 | layout(location = 6) out vec3 bitangent; 19 | 20 | void main() { 21 | 22 | vec3 edge1 = passFragPos[1] - passFragPos[0]; 23 | vec3 edge2 = passFragPos[2] - passFragPos[0]; 24 | vec2 deltaUV1 = passTexCoord[1].xy - passTexCoord[0].xy; 25 | vec2 deltaUV2 = passTexCoord[2].xy - passTexCoord[0].xy; 26 | 27 | float f = 1.0f / (deltaUV1.x * deltaUV2.y - deltaUV2.x * deltaUV1.y); 28 | 29 | tangent.x = f * (deltaUV2.y * edge1.x - deltaUV1.y * edge2.x); 30 | tangent.y = f * (deltaUV2.y * edge1.y - deltaUV1.y * edge2.y); 31 | tangent.z = f * (deltaUV2.y * edge1.z - deltaUV1.y * edge2.z); 32 | tangent = normalize(tangent); 33 | 34 | bitangent.x = f * (-deltaUV2.x * edge1.x + deltaUV1.x * edge2.x); 35 | bitangent.y = f * (-deltaUV2.x * edge1.y + deltaUV1.x * edge2.y); 36 | bitangent.z = f * (-deltaUV2.x * edge1.z + deltaUV1.x * edge2.z); 37 | bitangent = normalize(bitangent); 38 | 39 | drawID = passDrawID[0]; 40 | 41 | for (int i = 0; i < 3; i++) { 42 | gl_Position = gl_in[i].gl_Position; 43 | texCoord = passTexCoord[i]; 44 | pos = passFragPos[i]; 45 | normal = normalize(passNormal[i]); 46 | viewPos = passViewPos[i]; 47 | EmitVertex(); 48 | } 49 | EndPrimitive(); 50 | } 51 | 52 | -------------------------------------------------------------------------------- /shaders/texSFQ.frag: -------------------------------------------------------------------------------- 1 | #version 430 2 | #extension GL_ARB_bindless_texture : require 3 | 4 | in vec2 passTexCoord; 5 | //layout(pixel_center_integer​) in vec4 gl_FragCoord; 6 | 7 | out vec4 fragColor; 8 | 9 | layout(binding = 0, std430) buffer textureBuffer 10 | { 11 | sampler2D inputTexture; 12 | }; 13 | 14 | layout(binding = 1, std430) buffer immageSSBO 15 | { 16 | layout(r8ui) uimage2D image; 17 | }; 18 | 19 | void main() 20 | { 21 | //vec2 texc = vec2(gl_FragCoord.x/1920.0, gl_FragCoord.y/1080.0); 22 | vec4 inputTexPixel = texture(inputTexture, passTexCoord); 23 | ivec2 actualCoords = ivec2(gl_FragCoord.xy); 24 | imageStore(image, actualCoords, uvec4(1)); 25 | fragColor = inputTexPixel;//vec4(passTexCoord, 0.0, 1.0); 26 | } -------------------------------------------------------------------------------- /shaders/texSFQ.vert: -------------------------------------------------------------------------------- 1 | #version 430 2 | 3 | layout(location = 0) in vec2 position; 4 | layout(location = 1) in vec2 texCoord; 5 | 6 | out vec2 passTexCoord; 7 | 8 | void main() 9 | { 10 | passTexCoord = texCoord; 11 | gl_Position = vec4(position, 0.0f, 1.0f); 12 | } -------------------------------------------------------------------------------- /shaders/transform.vert: -------------------------------------------------------------------------------- 1 | #version 430 2 | layout (location = 0) in vec3 vertexPosition; 3 | 4 | uniform mat4 ModelMatrix; 5 | 6 | void main() 7 | { 8 | gl_Position = ModelMatrix * vec4(vertexPosition, 1.0); 9 | } -------------------------------------------------------------------------------- /shaders/voxelDebug.frag: -------------------------------------------------------------------------------- 1 | #version 430 core 2 | out vec4 fragColor; 3 | in vec3 geomColor; 4 | 5 | void main() 6 | { 7 | fragColor = vec4(geomColor, 1.0); 8 | } -------------------------------------------------------------------------------- /shaders/voxelDebug.geom: -------------------------------------------------------------------------------- 1 | #version 430 2 | 3 | layout (points) in; 4 | layout (triangle_strip, max_vertices = 24) out; 5 | 6 | in vec3 posColor[]; 7 | out vec3 geomColor; 8 | 9 | uniform mat4 dViewMat; 10 | uniform mat4 dProjMat; 11 | 12 | uniform float voxelSize; 13 | 14 | void main() { 15 | vec4 position = gl_in[0].gl_Position; 16 | geomColor = posColor[0]; 17 | vec4 pos = vec4(1.0f); 18 | mat4 pvMat = dProjMat * dViewMat; 19 | 20 | vec4[8] offsets = { vec4(-voxelSize, -voxelSize, voxelSize, 0.f), 21 | vec4(voxelSize, -voxelSize, voxelSize, 0.f), 22 | vec4(-voxelSize, voxelSize, voxelSize, 0.f), 23 | vec4(voxelSize, voxelSize, voxelSize, 0.f), 24 | vec4(-voxelSize, -voxelSize, -voxelSize, 0.f), 25 | vec4(voxelSize, -voxelSize, -voxelSize, 0.f), 26 | vec4(-voxelSize, voxelSize, -voxelSize, 0.f), 27 | vec4(voxelSize, voxelSize, -voxelSize, 0.f)}; 28 | 29 | { // front 30 | pos = position + offsets[0]; // 1:bottom-left 31 | gl_Position = pvMat * pos; 32 | EmitVertex(); 33 | 34 | pos = position + offsets[1]; // 2:bottom-right 35 | gl_Position = pvMat * pos; 36 | EmitVertex(); 37 | 38 | pos = position + offsets[2]; // 3:top-left 39 | gl_Position = pvMat * pos; 40 | EmitVertex(); 41 | 42 | pos = position + offsets[3]; // 4:top-right 43 | gl_Position = pvMat * pos; 44 | EmitVertex(); 45 | 46 | EndPrimitive(); 47 | } 48 | 49 | { // back 50 | pos = position + offsets[5]; // 1:bottom-left 51 | gl_Position = pvMat * pos; 52 | EmitVertex(); 53 | 54 | pos = position + offsets[4]; // 2:bottom-right 55 | gl_Position = pvMat * pos; 56 | EmitVertex(); 57 | 58 | pos = position + offsets[7]; // 3:top-left 59 | gl_Position = pvMat * pos; 60 | EmitVertex(); 61 | 62 | pos = position + offsets[6]; // 4:top-right 63 | gl_Position = pvMat * pos; 64 | EmitVertex(); 65 | 66 | EndPrimitive(); 67 | } 68 | 69 | { // left 70 | pos = position + offsets[4]; // 1:bottom-left 71 | gl_Position = pvMat * pos; 72 | EmitVertex(); 73 | 74 | pos = position + offsets[0]; // 2:bottom-right 75 | gl_Position = pvMat * pos; 76 | EmitVertex(); 77 | 78 | pos = position + offsets[6]; // 3:top-left 79 | gl_Position = pvMat * pos; 80 | EmitVertex(); 81 | 82 | pos = position + offsets[2]; // 4:top-right 83 | gl_Position = pvMat * pos; 84 | EmitVertex(); 85 | 86 | EndPrimitive(); 87 | } 88 | 89 | { // right 90 | pos = position + offsets[1]; // 1:bottom-left 91 | gl_Position = pvMat * pos; 92 | EmitVertex(); 93 | 94 | pos = position + offsets[5]; // 2:bottom-right 95 | gl_Position = pvMat * pos; 96 | EmitVertex(); 97 | 98 | pos = position + offsets[3]; // 3:top-left 99 | gl_Position = pvMat * pos; 100 | EmitVertex(); 101 | 102 | pos = position + offsets[7]; // 4:top-right 103 | gl_Position = pvMat * pos; 104 | EmitVertex(); 105 | 106 | EndPrimitive(); 107 | } 108 | 109 | { // top 110 | pos = position + offsets[2]; // 1:bottom-left 111 | gl_Position = pvMat * pos; 112 | EmitVertex(); 113 | 114 | pos = position + offsets[3]; // 2:bottom-right 115 | gl_Position = pvMat * pos; 116 | EmitVertex(); 117 | 118 | pos = position + offsets[6]; // 3:top-left 119 | gl_Position = pvMat * pos; 120 | EmitVertex(); 121 | 122 | pos = position + offsets[7]; // 4:top-right 123 | gl_Position = pvMat * pos; 124 | EmitVertex(); 125 | 126 | EndPrimitive(); 127 | } 128 | 129 | { // bottom 130 | pos = position + offsets[0]; // 1:bottom-left 131 | gl_Position = pvMat * pos; 132 | EmitVertex(); 133 | 134 | pos = position + offsets[4]; // 2:bottom-right 135 | gl_Position = pvMat * pos; 136 | EmitVertex(); 137 | 138 | pos = position + offsets[1]; // 3:top-left 139 | gl_Position = pvMat * pos; 140 | EmitVertex(); 141 | 142 | pos = position + offsets[5]; // 4:top-right 143 | gl_Position = pvMat * pos; 144 | EmitVertex(); 145 | 146 | EndPrimitive(); 147 | } 148 | } 149 | 150 | -------------------------------------------------------------------------------- /shaders/voxeldebug.vert: -------------------------------------------------------------------------------- 1 | #version 430 2 | #extension GL_ARB_bindless_texture : require 3 | 4 | out vec3 posColor; 5 | 6 | uniform ivec3 gridDim; 7 | 8 | uniform int positionSource = 0; 9 | uniform int dataMode = 0; 10 | 11 | layout(binding = 0, rgba32f) uniform image3D voxelGrid; 12 | 13 | void main() 14 | { 15 | int z = gl_VertexID / (gridDim.x * gridDim.y); 16 | int y = (gl_VertexID - z * gridDim.x * gridDim.y) / gridDim.x; 17 | int x = gl_VertexID - gridDim.x * (y + gridDim.y * z); 18 | ivec3 gridPos3D = ivec3(x, y, z); 19 | vec4 voxelDataContent = imageLoad(voxelGrid, gridPos3D); 20 | 21 | if(positionSource == 0) 22 | gl_Position = vec4(voxelDataContent.xyz, 1.0f); // place at position from voxel grid 23 | else 24 | gl_Position = vec4(gridPos3D, 1.0f); // place at vertex position 25 | 26 | if(dataMode == 0) 27 | posColor = voxelDataContent.xyz; 28 | else if(dataMode == 1) 29 | posColor = vec3(voxelDataContent.w); 30 | else 31 | posColor = vec3(gridPos3D) / gridDim; 32 | } --------------------------------------------------------------------------------