diff --git a/.gitmodules b/.gitmodules index d3b0a1404e8b1bb1a7b29154759d006adc8615e4..e1d38a91697947d5b87f0767f231f1dee48ec4ed 100644 --- a/.gitmodules +++ b/.gitmodules @@ -46,3 +46,6 @@ [submodule "lib/VulkanMemoryAllocator"] path = lib/VulkanMemoryAllocator url = https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git +[submodule "modules/tone_mapping/lib/glsl-tone-map"] + path = modules/tone_mapping/lib/glsl-tone-map + url = https://github.com/dmnsgn/glsl-tone-map.git diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt index fd3c4cfdfedff17e6952d8b2222aca37d0510d24..2d96cfe2e17c0d7276bf43ad9038054b924be88c 100644 --- a/modules/CMakeLists.txt +++ b/modules/CMakeLists.txt @@ -13,6 +13,7 @@ add_subdirectory(material) add_subdirectory(meshlet) add_subdirectory(scene) add_subdirectory(shader_compiler) +add_subdirectory(tone_mapping) add_subdirectory(upscaling) message(STATUS "Modules:") diff --git a/modules/effects/CMakeLists.txt b/modules/effects/CMakeLists.txt index 94bb819d2a00443827ed40f5e015cc0745f61667..ba5a4ff4369adb4290c0ba253688ad4ddf461e16 100644 --- a/modules/effects/CMakeLists.txt +++ b/modules/effects/CMakeLists.txt @@ -14,6 +14,9 @@ set(vkcv_effects_sources ${vkcv_effects_include}/vkcv/effects/BloomAndFlaresEffect.hpp ${vkcv_effects_source}/vkcv/effects/BloomAndFlaresEffect.cpp + + ${vkcv_effects_include}/vkcv/effects/GammaCorrectionEffect.hpp + ${vkcv_effects_source}/vkcv/effects/GammaCorrectionEffect.cpp ) filter_headers(vkcv_effects_sources ${vkcv_effects_include} vkcv_effects_headers) @@ -23,16 +26,19 @@ set(vkcv_effects_shaders ${PROJECT_SOURCE_DIR}/shaders) include_shader(${vkcv_effects_shaders}/bloomDownsample.comp ${vkcv_effects_include} ${vkcv_effects_source}) include_shader(${vkcv_effects_shaders}/bloomFlaresComposite.comp ${vkcv_effects_include} ${vkcv_effects_source}) include_shader(${vkcv_effects_shaders}/bloomUpsample.comp ${vkcv_effects_include} ${vkcv_effects_source}) +include_shader(${vkcv_effects_shaders}/gammaCorrection.comp ${vkcv_effects_include} ${vkcv_effects_source}) include_shader(${vkcv_effects_shaders}/lensFlares.comp ${vkcv_effects_include} ${vkcv_effects_source}) list(APPEND vkcv_effects_sources ${vkcv_effects_source}/bloomDownsample.comp.cxx) list(APPEND vkcv_effects_sources ${vkcv_effects_source}/bloomFlaresComposite.comp.cxx) list(APPEND vkcv_effects_sources ${vkcv_effects_source}/bloomUpsample.comp.cxx) +list(APPEND vkcv_effects_sources ${vkcv_effects_source}/gammaCorrection.comp.cxx) list(APPEND vkcv_effects_sources ${vkcv_effects_source}/lensFlares.comp.cxx) list(APPEND vkcv_effects_sources ${vkcv_effects_include}/bloomDownsample.comp.hxx) list(APPEND vkcv_effects_sources ${vkcv_effects_include}/bloomFlaresComposite.comp.hxx) list(APPEND vkcv_effects_sources ${vkcv_effects_include}/bloomUpsample.comp.hxx) +list(APPEND vkcv_effects_sources ${vkcv_effects_include}/gammaCorrection.comp.hxx) list(APPEND vkcv_effects_sources ${vkcv_effects_include}/lensFlares.comp.hxx) # adding source files to the project @@ -40,10 +46,21 @@ add_library(vkcv_effects ${vkcv_build_attribute} ${vkcv_effects_sources}) set_target_properties(vkcv_effects PROPERTIES PUBLIC_HEADER "${vkcv_effects_headers}") # link the required libraries to the module -target_link_libraries(vkcv_effects ${vkcv_effects_libraries} vkcv vkcv_shader_compiler vkcv_camera vkcv_asset_loader) +target_link_libraries(vkcv_effects + ${vkcv_effects_libraries} + vkcv + vkcv_shader_compiler + vkcv_camera + vkcv_asset_loader) # including headers of dependencies and the VkCV framework -target_include_directories(vkcv_effects SYSTEM BEFORE PRIVATE ${vkcv_effects_includes} ${vkcv_include} ${vkcv_includes} ${vkcv_shader_compiler_include} ${vkcv_camera_include} {vkcv_asset_loader_include}) +target_include_directories(vkcv_effects SYSTEM BEFORE PRIVATE + ${vkcv_effects_includes} + ${vkcv_include} + ${vkcv_includes} + ${vkcv_shader_compiler_include} + ${vkcv_camera_include} + ${vkcv_asset_loader_include}) # add the own include directory for public headers target_include_directories(vkcv_effects BEFORE PUBLIC ${vkcv_effects_include}) diff --git a/modules/effects/include/vkcv/effects/BloomAndFlaresEffect.hpp b/modules/effects/include/vkcv/effects/BloomAndFlaresEffect.hpp index f4a9d03d8afcaf3532570a0807b246a0d641e02d..71b8d1e4d9e13189a37bc06b6cd7e7ab4a58db8d 100644 --- a/modules/effects/include/vkcv/effects/BloomAndFlaresEffect.hpp +++ b/modules/effects/include/vkcv/effects/BloomAndFlaresEffect.hpp @@ -7,6 +7,11 @@ namespace vkcv::effects { + /** + * @addtogroup vkcv_effects + * @{ + */ + class BloomAndFlaresEffect : public Effect { private: bool m_advanced; @@ -57,8 +62,8 @@ namespace vkcv::effects { const ImageHandle &output); public: - BloomAndFlaresEffect(Core& core, - bool advanced = false); + explicit BloomAndFlaresEffect(Core& core, + bool advanced = false); void recordEffect(const CommandStreamHandle &cmdStream, const ImageHandle &input, @@ -70,4 +75,6 @@ namespace vkcv::effects { }; + /** @} */ + } diff --git a/modules/effects/include/vkcv/effects/Effect.hpp b/modules/effects/include/vkcv/effects/Effect.hpp index d068fb59404080aa421e49f6a183844e731c1c5e..f81d3d7b9e4190834f6fa40632b631131341121c 100644 --- a/modules/effects/include/vkcv/effects/Effect.hpp +++ b/modules/effects/include/vkcv/effects/Effect.hpp @@ -5,6 +5,12 @@ namespace vkcv::effects { + /** + * @defgroup vkcv_effects Effects Module + * A module to apply certain post-processing effects to an image in realtime. + * @{ + */ + class Effect { protected: Core& m_core; @@ -20,4 +26,6 @@ namespace vkcv::effects { }; + /** @} */ + } diff --git a/modules/effects/include/vkcv/effects/GammaCorrectionEffect.hpp b/modules/effects/include/vkcv/effects/GammaCorrectionEffect.hpp new file mode 100644 index 0000000000000000000000000000000000000000..1c41bdd3cd43b3c696ea6daf74df8e4aa5278fa5 --- /dev/null +++ b/modules/effects/include/vkcv/effects/GammaCorrectionEffect.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include "Effect.hpp" + +namespace vkcv::effects { + + /** + * @addtogroup vkcv_effects + * @{ + */ + + class GammaCorrectionEffect : public Effect { + private: + float m_gamma; + + ComputePipelineHandle m_pipeline; + + DescriptorSetLayoutHandle m_descriptorSetLayout; + + DescriptorSetHandle m_descriptorSet; + + public: + explicit GammaCorrectionEffect(Core& core); + + void recordEffect(const CommandStreamHandle& cmdStream, + const ImageHandle& input, + const ImageHandle& output) override; + + void setGamma(float gamma); + + [[nodiscard]] + float getGamma() const; + + }; + + /** @} */ + +} diff --git a/modules/effects/shaders/gammaCorrection.comp b/modules/effects/shaders/gammaCorrection.comp new file mode 100644 index 0000000000000000000000000000000000000000..392ac8e0c80cff5ac821cadb6a23d981f21420e5 --- /dev/null +++ b/modules/effects/shaders/gammaCorrection.comp @@ -0,0 +1,27 @@ +#version 450 + +layout(set=0, binding=0, rgba8) restrict readonly uniform image2D inImage; +layout(set=0, binding=1, rgba8) restrict writeonly uniform image2D outImage; + +layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; + +layout( push_constant ) uniform constants { + float gamma; +}; + +void main() { + if (any(greaterThanEqual(gl_GlobalInvocationID.xy, imageSize(inImage)))) { + return; + } + + if (any(greaterThanEqual(gl_GlobalInvocationID.xy, imageSize(outImage)))) { + return; + } + + ivec2 uv = ivec2(gl_GlobalInvocationID.xy); + vec3 color = imageLoad(inImage, uv).xyz; + + color = pow(color, vec3(1.0f / gamma)); + + imageStore(outImage, uv, vec4(color, 0.f)); +} \ No newline at end of file diff --git a/modules/effects/src/vkcv/effects/GammaCorrectionEffect.cpp b/modules/effects/src/vkcv/effects/GammaCorrectionEffect.cpp new file mode 100644 index 0000000000000000000000000000000000000000..088a3dbd97ae9654cdbfe6355b4837310c51bddc --- /dev/null +++ b/modules/effects/src/vkcv/effects/GammaCorrectionEffect.cpp @@ -0,0 +1,100 @@ + +#include "vkcv/effects/GammaCorrectionEffect.hpp" + +#include <vkcv/shader/GLSLCompiler.hpp> + +#include "gammaCorrection.comp.hxx" + +namespace vkcv::effects { + + static DescriptorBindings getDescriptorBindings() { + DescriptorBindings descriptorBindings = {}; + + auto binding_0 = DescriptorBinding { + 0, + DescriptorType::IMAGE_STORAGE, + 1, + ShaderStage::COMPUTE, + false, + false + }; + + auto binding_1 = DescriptorBinding { + 1, + DescriptorType::IMAGE_STORAGE, + 1, + ShaderStage::COMPUTE, + false, + false + }; + + descriptorBindings.insert(std::make_pair(0, binding_0)); + descriptorBindings.insert(std::make_pair(1, binding_1)); + + return descriptorBindings; + } + + GammaCorrectionEffect::GammaCorrectionEffect(Core &core) + : Effect(core), m_gamma(2.2f), m_descriptorSetLayout(), m_descriptorSet(), m_pipeline() { + vkcv::shader::GLSLCompiler compiler; + ShaderProgram program; + + compiler.compileSource( + ShaderStage::COMPUTE, + GAMMACORRECTION_COMP_SHADER.c_str(), + [&program](ShaderStage stage, const std::filesystem::path &path) { + program.addShader(stage, path); + } + ); + + m_descriptorSetLayout = m_core.createDescriptorSetLayout(getDescriptorBindings()); + m_descriptorSet = m_core.createDescriptorSet(m_descriptorSetLayout); + m_pipeline = m_core.createComputePipeline({ + program, + { m_descriptorSetLayout } + }); + } + + void GammaCorrectionEffect::recordEffect(const CommandStreamHandle &cmdStream, + const ImageHandle &input, + const ImageHandle &output) { + m_core.recordBeginDebugLabel(cmdStream, "Gamma Correction", std::array<float, 4>{ + 0.95f, 0.95f, 0.95f, 1.0f + }); + + m_core.prepareImageForStorage(cmdStream, input); + m_core.prepareImageForStorage(cmdStream, output); + + vkcv::DescriptorWrites writes; + + writes.writeStorageImage(0, input); + writes.writeStorageImage(1, output); + + m_core.writeDescriptorSet(m_descriptorSet, writes); + + const uint32_t width = m_core.getImageWidth(output); + const uint32_t height = m_core.getImageHeight(output); + + m_core.recordComputeDispatchToCmdStream( + cmdStream, + m_pipeline, + dispatchInvocations( + DispatchSize(width, height), + DispatchSize(8, 8) + ), + { useDescriptorSet(0, m_descriptorSet) }, + pushConstants<float>(m_gamma) + ); + + m_core.recordEndDebugLabel(cmdStream); + } + + void GammaCorrectionEffect::setGamma(float gamma) { + m_gamma = std::max(gamma, std::numeric_limits<float>::epsilon()); + } + + float GammaCorrectionEffect::getGamma() const { + return m_gamma; + } + +} diff --git a/modules/shader_compiler/include/vkcv/shader/GLSLCompiler.hpp b/modules/shader_compiler/include/vkcv/shader/GLSLCompiler.hpp index face4cba350122f22feee6bae878397dccf4a070..0cb3a39436675e722f818643808b769189165793 100644 --- a/modules/shader_compiler/include/vkcv/shader/GLSLCompiler.hpp +++ b/modules/shader_compiler/include/vkcv/shader/GLSLCompiler.hpp @@ -76,7 +76,7 @@ namespace vkcv::shader { */ bool compileSource(ShaderStage shaderStage, const char* shaderSource, const ShaderCompiledFunction& compiled, - const std::filesystem::path& includePath) override; + const std::filesystem::path& includePath = "") override; /** * Compile a GLSL shader from a specific file path for a target stage with diff --git a/modules/tone_mapping/CMakeLists.txt b/modules/tone_mapping/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..a63d74650b22716c49eda3842b7fcea6dba4b9cd --- /dev/null +++ b/modules/tone_mapping/CMakeLists.txt @@ -0,0 +1,83 @@ +cmake_minimum_required(VERSION 3.16) +project(vkcv_tone_mapping) + +# setting c++ standard for the project +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +set(vkcv_tone_mapping_source ${PROJECT_SOURCE_DIR}/src) +set(vkcv_tone_mapping_include ${PROJECT_SOURCE_DIR}/include) + +set(vkcv_tone_mapping_sources + ${vkcv_tone_mapping_include}/vkcv/tone/ToneMapping.hpp + ${vkcv_tone_mapping_source}/vkcv/tone/ToneMapping.cpp + + ${vkcv_tone_mapping_include}/vkcv/tone/ACESToneMapping.hpp + ${vkcv_tone_mapping_source}/vkcv/tone/ACESToneMapping.cpp + + ${vkcv_tone_mapping_include}/vkcv/tone/FilmicToneMapping.hpp + ${vkcv_tone_mapping_source}/vkcv/tone/FilmicToneMapping.cpp + + ${vkcv_tone_mapping_include}/vkcv/tone/LottesToneMapping.hpp + ${vkcv_tone_mapping_source}/vkcv/tone/LottesToneMapping.cpp + + ${vkcv_tone_mapping_include}/vkcv/tone/ReinhardToneMapping.hpp + ${vkcv_tone_mapping_source}/vkcv/tone/ReinhardToneMapping.cpp + + ${vkcv_tone_mapping_include}/vkcv/tone/Reinhard2ToneMapping.hpp + ${vkcv_tone_mapping_source}/vkcv/tone/Reinhard2ToneMapping.cpp + + ${vkcv_tone_mapping_include}/vkcv/tone/UchimuraToneMapping.hpp + ${vkcv_tone_mapping_source}/vkcv/tone/UchimuraToneMapping.cpp + + ${vkcv_tone_mapping_include}/vkcv/tone/Uncharted2ToneMapping.hpp + ${vkcv_tone_mapping_source}/vkcv/tone/Uncharted2ToneMapping.cpp + + ${vkcv_tone_mapping_include}/vkcv/tone/UnrealToneMapping.hpp + ${vkcv_tone_mapping_source}/vkcv/tone/UnrealToneMapping.cpp +) + +filter_headers(vkcv_tone_mapping_sources ${vkcv_tone_mapping_include} vkcv_tone_mapping_headers) + +# Setup some path variables to load libraries +set(vkcv_tone_mapping_lib lib) +set(vkcv_tone_mapping_lib_path ${PROJECT_SOURCE_DIR}/${vkcv_tone_mapping_lib}) + +# Check and load glsl-tone-map +include(config/GLSL_TONE_MAP.cmake) + +# Add compile definitions depending on the build context of the module +add_compile_definitions(${vkcv_tone_mapping_definitions}) + +# adding source files to the project +add_library(vkcv_tone_mapping ${vkcv_build_attribute} ${vkcv_tone_mapping_sources}) +set_target_properties(vkcv_tone_mapping PROPERTIES PUBLIC_HEADER "${vkcv_tone_mapping_headers}") + +# link the required libraries to the module +target_link_libraries(vkcv_tone_mapping + ${vkcv_tone_mapping_libraries} + vkcv + vkcv_shader_compiler +) + +# including headers of dependencies and the VkCV framework +target_include_directories(vkcv_tone_mapping SYSTEM BEFORE PRIVATE + ${vkcv_tone_mapping_includes} + ${vkcv_include} + ${vkcv_includes} + ${vkcv_shader_compiler_include} +) + +# add the own include directory for public headers +target_include_directories(vkcv_tone_mapping BEFORE PUBLIC ${vkcv_tone_mapping_include}) + +if (vkcv_parent_scope) + list(APPEND vkcv_modules_includes ${vkcv_tone_mapping_include}) + list(APPEND vkcv_modules_libraries vkcv_tone_mapping) + + set(vkcv_modules_includes ${vkcv_modules_includes} PARENT_SCOPE) + set(vkcv_modules_libraries ${vkcv_modules_libraries} PARENT_SCOPE) +endif() + +install(TARGETS vkcv_tone_mapping PUBLIC_HEADER DESTINATION + ${CMAKE_INSTALL_INCLUDEDIR}/vkcv/tone) diff --git a/modules/tone_mapping/config/GLSL_TONE_MAP.cmake b/modules/tone_mapping/config/GLSL_TONE_MAP.cmake new file mode 100644 index 0000000000000000000000000000000000000000..814344132d7e9f14e3e6df58544b9d7e88ee3677 --- /dev/null +++ b/modules/tone_mapping/config/GLSL_TONE_MAP.cmake @@ -0,0 +1,54 @@ + +use_git_submodule("${vkcv_tone_mapping_lib_path}/glsl-tone-map" glsl_tone_map_status) + +if (${glsl_tone_map_status}) + include_shader(${vkcv_tone_mapping_lib_path}/glsl-tone-map/aces.glsl + ${vkcv_tone_mapping_include} + ${vkcv_tone_mapping_source}) + + include_shader(${vkcv_tone_mapping_lib_path}/glsl-tone-map/filmic.glsl + ${vkcv_tone_mapping_include} + ${vkcv_tone_mapping_source}) + + include_shader(${vkcv_tone_mapping_lib_path}/glsl-tone-map/lottes.glsl + ${vkcv_tone_mapping_include} + ${vkcv_tone_mapping_source}) + + include_shader(${vkcv_tone_mapping_lib_path}/glsl-tone-map/reinhard.glsl + ${vkcv_tone_mapping_include} + ${vkcv_tone_mapping_source}) + + include_shader(${vkcv_tone_mapping_lib_path}/glsl-tone-map/reinhard2.glsl + ${vkcv_tone_mapping_include} + ${vkcv_tone_mapping_source}) + + include_shader(${vkcv_tone_mapping_lib_path}/glsl-tone-map/uchimura.glsl + ${vkcv_tone_mapping_include} + ${vkcv_tone_mapping_source}) + + include_shader(${vkcv_tone_mapping_lib_path}/glsl-tone-map/uncharted2.glsl + ${vkcv_tone_mapping_include} + ${vkcv_tone_mapping_source}) + + include_shader(${vkcv_tone_mapping_lib_path}/glsl-tone-map/unreal.glsl + ${vkcv_tone_mapping_include} + ${vkcv_tone_mapping_source}) + + list(APPEND vkcv_tone_mapping_sources ${vkcv_tone_mapping_source}/aces.glsl.cxx) + list(APPEND vkcv_tone_mapping_sources ${vkcv_tone_mapping_source}/filmic.glsl.cxx) + list(APPEND vkcv_tone_mapping_sources ${vkcv_tone_mapping_source}/lottes.glsl.cxx) + list(APPEND vkcv_tone_mapping_sources ${vkcv_tone_mapping_source}/reinhard.glsl.cxx) + list(APPEND vkcv_tone_mapping_sources ${vkcv_tone_mapping_source}/reinhard2.glsl.cxx) + list(APPEND vkcv_tone_mapping_sources ${vkcv_tone_mapping_source}/uchimura.glsl.cxx) + list(APPEND vkcv_tone_mapping_sources ${vkcv_tone_mapping_source}/uncharted2.glsl.cxx) + list(APPEND vkcv_tone_mapping_sources ${vkcv_tone_mapping_source}/unreal.glsl.cxx) + + list(APPEND vkcv_tone_mapping_sources ${vkcv_tone_mapping_include}/aces.glsl.hxx) + list(APPEND vkcv_tone_mapping_sources ${vkcv_tone_mapping_include}/filmic.glsl.hxx) + list(APPEND vkcv_tone_mapping_sources ${vkcv_tone_mapping_include}/lottes.glsl.hxx) + list(APPEND vkcv_tone_mapping_sources ${vkcv_tone_mapping_include}/reinhard.glsl.hxx) + list(APPEND vkcv_tone_mapping_sources ${vkcv_tone_mapping_include}/reinhard2.glsl.hxx) + list(APPEND vkcv_tone_mapping_sources ${vkcv_tone_mapping_include}/uchimura.glsl.hxx) + list(APPEND vkcv_tone_mapping_sources ${vkcv_tone_mapping_include}/uncharted2.glsl.hxx) + list(APPEND vkcv_tone_mapping_sources ${vkcv_tone_mapping_include}/unreal.glsl.hxx) +endif() diff --git a/modules/tone_mapping/include/vkcv/tone/ACESToneMapping.hpp b/modules/tone_mapping/include/vkcv/tone/ACESToneMapping.hpp new file mode 100644 index 0000000000000000000000000000000000000000..de1c02c5d9efa070aadeff5003c7e15e232af7ee --- /dev/null +++ b/modules/tone_mapping/include/vkcv/tone/ACESToneMapping.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include "ToneMapping.hpp" + +namespace vkcv::tone { + + /** + * @addtogroup vkcv_tone + * @{ + */ + + class ACESToneMapping : public ToneMapping { + private: + void initToneMapping() override; + + public: + explicit ACESToneMapping(Core& core, bool normalize = false); + + }; + + /** @} */ + +} diff --git a/modules/tone_mapping/include/vkcv/tone/FilmicToneMapping.hpp b/modules/tone_mapping/include/vkcv/tone/FilmicToneMapping.hpp new file mode 100644 index 0000000000000000000000000000000000000000..c25e1b74f7d1f78f74e84399bccc0beb063c7c12 --- /dev/null +++ b/modules/tone_mapping/include/vkcv/tone/FilmicToneMapping.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include "ToneMapping.hpp" + +namespace vkcv::tone { + + /** + * @addtogroup vkcv_tone + * @{ + */ + + class FilmicToneMapping : public ToneMapping { + private: + void initToneMapping() override; + + public: + explicit FilmicToneMapping(Core& core, bool normalize = false); + + }; + + /** @} */ + +} diff --git a/modules/tone_mapping/include/vkcv/tone/LottesToneMapping.hpp b/modules/tone_mapping/include/vkcv/tone/LottesToneMapping.hpp new file mode 100644 index 0000000000000000000000000000000000000000..37dad90397bdf8f3ae1e359a5961b65d085d651b --- /dev/null +++ b/modules/tone_mapping/include/vkcv/tone/LottesToneMapping.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include "ToneMapping.hpp" + +namespace vkcv::tone { + + /** + * @addtogroup vkcv_tone + * @{ + */ + + class LottesToneMapping : public ToneMapping { + private: + void initToneMapping() override; + + public: + explicit LottesToneMapping(Core& core, bool normalize = false); + + }; + + /** @} */ + +} diff --git a/modules/tone_mapping/include/vkcv/tone/Reinhard2ToneMapping.hpp b/modules/tone_mapping/include/vkcv/tone/Reinhard2ToneMapping.hpp new file mode 100644 index 0000000000000000000000000000000000000000..9bcf9f9e28a734b7de481e9dd90ffae3e98254bd --- /dev/null +++ b/modules/tone_mapping/include/vkcv/tone/Reinhard2ToneMapping.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include "ToneMapping.hpp" + +namespace vkcv::tone { + + /** + * @addtogroup vkcv_tone + * @{ + */ + + class Reinhard2ToneMapping : public ToneMapping { + private: + void initToneMapping() override; + + public: + explicit Reinhard2ToneMapping(Core& core, bool normalize = false); + + }; + + /** @} */ + +} diff --git a/modules/tone_mapping/include/vkcv/tone/ReinhardToneMapping.hpp b/modules/tone_mapping/include/vkcv/tone/ReinhardToneMapping.hpp new file mode 100644 index 0000000000000000000000000000000000000000..ac7fb5c9e3856de5aeb5f743793a0668c55b2bf1 --- /dev/null +++ b/modules/tone_mapping/include/vkcv/tone/ReinhardToneMapping.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include "ToneMapping.hpp" + +namespace vkcv::tone { + + /** + * @addtogroup vkcv_tone + * @{ + */ + + class ReinhardToneMapping : public ToneMapping { + private: + void initToneMapping() override; + + public: + explicit ReinhardToneMapping(Core& core, bool normalize = false); + + }; + + /** @} */ + +} diff --git a/modules/tone_mapping/include/vkcv/tone/ToneMapping.hpp b/modules/tone_mapping/include/vkcv/tone/ToneMapping.hpp new file mode 100644 index 0000000000000000000000000000000000000000..00e8c287c8bb2bca503361e2e249d0a19b4edbf4 --- /dev/null +++ b/modules/tone_mapping/include/vkcv/tone/ToneMapping.hpp @@ -0,0 +1,93 @@ +#pragma once + +#include <vkcv/Core.hpp> + +namespace vkcv::tone { + + /** + * @defgroup vkcv_tone Tone Mapping Module + * A module to apply tone mapping to an image in realtime. + * @{ + */ + + class ToneMapping { + private: + /** + * Reference to the current Core instance. + */ + Core& m_core; + + /** + * The name of the tone mapping instance. + */ + std::string m_name; + + /** + * Flag whether tone mapping should normalize before mapping. + */ + bool m_normalize; + + /** + * The compute pipeline of the tone mapping instance. + */ + ComputePipelineHandle m_pipeline; + + /** + * The descriptor set layout of the tone mapping pipeline. + */ + DescriptorSetLayoutHandle m_descriptorSetLayout; + + /** + * The descriptor set for the tone mapping pipeline. + */ + DescriptorSetHandle m_descriptorSet; + + protected: + ShaderProgram compileShaderProgram(const std::string& functionName, + const std::string& functionSource); + + void buildComputePipeline(const std::string& functionName, + const std::string& functionSource); + + virtual void initToneMapping() = 0; + + public: + /** + * Constructor to create an tone mapping instance. + * + * @param[in,out] core Reference to a Core instance + * @param[in] name Name of the tone mapping function + * @param[in] normalize (Optional) Flag to normalize color values + */ + explicit ToneMapping(Core& core, + const std::string& name, + bool normalize = false); + + ~ToneMapping() = default; + + /** + * Return name of the tone mapping instance. + * + * @return Name of the tone mapping + */ + [[nodiscard]] + const std::string& getName() const; + + /** + * Record the commands of the given tone mapping instance to + * process the image of the input handle mapping its colors into + * the regarding output image handle. + * + * @param[in] cmdStream Command stream handle to record commands + * @param[in] input Input image handle + * @param[in] output Output image handle + */ + void recordToneMapping(const CommandStreamHandle& cmdStream, + const ImageHandle& input, + const ImageHandle& output); + + }; + + /** @} */ + +} diff --git a/modules/tone_mapping/include/vkcv/tone/UchimuraToneMapping.hpp b/modules/tone_mapping/include/vkcv/tone/UchimuraToneMapping.hpp new file mode 100644 index 0000000000000000000000000000000000000000..83afa0c2cfa2038c64bf78a74b8886fd5aa2d54e --- /dev/null +++ b/modules/tone_mapping/include/vkcv/tone/UchimuraToneMapping.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include "ToneMapping.hpp" + +namespace vkcv::tone { + + /** + * @addtogroup vkcv_tone + * @{ + */ + + class UchimuraToneMapping : public ToneMapping { + private: + void initToneMapping() override; + + public: + explicit UchimuraToneMapping(Core& core, bool normalize = false); + + }; + + /** @} */ + +} diff --git a/modules/tone_mapping/include/vkcv/tone/Uncharted2ToneMapping.hpp b/modules/tone_mapping/include/vkcv/tone/Uncharted2ToneMapping.hpp new file mode 100644 index 0000000000000000000000000000000000000000..fc1db5b4b5e66ff584df9679cc9b8a0ddad89ec4 --- /dev/null +++ b/modules/tone_mapping/include/vkcv/tone/Uncharted2ToneMapping.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include "ToneMapping.hpp" + +namespace vkcv::tone { + + /** + * @addtogroup vkcv_tone + * @{ + */ + + class Uncharted2ToneMapping : public ToneMapping { + private: + void initToneMapping() override; + + public: + explicit Uncharted2ToneMapping(Core& core, bool normalize = false); + + }; + + /** @} */ + +} diff --git a/modules/tone_mapping/include/vkcv/tone/UnrealToneMapping.hpp b/modules/tone_mapping/include/vkcv/tone/UnrealToneMapping.hpp new file mode 100644 index 0000000000000000000000000000000000000000..10fb9cc6b52feb543fe1b8fb61f5b0b91e6e5acc --- /dev/null +++ b/modules/tone_mapping/include/vkcv/tone/UnrealToneMapping.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include "ToneMapping.hpp" + +namespace vkcv::tone { + + /** + * @addtogroup vkcv_tone + * @{ + */ + + class UnrealToneMapping : public ToneMapping { + private: + void initToneMapping() override; + + public: + explicit UnrealToneMapping(Core& core, bool normalize = false); + + }; + + /** @} */ + +} diff --git a/modules/tone_mapping/lib/glsl-tone-map b/modules/tone_mapping/lib/glsl-tone-map new file mode 160000 index 0000000000000000000000000000000000000000..e3d822adee738de936da5d9541dff266f899ed46 --- /dev/null +++ b/modules/tone_mapping/lib/glsl-tone-map @@ -0,0 +1 @@ +Subproject commit e3d822adee738de936da5d9541dff266f899ed46 diff --git a/modules/tone_mapping/src/vkcv/tone/ACESToneMapping.cpp b/modules/tone_mapping/src/vkcv/tone/ACESToneMapping.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4835fdcd6ef2acd22d4d867e284f90fc5ba6546b --- /dev/null +++ b/modules/tone_mapping/src/vkcv/tone/ACESToneMapping.cpp @@ -0,0 +1,17 @@ + +#include "vkcv/tone/ACESToneMapping.hpp" + +#include "aces.glsl.hxx" + +namespace vkcv::tone { + + void ACESToneMapping::initToneMapping() { + buildComputePipeline("aces", ACES_GLSL_SHADER); + } + + ACESToneMapping::ACESToneMapping(Core &core, bool normalize) + : ToneMapping(core, "ACES Tone Mapping", normalize) { + initToneMapping(); + } + +} diff --git a/modules/tone_mapping/src/vkcv/tone/FilmicToneMapping.cpp b/modules/tone_mapping/src/vkcv/tone/FilmicToneMapping.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3d93ada18d39fcea59cc0258360fbea79338a631 --- /dev/null +++ b/modules/tone_mapping/src/vkcv/tone/FilmicToneMapping.cpp @@ -0,0 +1,17 @@ + +#include "vkcv/tone/FilmicToneMapping.hpp" + +#include "filmic.glsl.hxx" + +namespace vkcv::tone { + + void FilmicToneMapping::initToneMapping() { + buildComputePipeline("filmic", FILMIC_GLSL_SHADER); + } + + FilmicToneMapping::FilmicToneMapping(Core &core, bool normalize) + : ToneMapping(core, "Filmic Tone Mapping", normalize) { + initToneMapping(); + } + +} diff --git a/modules/tone_mapping/src/vkcv/tone/LottesToneMapping.cpp b/modules/tone_mapping/src/vkcv/tone/LottesToneMapping.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9ae38055831164933e009229d0e6510aaf99d1e5 --- /dev/null +++ b/modules/tone_mapping/src/vkcv/tone/LottesToneMapping.cpp @@ -0,0 +1,17 @@ + +#include "vkcv/tone/LottesToneMapping.hpp" + +#include "lottes.glsl.hxx" + +namespace vkcv::tone { + + void LottesToneMapping::initToneMapping() { + buildComputePipeline("lottes", LOTTES_GLSL_SHADER); + } + + LottesToneMapping::LottesToneMapping(Core &core, bool normalize) + : ToneMapping(core, "Lottes Tone Mapping", normalize) { + initToneMapping(); + } + +} diff --git a/modules/tone_mapping/src/vkcv/tone/Reinhard2ToneMapping.cpp b/modules/tone_mapping/src/vkcv/tone/Reinhard2ToneMapping.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e81b952654337b49e310111ab08f345cf2106bcb --- /dev/null +++ b/modules/tone_mapping/src/vkcv/tone/Reinhard2ToneMapping.cpp @@ -0,0 +1,17 @@ + +#include "vkcv/tone/Reinhard2ToneMapping.hpp" + +#include "reinhard2.glsl.hxx" + +namespace vkcv::tone { + + void Reinhard2ToneMapping::initToneMapping() { + buildComputePipeline("reinhard2", REINHARD2_GLSL_SHADER); + } + + Reinhard2ToneMapping::Reinhard2ToneMapping(Core &core, bool normalize) + : ToneMapping(core, "Reinhard2 Tone Mapping", normalize) { + initToneMapping(); + } + +} diff --git a/modules/tone_mapping/src/vkcv/tone/ReinhardToneMapping.cpp b/modules/tone_mapping/src/vkcv/tone/ReinhardToneMapping.cpp new file mode 100644 index 0000000000000000000000000000000000000000..258550d80c6b099e84cf93541aa01aa157a3645c --- /dev/null +++ b/modules/tone_mapping/src/vkcv/tone/ReinhardToneMapping.cpp @@ -0,0 +1,17 @@ + +#include "vkcv/tone/ReinhardToneMapping.hpp" + +#include "reinhard.glsl.hxx" + +namespace vkcv::tone { + + void ReinhardToneMapping::initToneMapping() { + buildComputePipeline("reinhard", REINHARD_GLSL_SHADER); + } + + ReinhardToneMapping::ReinhardToneMapping(Core &core, bool normalize) + : ToneMapping(core, "Reinhard Tone Mapping", normalize) { + initToneMapping(); + } + +} diff --git a/modules/tone_mapping/src/vkcv/tone/ToneMapping.cpp b/modules/tone_mapping/src/vkcv/tone/ToneMapping.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3323d8797c34afd2890c433c5849bd8fdf9c807e --- /dev/null +++ b/modules/tone_mapping/src/vkcv/tone/ToneMapping.cpp @@ -0,0 +1,144 @@ + +#include "vkcv/tone/ToneMapping.hpp" + +#include <vkcv/shader/GLSLCompiler.hpp> + +#include <sstream> + +namespace vkcv::tone { + + static DescriptorBindings getDescriptorBindings() { + DescriptorBindings descriptorBindings = {}; + + auto binding_0 = DescriptorBinding { + 0, + DescriptorType::IMAGE_STORAGE, + 1, + ShaderStage::COMPUTE, + false, + false + }; + + auto binding_1 = DescriptorBinding { + 1, + DescriptorType::IMAGE_STORAGE, + 1, + ShaderStage::COMPUTE, + false, + false + }; + + descriptorBindings.insert(std::make_pair(0, binding_0)); + descriptorBindings.insert(std::make_pair(1, binding_1)); + + return descriptorBindings; + } + + ShaderProgram ToneMapping::compileShaderProgram(const std::string &functionName, + const std::string &functionSource) { + vkcv::shader::GLSLCompiler compiler; + ShaderProgram program; + + std::ostringstream stream; + stream << "#version 450" << std::endl; + stream << "layout(set=0, binding=0, rgba16f) restrict readonly uniform image2D inImage;" << std::endl; + stream << "layout(set=0, binding=1, rgba8) restrict writeonly uniform image2D outImage;" << std::endl; + stream << "layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;" << std::endl; + stream << functionSource << std::endl; + stream << "void main() {" << std::endl; + stream << " if (any(greaterThanEqual(gl_GlobalInvocationID.xy, imageSize(inImage)))) {" << std::endl; + stream << " return;" << std::endl; + stream << " }" << std::endl; + stream << " if (any(greaterThanEqual(gl_GlobalInvocationID.xy, imageSize(outImage)))) {" << std::endl; + stream << " return;" << std::endl; + stream << " }" << std::endl; + stream << " ivec2 uv = ivec2(gl_GlobalInvocationID.xy);" << std::endl; + stream << " vec4 color = imageLoad(inImage, uv);" << std::endl; + + if (m_normalize) { + stream << " color /= color.w;" << std::endl; + } + + stream << " color = vec4(" << functionName << "(color.xyz), color.w);" << std::endl; + stream << " imageStore(outImage, uv, color);" << std::endl; + stream << "}" << std::endl; + + compiler.compileSource( + ShaderStage::COMPUTE, + stream.str().c_str(), + [&](ShaderStage stage, const std::filesystem::path &path) { + program.addShader(stage, path); + } + ); + + return program; + } + + void ToneMapping::buildComputePipeline(const std::string &functionName, + const std::string &functionSource) { + const ShaderProgram program = compileShaderProgram( + functionName, + functionSource + ); + + m_descriptorSetLayout = m_core.createDescriptorSetLayout( + getDescriptorBindings() + ); + + m_descriptorSet = m_core.createDescriptorSet(m_descriptorSetLayout); + + m_pipeline = m_core.createComputePipeline({ + program, + { m_descriptorSetLayout } + }); + } + + ToneMapping::ToneMapping(Core &core, + const std::string &name, + bool normalize) + : m_core(core), + m_name(name), + m_normalize(normalize), + m_pipeline(), + m_descriptorSetLayout(), + m_descriptorSet() {} + + const std::string &ToneMapping::getName() const { + return m_name; + } + + void ToneMapping::recordToneMapping(const CommandStreamHandle& cmdStream, + const ImageHandle& input, + const ImageHandle& output) { + m_core.recordBeginDebugLabel(cmdStream, m_name, std::array<float, 4>{ + 0.75f, 0.75f, 0.75f, 1.0f + }); + + m_core.prepareImageForStorage(cmdStream, input); + m_core.prepareImageForStorage(cmdStream, output); + + vkcv::DescriptorWrites writes; + + writes.writeStorageImage(0, input); + writes.writeStorageImage(1, output); + + m_core.writeDescriptorSet(m_descriptorSet, writes); + + const uint32_t width = m_core.getImageWidth(output); + const uint32_t height = m_core.getImageHeight(output); + + m_core.recordComputeDispatchToCmdStream( + cmdStream, + m_pipeline, + dispatchInvocations( + DispatchSize(width, height), + DispatchSize(8, 8) + ), + { useDescriptorSet(0, m_descriptorSet) }, + PushConstants(0) + ); + + m_core.recordEndDebugLabel(cmdStream); + } + +} diff --git a/modules/tone_mapping/src/vkcv/tone/UchimuraToneMapping.cpp b/modules/tone_mapping/src/vkcv/tone/UchimuraToneMapping.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f063569ad35f7b2ccdb7b1a75df3a0ef3c122ef9 --- /dev/null +++ b/modules/tone_mapping/src/vkcv/tone/UchimuraToneMapping.cpp @@ -0,0 +1,17 @@ + +#include "vkcv/tone/UchimuraToneMapping.hpp" + +#include "uchimura.glsl.hxx" + +namespace vkcv::tone { + + void UchimuraToneMapping::initToneMapping() { + buildComputePipeline("uchimura", UCHIMURA_GLSL_SHADER); + } + + UchimuraToneMapping::UchimuraToneMapping(Core &core, bool normalize) + : ToneMapping(core, "Uchimura Tone Mapping", normalize) { + initToneMapping(); + } + +} diff --git a/modules/tone_mapping/src/vkcv/tone/Uncharted2ToneMapping.cpp b/modules/tone_mapping/src/vkcv/tone/Uncharted2ToneMapping.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c83ad5d01632072869655a56fcba217df43f35ca --- /dev/null +++ b/modules/tone_mapping/src/vkcv/tone/Uncharted2ToneMapping.cpp @@ -0,0 +1,17 @@ + +#include "vkcv/tone/Uncharted2ToneMapping.hpp" + +#include "uncharted2.glsl.hxx" + +namespace vkcv::tone { + + void Uncharted2ToneMapping::initToneMapping() { + buildComputePipeline("uncharted2", UNCHARTED2_GLSL_SHADER); + } + + Uncharted2ToneMapping::Uncharted2ToneMapping(Core &core, bool normalize) + : ToneMapping(core, "Uncharted2 Tone Mapping", normalize) { + initToneMapping(); + } + +} diff --git a/modules/tone_mapping/src/vkcv/tone/UnrealToneMapping.cpp b/modules/tone_mapping/src/vkcv/tone/UnrealToneMapping.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d41c9e3fadce145765d2d237175eb7622792672d --- /dev/null +++ b/modules/tone_mapping/src/vkcv/tone/UnrealToneMapping.cpp @@ -0,0 +1,17 @@ + +#include "vkcv/tone/UnrealToneMapping.hpp" + +#include "unreal.glsl.hxx" + +namespace vkcv::tone { + + void UnrealToneMapping::initToneMapping() { + buildComputePipeline("unreal", UNREAL_GLSL_SHADER); + } + + UnrealToneMapping::UnrealToneMapping(Core &core, bool normalize) + : ToneMapping(core, "Unreal Tone Mapping", normalize) { + initToneMapping(); + } + +} diff --git a/projects/fire_works/CMakeLists.txt b/projects/fire_works/CMakeLists.txt index 7f9fd1fdd30bff0b331138821f10035f4b7dc64d..4907967793dd843a4016e9577ffb67dee1d780d4 100644 --- a/projects/fire_works/CMakeLists.txt +++ b/projects/fire_works/CMakeLists.txt @@ -16,6 +16,7 @@ target_include_directories(fire_works SYSTEM BEFORE PRIVATE ${vkcv_camera_include} ${vkcv_gui_include} ${vkcv_shader_compiler_include} + ${vkcv_tone_mapping_include} ${vkcv_effects_include}) # linking with libraries from all dependencies and the VkCV framework @@ -24,4 +25,5 @@ target_link_libraries(fire_works vkcv_camera vkcv_gui vkcv_shader_compiler + vkcv_tone_mapping vkcv_effects) diff --git a/projects/fire_works/shaders/tonemapping.comp b/projects/fire_works/shaders/tonemapping.comp deleted file mode 100644 index 5e6cc8412a77939888fc8e961ea5e9ef29534a81..0000000000000000000000000000000000000000 --- a/projects/fire_works/shaders/tonemapping.comp +++ /dev/null @@ -1,21 +0,0 @@ -#version 440 - -layout(set=0, binding=0, rgba16f) readonly uniform image2D inImage; -layout(set=0, binding=1, rgba8) writeonly uniform image2D outImage; - - -layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; - -void main() { - if(any(greaterThanEqual(gl_GlobalInvocationID.xy, imageSize(inImage)))){ - return; - } - - ivec2 uv = ivec2(gl_GlobalInvocationID.xy); - vec3 linearColor = imageLoad(inImage, uv).rgb; - - vec3 tonemapped = linearColor / (dot(linearColor, vec3(0.21, 0.71, 0.08)) + 1); // reinhard tonemapping - vec3 gammaCorrected = pow(tonemapped, vec3(1.f / 2.2f)); - - imageStore(outImage, uv, vec4(gammaCorrected, 0.f)); -} \ No newline at end of file diff --git a/projects/fire_works/src/main.cpp b/projects/fire_works/src/main.cpp index 2bec78711c12a221fd7e82da06af6d87ee5be0fe..aa23f74a75f4c4deab44632bdf7f7c53f543098e 100644 --- a/projects/fire_works/src/main.cpp +++ b/projects/fire_works/src/main.cpp @@ -8,9 +8,11 @@ #include <vkcv/Sampler.hpp> #include <vkcv/camera/CameraManager.hpp> -#include <vkcv/shader/GLSLCompiler.hpp> -#include <vkcv/gui/GUI.hpp> #include <vkcv/effects/BloomAndFlaresEffect.hpp> +#include <vkcv/effects/GammaCorrectionEffect.hpp> +#include <vkcv/gui/GUI.hpp> +#include <vkcv/shader/GLSLCompiler.hpp> +#include <vkcv/tone/ReinhardToneMapping.hpp> struct particle_t { glm::vec3 position; @@ -910,17 +912,8 @@ int main(int argc, const char **argv) { { addDescriptorLayout, generationDescriptorLayout } }); - vkcv::ShaderProgram tonemappingShader; - compiler.compile(vkcv::ShaderStage::COMPUTE, "shaders/tonemapping.comp", [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { - tonemappingShader.addShader(shaderStage, path); - }); - - vkcv::DescriptorSetLayoutHandle tonemappingDescriptorLayout = core.createDescriptorSetLayout(tonemappingShader.getReflectedDescriptors().at(0)); - vkcv::DescriptorSetHandle tonemappingDescriptor = core.createDescriptorSet(tonemappingDescriptorLayout); - vkcv::ComputePipelineHandle tonemappingPipe = core.createComputePipeline({ - tonemappingShader, - { tonemappingDescriptorLayout } - }); + vkcv::tone::ReinhardToneMapping toneMapping (core); + vkcv::effects::GammaCorrectionEffect gammaCorrection (core); vkcv::ImageHandle swapchainImage = vkcv::ImageHandle::createSwapchainImageHandle(); @@ -1273,29 +1266,8 @@ int main(int argc, const char **argv) { core.recordEndDebugLabel(cmdStream); bloomAndFlares.recordEffect(cmdStream, colorBuffers.back(), colorBuffers.back()); - - core.recordBeginDebugLabel(cmdStream, "Tonemapping", { 0.0f, 1.0f, 0.0f, 1.0f }); - core.prepareImageForStorage(cmdStream, colorBuffers.back()); - core.prepareImageForStorage(cmdStream, swapchainImage); - - vkcv::DescriptorWrites tonemappingDescriptorWrites; - tonemappingDescriptorWrites.writeStorageImage( - 0, colorBuffers.back() - ).writeStorageImage( - 1, swapchainImage - ); - - core.writeDescriptorSet(tonemappingDescriptor, tonemappingDescriptorWrites); - - core.recordComputeDispatchToCmdStream( - cmdStream, - tonemappingPipe, - colorDispatchCount, - { vkcv::useDescriptorSet(0, tonemappingDescriptor) }, - vkcv::PushConstants(0) - ); - - core.recordEndDebugLabel(cmdStream); + toneMapping.recordToneMapping(cmdStream, colorBuffers.back(), colorBuffers.back()); + gammaCorrection.recordEffect(cmdStream, colorBuffers.back(), swapchainImage); core.prepareSwapchainImageForPresent(cmdStream); core.submitCommandStream(cmdStream); @@ -1321,6 +1293,11 @@ int main(int argc, const char **argv) { bool colorChanged = ImGui::ColorPicker3("Color", (float*) & color); + float gamma = gammaCorrection.getGamma(); + if (ImGui::SliderFloat("Gamma", &gamma, 0.0f, 10.0f)) { + gammaCorrection.setGamma(gamma); + } + ImGui::End(); gui.endGUI(); diff --git a/projects/particle_simulation/CMakeLists.txt b/projects/particle_simulation/CMakeLists.txt index ed0874fb071aadf801b03be62b7b1b8e8da47aaa..0f4e0acd2d7e1e14a82ed2f045be0e2e326b6330 100644 --- a/projects/particle_simulation/CMakeLists.txt +++ b/projects/particle_simulation/CMakeLists.txt @@ -19,6 +19,7 @@ target_include_directories(particle_simulation SYSTEM BEFORE PRIVATE ${vkcv_includes} ${vkcv_camera_include} ${vkcv_shader_compiler_include} + ${vkcv_tone_mapping_include} ${vkcv_effects_include}) # linking with libraries from all dependencies and the VkCV framework @@ -26,4 +27,5 @@ target_link_libraries(particle_simulation vkcv vkcv_camera vkcv_shader_compiler + vkcv_tone_mapping vkcv_effects) diff --git a/projects/particle_simulation/shaders/tonemapping.comp b/projects/particle_simulation/shaders/tonemapping.comp deleted file mode 100644 index 26f0232d66e3475afdd1266c0cc6288b47ed1c38..0000000000000000000000000000000000000000 --- a/projects/particle_simulation/shaders/tonemapping.comp +++ /dev/null @@ -1,19 +0,0 @@ -#version 440 - -layout(set=0, binding=0, rgba16f) uniform image2D inImage; -layout(set=0, binding=1, rgba8) uniform image2D outImage; - - -layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; - -void main(){ - - if(any(greaterThanEqual(gl_GlobalInvocationID.xy, imageSize(inImage)))){ - return; - } - ivec2 uv = ivec2(gl_GlobalInvocationID.xy); - vec3 linearColor = imageLoad(inImage, uv).rgb; - vec3 tonemapped = linearColor / (dot(linearColor, vec3(0.21, 0.71, 0.08)) + 1); // reinhard tonemapping - vec3 gammaCorrected = pow(tonemapped, vec3(1.f / 2.2f)); - imageStore(outImage, uv, vec4(gammaCorrected, 0.f)); -} \ No newline at end of file diff --git a/projects/particle_simulation/src/main.cpp b/projects/particle_simulation/src/main.cpp index 7f270706eb2e385c539af4cdd6cb7eca3236b138..09cb702809f9f7c48105d8b95b4f398f2bbeb014 100644 --- a/projects/particle_simulation/src/main.cpp +++ b/projects/particle_simulation/src/main.cpp @@ -4,13 +4,12 @@ #include <vkcv/Pass.hpp> #include <GLFW/glfw3.h> #include <vkcv/camera/CameraManager.hpp> -#include <chrono> #include "ParticleSystem.hpp" #include <random> -#include <glm/gtc/matrix_access.hpp> -#include <ctime> #include <vkcv/shader/GLSLCompiler.hpp> #include <vkcv/effects/BloomAndFlaresEffect.hpp> +#include <vkcv/effects/GammaCorrectionEffect.hpp> +#include <vkcv/tone/ReinhardToneMapping.hpp> int main(int argc, const char **argv) { const std::string applicationName = "Particlesystem"; @@ -222,18 +221,9 @@ int main(int argc, const char **argv) { vkcv::effects::BloomAndFlaresEffect bloomAndFlares (core); bloomAndFlares.setUpsamplingLimit(3); - - vkcv::ShaderProgram tonemappingShader; - compiler.compile(vkcv::ShaderStage::COMPUTE, "shaders/tonemapping.comp", [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { - tonemappingShader.addShader(shaderStage, path); - }); - - vkcv::DescriptorSetLayoutHandle tonemappingDescriptorLayout = core.createDescriptorSetLayout(tonemappingShader.getReflectedDescriptors().at(0)); - vkcv::DescriptorSetHandle tonemappingDescriptor = core.createDescriptorSet(tonemappingDescriptorLayout); - vkcv::ComputePipelineHandle tonemappingPipe = core.createComputePipeline({ - tonemappingShader, - { tonemappingDescriptorLayout } - }); + + vkcv::tone::ReinhardToneMapping toneMapping (core); + vkcv::effects::GammaCorrectionEffect gammaCorrection (core); std::uniform_real_distribution<float> rdm = std::uniform_real_distribution<float>(0.95f, 1.05f); std::default_random_engine rdmEngine; @@ -295,31 +285,8 @@ int main(int argc, const char **argv) { ); bloomAndFlares.recordEffect(cmdStream, colorBuffer, colorBuffer); - - core.prepareImageForStorage(cmdStream, colorBuffer); - core.prepareImageForStorage(cmdStream, swapchainInput); - - vkcv::DescriptorWrites tonemappingDescriptorWrites; - tonemappingDescriptorWrites.writeStorageImage( - 0, colorBuffer - ).writeStorageImage( - 1, swapchainInput - ); - - core.writeDescriptorSet(tonemappingDescriptor, tonemappingDescriptorWrites); - - const auto tonemappingDispatchCount = vkcv::dispatchInvocations( - vkcv::DispatchSize(swapchainWidth, swapchainHeight), - vkcv::DispatchSize(8, 8) - ); - - core.recordComputeDispatchToCmdStream( - cmdStream, - tonemappingPipe, - tonemappingDispatchCount, - { vkcv::useDescriptorSet(0, tonemappingDescriptor) }, - vkcv::PushConstants(0) - ); + toneMapping.recordToneMapping(cmdStream, colorBuffer, colorBuffer); + gammaCorrection.recordEffect(cmdStream, colorBuffer, swapchainInput); core.prepareSwapchainImageForPresent(cmdStream); core.submitCommandStream(cmdStream); diff --git a/projects/path_tracer/CMakeLists.txt b/projects/path_tracer/CMakeLists.txt index 03e5eec5ddbada873297d53d224d57f97b4436a9..e0287b28f177708b7ef9bd0935475de365e421fb 100644 --- a/projects/path_tracer/CMakeLists.txt +++ b/projects/path_tracer/CMakeLists.txt @@ -14,7 +14,9 @@ target_include_directories(path_tracer SYSTEM BEFORE PRIVATE ${vkcv_includes} ${vkcv_asset_loader_include} ${vkcv_camera_include} + ${vkcv_effects_include} ${vkcv_shader_compiler_include} + ${vkcv_tone_mapping_include} ${vkcv_gui_include}) # linking with libraries from all dependencies and the VkCV framework @@ -23,5 +25,7 @@ target_link_libraries(path_tracer vkcv_asset_loader ${vkcv_asset_loader_libraries} vkcv_camera + vkcv_effects vkcv_shader_compiler + vkcv_tone_mapping vkcv_gui) diff --git a/projects/path_tracer/shaders/presentImage.comp b/projects/path_tracer/shaders/presentImage.comp deleted file mode 100644 index a52159c0c6173779b091e5d4153b15b0a6361780..0000000000000000000000000000000000000000 --- a/projects/path_tracer/shaders/presentImage.comp +++ /dev/null @@ -1,23 +0,0 @@ -#version 440 -#extension GL_GOOGLE_include_directive : enable - -layout(set=0, binding=0, rgba32f) uniform image2D inImage; -layout(set=0, binding=1, rgba8) uniform image2D outImage; - -layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; - -void main(){ - - ivec2 outImageRes = imageSize(outImage); - ivec2 coord = ivec2(gl_GlobalInvocationID.xy); - - if(any(greaterThanEqual(coord, outImageRes))) - return; - - vec4 colorRaw = imageLoad(inImage, coord); - vec3 colorNormalized = colorRaw.rgb / colorRaw.a; - vec3 colorTonemapped = colorNormalized / (1 + dot(colorNormalized, vec3(0.71, 0.21, 0.08))); // reinhard tonemapping - vec3 colorGammaCorrected = pow(colorTonemapped, vec3(1.f / 2.2)); - - imageStore(outImage, coord, vec4(colorGammaCorrected, 0)); -} \ No newline at end of file diff --git a/projects/path_tracer/src/main.cpp b/projects/path_tracer/src/main.cpp index 75ee36b2ac232e20d7baf29db34909dee67cca00..1a87015e58aee80feebb4bc5fafac0a482da5743 100644 --- a/projects/path_tracer/src/main.cpp +++ b/projects/path_tracer/src/main.cpp @@ -1,11 +1,11 @@ #include <vkcv/Buffer.hpp> #include <vkcv/Core.hpp> -#include <vkcv/Pass.hpp> #include <vkcv/camera/CameraManager.hpp> #include <vkcv/asset/asset_loader.hpp> +#include <vkcv/effects/GammaCorrectionEffect.hpp> #include <vkcv/shader/GLSLCompiler.hpp> -#include "vkcv/gui/GUI.hpp" -#include <chrono> +#include <vkcv/tone/ReinhardToneMapping.hpp> +#include <vkcv/gui/GUI.hpp> #include <vector> int main(int argc, const char** argv) { @@ -81,6 +81,11 @@ int main(int argc, const char** argv) { vk::Format::eR32G32B32A32Sfloat, imageConfig ); + + vkcv::ImageHandle mappedImage = core.createImage( + vk::Format::eR8G8B8A8Unorm, + imageConfig + ); vkcv::shader::GLSLCompiler compiler; @@ -113,21 +118,9 @@ int main(int argc, const char** argv) { vkcv::DescriptorWrites imageCombineDescriptorWrites; imageCombineDescriptorWrites.writeStorageImage(0, outputImage).writeStorageImage(1, meanImage); core.writeDescriptorSet(imageCombineDescriptorSet, imageCombineDescriptorWrites); - - // image present shader - vkcv::ShaderProgram presentShaderProgram{}; - - compiler.compile(vkcv::ShaderStage::COMPUTE, "shaders/presentImage.comp", [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { - presentShaderProgram.addShader(shaderStage, path); - }); - - const vkcv::DescriptorBindings& presentDescriptorBindings = presentShaderProgram.getReflectedDescriptors().at(0); - vkcv::DescriptorSetLayoutHandle presentDescriptorSetLayout = core.createDescriptorSetLayout(presentDescriptorBindings); - vkcv::DescriptorSetHandle presentDescriptorSet = core.createDescriptorSet(presentDescriptorSetLayout); - vkcv::ComputePipelineHandle presentPipeline = core.createComputePipeline({ - presentShaderProgram, - { presentDescriptorSetLayout } - }); + + vkcv::tone::ReinhardToneMapping toneMapping (core, true); + vkcv::effects::GammaCorrectionEffect gammaCorrection (core); // clear shader vkcv::ShaderProgram clearShaderProgram{}; @@ -253,13 +246,18 @@ int main(int argc, const char** argv) { // resize images outputImage = core.createImage( - vk::Format::eR32G32B32A32Sfloat, - imageConfig + vk::Format::eR32G32B32A32Sfloat, + imageConfig ); meanImage = core.createImage( - vk::Format::eR32G32B32A32Sfloat, - imageConfig + vk::Format::eR32G32B32A32Sfloat, + imageConfig + ); + + mappedImage = core.createImage( + vk::Format::eR8G8B8A8Unorm, + imageConfig ); // update descriptor sets @@ -379,23 +377,9 @@ int main(int argc, const char** argv) { // present image const vkcv::ImageHandle swapchainInput = vkcv::ImageHandle::createSwapchainImageHandle(); - - vkcv::DescriptorWrites presentDescriptorWrites; - presentDescriptorWrites.writeStorageImage( - 0, meanImage - ).writeStorageImage( - 1, swapchainInput - ); - core.writeDescriptorSet(presentDescriptorSet, presentDescriptorWrites); - - core.prepareImageForStorage(cmdStream, swapchainInput); - - core.recordComputeDispatchToCmdStream(cmdStream, - presentPipeline, - fullscreenDispatchCount, - { vkcv::useDescriptorSet(0, presentDescriptorSet) }, - vkcv::PushConstants(0)); + toneMapping.recordToneMapping(cmdStream, meanImage, mappedImage); + gammaCorrection.recordEffect(cmdStream, mappedImage, swapchainInput); core.prepareSwapchainImageForPresent(cmdStream); core.submitCommandStream(cmdStream); diff --git a/projects/sph/CMakeLists.txt b/projects/sph/CMakeLists.txt index 01a6e083116622965b9f58c2837f6287871da50e..46e83abfbe1913ea69038db7320d370e114caa3d 100644 --- a/projects/sph/CMakeLists.txt +++ b/projects/sph/CMakeLists.txt @@ -19,6 +19,7 @@ target_include_directories(sph SYSTEM BEFORE PRIVATE ${vkcv_includes} ${vkcv_camera_include} ${vkcv_shader_compiler_include} + ${vkcv_tone_mapping_include} ${vkcv_effects_include}) # linking with libraries from all dependencies and the VkCV framework @@ -26,4 +27,5 @@ target_link_libraries(sph vkcv vkcv_camera vkcv_shader_compiler + vkcv_tone_mapping vkcv_effects) diff --git a/projects/sph/shaders/tonemapping.comp b/projects/sph/shaders/tonemapping.comp deleted file mode 100644 index 26f0232d66e3475afdd1266c0cc6288b47ed1c38..0000000000000000000000000000000000000000 --- a/projects/sph/shaders/tonemapping.comp +++ /dev/null @@ -1,19 +0,0 @@ -#version 440 - -layout(set=0, binding=0, rgba16f) uniform image2D inImage; -layout(set=0, binding=1, rgba8) uniform image2D outImage; - - -layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; - -void main(){ - - if(any(greaterThanEqual(gl_GlobalInvocationID.xy, imageSize(inImage)))){ - return; - } - ivec2 uv = ivec2(gl_GlobalInvocationID.xy); - vec3 linearColor = imageLoad(inImage, uv).rgb; - vec3 tonemapped = linearColor / (dot(linearColor, vec3(0.21, 0.71, 0.08)) + 1); // reinhard tonemapping - vec3 gammaCorrected = pow(tonemapped, vec3(1.f / 2.2f)); - imageStore(outImage, uv, vec4(gammaCorrected, 0.f)); -} \ No newline at end of file diff --git a/projects/sph/src/main.cpp b/projects/sph/src/main.cpp index 904d9e8965e41914271afb0ac31853b1581f6ca7..89f2df703ca14f7e622521e728e3b0216aa4624b 100644 --- a/projects/sph/src/main.cpp +++ b/projects/sph/src/main.cpp @@ -3,11 +3,13 @@ #include <vkcv/Buffer.hpp> #include <vkcv/Pass.hpp> #include <vkcv/camera/CameraManager.hpp> -#include <chrono> #include <random> #include <ctime> #include <vkcv/shader/GLSLCompiler.hpp> #include <vkcv/effects/BloomAndFlaresEffect.hpp> +#include <vkcv/effects/GammaCorrectionEffect.hpp> +#include <vkcv/tone/ReinhardToneMapping.hpp> + #include "PipelineInit.hpp" #include "Particle.hpp" @@ -237,15 +239,9 @@ int main(int argc, const char **argv) { vkcv::effects::BloomAndFlaresEffect bloomAndFlares (core); bloomAndFlares.setUpsamplingLimit(3); - - //tone mapping shader & pipeline - vkcv::ComputePipelineHandle tonemappingPipe; - vkcv::DescriptorSetHandle tonemappingDescriptor = PipelineInit::ComputePipelineInit( - &core, - vkcv::ShaderStage::COMPUTE, - "shaders/tonemapping.comp", - tonemappingPipe - ); + + vkcv::tone::ReinhardToneMapping toneMapping (core); + vkcv::effects::GammaCorrectionEffect gammaCorrection (core); core.run([&](const vkcv::WindowHandle &windowHandle, double t, double dt, uint32_t swapchainWidth, uint32_t swapchainHeight) { @@ -395,31 +391,8 @@ int main(int argc, const char **argv) { ); bloomAndFlares.recordEffect(cmdStream, colorBuffer, colorBuffer); - - core.prepareImageForStorage(cmdStream, colorBuffer); - core.prepareImageForStorage(cmdStream, swapchainInput); - - vkcv::DescriptorWrites tonemappingDescriptorWrites; - tonemappingDescriptorWrites.writeStorageImage( - 0, colorBuffer - ).writeStorageImage( - 1, swapchainInput - ); - - core.writeDescriptorSet(tonemappingDescriptor, tonemappingDescriptorWrites); - - const auto tonemappingDispatchCount = vkcv::dispatchInvocations( - vkcv::DispatchSize(swapchainWidth, swapchainHeight), - vkcv::DispatchSize(8, 8) - ); - - core.recordComputeDispatchToCmdStream( - cmdStream, - tonemappingPipe, - tonemappingDispatchCount, - { vkcv::useDescriptorSet(0, tonemappingDescriptor) }, - vkcv::PushConstants(0) - ); + toneMapping.recordToneMapping(cmdStream, colorBuffer, colorBuffer); + gammaCorrection.recordEffect(cmdStream, colorBuffer, swapchainInput); core.prepareSwapchainImageForPresent(cmdStream); core.submitCommandStream(cmdStream); diff --git a/projects/voxelization/CMakeLists.txt b/projects/voxelization/CMakeLists.txt index 34178021a517485e54ef8dcafe0f170a834e5186..f8735582caa27ceaf111c969d8ae716679dee1e5 100644 --- a/projects/voxelization/CMakeLists.txt +++ b/projects/voxelization/CMakeLists.txt @@ -21,6 +21,7 @@ target_include_directories(voxelization SYSTEM BEFORE PRIVATE ${vkcv_asset_loader_include} ${vkcv_camera_include} ${vkcv_shader_compiler_include} + ${vkcv_tone_mapping_include} ${vkcv_gui_include} ${vkcv_upscaling_include} ${vkcv_effects_include} @@ -34,6 +35,7 @@ target_link_libraries(voxelization ${vkcv_asset_loader_libraries} vkcv_camera vkcv_shader_compiler + vkcv_tone_mapping vkcv_gui vkcv_upscaling vkcv_effects diff --git a/projects/voxelization/assets/shaders/tonemapping.comp b/projects/voxelization/assets/shaders/tonemapping.comp deleted file mode 100644 index ffadc9a71e207f97fec9a8815aa1c61bc709c369..0000000000000000000000000000000000000000 --- a/projects/voxelization/assets/shaders/tonemapping.comp +++ /dev/null @@ -1,34 +0,0 @@ -#version 440 -#extension GL_GOOGLE_include_directive : enable - -layout(set=0, binding=0) uniform texture2D inTexture; -layout(set=0, binding=1) uniform sampler textureSampler; -layout(set=0, binding=2, rgba8) uniform image2D outImage; - -layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; - -// from: https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/ -vec3 ACESFilm(vec3 x) -{ - float a = 2.51f; - float b = 0.03f; - float c = 2.43f; - float d = 0.59f; - float e = 0.14f; - return clamp((x*(a*x+b))/(x*(c*x+d)+e), 0, 1); -} - -void main(){ - - if(any(greaterThanEqual(gl_GlobalInvocationID.xy, imageSize(outImage)))){ - return; - } - ivec2 textureRes = textureSize(sampler2D(inTexture, textureSampler), 0); - ivec2 coord = ivec2(gl_GlobalInvocationID.xy); - vec2 uv = vec2(coord) / textureRes; - - vec3 linearColor = texture(sampler2D(inTexture, textureSampler), uv).rgb; - vec3 tonemapped = ACESFilm(linearColor); - - imageStore(outImage, coord, vec4(tonemapped, 0.f)); -} \ No newline at end of file diff --git a/projects/voxelization/src/main.cpp b/projects/voxelization/src/main.cpp index 9b9bf39b205cd65b8a0f5813b7f4376ee68152a9..d9d9aedcc5a32552b83e2d9fe48733410ec2f9c7 100644 --- a/projects/voxelization/src/main.cpp +++ b/projects/voxelization/src/main.cpp @@ -4,7 +4,6 @@ #include <vkcv/Sampler.hpp> #include <GLFW/glfw3.h> #include <vkcv/camera/CameraManager.hpp> -#include <chrono> #include <vkcv/asset/asset_loader.hpp> #include <vkcv/shader/GLSLCompiler.hpp> #include "Voxelization.hpp" @@ -15,6 +14,7 @@ #include <vkcv/upscaling/NISUpscaling.hpp> #include <vkcv/effects/BloomAndFlaresEffect.hpp> #include <vkcv/algorithm/SinglePassDownsampler.hpp> +#include <vkcv/tone/ACESToneMapping.hpp> int main(int argc, const char** argv) { const std::string applicationName = "Voxelization"; @@ -474,21 +474,6 @@ int main(int argc, const char** argv) { renderUI = !renderUI; } }); - - // tonemapping compute shader - vkcv::ShaderProgram tonemappingProgram; - compiler.compile(vkcv::ShaderStage::COMPUTE, "assets/shaders/tonemapping.comp", - [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { - tonemappingProgram.addShader(shaderStage, path); - }); - - vkcv::DescriptorSetLayoutHandle tonemappingDescriptorSetLayout = core.createDescriptorSetLayout( - tonemappingProgram.getReflectedDescriptors().at(0)); - vkcv::DescriptorSetHandle tonemappingDescriptorSet = core.createDescriptorSet(tonemappingDescriptorSetLayout); - vkcv::ComputePipelineHandle tonemappingPipeline = core.createComputePipeline({ - tonemappingProgram, - { tonemappingDescriptorSetLayout } - }); // tonemapping compute shader vkcv::ShaderProgram postEffectsProgram; @@ -609,6 +594,8 @@ int main(int argc, const char** argv) { ); core.writeDescriptorSet(forwardShadingDescriptorSet, forwardDescriptorWrites); + + vkcv::tone::ACESToneMapping acesToneMapping (core); vkcv::upscaling::FSRUpscaling upscaling (core); uint32_t fsrWidth = swapchainExtent.width, fsrHeight = swapchainExtent.height; @@ -729,14 +716,6 @@ int main(int argc, const char** argv) { swapBufferConfig ); } - - // update descriptor sets which use swapchain image - vkcv::DescriptorWrites tonemappingDescriptorWrites; - tonemappingDescriptorWrites.writeSampledImage(0, resolvedColorBuffer); - tonemappingDescriptorWrites.writeSampler(1, colorSampler); - tonemappingDescriptorWrites.writeStorageImage(2, swapBuffer); - - core.writeDescriptorSet(tonemappingDescriptorSet, tonemappingDescriptorWrites); // update descriptor sets which use swapchain image vkcv::DescriptorWrites postEffectsDescriptorWrites; @@ -892,22 +871,10 @@ int main(int argc, const char** argv) { bloomFlares.updateCameraDirection(cameraManager.getActiveCamera()); bloomFlares.recordEffect(cmdStream, resolvedColorBuffer, resolvedColorBuffer); - - core.prepareImageForStorage(cmdStream, swapBuffer); - core.prepareImageForSampling(cmdStream, resolvedColorBuffer); - - core.recordBeginDebugLabel(cmdStream, "Tonemapping", { 1, 1, 1, 1 }); - core.recordComputeDispatchToCmdStream( - cmdStream, - tonemappingPipeline, - fullscreenDispatchCount, - { vkcv::useDescriptorSet(0, tonemappingDescriptorSet) }, - vkcv::PushConstants(0) - ); + acesToneMapping.recordToneMapping(cmdStream, resolvedColorBuffer, swapBuffer); core.prepareImageForStorage(cmdStream, swapBuffer2); core.prepareImageForSampling(cmdStream, swapBuffer); - core.recordEndDebugLabel(cmdStream); switch (upscalingMode) { case 0: @@ -1011,23 +978,6 @@ int main(int argc, const char** argv) { } } - if (ImGui::Button("Reload tonemapping")) { - vkcv::ShaderProgram newProgram; - compiler.compile(vkcv::ShaderStage::COMPUTE, std::filesystem::path("assets/shaders/tonemapping.comp"), - [&](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { - newProgram.addShader(shaderStage, path); - }); - - vkcv::ComputePipelineHandle newPipeline = core.createComputePipeline({ - newProgram, - { tonemappingDescriptorSetLayout } - }); - - if (newPipeline) { - tonemappingPipeline = newPipeline; - } - } - ImGui::End(); }