From 4b7c75b493aa51bd9ad2182c9c3e2d01878796e6 Mon Sep 17 00:00:00 2001 From: Antoine Pilote Date: Wed, 2 Aug 2023 22:00:17 -0400 Subject: [PATCH] Better SSAO --- Editor/resources/Shaders/ssao.shader | 79 ++++++++++++++++----------- Nuake/src/Rendering/PostFX/SSAO.cpp | 4 +- Nuake/src/Rendering/PostFX/SSAO.h | 6 +- Nuake/src/Rendering/SceneRenderer.cpp | 2 - 4 files changed, 51 insertions(+), 40 deletions(-) diff --git a/Editor/resources/Shaders/ssao.shader b/Editor/resources/Shaders/ssao.shader index 85a48f63..59132ca8 100644 --- a/Editor/resources/Shaders/ssao.shader +++ b/Editor/resources/Shaders/ssao.shader @@ -8,6 +8,7 @@ out flat vec2 UV; out mat4 v_InvView; out mat4 v_InvProjection; out mat4 v_View; +out mat4 v_Projection; uniform mat4 u_View; uniform mat4 u_Projection; @@ -15,6 +16,7 @@ uniform mat4 u_Projection; void main() { v_View = u_View; + v_Projection = u_Projection; v_InvView = inverse(u_View); v_InvProjection = inverse(u_Projection); @@ -28,7 +30,6 @@ void main() uniform sampler2D u_Depth; uniform sampler2D u_Normal; uniform sampler2D u_Noise; - uniform int u_KernelSize = 64; uniform vec3 u_Samples[64]; @@ -39,13 +40,20 @@ uniform float u_Bias = 0.025f; uniform float u_Falloff = 0.0022; uniform float u_Area = 0.0075; uniform float u_Strength = 2.0f; + in vec2 UV; in mat4 v_View; in mat4 v_InvView; in mat4 v_InvProjection; +in mat4 v_Projection; out vec4 FragColor; +float linearize_depth(float d, float zNear, float zFar) +{ + return zNear * zFar / (zFar + d * (zNear - zFar)); +} + vec3 WorldPosFromDepth(float depth) { float z = depth * 2.0 - 1.0; @@ -91,46 +99,51 @@ vec3 normal_from_depth(float depth, vec2 texcoords) { void main() { - float depth = texture(u_Depth, UV).r ; - vec3 fragPos = ViewPosFromDepth(depth); - float normalizedRadius = u_Radius; - if(depth > 0.9999999f) + float depth = texture(u_Depth, UV).r; + if (depth > 0.9999999f ) { FragColor = vec4(0, 0, 0, 0); return; } - vec3 goodNormal = normal_from_depth(depth, UV); - vec3 normal = texture(u_Normal, UV).rgb * 2.0 - 1.0; - vec4 normalT = v_View * vec4(normal, 1.0); - normalT *= -1.0f; - normal = normalT.xyz; - normal = normalize(normal); - normal = goodNormal; - vec3 randomVec = texture(u_Noise, UV * u_NoiseScale).xyz; - float radius_depth = normalizedRadius / depth; + + const float SCALING_NEAR = 0.9; + float depthScaler = (depth - SCALING_NEAR) * 1.0 / (1.0 - SCALING_NEAR); + depthScaler = min(max(depthScaler, 0.0), 1.0); + float scaledRadius = u_Radius * depthScaler; + + vec3 fragPos = ViewPosFromDepth(depth); + vec3 normal = texture(u_Normal, UV).xyz * 2.0 - 1.0;//normal_from_depth(depth, UV); + normal.z *= -1.0f; + // Remove translation from view; + mat4 invView = v_InvView; + invView[3] = vec4(0, 0, 0, 1); + + normal = (invView * vec4(normal, 1.0f)).xyz; + vec3 randomVec = texture(u_Noise, UV * u_NoiseScale).xyz; + + vec3 tangent = normalize(randomVec - normal * dot(randomVec, normal)); + vec3 bitangent = cross(normal, tangent); + mat3 TBN = mat3(tangent, bitangent, normal); + float occlusion = 0.0; - vec3 position = vec3(UV, depth); - - int skipped = 0; - float rangeCheckC = 0.0f; - for(int i=0; i < 64; i++) + for(int i= 0; i < 64; i++) { - vec3 ray = u_Radius * reflect(u_Samples[i], randomVec); - vec3 hemi_ray = position + sign(dot(ray, normal)) * ray; - - float sampleDepth = texture(u_Depth, hemi_ray.xy).r; - float rangeCheck = smoothstep(0.0, 1.0, u_Radius * 0.8 / abs(depth - sampleDepth)); - float ao = hemi_ray.z >= sampleDepth + u_Bias ? 1.0 : 0.0; - occlusion += ao * rangeCheck; - rangeCheckC += rangeCheck; + vec3 samplePos = TBN * u_Samples[i]; // generate a random point + samplePos.z *= -1.0f; + samplePos = fragPos + samplePos * scaledRadius; + + vec4 offset = vec4(samplePos, 1.0); // make it a 4-vector + offset = v_Projection * offset; // project on the near clipping plane + offset.xyz /= offset.w; // perform perspective divide + offset.xyz = offset.xyz * 0.5 + 0.5; // transform to (0,1) range + float sampleDepth = texture(u_Depth, offset.xy).r; + float rangeCheck = smoothstep(0.0, 1.0, scaledRadius / abs((samplePos.z) - sampleDepth)); + occlusion += (sampleDepth <= depth - u_Bias / 100.0 ? 1.0 : 0.0) * rangeCheck; } - + float ao = 1.0 - (occlusion / 64.0); - rangeCheckC /= 64.0; - float finalAO = pow(ao, u_Strength); + float finalAO = pow(ao, u_Strength * 100.0); FragColor = vec4(finalAO, finalAO, finalAO, 1.0); - //FragColor = vec4(rangeCheckC, rangeCheckC, rangeCheckC, 1.0); - - //FragColor = vec4(1.0, 1.0, 1.0, 1.0); + //FragColor = vec4(samplePos.z, samplePos.z, samplePos.z, 1.0); } \ No newline at end of file diff --git a/Nuake/src/Rendering/PostFX/SSAO.cpp b/Nuake/src/Rendering/PostFX/SSAO.cpp index 02a75aaf..18d22228 100644 --- a/Nuake/src/Rendering/PostFX/SSAO.cpp +++ b/Nuake/src/Rendering/PostFX/SSAO.cpp @@ -130,13 +130,13 @@ namespace Nuake } _ssaoBlurFramebuffer->Unbind(); - /* + if (ImGui::Begin("SSAO debug")) { ImGui::Image((void*)(uintptr_t)(_ssaoFramebuffer->GetTexture(GL_COLOR_ATTACHMENT0)->GetID()), ImGui::GetContentRegionAvail(), ImVec2(0, 1), ImVec2(1, 0)); } ImGui::End(); - */ + } Ref SSAO::GetOuput() const diff --git a/Nuake/src/Rendering/PostFX/SSAO.h b/Nuake/src/Rendering/PostFX/SSAO.h index 2dd6dece..5c37cc4a 100644 --- a/Nuake/src/Rendering/PostFX/SSAO.h +++ b/Nuake/src/Rendering/PostFX/SSAO.h @@ -27,11 +27,11 @@ namespace Nuake } public: - float Radius = 0.060f; - float Bias = 0.00125f; + float Radius = 0.997f; + float Bias = 0.045f; float Area = 0.0075f; float Falloff = 0.002f; - float Strength = 0.5f; + float Strength = 0.2f; void Resize(const Vector2& size); SSAO(); void Draw(FrameBuffer* gBuffer, const Matrix4& projection, const Matrix4& view); diff --git a/Nuake/src/Rendering/SceneRenderer.cpp b/Nuake/src/Rendering/SceneRenderer.cpp index db19889a..05819caa 100644 --- a/Nuake/src/Rendering/SceneRenderer.cpp +++ b/Nuake/src/Rendering/SceneRenderer.cpp @@ -144,8 +144,6 @@ namespace Nuake } framebuffer.Unbind(); - - RenderCommand::Enable(RendererEnum::DEPTH_TEST); Renderer::EndDraw(); }