From 3de1e197aacb0f3016472863b2e4e2f1480cde2e Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Wed, 12 Feb 2020 18:26:44 -0800 Subject: [PATCH] improve SSrefr highlights at low roughness We untonemap/tonemap the first level of blur to reduce the very high frequencies due to HDR highlights in the image, this produce a softer image at higher roughness. This can programmatically be turned off, but that setting is not exposed. --- filament/src/PostProcessManager.cpp | 8 ++-- filament/src/PostProcessManager.h | 4 +- filament/src/Renderer.cpp | 2 +- .../src/materials/separableGaussianBlur.mat | 38 +++++++++++++++---- 4 files changed, 39 insertions(+), 13 deletions(-) diff --git a/filament/src/PostProcessManager.cpp b/filament/src/PostProcessManager.cpp index cdd91a194e..c296b3b6d6 100644 --- a/filament/src/PostProcessManager.cpp +++ b/filament/src/PostProcessManager.cpp @@ -729,9 +729,10 @@ FrameGraphId PostProcessManager::bilateralBlurPass(FrameGraph FrameGraphId PostProcessManager::generateGaussianMipmap(FrameGraph& fg, FrameGraphId input, size_t roughnessLodCount, - size_t kernelWidth, float sigmaRatio) noexcept { + bool reinhard, size_t kernelWidth, float sigmaRatio) noexcept { for (size_t i = 1; i < roughnessLodCount; i++) { - input = gaussianBlurPass(fg, input, i - 1, input, i, kernelWidth, sigmaRatio); + input = gaussianBlurPass(fg, input, i - 1, input, i, reinhard, kernelWidth, sigmaRatio); + reinhard = false; // only do the reinhard filtering on the first level } return input; } @@ -739,7 +740,7 @@ FrameGraphId PostProcessManager::generateGaussianMipmap(Frame FrameGraphId PostProcessManager::gaussianBlurPass(FrameGraph& fg, FrameGraphId input, uint8_t srcLevel, FrameGraphId output, uint8_t dstLevel, - size_t kernelWidth, float sigmaRatio) noexcept { + bool reinhard, size_t kernelWidth, float sigmaRatio) noexcept { const float sigma = (kernelWidth + 1) / sigmaRatio; @@ -849,6 +850,7 @@ FrameGraphId PostProcessManager::gaussianBlurPass(FrameGraph& .filterMin = SamplerMinFilter::LINEAR_MIPMAP_NEAREST }); mi->setParameter("level", (float)srcLevel); + mi->setParameter("reinhard", reinhard ? uint32_t(1) : uint32_t(0)); mi->setParameter("resolution", float4{ tempDesc.width, tempDesc.height, 1.0f / tempDesc.width, 1.0f / tempDesc.height }); diff --git a/filament/src/PostProcessManager.h b/filament/src/PostProcessManager.h index 1be3f068db..43401c8514 100644 --- a/filament/src/PostProcessManager.h +++ b/filament/src/PostProcessManager.h @@ -69,13 +69,13 @@ public: View::AmbientOcclusionOptions const& options) noexcept; FrameGraphId generateGaussianMipmap(FrameGraph& fg, - FrameGraphId input, size_t roughnessLodCount, + FrameGraphId input, size_t roughnessLodCount, bool reinhard, size_t kernelWidth, float sigmaRatio = 6.0f) noexcept; FrameGraphId gaussianBlurPass(FrameGraph& fg, FrameGraphId input, uint8_t srcLevel, FrameGraphId output, uint8_t dstLevel, - size_t kernelWidth, float sigma = 6.0f) noexcept; + bool reinhard, size_t kernelWidth, float sigma = 6.0f) noexcept; backend::Handle getNoSSAOTexture() const { return mNoSSAOTexture; diff --git a/filament/src/Renderer.cpp b/filament/src/Renderer.cpp index ab083d5fee..9b5e9e3195 100644 --- a/filament/src/Renderer.cpp +++ b/filament/src/Renderer.cpp @@ -513,7 +513,7 @@ FrameGraphId FRenderer::refractionPass(FrameGraph& fg, .format = TextureFormat::R11F_G11F_B10F, }); - input = ppm.generateGaussianMipmap(fg, input, roughnessLodCount, kernelSize); + input = ppm.generateGaussianMipmap(fg, input, roughnessLodCount, true, kernelSize); struct PrepareSSRData { FrameGraphId ssr; diff --git a/filament/src/materials/separableGaussianBlur.mat b/filament/src/materials/separableGaussianBlur.mat index f02fb2b0b7..d82aafab06 100644 --- a/filament/src/materials/separableGaussianBlur.mat +++ b/filament/src/materials/separableGaussianBlur.mat @@ -23,6 +23,10 @@ material { type : int, name : count }, + { + type : int, + name : reinhard + }, { type : float2[32], name : kernel @@ -51,19 +55,39 @@ fragment { sum += s * weight; } + void tapReinhard(inout vec3 sum, inout float totalWeight, float weight, highp vec2 position) { + vec3 s = textureLod(materialParams_source, position, materialParams.level).rgb; + float w = weight / (1.0 + max3(s)); + totalWeight += w; + sum += s * w; + } + void postProcess(inout PostProcessInputs postProcess) { highp vec2 uv = variable_vertex.xy; // we handle the center pixel separately vec3 sum = vec3(0); - tap(sum, materialParams.kernel[0].x, uv); - vec2 offset = materialParams.axis; - for (int i = 1; i < materialParams.count; i++, offset += materialParams.axis * 2.0) { - float k = materialParams.kernel[i].x; - vec2 o = offset + materialParams.axis * materialParams.kernel[i].y; - tap(sum, k, uv + o); - tap(sum, k, uv - o); + if (materialParams.reinhard != 0) { + float totalWeight = 0.0; + tapReinhard(sum, totalWeight, materialParams.kernel[0].x, uv); + vec2 offset = materialParams.axis; + for (int i = 1; i < materialParams.count; i++, offset += materialParams.axis * 2.0) { + float k = materialParams.kernel[i].x; + vec2 o = offset + materialParams.axis * materialParams.kernel[i].y; + tapReinhard(sum, totalWeight, k, uv + o); + tapReinhard(sum, totalWeight, k, uv - o); + } + sum *= 1.0 / totalWeight; + } else { + tap(sum, materialParams.kernel[0].x, uv); + vec2 offset = materialParams.axis; + for (int i = 1; i < materialParams.count; i++, offset += materialParams.axis * 2.0) { + float k = materialParams.kernel[i].x; + vec2 o = offset + materialParams.axis * materialParams.kernel[i].y; + tap(sum, k, uv + o); + tap(sum, k, uv - o); + } } postProcess.color.rgb = sum;