diff --git a/assets/shaders/gamma_correction.frag b/assets/shaders/gamma_correction.frag new file mode 100644 index 0000000..6a4dde4 --- /dev/null +++ b/assets/shaders/gamma_correction.frag @@ -0,0 +1,11 @@ +#version 450 core + +uniform sampler2D colorTexture; +uniform float power = 2.2; + +layout(location = 0) out vec4 color; + +void main() { + vec4 pixel = texelFetch(colorTexture, ivec2(gl_FragCoord.xy), 0); + color = vec4(pow(pixel.xyz, vec3(1) / power), pixel.w); +} diff --git a/assets/shaders/gamma_correction.vert b/assets/shaders/gamma_correction.vert new file mode 100644 index 0000000..2f55184 --- /dev/null +++ b/assets/shaders/gamma_correction.vert @@ -0,0 +1,7 @@ +#version 450 core + +layout(location = 0) in vec3 position; + +void main() { + gl_Position = vec4(position, 1); +} diff --git a/src/Scene/Effects/ChromaticAberrationEffect.h b/src/Scene/Effects/ChromaticAberrationEffect.h new file mode 100644 index 0000000..0c9f814 --- /dev/null +++ b/src/Scene/Effects/ChromaticAberrationEffect.h @@ -0,0 +1,37 @@ +#ifndef CHROMATICABERRATIONEFFECT_H +#define CHROMATICABERRATIONEFFECT_H + +#include "PostProcessEffect.h" + +class ChromaticAberrationEffect : public PostProcessEffect { + float aberrationStart = 1.5f; + float aberrationROffset = 0.005; + float aberrationGOffset = 0.01; + float aberrationBOffset = -0.005; + +public: + ChromaticAberrationEffect(bool enabled) + : PostProcessEffect(AssetManager::instance().loadShaderProgram("assets/shaders/chromatic_aberration_effect"), + enabled) {} + + void renderGui() override { + ImGui::Checkbox("Enable chromatic aberration effect", &enabled); + + if (enabled) { + ImGui::SliderFloat("Aberration start", &aberrationStart, 0.5, 3); + ImGui::SliderFloat("Aberration R Offset", &aberrationROffset, -0.01, 0.01); + ImGui::SliderFloat("Aberration G Offset", &aberrationGOffset, -0.01, 0.01); + ImGui::SliderFloat("Aberration B Offset", &aberrationBOffset, -0.01, 0.01); + } + } + + void updateUniforms() override { + shader->setFloat("start", aberrationStart); + shader->setFloat("rOffset", aberrationROffset); + shader->setFloat("gOffset", aberrationGOffset); + shader->setFloat("bOffset", aberrationBOffset); + } +}; + + +#endif diff --git a/src/Scene/Effects/CrosshairEffect.h b/src/Scene/Effects/CrosshairEffect.h new file mode 100644 index 0000000..ff20614 --- /dev/null +++ b/src/Scene/Effects/CrosshairEffect.h @@ -0,0 +1,38 @@ +#ifndef CROSSHAIREFFECT_H +#define CROSSHAIREFFECT_H + +#include "../../Application/Window.h" +#include "./PostProcessEffect.h" + +class CrosshairEffect : public PostProcessEffect { + float crosshairSize = 0.015f; + float crosshairVerticalWidth = 0.2f; + float crosshairHorizontalWidth = 0.15f; + +public: + CrosshairEffect(bool enabled) + : PostProcessEffect(AssetManager::instance().loadShaderProgram("assets/shaders/crosshair"), enabled) {} + void renderGui() override { + ImGui::Checkbox("Enable crosshair", &enabled); + if (enabled) { + ImGui::SliderFloat("Crosshair size", &crosshairSize, 0.01, 1); + ImGui::SliderFloat("Crosshair vertical width", &crosshairVerticalWidth, 0.01, 1); + ImGui::SliderFloat("Crosshair horizontal width", &crosshairHorizontalWidth, 0.01, 1); + } + } + + void updateUniforms() override { + auto& window = Window::instance(); + auto width = window.getWindowWidth(); + auto height = window.getWindowHeight(); + float aspectRatio = width == 0 || height == 0 ? 0 : static_cast(width) / static_cast(height); + + shader->setFloat("size", crosshairSize); + shader->setFloat("verticalWidth", crosshairVerticalWidth); + shader->setFloat("horizontalWidth", crosshairHorizontalWidth); + shader->setFloat("aspectRatio", aspectRatio); + } +}; + + +#endif diff --git a/src/Scene/Effects/InvertEffect.h b/src/Scene/Effects/InvertEffect.h new file mode 100644 index 0000000..aeb8495 --- /dev/null +++ b/src/Scene/Effects/InvertEffect.h @@ -0,0 +1,19 @@ +#ifndef INVERTEFFECT_H +#define INVERTEFFECT_H + +#include "PostProcessEffect.h" + +class InvertEffect : public PostProcessEffect { +public: + InvertEffect(bool enabled) + : PostProcessEffect(AssetManager::instance().loadShaderProgram("assets/shaders/invert_effect"), enabled){} + + void updateUniforms() override {} + + void renderGui() override { + ImGui::Checkbox("Enable invert effect", &enabled); + } +}; + + +#endif diff --git a/src/Scene/PostProcessEffect.cpp b/src/Scene/Effects/PostProcessEffect.cpp similarity index 79% rename from src/Scene/PostProcessEffect.cpp rename to src/Scene/Effects/PostProcessEffect.cpp index 1067d43..8784d09 100644 --- a/src/Scene/PostProcessEffect.cpp +++ b/src/Scene/Effects/PostProcessEffect.cpp @@ -1,11 +1,17 @@ #include "PostProcessEffect.h" -#include "../Application/Window.h" -#include "../Rendering/ColorRenderPass.h" +#include "../../Application/Window.h" +#include "../../Rendering/ColorRenderPass.h" -PostProcessEffect::PostProcessEffect(const Ref& shader) : shader(shader) {} +PostProcessEffect::PostProcessEffect(const Ref& shader, bool enabled) + : shader(shader), + enabled(enabled) {} void PostProcessEffect::render() { + if (!enabled) { + return; + } + Window& window = Window::instance(); int32_t width = window.getWindowWidth(); int32_t height = window.getWindowHeight(); @@ -16,6 +22,8 @@ void PostProcessEffect::render() { Ref framebufferStack = window.getFramebufferStack(); Ref colorSource = framebufferStack->peek(); framebufferStack->push(framebuffer, 1); + + updateUniforms(); ColorRenderPass::renderTextureWithEffect(colorSource->getColorAttachment(0), shader); Ref resultFbo = framebufferStack->pop(); diff --git a/src/Scene/Effects/PostProcessEffect.h b/src/Scene/Effects/PostProcessEffect.h new file mode 100644 index 0000000..1de62a8 --- /dev/null +++ b/src/Scene/Effects/PostProcessEffect.h @@ -0,0 +1,27 @@ +#ifndef POSTPROCESSEFFECT_H +#define POSTPROCESSEFFECT_H + +#include "../../AssetManager/AssetManager.h" +#include "../../Rendering/FrameBuffer.h" +#include "../../Rendering/ShaderProgram.h" +#include "../../glCraft.h" + +class PostProcessEffect { +protected: + bool enabled; + Ref shader; + Ref framebuffer; + +public: + explicit PostProcessEffect(const Ref& shader, bool enabled = false); + + Ref getShader() { return shader; }; + + virtual void updateUniforms() = 0; + virtual void renderGui() = 0; + void render(); + + virtual ~PostProcessEffect() = default; +}; + +#endif diff --git a/src/Scene/Effects/VignetteEffect.h b/src/Scene/Effects/VignetteEffect.h new file mode 100644 index 0000000..bd86bbc --- /dev/null +++ b/src/Scene/Effects/VignetteEffect.h @@ -0,0 +1,34 @@ +#ifndef VIGNETTEEFFECT_H +#define VIGNETTEEFFECT_H + +#include "PostProcessEffect.h" + +class VignetteEffect : public PostProcessEffect { + float vignetteIntensity = 2.9; + float vignetteStart = 1.5f; + +public: + VignetteEffect(bool enabled) + : PostProcessEffect(AssetManager::instance().loadShaderProgram("assets/shaders/vignette_effect"), enabled) {} + + void updateUniforms() override { + shader->setFloat("intensity", vignetteIntensity); + shader->setFloat("start", vignetteStart); + } + + void renderGui() override { + ImGui::Checkbox("Enable vignette effect", &enabled); + + if (enabled) { + float invertedIntensity = 4 - vignetteIntensity; + if (ImGui::SliderFloat("Vignette intensity", &invertedIntensity, 1, 3)) { + vignetteIntensity = 4 - invertedIntensity; + } + + ImGui::SliderFloat("Vignette start", &vignetteStart, 0, 3); + } + } +}; + + +#endif diff --git a/src/Scene/PostProcessEffect.h b/src/Scene/PostProcessEffect.h deleted file mode 100644 index b221a54..0000000 --- a/src/Scene/PostProcessEffect.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef VIGNETTEEFFECT_H -#define VIGNETTEEFFECT_H - -#include "../Rendering/FrameBuffer.h" -#include "../Rendering/ShaderProgram.h" - -class PostProcessEffect { - Ref shader; - Ref framebuffer; - -public: - explicit PostProcessEffect(const Ref& shader); - - Ref getShader() { return shader; }; - - void render(); -}; - -#endif diff --git a/src/Scene/Scene.cpp b/src/Scene/Scene.cpp index 53d3ffe..f41e981 100644 --- a/src/Scene/Scene.cpp +++ b/src/Scene/Scene.cpp @@ -7,12 +7,7 @@ Scene::Scene(const std::string& savePath) : persistence(std::make_shared(savePath)), world(std::make_shared(persistence)), - player(world, persistence), - vignetteEffect(AssetManager::instance().loadShaderProgram("assets/shaders/vignette_effect")), - invertEffect(AssetManager::instance().loadShaderProgram("assets/shaders/invert_effect")), - chromaticAberrationEffect( - AssetManager::instance().loadShaderProgram("assets/shaders/chromatic_aberration_effect")), - crosshair(AssetManager::instance().loadShaderProgram("assets/shaders/crosshair")) { + player(world, persistence) { onResized(Application::instance().getWindowWidth(), Application::instance().getWindowHeight()); updateMouse(); } @@ -54,30 +49,8 @@ void Scene::render() { outline.render(mvp * glm::translate(ray.getHitTarget().position)); } - if (enableCrosshair) { - crosshair.getShader()->setFloat("size", crosshairSize); - crosshair.getShader()->setFloat("verticalWidth", crosshairVerticalWidth); - crosshair.getShader()->setFloat("horizontalWidth", crosshairHorizontalWidth); - crosshair.getShader()->setFloat("aspectRatio", aspectRatio); - crosshair.render(); - } - - if (enableChromaticAberration) { - chromaticAberrationEffect.getShader()->setFloat("start", aberrationStart); - chromaticAberrationEffect.getShader()->setFloat("rOffset", aberrationROffset); - chromaticAberrationEffect.getShader()->setFloat("gOffset", aberrationGOffset); - chromaticAberrationEffect.getShader()->setFloat("bOffset", aberrationBOffset); - chromaticAberrationEffect.render(); - } - - if (enableInvertEffect) { - invertEffect.render(); - } - - if (enableVignetteEffect) { - vignetteEffect.getShader()->setFloat("intensity", vignetteIntensity); - vignetteEffect.getShader()->setFloat("start", vignetteStart); - vignetteEffect.render(); + for (auto& effect: postProcessingEffects) { + effect->render(); } } @@ -87,7 +60,6 @@ void Scene::renderMenu() { ImGui::Text("Player position: x:%f, y:%f, z:%f", position.x, position.y, position.z); glm::vec3 lookDirection = player.getCamera().getLookDirection(); ImGui::Text("Player direction: x:%f, y:%f, z:%f", lookDirection.x, lookDirection.y, lookDirection.z); - ImGui::Text("Screen aspect ratio: %f", aspectRatio); ImGui::Spacing(); ImGui::Spacing(); @@ -107,52 +79,18 @@ void Scene::renderMenu() { ImGui::Spacing(); ImGui::Spacing(); - ImGui::Checkbox("Enable crosshair", &enableCrosshair); - if (enableCrosshair) { - ImGui::SliderFloat("Crosshair size", &crosshairSize, 0.01, 1); - ImGui::SliderFloat("Crosshair vertical width", &crosshairVerticalWidth, 0.01, 1); - ImGui::SliderFloat("Crosshair horizontal width", &crosshairHorizontalWidth, 0.01, 1); - } - - ImGui::Spacing(); - ImGui::Spacing(); - ImGui::Checkbox("Enable XRay", &enableXRay); ImGui::Spacing(); ImGui::Spacing(); - ImGui::Checkbox("Enable chromatic aberration effect", &enableChromaticAberration); - - if (enableChromaticAberration) { - ImGui::SliderFloat("Aberration start", &aberrationStart, 0.5, 3); - ImGui::SliderFloat("Aberration R Offset", &aberrationROffset, -0.01, 0.01); - ImGui::SliderFloat("Aberration G Offset", &aberrationGOffset, -0.01, 0.01); - ImGui::SliderFloat("Aberration B Offset", &aberrationBOffset, -0.01, 0.01); - } - - ImGui::Spacing(); - ImGui::Spacing(); - - ImGui::Checkbox("Enable invert effect", &enableInvertEffect); - - ImGui::Spacing(); - ImGui::Spacing(); + for (auto& effect: postProcessingEffects) { + effect->renderGui(); - ImGui::Checkbox("Enable vignette effect", &enableVignetteEffect); - - if (enableVignetteEffect) { - float invertedIntensity = 4 - vignetteIntensity; - if (ImGui::SliderFloat("Vignette intensity", &invertedIntensity, 1, 3)) { - vignetteIntensity = 4 - invertedIntensity; - } - - ImGui::SliderFloat("Vignette start", &vignetteStart, 0, 3); + ImGui::Spacing(); + ImGui::Spacing(); } - ImGui::Spacing(); - ImGui::Spacing(); - BlockData::BlockType blockToPlace = player.getBlockToPlace(); ImGui::Text("Selected Block: %s", BlockName::blockTypeToName(blockToPlace)); @@ -266,7 +204,7 @@ void Scene::renderGui() { } void Scene::onResized(int32_t width, int32_t height) { - aspectRatio = width == 0 || height == 0 ? 0 : static_cast(width) / static_cast(height); + float aspectRatio = width == 0 || height == 0 ? 0 : static_cast(width) / static_cast(height); projectionMatrix = glm::perspective(glm::half_pi(), aspectRatio, zNear, zFar); } diff --git a/src/Scene/Scene.h b/src/Scene/Scene.h index 097c088..4c3778b 100644 --- a/src/Scene/Scene.h +++ b/src/Scene/Scene.h @@ -9,8 +9,12 @@ #include "../World/World.h" #include "../glCraft.h" #include "BlockOutline.h" +#include "Effects/ChromaticAberrationEffect.h" +#include "Effects/CrosshairEffect.h" +#include "Effects/InvertEffect.h" +#include "Effects/PostProcessEffect.h" +#include "Effects/VignetteEffect.h" #include "Player.h" -#include "PostProcessEffect.h" #include "Skybox.h" class Scene { @@ -26,34 +30,15 @@ class Scene { glm::mat4 projectionMatrix = glm::mat4(1); BlockOutline outline; - PostProcessEffect vignetteEffect; - PostProcessEffect invertEffect; - PostProcessEffect chromaticAberrationEffect; - PostProcessEffect crosshair; + std::vector> postProcessingEffects = { + std::make_shared(true), std::make_shared(false), + std::make_shared(false), std::make_shared(true)}; bool isMenuOpen = false; bool showIntermediateTextures = false; - bool enableChromaticAberration = false; - float aberrationStart = 1.5f; - - float aberrationROffset = 0.005; - float aberrationGOffset = 0.01; - float aberrationBOffset = -0.005; bool enableXRay = false; - bool enableVignetteEffect = true; - float vignetteIntensity = 2.9; - float vignetteStart = 1.5f; - - bool enableInvertEffect = false; - - float aspectRatio = 1.0f; - bool enableCrosshair = true; - float crosshairSize = 0.015f; - float crosshairVerticalWidth = 0.2f; - float crosshairHorizontalWidth = 0.15f; - void toggleMenu(); void updateMouse();