From 443d6dfacb1716d45ae8a03bd1a8e7987cb209fa Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Mon, 25 Sep 2017 14:24:40 +0200 Subject: [PATCH] Added user definable taps in blur task --- libraries/render/src/render/BlurTask.cpp | 56 ++++++++++++- libraries/render/src/render/BlurTask.h | 11 ++- libraries/render/src/render/BlurTask.slh | 83 ++++++++----------- .../render/src/render/BlurTask_shared.slh | 10 +++ 4 files changed, 107 insertions(+), 53 deletions(-) create mode 100644 libraries/render/src/render/BlurTask_shared.slh diff --git a/libraries/render/src/render/BlurTask.cpp b/libraries/render/src/render/BlurTask.cpp index 73a8e0a0dd..2d51fd1271 100644 --- a/libraries/render/src/render/BlurTask.cpp +++ b/libraries/render/src/render/BlurTask.cpp @@ -29,11 +29,10 @@ enum BlurShaderMapSlots { BlurTask_DepthSlot, }; -const float BLUR_NUM_SAMPLES = 7.0f; - BlurParams::BlurParams() { Params params; _parametersBuffer = gpu::BufferView(std::make_shared(sizeof(Params), (const gpu::Byte*) ¶ms)); + setGaussianFilterTaps(3); } void BlurParams::setWidthHeight(int width, int height, bool isStereo) { @@ -60,7 +59,58 @@ void BlurParams::setFilterRadiusScale(float scale) { auto filterInfo = _parametersBuffer.get().filterInfo; if (scale != filterInfo.x) { _parametersBuffer.edit().filterInfo.x = scale; - _parametersBuffer.edit().filterInfo.y = scale / BLUR_NUM_SAMPLES; + } +} + +void BlurParams::setFilterNumTaps(int count) { + assert(count <= BLUR_MAX_NUM_TAPS); + auto filterInfo = _parametersBuffer.get().filterInfo; + if (count != (int)filterInfo.y) { + _parametersBuffer.edit().filterInfo.y = count; + } +} + +void BlurParams::setFilterTap(int index, float offset, float value) { + auto filterTaps = _parametersBuffer.edit().filterTaps; + assert(index < BLUR_MAX_NUM_TAPS); + filterTaps[index].x = offset; + filterTaps[index].y = value; +} + +void BlurParams::setGaussianFilterTaps(int numHalfTaps, float sigma, bool normalize) { + auto& params = _parametersBuffer.edit(); + const int numTaps = 2 * numHalfTaps + 1; + assert(numTaps <= BLUR_MAX_NUM_TAPS); + assert(sigma > 0.0f); + const float inverseTwoSigmaSquared = float(0.5 / (sigma*sigma)); + float totalWeight = 1.0f; + float weight; + float offset; + int i; + + params.filterInfo.y = numTaps; + params.filterTaps[0].x = 0.0f; + params.filterTaps[0].y = 1.0f; + + for (i = 0; i < numHalfTaps; i++) { + offset = i + 1; + weight = (float)exp(-offset*offset * inverseTwoSigmaSquared); + params.filterTaps[i + 1].x = offset; + params.filterTaps[i + 1].y = weight; + params.filterTaps[i + 1 + numHalfTaps].x = -offset; + params.filterTaps[i + 1 + numHalfTaps].y = weight; + totalWeight += 2 * weight; + } + + float normalizer; + if (normalize) { + normalizer = float(1.0 / totalWeight); + } else { + normalizer = float(1.0 / (sqrt(2 * M_PI)*sigma)); + } + + for (i = 0; i < numTaps; i++) { + params.filterTaps[i].y *= normalizer; } } diff --git a/libraries/render/src/render/BlurTask.h b/libraries/render/src/render/BlurTask.h index f023aabfe7..011da6ab68 100644 --- a/libraries/render/src/render/BlurTask.h +++ b/libraries/render/src/render/BlurTask.h @@ -14,6 +14,8 @@ #include "Engine.h" +#include "BlurTask_shared.slh" + namespace render { @@ -25,6 +27,10 @@ public: void setTexcoordTransform(const glm::vec4 texcoordTransformViewport); void setFilterRadiusScale(float scale); + void setFilterNumTaps(int count); + // Tap 0 is considered the center of the kernel + void setFilterTap(int index, float offset, float value); + void setGaussianFilterTaps(int numHalfTaps, float sigma = 1.47f, bool normalize = true); void setDepthPerspective(float oneOverTan2FOV); void setDepthThreshold(float threshold); @@ -40,7 +46,7 @@ public: // Viewport to Texcoord info, if the region of the blur (viewport) is smaller than the full frame glm::vec4 texcoordTransform{ 0.0f, 0.0f, 1.0f, 1.0f }; - // Filter info (radius scale + // Filter info (radius scale, number of taps, mix) glm::vec4 filterInfo{ 1.0f, 0.0f, 0.0f, 0.0f }; // Depth info (radius scale @@ -52,6 +58,9 @@ public: // LinearDepth info is { f } glm::vec4 linearDepthInfo{ 0.0f }; + // Taps (offset, weight) + glm::vec2 filterTaps[BLUR_MAX_NUM_TAPS]; + Params() {} }; gpu::BufferView _parametersBuffer; diff --git a/libraries/render/src/render/BlurTask.slh b/libraries/render/src/render/BlurTask.slh index de2614eb51..b871b59bed 100644 --- a/libraries/render/src/render/BlurTask.slh +++ b/libraries/render/src/render/BlurTask.slh @@ -9,17 +9,7 @@ <@func declareBlurUniforms()@> -#define NUM_TAPS 7 -#define NUM_TAPS_OFFSET 3.0f - -float uniformFilterWidth = 0.05f; - -const float gaussianDistributionCurve[NUM_TAPS] = float[]( - 0.383f, 0.006f, 0.061f, 0.242f, 0.242f, 0.061f, 0.006f -); -const float gaussianDistributionOffset[NUM_TAPS] = float[]( - 0.0f, -3.0f, -2.0f, -1.0f, 1.0f, 2.0f, 3.0f -); +<@include BlurTask_shared.slh@> struct BlurParameters { vec4 resolutionInfo; @@ -28,6 +18,7 @@ struct BlurParameters { vec4 depthInfo; vec4 stereoInfo; vec4 linearDepthInfo; + vec2 taps[BLUR_MAX_NUM_TAPS]; }; uniform blurParamsBuffer { @@ -46,6 +37,25 @@ float getFilterScale() { return parameters.filterInfo.x; } +int getFilterNumTaps() { + return int(parameters.filterInfo.y); +} + +float getFilterMix() { + return parameters.filterInfo.z; +} + +vec2 getFilterTap(int index) { + return parameters.taps[index]; +} + +float getFilterTapOffset(vec2 tap) { + return tap.x; +} + +float getFilterTapWeight(vec2 tap) { + return tap.y; +} float getDepthThreshold() { return parameters.depthInfo.x; @@ -70,17 +80,18 @@ uniform sampler2D sourceMap; vec4 pixelShaderGaussian(vec2 texcoord, vec2 direction, vec2 pixelStep) { texcoord = evalTexcoordTransformed(texcoord); - vec4 sampleCenter = texture(sourceMap, texcoord); vec2 finalStep = getFilterScale() * direction * pixelStep; vec4 srcBlurred = vec4(0.0); + int numTaps = getFilterNumTaps(); - for(int i = 0; i < NUM_TAPS; i++) { + for(int i = 0; i < numTaps; i++) { + vec2 tapInfo = getFilterTap(i); // Fetch color and depth for current sample. - vec2 sampleCoord = texcoord + (gaussianDistributionOffset[i] * finalStep); + vec2 sampleCoord = texcoord + (getFilterTapOffset(tapInfo) * finalStep); vec4 srcSample = texture(sourceMap, sampleCoord); // Accumulate. - srcBlurred += gaussianDistributionCurve[i] * srcSample; + srcBlurred += getFilterTapWeight(tapInfo) * srcSample; } return srcBlurred; @@ -95,15 +106,6 @@ vec4 pixelShaderGaussian(vec2 texcoord, vec2 direction, vec2 pixelStep) { uniform sampler2D sourceMap; uniform sampler2D depthMap; -#define NUM_HALF_TAPS 4 - -const float gaussianDistributionCurveHalf[NUM_HALF_TAPS] = float[]( - 0.383f, 0.242f, 0.061f, 0.006f -); -const float gaussianDistributionOffsetHalf[NUM_HALF_TAPS] = float[]( - 0.0f, 1.0f, 2.0f, 3.0f -); - vec4 pixelShaderGaussianDepthAware(vec2 texcoord, vec2 direction, vec2 pixelStep) { texcoord = evalTexcoordTransformed(texcoord); float sampleDepth = texture(depthMap, texcoord).x; @@ -122,13 +124,17 @@ vec4 pixelShaderGaussianDepthAware(vec2 texcoord, vec2 direction, vec2 pixelStep float scale = distanceToProjectionWindow / sampleDepth; vec2 finalStep = filterScale * scale * direction * pixelStep; + int numTaps = getFilterNumTaps(); // Accumulate the center sample - vec4 srcBlurred = gaussianDistributionCurve[0] * sampleCenter; + vec2 tapInfo = getFilterTap(0); + vec4 srcBlurred = getFilterTapWeight(tapInfo) * sampleCenter; + + for(int i = 1; i < numTaps; i++) { + tapInfo = getFilterTap(i); - for(int i = 1; i < NUM_TAPS; i++) { // Fetch color and depth for current sample. - vec2 sampleCoord = texcoord + (gaussianDistributionOffset[i] * finalStep); + vec2 sampleCoord = texcoord + (getFilterTapOffset(tapInfo) * finalStep); float srcDepth = texture(depthMap, sampleCoord).x; vec4 srcSample = texture(sourceMap, sampleCoord); @@ -137,29 +143,8 @@ vec4 pixelShaderGaussianDepthAware(vec2 texcoord, vec2 direction, vec2 pixelStep srcSample = mix(srcSample, sampleCenter, s); // Accumulate. - srcBlurred += gaussianDistributionCurve[i] * srcSample; + srcBlurred += getFilterTapWeight(tapInfo) * srcSample; } - - /* - for(int i = 1; i < NUM_HALF_TAPS; i++) { - // Fetch color and depth for current sample. - vec2 texcoordOffset = (gaussianDistributionOffsetHalf[i] * finalStep); - - float srcDepthN = texture(depthMap, texcoord - texcoordOffset).x; - float srcDepthP = texture(depthMap, texcoord + texcoordOffset).x; - vec4 srcSampleN = texture(sourceMap, texcoord - texcoordOffset); - vec4 srcSampleP = texture(sourceMap, texcoord + texcoordOffset); - - // If the difference in depth is huge, we lerp color back. - float sN = clamp(depthThreshold * distanceToProjectionWindow * filterScale * abs(srcDepthN - sampleDepth), 0.0, 1.0); - float sP = clamp(depthThreshold * distanceToProjectionWindow * filterScale * abs(srcDepthP - sampleDepth), 0.0, 1.0); - - srcSampleN = mix(srcSampleN, sampleCenter, sN); - srcSampleP = mix(srcSampleP, sampleCenter, sP); - - // Accumulate. - srcBlurred += gaussianDistributionCurveHalf[i] * (srcSampleP + srcSampleN); - }*/ return srcBlurred; } diff --git a/libraries/render/src/render/BlurTask_shared.slh b/libraries/render/src/render/BlurTask_shared.slh new file mode 100644 index 0000000000..94417fa939 --- /dev/null +++ b/libraries/render/src/render/BlurTask_shared.slh @@ -0,0 +1,10 @@ +// Generated on <$_SCRIBE_DATE$> +// +// Created by Olivier Prat on 09/25/17. +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#define BLUR_MAX_NUM_TAPS 21