Bilateral blur

This commit is contained in:
Olivier Prat 2018-09-12 17:59:57 +02:00
parent 6c0309402f
commit 45b4881edc
11 changed files with 251 additions and 99 deletions

View file

@ -41,7 +41,7 @@ gpu::PipelinePointer AmbientOcclusionEffect::_mipCreationPipeline;
AmbientOcclusionFramebuffer::AmbientOcclusionFramebuffer() {
}
void AmbientOcclusionFramebuffer::updateLinearDepth(const gpu::TexturePointer& linearDepthBuffer) {
bool AmbientOcclusionFramebuffer::updateLinearDepth(const gpu::TexturePointer& linearDepthBuffer) {
//If the depth buffer or size changed, we need to delete our FBOs
bool reset = false;
if ((_linearDepthTexture != linearDepthBuffer)) {
@ -59,6 +59,8 @@ void AmbientOcclusionFramebuffer::updateLinearDepth(const gpu::TexturePointer& l
if (reset) {
clear();
}
return reset;
}
void AmbientOcclusionFramebuffer::clear() {
@ -170,6 +172,41 @@ public:
}
};
AmbientOcclusionEffectConfig::AmbientOcclusionEffectConfig() :
render::GPUJobConfig::Persistent(QStringList() << "Render" << "Engine" << "Ambient Occlusion", false),
#if SSAO_USE_HORIZON_BASED
radius{ 0.1f },
#else
radius{ 0.5f },
#endif
perspectiveScale{ 1.0f },
obscuranceLevel{ 0.5f },
falloffBias{ 0.01f },
edgeSharpness{ 1.0f },
blurDeviation{ 2.5f },
numSpiralTurns{ 7.0f },
#if SSAO_USE_HORIZON_BASED
numSamples{ 1 },
#else
numSamples{ 16 },
#endif
resolutionLevel{ 1 },
blurRadius{ 4 },
ditheringEnabled{ true },
borderingEnabled{ true },
fetchMipsEnabled{ true } {
}
AmbientOcclusionEffect::AOParameters::AOParameters() :
resolutionInfo{ -1.0f, 0.0f, 1.0f, 0.0f },
radiusInfo{ 0.5f, 0.5f * 0.5f, 1.0f / (0.25f * 0.25f * 0.25f), 1.0f },
ditheringInfo{ 0.0f, 0.0f, 0.01f, 1.0f },
sampleInfo{ 11.0f, 1.0f / 11.0f, 7.0f, 1.0f },
blurInfo{ 1.0f, 3.0f, 2.0f, 0.0f } {
}
AmbientOcclusionEffect::AmbientOcclusionEffect() {
}
@ -177,11 +214,12 @@ void AmbientOcclusionEffect::configure(const Config& config) {
DependencyManager::get<DeferredLightingEffect>()->setAmbientOcclusionEnabled(config.enabled);
bool shouldUpdateGaussian = false;
bool shouldUpdateBlurs = false;
const double RADIUS_POWER = 6.0;
const auto& radius = config.radius;
if (radius != _parametersBuffer->getRadius()) {
auto& current = _parametersBuffer.edit().radiusInfo;
if (radius != _aoParametersBuffer->getRadius()) {
auto& current = _aoParametersBuffer.edit().radiusInfo;
current.x = radius;
current.y = radius * radius;
current.z = 10.0f;
@ -190,74 +228,97 @@ void AmbientOcclusionEffect::configure(const Config& config) {
#endif
}
if (config.obscuranceLevel != _parametersBuffer->getObscuranceLevel()) {
auto& current = _parametersBuffer.edit().radiusInfo;
if (config.obscuranceLevel != _aoParametersBuffer->getObscuranceLevel()) {
auto& current = _aoParametersBuffer.edit().radiusInfo;
current.w = config.obscuranceLevel;
}
if (config.falloffBias != _parametersBuffer->getFalloffBias()) {
auto& current = _parametersBuffer.edit().ditheringInfo;
if (config.falloffBias != _aoParametersBuffer->getFalloffBias()) {
auto& current = _aoParametersBuffer.edit().ditheringInfo;
current.z = config.falloffBias;
}
if (config.edgeSharpness != _parametersBuffer->getEdgeSharpness()) {
auto& current = _parametersBuffer.edit().blurInfo;
if (config.edgeSharpness != _aoParametersBuffer->getEdgeSharpness()) {
auto& current = _aoParametersBuffer.edit().blurInfo;
current.x = config.edgeSharpness;
}
if (config.blurDeviation != _parametersBuffer->getBlurDeviation()) {
auto& current = _parametersBuffer.edit().blurInfo;
if (config.blurDeviation != _aoParametersBuffer->getBlurDeviation()) {
auto& current = _aoParametersBuffer.edit().blurInfo;
current.z = config.blurDeviation;
shouldUpdateGaussian = true;
}
if (config.numSpiralTurns != _parametersBuffer->getNumSpiralTurns()) {
auto& current = _parametersBuffer.edit().sampleInfo;
if (config.numSpiralTurns != _aoParametersBuffer->getNumSpiralTurns()) {
auto& current = _aoParametersBuffer.edit().sampleInfo;
current.z = config.numSpiralTurns;
}
if (config.numSamples != _parametersBuffer->getNumSamples()) {
auto& current = _parametersBuffer.edit().sampleInfo;
if (config.numSamples != _aoParametersBuffer->getNumSamples()) {
auto& current = _aoParametersBuffer.edit().sampleInfo;
current.x = config.numSamples;
current.y = 1.0f / config.numSamples;
}
if (config.fetchMipsEnabled != _parametersBuffer->isFetchMipsEnabled()) {
auto& current = _parametersBuffer.edit().sampleInfo;
if (config.fetchMipsEnabled != _aoParametersBuffer->isFetchMipsEnabled()) {
auto& current = _aoParametersBuffer.edit().sampleInfo;
current.w = (float)config.fetchMipsEnabled;
}
if (!_framebuffer) {
_framebuffer = std::make_shared<AmbientOcclusionFramebuffer>();
shouldUpdateBlurs = true;
}
if (config.perspectiveScale != _parametersBuffer->getPerspectiveScale()) {
_parametersBuffer.edit().resolutionInfo.z = config.perspectiveScale;
if (config.perspectiveScale != _aoParametersBuffer->getPerspectiveScale()) {
_aoParametersBuffer.edit().resolutionInfo.z = config.perspectiveScale;
}
if (config.resolutionLevel != _parametersBuffer->getResolutionLevel()) {
auto& current = _parametersBuffer.edit().resolutionInfo;
if (config.resolutionLevel != _aoParametersBuffer->getResolutionLevel()) {
auto& current = _aoParametersBuffer.edit().resolutionInfo;
current.x = (float) config.resolutionLevel;
shouldUpdateBlurs = true;
}
if (config.blurRadius != _parametersBuffer->getBlurRadius()) {
auto& current = _parametersBuffer.edit().blurInfo;
if (config.blurRadius != _aoParametersBuffer->getBlurRadius()) {
auto& current = _aoParametersBuffer.edit().blurInfo;
current.y = (float)config.blurRadius;
shouldUpdateGaussian = true;
}
if (config.ditheringEnabled != _parametersBuffer->isDitheringEnabled()) {
auto& current = _parametersBuffer.edit().ditheringInfo;
if (config.ditheringEnabled != _aoParametersBuffer->isDitheringEnabled()) {
auto& current = _aoParametersBuffer.edit().ditheringInfo;
current.x = (float)config.ditheringEnabled;
}
if (config.borderingEnabled != _parametersBuffer->isBorderingEnabled()) {
auto& current = _parametersBuffer.edit().ditheringInfo;
if (config.borderingEnabled != _aoParametersBuffer->isBorderingEnabled()) {
auto& current = _aoParametersBuffer.edit().ditheringInfo;
current.w = (float)config.borderingEnabled;
}
if (shouldUpdateGaussian) {
updateGaussianDistribution();
}
if (shouldUpdateBlurs) {
updateBlurParameters();
}
}
void AmbientOcclusionEffect::updateBlurParameters() {
const auto resolutionLevel = _aoParametersBuffer->getResolutionLevel();
const auto resolutionScale = 1 << resolutionLevel;
auto& vblur = _vblurParametersBuffer.edit();
auto& hblur = _hblurParametersBuffer.edit();
auto frameSize = _framebuffer->getSourceFrameSize();
hblur.scaleHeight.x = 1.0f / (frameSize.x * resolutionScale);
hblur.scaleHeight.y = 1.0f / frameSize.x;
hblur.scaleHeight.z = frameSize.y / resolutionScale;
vblur.scaleHeight.x = 1.0f / (frameSize.y * resolutionScale);
vblur.scaleHeight.y = 1.0f / frameSize.y;
vblur.scaleHeight.z = frameSize.y;
}
const gpu::PipelinePointer& AmbientOcclusionEffect::getOcclusionPipeline() {
@ -309,8 +370,8 @@ const gpu::PipelinePointer& AmbientOcclusionEffect::getMipCreationPipeline() {
}
void AmbientOcclusionEffect::updateGaussianDistribution() {
auto coefs = _parametersBuffer.edit()._gaussianCoefs;
GaussianDistribution::evalSampling(coefs, Parameters::GAUSSIAN_COEFS_LENGTH, _parametersBuffer->getBlurRadius(), _parametersBuffer->getBlurDeviation());
auto coefs = _aoParametersBuffer.edit()._gaussianCoefs;
GaussianDistribution::evalSampling(coefs, AOParameters::GAUSSIAN_COEFS_LENGTH, _aoParametersBuffer->getBlurRadius(), _aoParametersBuffer->getBlurDeviation());
}
void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs) {
@ -325,6 +386,7 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
auto linearDepthTexture = linearDepthFramebuffer->getLinearDepthTexture();
auto sourceViewport = args->_viewport;
auto occlusionViewport = sourceViewport;
auto firstBlurViewport = sourceViewport;
if (!_gpuTimer) {
_gpuTimer = std::make_shared < gpu::RangeTimer>(__FUNCTION__);
@ -334,18 +396,21 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
_framebuffer = std::make_shared<AmbientOcclusionFramebuffer>();
}
if (_parametersBuffer->getResolutionLevel() > 0) {
linearDepthTexture = linearDepthFramebuffer->getHalfLinearDepthTexture();
occlusionViewport = occlusionViewport >> _parametersBuffer->getResolutionLevel();
const auto resolutionScale = powf(0.5f, _aoParametersBuffer->getResolutionLevel());
if (_aoParametersBuffer->getResolutionLevel() > 0) {
occlusionViewport = occlusionViewport >> _aoParametersBuffer->getResolutionLevel();
firstBlurViewport.w = firstBlurViewport.w >> _aoParametersBuffer->getResolutionLevel();
}
_framebuffer->updateLinearDepth(linearDepthTexture);
if (_framebuffer->updateLinearDepth(linearDepthTexture)) {
updateBlurParameters();
}
auto occlusionFBO = _framebuffer->getOcclusionFramebuffer();
auto occlusionBlurredFBO = _framebuffer->getOcclusionBlurredFramebuffer();
outputs.edit0() = _framebuffer;
outputs.edit1() = _parametersBuffer;
outputs.edit1() = _aoParametersBuffer;
auto framebufferSize = _framebuffer->getSourceFrameSize();
@ -380,7 +445,7 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
batch.popProfileRange();
batch.setUniformBuffer(render_utils::slot::buffer::DeferredFrameTransform, frameTransform->getFrameTransformBuffer());
batch.setUniformBuffer(render_utils::slot::buffer::SsaoParams, _parametersBuffer);
batch.setUniformBuffer(render_utils::slot::buffer::SsaoParams, _aoParametersBuffer);
// Occlusion pass
batch.setFramebuffer(occlusionFBO);
@ -389,16 +454,24 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
batch.setResourceTexture(render_utils::slot::texture::SsaoPyramid, _framebuffer->getLinearDepthTexture());
batch.draw(gpu::TRIANGLE_STRIP, 4);
if (_parametersBuffer->getBlurRadius() > 0) {
/* TEMPO OP if (_aoParametersBuffer->getBlurRadius() > 0)*/ {
PROFILE_RANGE_BATCH(batch, "Blur");
// Blur 1st pass
model.setScale(resolutionScale);
batch.setModelTransform(model);
batch.setViewportTransform(firstBlurViewport);
batch.setFramebuffer(occlusionBlurredFBO);
batch.setUniformBuffer(render_utils::slot::buffer::SsaoBlurParams, _hblurParametersBuffer);
batch.setPipeline(firstHBlurPipeline);
batch.setResourceTexture(render_utils::slot::texture::SsaoOcclusion, occlusionFBO->getRenderBuffer(0));
batch.draw(gpu::TRIANGLE_STRIP, 4);
// Blur 2nd pass
model.setScale(glm::vec3(1.0f, resolutionScale, 1.0f));
batch.setModelTransform(model);
batch.setViewportTransform(sourceViewport);
batch.setFramebuffer(occlusionFBO);
batch.setUniformBuffer(render_utils::slot::buffer::SsaoBlurParams, _vblurParametersBuffer);
batch.setPipeline(lastVBlurPipeline);
batch.setResourceTexture(render_utils::slot::texture::SsaoOcclusion, occlusionBlurredFBO->getRenderBuffer(0));
batch.draw(gpu::TRIANGLE_STRIP, 4);

View file

@ -32,7 +32,7 @@ public:
gpu::TexturePointer getOcclusionBlurredTexture();
// Update the source framebuffer size which will drive the allocation of all the other resources.
void updateLinearDepth(const gpu::TexturePointer& linearDepthBuffer);
bool updateLinearDepth(const gpu::TexturePointer& linearDepthBuffer);
gpu::TexturePointer getLinearDepthTexture();
const glm::ivec2& getSourceFrameSize() const { return _frameSize; }
@ -71,7 +71,7 @@ class AmbientOcclusionEffectConfig : public render::GPUJobConfig::Persistent {
Q_PROPERTY(int blurRadius MEMBER blurRadius WRITE setBlurRadius)
public:
AmbientOcclusionEffectConfig() : render::GPUJobConfig::Persistent(QStringList() << "Render" << "Engine" << "Ambient Occlusion", false) {}
AmbientOcclusionEffectConfig();
const int MAX_RESOLUTION_LEVEL = 4;
const int MAX_BLUR_RADIUS = 6;
@ -86,19 +86,19 @@ public:
void setResolutionLevel(int level) { resolutionLevel = std::max(0, std::min(level, MAX_RESOLUTION_LEVEL)); emit dirty(); }
void setBlurRadius(int radius) { blurRadius = std::max(0, std::min(MAX_BLUR_RADIUS, radius)); emit dirty(); }
float radius{ 0.5f };
float perspectiveScale{ 1.0f };
float obscuranceLevel{ 0.5f }; // intensify or dim down the obscurance effect
float falloffBias{ 0.01f };
float edgeSharpness{ 1.0f };
float blurDeviation{ 2.5f };
float numSpiralTurns{ 7.0f }; // defining an angle span to distribute the samples ray directions
int numSamples{ 16 };
int resolutionLevel{ 1 };
int blurRadius{ 4 }; // 0 means no blurring
bool ditheringEnabled{ true }; // randomize the distribution of taps per pixel, should always be true
bool borderingEnabled{ true }; // avoid evaluating information from non existing pixels out of the frame, should always be true
bool fetchMipsEnabled{ true }; // fetch taps in sub mips to otpimize cache, should always be true
float radius;
float perspectiveScale;
float obscuranceLevel; // intensify or dim down the obscurance effect
float falloffBias;
float edgeSharpness;
float blurDeviation;
float numSpiralTurns; // defining an angle span to distribute the samples ray directions
int numSamples;
int resolutionLevel;
int blurRadius; // 0 means no blurring
bool ditheringEnabled; // randomize the distribution of taps per pixel, should always be true
bool borderingEnabled; // avoid evaluating information from non existing pixels out of the frame, should always be true
bool fetchMipsEnabled; // fetch taps in sub mips to otpimize cache, should always be true
signals:
void dirty();
@ -118,23 +118,23 @@ public:
// Class describing the uniform buffer with all the parameters common to the AO shaders
class Parameters {
class AOParameters {
public:
// Resolution info
glm::vec4 resolutionInfo { -1.0f, 0.0f, 1.0f, 0.0f };
glm::vec4 resolutionInfo;
// radius info is { R, R^2, 1 / R^6, ObscuranceScale}
glm::vec4 radiusInfo{ 0.5f, 0.5f * 0.5f, 1.0f / (0.25f * 0.25f * 0.25f), 1.0f };
glm::vec4 radiusInfo;
// Dithering info
glm::vec4 ditheringInfo { 0.0f, 0.0f, 0.01f, 1.0f };
glm::vec4 ditheringInfo;
// Sampling info
glm::vec4 sampleInfo { 11.0f, 1.0f/11.0f, 7.0f, 1.0f };
glm::vec4 sampleInfo;
// Blurring info
glm::vec4 blurInfo { 1.0f, 3.0f, 2.0f, 0.0f };
glm::vec4 blurInfo;
// gaussian distribution coefficients first is the sampling radius (max is 6)
const static int GAUSSIAN_COEFS_LENGTH = 8;
float _gaussianCoefs[GAUSSIAN_COEFS_LENGTH];
Parameters() {}
AOParameters();
int getResolutionLevel() const { return resolutionInfo.x; }
float getRadius() const { return radiusInfo.x; }
@ -152,12 +152,26 @@ public:
bool isDitheringEnabled() const { return ditheringInfo.x; }
bool isBorderingEnabled() const { return ditheringInfo.w; }
};
using ParametersBuffer = gpu::StructBuffer<Parameters>;
using AOParametersBuffer = gpu::StructBuffer<AOParameters>;
private:
// Class describing the uniform buffer with all the parameters common to the bilateral blur shaders
class BlurParameters {
public:
glm::vec4 scaleHeight{ 0.0f };
BlurParameters() {}
};
using BlurParametersBuffer = gpu::StructBuffer<BlurParameters>;
void updateGaussianDistribution();
void updateBlurParameters();
ParametersBuffer _parametersBuffer;
AOParametersBuffer _aoParametersBuffer;
BlurParametersBuffer _vblurParametersBuffer;
BlurParametersBuffer _hblurParametersBuffer;
static const gpu::PipelinePointer& getOcclusionPipeline();
static const gpu::PipelinePointer& getHBlurPipeline(); // first
@ -195,7 +209,7 @@ signals:
class DebugAmbientOcclusion {
public:
using Inputs = render::VaryingSet4<DeferredFrameTransformPointer, DeferredFramebufferPointer, LinearDepthFramebufferPointer, AmbientOcclusionEffect::ParametersBuffer>;
using Inputs = render::VaryingSet4<DeferredFrameTransformPointer, DeferredFramebufferPointer, LinearDepthFramebufferPointer, AmbientOcclusionEffect::AOParametersBuffer>;
using Config = DebugAmbientOcclusionConfig;
using JobModel = render::Job::ModelI<DebugAmbientOcclusion, Inputs, Config>;

View file

@ -64,14 +64,15 @@ void LinearDepthFramebuffer::allocate() {
auto height = _frameSize.y;
// For Linear Depth:
_linearDepthTexture = gpu::Texture::createRenderBuffer(gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::RED), width, height, gpu::Texture::SINGLE_MIP,
const uint16_t LINEAR_DEPTH_MAX_MIP_LEVEL = 5;
_linearDepthTexture = gpu::Texture::createRenderBuffer(gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::RED), width, height, LINEAR_DEPTH_MAX_MIP_LEVEL,
gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT));
_linearDepthFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("linearDepth"));
_linearDepthFramebuffer->setRenderBuffer(0, _linearDepthTexture);
_linearDepthFramebuffer->setDepthStencilBuffer(_primaryDepthTexture, _primaryDepthTexture->getTexelFormat());
// For Downsampling:
const uint16_t HALF_LINEAR_DEPTH_MAX_MIP_LEVEL = 5;
const uint16_t HALF_LINEAR_DEPTH_MAX_MIP_LEVEL = LINEAR_DEPTH_MAX_MIP_LEVEL;
_halfLinearDepthTexture = gpu::Texture::createRenderBuffer(gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::RED), _halfFrameSize.x, _halfFrameSize.y, HALF_LINEAR_DEPTH_MAX_MIP_LEVEL,
gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT));

View file

@ -86,6 +86,7 @@
// Ambient occlusion
#define RENDER_UTILS_BUFFER_SSAO_PARAMS 2
#define RENDER_UTILS_BUFFER_SSAO_DEBUG_PARAMS 3
#define RENDER_UTILS_BUFFER_SSAO_BLUR_PARAMS 4
#define RENDER_UTILS_TEXTURE_SSAO_PYRAMID 1
#define RENDER_UTILS_TEXTURE_SSAO_OCCLUSION 0
@ -153,6 +154,7 @@ enum Buffer {
SsscParams = RENDER_UTILS_BUFFER_SSSC_PARAMS,
SsaoParams = RENDER_UTILS_BUFFER_SSAO_PARAMS,
SsaoDebugParams = RENDER_UTILS_BUFFER_SSAO_DEBUG_PARAMS,
SsaoBlurParams = RENDER_UTILS_BUFFER_SSAO_BLUR_PARAMS,
LightIndex = RENDER_UTILS_BUFFER_LIGHT_INDEX,
TaaParams = RENDER_UTILS_BUFFER_TAA_PARAMS,
HighlightParams = RENDER_UTILS_BUFFER_HIGHLIGHT_PARAMS,

View file

@ -1 +1 @@
VERTEX gpu::vertex::DrawViewportQuadTransformTexcoord
VERTEX ssao_blur

View file

@ -1 +1 @@
VERTEX gpu::vertex::DrawViewportQuadTransformTexcoord
VERTEX ssao_blur

View file

@ -425,73 +425,90 @@ float evalVisibilityHBAO(ivec4 side, ivec2 centerPixelPos, vec2 imageSize, vec2
<$declarePackOcclusionDepth()$>
<$declareAmbientOcclusion()$>
<$declareFetchDepthPyramidMap()$>
// the source occlusion texture
layout(binding=RENDER_UTILS_TEXTURE_SSAO_OCCLUSION) uniform sampler2D occlusionMap;
struct BlurParams {
vec4 scaleHeight;
};
vec2 fetchOcclusionDepthRaw(ivec2 coords, out vec3 raw) {
raw = texelFetch(occlusionMap, coords, 0).xyz;
return unpackOcclusionDepth(raw);
layout(binding=RENDER_UTILS_BUFFER_SSAO_BLUR_PARAMS) uniform blurParamsBuffer {
BlurParams blurParams;
};
float getOcclusionBlurScale() {
return blurParams.scaleHeight.x;
}
vec2 fetchOcclusionDepth(ivec2 coords) {
return unpackOcclusionDepth(texelFetch(occlusionMap, coords, 0).xyz);
float getDepthBlurScale() {
return blurParams.scaleHeight.y;
}
int getBlurImageHeight() {
return int(blurParams.scaleHeight.z);
}
float fetchOcclusion(vec2 coords) {
vec3 raw = texture(occlusionMap, coords, 0).xyz;
return raw.x;
}
const int RADIUS_SCALE = 1;
const float BLUR_WEIGHT_OFFSET = 0.05;
const float BLUR_EDGE_SCALE = 5000.0;
const float BLUR_EDGE_SCALE = 100.0;
vec2 evalTapWeightedValue(ivec3 side, int r, ivec2 ssC, float key) {
ivec2 tapOffset = <$axis$> * (r * RADIUS_SCALE);
ivec2 ssP = (ssC + tapOffset);
vec2 evalTapWeightedValue(ivec3 side, int r, ivec2 destPixelCoord, vec2 scaledTexCoord, vec2 fullTexCoord, float key) {
ivec2 tapOffset = <$axis$> * r;
ivec2 tapPixelCoord = destPixelCoord + tapOffset;
if ((ssP.x < side.y || ssP.x >= side.z + side.y) || (ssP.y < 0 || ssP.y >= int(getWidthHeight(getResolutionLevel()).y))) {
if ((tapPixelCoord.x < side.y || tapPixelCoord.x >= side.z + side.y) || (tapPixelCoord.y < 0 || tapPixelCoord.y >= getBlurImageHeight())) {
return vec2(0.0);
}
vec2 tapOZ = fetchOcclusionDepth(ssC + tapOffset);
vec2 tapTexCoord = scaledTexCoord + tapOffset * getOcclusionBlurScale();
float tapOcclusion = fetchOcclusion(tapTexCoord);
tapTexCoord = fullTexCoord + tapOffset * getDepthBlurScale();
float tapDepth = getZEyeAtUV(tapTexCoord, 0);
// spatial domain: offset gaussian tap
float weight = BLUR_WEIGHT_OFFSET + getBlurCoef(abs(r));
// range domain (the "bilateral" weight). As depth difference increases, decrease weight.
weight *= max(0.0, 1.0 - (getBlurEdgeSharpness() * BLUR_EDGE_SCALE) * abs(tapOZ.y - key));
weight *= max(0.0, 1.0 - (getBlurEdgeSharpness() * BLUR_EDGE_SCALE) * abs(tapDepth - key));
return vec2(tapOZ.x * weight, weight);
return vec2(tapOcclusion * weight, weight);
}
vec3 getBlurredOcclusion(vec2 coord) {
ivec2 ssC = ivec2(coord);
vec3 getBlurredOcclusion(ivec2 destPixelCoord, vec2 scaledTexCoord, vec2 fullTexCoord) {
// Stereo side info
ivec4 side = getStereoSideInfo(ssC.x, getResolutionLevel());
ivec4 side = getStereoSideInfo(destPixelCoord.x, 0);
vec3 rawSample;
vec2 occlusionDepth = fetchOcclusionDepthRaw(ssC, rawSample);
float key = occlusionDepth.y;
float pixelDepth = getZEyeAtUV(fullTexCoord, 0);
vec2 weightedSums = vec2(0.0);
// Central pixel contribution
float mainWeight = getBlurCoef(0);
vec2 weightedSums = vec2(occlusionDepth.x * mainWeight, mainWeight);
// Accumulate weighted contributions along the bluring axis in the [-radius, radius] range
int blurRadius = getBlurRadius();
// negative side first
for (int r = -blurRadius; r <= -1; ++r) {
weightedSums += evalTapWeightedValue(side.xyz, r, ssC, key);
weightedSums += evalTapWeightedValue(side.xyz, r, destPixelCoord, scaledTexCoord, fullTexCoord, pixelDepth);
}
// Central pixel contribution
float mainWeight = getBlurCoef(0);
float pixelOcclusion = fetchOcclusion(scaledTexCoord);
weightedSums += vec2(pixelOcclusion * mainWeight, mainWeight);
// then positive side
for (int r = 1; r <= blurRadius; ++r) {
weightedSums += evalTapWeightedValue(side.xyz, r, ssC, key);
weightedSums += evalTapWeightedValue(side.xyz, r, destPixelCoord, scaledTexCoord, fullTexCoord, pixelDepth);
}
// Final normalization
const float epsilon = 0.0001;
float result = weightedSums.x / (weightedSums.y + epsilon);
rawSample.x = result;
return rawSample;
return vec3(result);
}
<@endfunc@>

View file

@ -0,0 +1,42 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
//
// ssao_blur.vert
//
// Draw the unit quad [-1,-1 -> 1,1] filling in
// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed
//
// Created by Olivier Prat on 9/12/2018
// Copyright 2018 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
//
<@include gpu/Transform.slh@>
<$declareStandardTransform()$>
layout(location=0) out vec4 varTexCoord0;
void main(void) {
const vec4 UNIT_QUAD[4] = vec4[4](
vec4(-1.0, -1.0, 0.0, 1.0),
vec4(1.0, -1.0, 0.0, 1.0),
vec4(-1.0, 1.0, 0.0, 1.0),
vec4(1.0, 1.0, 0.0, 1.0)
);
vec4 pos = UNIT_QUAD[gl_VertexID];
// standard transform but applied to the Texcoord
vec2 fullTexCoord = (pos.xy + 1.0) * 0.5;
vec4 tc = vec4(fullTexCoord, pos.zw);
TransformObject obj = getTransformObject();
<$transformModelToWorldPos(obj, tc, tc)$>
gl_Position = pos;
varTexCoord0.xy = tc.xy;
varTexCoord0.zw = fullTexCoord.xy;
}

View file

@ -16,9 +16,10 @@
const ivec2 horizontal = ivec2(1,0);
<$declareBlurPass(horizontal)$>
layout(location=0) in vec4 varTexCoord0;
layout(location=0) out vec4 outFragColor;
void main(void) {
outFragColor = vec4(getBlurredOcclusion(gl_FragCoord.xy), 1.0);
outFragColor = vec4(getBlurredOcclusion(ivec2(gl_FragCoord.xy), varTexCoord0.xy, varTexCoord0.zw), 1.0);
}

View file

@ -30,9 +30,6 @@ void main(void) {
vec2 fragCoord = gl_FragCoord.xy;
ivec2 centerPixelPos = ivec2(fragCoord.xy);
// Fetch the z under the pixel (stereo or not)
float Zeye = getZEyeAtPixel(centerPixelPos, 0);
// Stereo side info
ivec4 side = getStereoSideInfo(centerPixelPos.x, getResolutionLevel());
@ -40,6 +37,9 @@ void main(void) {
centerPixelPos.x -= side.y;
vec2 fragUVPos = (vec2(centerPixelPos) + vec2(0.5)) / imageSize;
// Fetch the z under the pixel (stereo or not)
float Zeye = getZEyeAtUV(fragUVPos, 0);
// The position and normal of the pixel fragment in Eye space
vec3 fragPositionES = evalEyePositionFromZeye(side.x, Zeye, fragUVPos);
vec3 fragNormalES = evalEyeNormal(fragPositionES);

View file

@ -15,9 +15,11 @@
const ivec2 vertical = ivec2(0,1);
<$declareBlurPass(vertical)$>
layout(location=0) in vec4 varTexCoord0;
layout(location=0) out vec4 outFragColor;
void main(void) {
float occlusion = getBlurredOcclusion(gl_FragCoord.xy).x;
float occlusion = getBlurredOcclusion(ivec2(gl_FragCoord.xy), varTexCoord0.xy, varTexCoord0.zw).x;
outFragColor = vec4(occlusion, 0.0, 0.0, occlusion);
}