Added user definable taps in blur task

This commit is contained in:
Olivier Prat 2017-09-25 14:24:40 +02:00
parent bcec3680b6
commit 443d6dfacb
4 changed files with 107 additions and 53 deletions

View file

@ -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<gpu::Buffer>(sizeof(Params), (const gpu::Byte*) &params));
setGaussianFilterTaps(3);
}
void BlurParams::setWidthHeight(int width, int height, bool isStereo) {
@ -60,7 +59,58 @@ void BlurParams::setFilterRadiusScale(float scale) {
auto filterInfo = _parametersBuffer.get<Params>().filterInfo;
if (scale != filterInfo.x) {
_parametersBuffer.edit<Params>().filterInfo.x = scale;
_parametersBuffer.edit<Params>().filterInfo.y = scale / BLUR_NUM_SAMPLES;
}
}
void BlurParams::setFilterNumTaps(int count) {
assert(count <= BLUR_MAX_NUM_TAPS);
auto filterInfo = _parametersBuffer.get<Params>().filterInfo;
if (count != (int)filterInfo.y) {
_parametersBuffer.edit<Params>().filterInfo.y = count;
}
}
void BlurParams::setFilterTap(int index, float offset, float value) {
auto filterTaps = _parametersBuffer.edit<Params>().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<Params>();
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;
}
}

View file

@ -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;

View file

@ -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;
}

View file

@ -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