From 9b973784c1e9f1e76f7dee4978f3befa5e38a749 Mon Sep 17 00:00:00 2001 From: Antoine Pilote Date: Wed, 5 Jul 2023 09:57:09 -0400 Subject: [PATCH] Improved volumetric performance --- Editor/resources/Shaders/blur.shader | 7 +- .../resources/Shaders/depth_aware_blur.shader | 67 +++++++++++++++++++ Editor/resources/Shaders/volumetric.shader | 15 +++-- Nuake/src/Rendering/PostFX/Volumetric.cpp | 29 ++++++-- Nuake/src/Rendering/PostFX/Volumetric.h | 4 +- 5 files changed, 106 insertions(+), 16 deletions(-) create mode 100644 Editor/resources/Shaders/depth_aware_blur.shader diff --git a/Editor/resources/Shaders/blur.shader b/Editor/resources/Shaders/blur.shader index 4e28d40d..1887f3b9 100644 --- a/Editor/resources/Shaders/blur.shader +++ b/Editor/resources/Shaders/blur.shader @@ -22,15 +22,14 @@ uniform sampler2D u_Input; void main() { vec2 texelSize = 1.0 / vec2(textureSize(u_Input, 0)); - float result = 0.0; + vec4 result = vec4(0); for (int x = -2; x < 2; ++x) { for (int y = -2; y < 2; ++y) { vec2 offset = vec2(float(x), float(y)) * texelSize; - result += texture(u_Input, UV + offset).r; + result += texture(u_Input, UV + offset); } } - float channel = result / (4.0 * 4.0); - FragColor = vec4(channel, channel, channel, 1.0); + FragColor = result / (4.0 * 4.0); } \ No newline at end of file diff --git a/Editor/resources/Shaders/depth_aware_blur.shader b/Editor/resources/Shaders/depth_aware_blur.shader new file mode 100644 index 00000000..1b2d3e5f --- /dev/null +++ b/Editor/resources/Shaders/depth_aware_blur.shader @@ -0,0 +1,67 @@ +#shader vertex +#version 460 core + +layout(location = 0) in vec3 VertexPosition; +layout(location = 1) in vec2 UVPosition; + +out flat vec2 UV; + +void main() +{ + UV = UVPosition; + gl_Position = vec4(VertexPosition, 1.0f); +} + +#shader fragment +#version 460 core +out vec4 FragColor; + +in vec2 UV; + +uniform sampler2D u_Input; +uniform sampler2D u_Depth; + +const float SHARPNESS = 10.0f; +const float KERNEL_RADIUS = 8.0f; + +void main() { + + vec2 texelSize = 1.0 / vec2(textureSize(u_Input, 0)); + vec4 result = vec4(0); + + float centerDepth = texture(u_Depth, UV).r; + float totalWeight = 0.0f; + for (int x = -2; x < 2; ++x) + { + vec2 offset = vec2(float(x), float(0)) * texelSize; + + vec2 uv = UV + offset; + float depth = texture(u_Depth, uv).r; + + const float blurSigma = float(KERNEL_RADIUS) * 0.5f; + const float blurFalloff = 1.0 / (2.0 * blurSigma * blurSigma); + + float depthDiff = abs(depth - centerDepth) * SHARPNESS; + float weight = exp2(-x * x * blurFalloff - depthDiff * depthDiff); + totalWeight += weight; + result += texture(u_Input, uv) * weight; + } + + for (int y = -2; y < 2; ++y) + { + vec2 offset = vec2(float(0), float(y)) * texelSize; + + vec2 uv = UV + offset; + float depth = texture(u_Depth, uv).r; + + const float blurSigma = float(KERNEL_RADIUS) * 0.5f; + const float blurFalloff = 1.0 / (2.0 * blurSigma * blurSigma); + + float depthDiff = abs(depth - centerDepth) * SHARPNESS; + float weight = exp2(-y * y * blurFalloff - depthDiff * depthDiff); + totalWeight += weight; + result += texture(u_Input, uv) * weight; + } + + FragColor = result / totalWeight; +} \ No newline at end of file diff --git a/Editor/resources/Shaders/volumetric.shader b/Editor/resources/Shaders/volumetric.shader index 941bd7bf..b005ee52 100644 --- a/Editor/resources/Shaders/volumetric.shader +++ b/Editor/resources/Shaders/volumetric.shader @@ -22,6 +22,11 @@ void main() #shader fragment #version 460 core +float ditherPattern[4][4] = { { 0.0f, 0.5f, 0.125f, 0.625f}, +{ 0.75f, 0.22f, 0.875f, 0.375f}, +{ 0.1875f, 0.6875f, 0.0625f, 0.5625}, +{ 0.9375f, 0.4375f, 0.8125f, 0.3125} }; + in mat4 InvView; in mat4 InvProjection; @@ -52,7 +57,7 @@ const float PI = 3.141592653589793f; // Mie scaterring approximated with Henyey-Greenstein phase function. float ComputeScattering(float lightDotView) { - float result = 1.0f - u_FogAmount * u_FogAmount; + float result = 1.0f - u_FogAmount ; result /= (4.0f * PI * pow(1.0f + u_FogAmount * u_FogAmount - (2.0f * u_FogAmount) * lightDotView, 1.5f)); return result; } @@ -64,7 +69,7 @@ vec3 ComputeVolumetric(vec3 FragPos, Light light) float rayLength = length(rayVector); // Length of the raymarched //if(rayLength > 1000.0) - // return vec3(0.0, 0.0, 0.0); + // return vec3(1.0, 1.0, 1.0); float stepLength = rayLength / u_StepCount; // Step length vec3 rayDirection = rayVector / rayLength; vec3 step = rayDirection * stepLength; // Normalized to step length direction @@ -91,12 +96,12 @@ vec3 ComputeVolumetric(vec3 FragPos, Light light) //accumFog = vec3(projCoords.x, projCoords.y, 1.0); } - currentPosition += step; //* ditherPattern[int(gl_FragCoord.x) % 4][int(gl_FragCoord.y) % 4]; + currentPosition += step * ditherPattern[int(gl_FragCoord.x) % 4][int(gl_FragCoord.y) % 4]; //accumFog = vec3(projCoords); } accumFog /= u_StepCount; - return accumFog * 5.0; + return accumFog * 4.0; } // Converts depth to World space coords. @@ -125,7 +130,7 @@ void main() fog += ComputeVolumetric(globalFragmentPosition, u_Lights[i]); } - FragColor = vec4(fog, 1.0f); + FragColor = vec4(fog, 1.0); //FragColor = vec4(mix(fog, ComputeVolumetric(globalFragmentPosition, u_Lights[0]), 0.9f), 0.01); //FragColor = vec4(globalFragmentPosition * 10.0, 1.0f); //FragColor = vec4(globalFragmentPosition.xyz * 100.0, 1.0f); diff --git a/Nuake/src/Rendering/PostFX/Volumetric.cpp b/Nuake/src/Rendering/PostFX/Volumetric.cpp index bbf043c9..ed851b15 100644 --- a/Nuake/src/Rendering/PostFX/Volumetric.cpp +++ b/Nuake/src/Rendering/PostFX/Volumetric.cpp @@ -20,6 +20,9 @@ namespace Nuake { { mFinalFramebuffer = CreateScope(true, mSize); mFinalFramebuffer->SetTexture(CreateRef(mSize, GL_RGBA, GL_RGBA16F, GL_FLOAT)); + + mVolumetricFramebuffer = CreateScope(true, mSize); + mVolumetricFramebuffer->SetTexture(CreateRef(mSize, GL_RGBA, GL_RGBA16F, GL_FLOAT)); } void Volumetric::Resize(Vector2 size) @@ -28,14 +31,15 @@ namespace Nuake { return; mSize = size * mRenderRatio; - mFinalFramebuffer->QueueResize(mSize); + mVolumetricFramebuffer->QueueResize(mSize); + mVolumetricFramebuffer->QueueResize(mSize); } void Volumetric::Draw(Matrix4 projection, Matrix4 view, const Vector3& camPos, std::vector& lights) { - mFinalFramebuffer->Bind(); - - mFinalFramebuffer->Clear(); + mVolumetricFramebuffer->Bind(); + { + mVolumetricFramebuffer->Clear(); RenderCommand::Disable(RendererEnum::FACE_CULL); auto cameraPosition = Vector3(view[3]); @@ -62,17 +66,30 @@ namespace Nuake { volumetricShader->SetUniform1f(u_light + "strength", light.Strength); } + Renderer::DrawQuad(); + } + mVolumetricFramebuffer->Unbind(); + + // Blur + mFinalFramebuffer->Bind(); + { + mFinalFramebuffer->Clear(); + Shader* blurShader = ShaderManager::GetShader("resources/Shaders/blur.shader"); + blurShader->Bind(); + //blurShader->SetUniformTex("u_Depth", mDepth, 1); + blurShader->SetUniformTex("u_Input", mVolumetricFramebuffer->GetTexture().get()); Renderer::DrawQuad(); - + } mFinalFramebuffer->Unbind(); - /* if (ImGui::Begin("Volumetric debug")) { ImGui::Image((void*)(uintptr_t)(mFinalFramebuffer->GetTexture()->GetID()), ImGui::GetContentRegionAvail(), ImVec2(0, 1), ImVec2(1, 0)); } ImGui::End(); + + /* if (ImGui::Begin("Volumetric debug depth")) { ImGui::Image((void*)(uintptr_t)(mDepth->GetID()), ImGui::GetContentRegionAvail(), ImVec2(0, 1), ImVec2(1, 0)); diff --git a/Nuake/src/Rendering/PostFX/Volumetric.h b/Nuake/src/Rendering/PostFX/Volumetric.h index 2ded3bae..9b366ae7 100644 --- a/Nuake/src/Rendering/PostFX/Volumetric.h +++ b/Nuake/src/Rendering/PostFX/Volumetric.h @@ -10,11 +10,13 @@ namespace Nuake { { private: uint32_t mStepCount = 50; - float mRenderRatio = 1.0f; + float mRenderRatio = 0.75f; float mFogAmount = 0.4f; Vector2 mSize; Texture* mDepth; + + Scope mVolumetricFramebuffer; Scope mFinalFramebuffer; public: