diff --git a/data/shader/deferred/indirect.csh b/data/shader/deferred/indirect.csh index 25b02874b..bbdf7cf5a 100644 --- a/data/shader/deferred/indirect.csh +++ b/data/shader/deferred/indirect.csh @@ -90,6 +90,8 @@ float UpsampleAo2x(float referenceDepth) { float invocationDepths[9]; + referenceDepth = ConvertDepthToViewSpaceDepth(referenceDepth); + for (uint i = 0; i < 9; i++) { int sharedMemoryOffset = Flatten2D(pixel + offsets[i], unflattenedDepthDataSize); invocationDepths[i] = depths[sharedMemoryOffset]; @@ -222,19 +224,24 @@ void main() { indirectSpecular *= EvaluateIndirectSpecularBRDF(surface); indirect = (indirectDiffuse + indirectSpecular) * surface.material.ao; +#ifdef SSGI + vec4 ssgi = UpsampleGi2x(depth, texCoord); +#endif + // This normally only accounts for diffuse occlusion, we need seperate terms // for diffuse and specular. #ifdef AO float occlusionFactor = Uniforms.aoEnabled > 0 ? Uniforms.aoDownsampled2x > 0 ? UpsampleAo2x(depth) : texture(aoTexture, texCoord).r : 1.0; -#ifdef SSGI - vec4 ssgi = UpsampleGi2x(depth, texCoord); - occlusionFactor = ssgi.a; -#endif + indirect *= vec3(pow(occlusionFactor, Uniforms.aoStrength)); +#endif #ifdef SSGI - indirect += EvaluateIndirectDiffuseBRDF(surface) * ssgi.rgb; + // Only apply SSGI ao if normal AO is turned off +#ifndef AO + indirect *= vec3(pow(ssgi.a, Uniforms.aoStrength)); #endif + indirect += EvaluateIndirectDiffuseBRDF(surface) * ssgi.rgb; #endif } diff --git a/data/shader/reflection/temporal.csh b/data/shader/reflection/temporal.csh index 5480747f3..06bcba7b8 100644 --- a/data/shader/reflection/temporal.csh +++ b/data/shader/reflection/temporal.csh @@ -1,3 +1,5 @@ +//#define BICUBIC_FILTER + #include <../common/utility.hsh> #include <../common/convert.hsh> #include <../common/PI.hsh> @@ -221,12 +223,37 @@ bool SampleHistory(ivec2 pixel, vec2 historyPixel, out vec4 history, out vec4 hi } -void SampleCatmullRom(ivec2 pixel, vec2 uv, out vec4 history) { +float IsHistoryPixelValid(ivec2 pixel, float linearDepth, vec3 normal) { + + float confidence = 1.0; + + vec3 historyNormal = DecodeNormal(texelFetch(historyNormalTexture, pixel, 0).rg); + confidence *= pow(abs(dot(historyNormal, normal)), 16.0); + + float depthPhi = max(1.0, abs(0.25 * linearDepth)); + float historyDepth = texelFetch(historyDepthTexture, pixel, 0).r; + float historyLinearDepth = historyDepth; + confidence *= min(1.0 , exp(-abs(linearDepth - historyLinearDepth))); + + return confidence > 0.1 ? 1.0 : 0.0; + +} + +vec4 GetCatmullRomSample(ivec2 pixel, inout float weight, float linearDepth, vec3 normal) { + + pixel = clamp(pixel, ivec2(0), ivec2(imageSize(resolveImage) - 1)); + + weight *= IsHistoryPixelValid(pixel, linearDepth, normal); + + return texelFetch(historyTexture, pixel, 0) * weight; + +} + +bool SampleCatmullRom(ivec2 pixel, vec2 uv, out vec4 history) { + + vec3 normal = DecodeNormal(texelFetch(normalTexture, pixel, 0).rg); + float depth = texelFetch(depthTexture, pixel, 0).r; - // http://advances.realtimerendering.com/s2016/Filmic%20SMAA%20v7.pptx - // Credit: Jorge Jimenez (SIGGRAPH 2016) - // Ignores the 4 corners of the 4x4 grid - // Learn more: http://vec3.ca/bicubic-filtering-in-fewer-taps/ vec2 position = uv * resolution; vec2 center = floor(position - 0.5) + 0.5; @@ -239,45 +266,35 @@ void SampleCatmullRom(ivec2 pixel, vec2 uv, out vec4 history) { vec2 w3 = 0.5 * (f3 - f2); vec2 w2 = 1.0 - w0 - w1 - w3; - vec2 w12 = w1 + w2; - - vec2 tc0 = (center - 1.0) * invResolution; - vec2 tc12 = (center + w2 / w12) * invResolution; - vec2 tc3 = (center + 2.0) * invResolution; - - vec2 uv0 = clamp(vec2(tc12.x, tc0.y), vec2(0.0), vec2(1.0)) * resolution - vec2(0.5); - vec2 uv1 = clamp(vec2(tc0.x, tc12.y), vec2(0.0), vec2(1.0)) * resolution - vec2(0.5); - vec2 uv2 = clamp(vec2(tc12.x, tc12.y), vec2(0.0), vec2(1.0)) * resolution - vec2(0.5); - vec2 uv3 = clamp(vec2(tc3.x, tc12.y), vec2(0.0), vec2(1.0)) * resolution - vec2(0.5); - vec2 uv4 = clamp(vec2(tc12.x, tc3.y), vec2(0.0), vec2(1.0)) * resolution - vec2(0.5); + ivec2 uv0 = ivec2(center - 1.0); + ivec2 uv1 = ivec2(center); + ivec2 uv2 = ivec2(center + 1.0); + ivec2 uv3 = ivec2(center + 2.0); - float weight0 = w12.x * w0.y; - float weight1 = w0.x * w12.y; - float weight2 = w12.x * w12.y; - float weight3 = w3.x * w12.y; - float weight4 = w12.x * w3.y; - - vec4 sample0, sample1, sample2, sample3, sample4; - vec4 moments0, moments1, moments2, moments3, moments4; + ivec2 uvs[4] = { uv0, uv1, uv2, uv3 }; + vec2 weights[4] = { w0, w1, w2, w3 }; - SampleHistory(pixel, uv0, sample0, moments0); - SampleHistory(pixel, uv1, sample1, moments1); - SampleHistory(pixel, uv2, sample2, moments2); - SampleHistory(pixel, uv3, sample3, moments3); - SampleHistory(pixel, uv4, sample4, moments4); + history = vec4(0.0); - sample0 *= weight0; - sample1 *= weight1; - sample2 *= weight2; - sample3 *= weight3; - sample4 *= weight4; + float totalWeight = 0.0; - float totalWeight = weight0 + weight1 + - weight2 + weight3 + weight4; + for (int x = 0; x <= 3; x++) { + for (int y = 0; y <= 3; y++) { + float weight = weights[x].x * weights[y].y; + ivec2 uv = ivec2(uvs[x].x, uvs[y].y); - history = sample0 + sample1 + - sample2 + sample3 + sample4; + history += GetCatmullRomSample(uv, weight, depth, normal); + totalWeight += weight; + } + } + + if (totalWeight > 0.5) { + history /= totalWeight; + + return true; + } + return false; } void ComputeVarianceMinMax(out vec3 mean, out vec3 std) { @@ -341,7 +358,12 @@ void main() { vec4 historyMoments; valid = SampleHistory(pixel, historyPixel, history, historyMoments); - SampleCatmullRom(pixel, uv, history); +#ifdef BICUBIC_FILTER + // This should be implemented more efficiently, see + vec4 catmullRomHistory; + bool success = SampleCatmullRom(pixel, historyPixel, catmullRomHistory); + history = success && valid ? catmullRomHistory : history; +#endif vec3 historyColor = history.rgb; vec3 currentColor = texelFetch(currentTexture, pixel, 0).rgb; diff --git a/src/demo/App.cpp b/src/demo/App.cpp index 4aa1a184e..a609601fd 100644 --- a/src/demo/App.cpp +++ b/src/demo/App.cpp @@ -58,6 +58,8 @@ void App::LoadContent() { scene->ao = Atlas::CreateRef(16); scene->ao->rt = true; + // Use SSGI by default + scene->ao->enable = false; scene->reflection = Atlas::CreateRef(1); scene->reflection->useShadowMap = true; diff --git a/src/engine/graphics/GraphicsDevice.cpp b/src/engine/graphics/GraphicsDevice.cpp index 1124b7c23..2d0b33379 100644 --- a/src/engine/graphics/GraphicsDevice.cpp +++ b/src/engine/graphics/GraphicsDevice.cpp @@ -983,7 +983,7 @@ namespace Atlas { featureBuilder.Append(rtPipelineFeature); featureBuilder.Append(rayQueryFeature); - support.hardwareRayTracing = false; + support.hardwareRayTracing = true; } if (supportedExtensions.contains(VK_KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME)) { diff --git a/src/engine/renderer/IndirectLightRenderer.cpp b/src/engine/renderer/IndirectLightRenderer.cpp index f15fdf655..54d4c9cdd 100644 --- a/src/engine/renderer/IndirectLightRenderer.cpp +++ b/src/engine/renderer/IndirectLightRenderer.cpp @@ -30,10 +30,7 @@ namespace Atlas { auto reflectionEnabled = reflection && reflection->enable && rtDataValid; auto aoEnabled = ao && ao->enable && (!ao->rt || rtDataValid); auto ssgiEnabled = ssgi && ssgi->enable && (!ssgi->rt || rtDataValid); - - bool ssgiAo = ssgi && ssgi->enable && ssgi->enableAo; - aoEnabled |= ssgiAo; - + bool ssgiAo = ssgi && ssgi->enable && ssgi->enableAo; pipelineConfig.ManageMacro("DDGI", ddgiEnabled); pipelineConfig.ManageMacro("REFLECTION", reflectionEnabled); @@ -56,11 +53,11 @@ namespace Atlas { } auto uniforms = Uniforms{ - .aoEnabled = aoEnabled ? 1 : 0, + .aoEnabled = aoEnabled || ssgiAo ? 1 : 0, .aoDownsampled2x = ssgiAo ? target->GetGIResolution() == RenderResolution::HALF_RES : target->GetAOResolution() == RenderResolution::HALF_RES, .reflectionEnabled = reflectionEnabled ? 1 : 0, - .aoStrength = aoEnabled ? (ssgiAo ? ssgi->aoStrength / sqrt(ssgi->radius) : ao->strength) : 1.0f, + .aoStrength = aoEnabled || ssgiAo ? (aoEnabled ? ao->strength : ssgi->aoStrength / sqrt(ssgi->radius)) : 1.0f, .specularProbeMipLevels = int32_t(scene->sky.GetProbe() ? scene->sky.GetProbe()->cubemap.image->mipLevels : 1) }; uniformBuffer.SetData(&uniforms, 0);