Quarter resolution with split rendering

This commit is contained in:
Olivier Prat 2018-09-19 17:24:31 +02:00
parent 3493d40fd7
commit 8a11d18f0d
11 changed files with 194 additions and 91 deletions

View file

@ -35,6 +35,7 @@ gpu::PipelinePointer AmbientOcclusionEffect::_hBlurPipeline;
gpu::PipelinePointer AmbientOcclusionEffect::_vBlurPipeline;
gpu::PipelinePointer AmbientOcclusionEffect::_mipCreationPipeline;
gpu::PipelinePointer AmbientOcclusionEffect::_gatherPipeline;
gpu::PipelinePointer AmbientOcclusionEffect::_buildNormalsPipeline;
AmbientOcclusionFramebuffer::AmbientOcclusionFramebuffer() {
}
@ -66,6 +67,8 @@ void AmbientOcclusionFramebuffer::clear() {
_occlusionTexture.reset();
_occlusionBlurredFramebuffer.reset();
_occlusionBlurredTexture.reset();
_normalFramebuffer.reset();
_normalTexture.reset();
}
gpu::TexturePointer AmbientOcclusionFramebuffer::getLinearDepthTexture() {
@ -73,18 +76,21 @@ gpu::TexturePointer AmbientOcclusionFramebuffer::getLinearDepthTexture() {
}
void AmbientOcclusionFramebuffer::allocate() {
auto width = _frameSize.x;
auto height = _frameSize.y;
auto format = gpu::Element::COLOR_R_8;
_occlusionTexture = gpu::Texture::createRenderBuffer(format, width, height, gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT, gpu::Sampler::WRAP_CLAMP));
_occlusionTexture = gpu::Texture::createRenderBuffer(format, width, height, gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR, gpu::Sampler::WRAP_CLAMP));
_occlusionFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("occlusion"));
_occlusionFramebuffer->setRenderBuffer(0, _occlusionTexture);
_occlusionBlurredTexture = gpu::Texture::createRenderBuffer(format, width, height, gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT, gpu::Sampler::WRAP_CLAMP));
_occlusionBlurredTexture = gpu::Texture::createRenderBuffer(format, width, height, gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR, gpu::Sampler::WRAP_CLAMP));
_occlusionBlurredFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("occlusionBlurred"));
_occlusionBlurredFramebuffer->setRenderBuffer(0, _occlusionBlurredTexture);
_normalTexture = gpu::Texture::createRenderBuffer(gpu::Element::COLOR_R11G11B10, width, height, gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT, gpu::Sampler::WRAP_CLAMP));
_normalFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("ssaoNormals"));
_normalFramebuffer->setRenderBuffer(0, _normalTexture);
}
gpu::FramebufferPointer AmbientOcclusionFramebuffer::getOcclusionFramebuffer() {
@ -115,6 +121,19 @@ gpu::TexturePointer AmbientOcclusionFramebuffer::getOcclusionBlurredTexture() {
return _occlusionBlurredTexture;
}
gpu::FramebufferPointer AmbientOcclusionFramebuffer::getNormalFramebuffer() {
if (!_normalFramebuffer) {
allocate();
}
return _normalFramebuffer;
}
gpu::TexturePointer AmbientOcclusionFramebuffer::getNormalTexture() {
if (!_normalTexture) {
allocate();
}
return _normalTexture;
}
class GaussianDistribution {
public:
@ -189,11 +208,11 @@ AmbientOcclusionEffectConfig::AmbientOcclusionEffectConfig() :
blurDeviation{ 2.5f },
numSpiralTurns{ 7.0f },
#if SSAO_USE_HORIZON_BASED
numSamples{ 1 },
numSamples{ 2 },
#else
numSamples{ 16 },
#endif
resolutionLevel{ 1 },
resolutionLevel{ 2 },
blurRadius{ 4 },
ditheringEnabled{ true },
borderingEnabled{ true },
@ -262,8 +281,8 @@ void AmbientOcclusionEffect::configure(const Config& config) {
current.x = config.numSamples;
current.y = 1.0f / config.numSamples;
// Regenerate halton sequence
const int B = config.numSamples + 1;
// Regenerate offsets
const int B = 3;
const float invB = 1.0f / (float)B;
for (int i = 0; i < _randomSamples.size(); i++) {
@ -276,7 +295,7 @@ void AmbientOcclusionEffect::configure(const Config& config) {
r = r + f * (float)(index % B);
index = index / B;
}
_randomSamples[i] = r;
_randomSamples[i] = r * M_PI / config.numSamples;
}
}
@ -296,7 +315,7 @@ void AmbientOcclusionEffect::configure(const Config& config) {
if (config.resolutionLevel != _aoParametersBuffer->getResolutionLevel()) {
auto& current = _aoParametersBuffer.edit()._resolutionInfo;
current.x = (float) config.resolutionLevel;
current.x = (float)config.resolutionLevel;
shouldUpdateBlurs = true;
_aoFrameParametersBuffer[0].edit()._pixelOffsets = { 0, 0, 0, 0 };
@ -307,7 +326,7 @@ void AmbientOcclusionEffect::configure(const Config& config) {
#endif
}
if (config.blurRadius != _aoParametersBuffer->getBlurRadius()) {
if (config.blurRadius != _aoParametersBuffer.get().getBlurRadius()) {
auto& current = _aoParametersBuffer.edit()._blurInfo;
current.y = (float)config.blurRadius;
shouldUpdateGaussian = true;
@ -361,7 +380,6 @@ const gpu::PipelinePointer& AmbientOcclusionEffect::getOcclusionPipeline() {
return _occlusionPipeline;
}
const gpu::PipelinePointer& AmbientOcclusionEffect::getHBlurPipeline() {
if (!_hBlurPipeline) {
gpu::ShaderPointer program = gpu::Shader::createProgram(shader::render_utils::program::ssao_makeHorizontalBlur);
@ -409,9 +427,24 @@ const gpu::PipelinePointer& AmbientOcclusionEffect::getGatherPipeline() {
return _gatherPipeline;
}
const gpu::PipelinePointer& AmbientOcclusionEffect::getBuildNormalsPipeline() {
if (!_buildNormalsPipeline) {
gpu::ShaderPointer program = gpu::Shader::createProgram(shader::render_utils::program::ssao_buildNormals);
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
state->setColorWriteMask(true, true, true, false);
// Good to go add the brand new pipeline
_buildNormalsPipeline = gpu::Pipeline::create(program, state);
}
return _buildNormalsPipeline;
}
void AmbientOcclusionEffect::updateGaussianDistribution() {
auto coefs = _aoParametersBuffer.edit()._gaussianCoefs;
GaussianDistribution::evalSampling(coefs, SSAO_BLUR_GAUSSIAN_COEFS_COUNT, _aoParametersBuffer->getBlurRadius(), _aoParametersBuffer->getBlurDeviation());
auto filterTaps = _aoParametersBuffer.edit()._blurFilterTaps;
auto blurRadius = _aoParametersBuffer.get().getBlurRadius();
GaussianDistribution::evalSampling(filterTaps, SSAO_BLUR_GAUSSIAN_COEFS_COUNT, blurRadius, _aoParametersBuffer->getBlurDeviation() * 4.0f / blurRadius);
}
void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs) {
@ -436,7 +469,7 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
if (!_framebuffer) {
_framebuffer = std::make_shared<AmbientOcclusionFramebuffer>();
}
const auto resolutionScale = powf(0.5f, _aoParametersBuffer->getResolutionLevel());
if (_aoParametersBuffer->getResolutionLevel() > 0) {
occlusionViewport = occlusionViewport >> _aoParametersBuffer->getResolutionLevel();
@ -464,15 +497,19 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
#endif
#if SSAO_USE_QUAD_SPLIT
auto gatherPipeline = getGatherPipeline();
auto buildNormalsPipeline = getBuildNormalsPipeline();
auto occlusionNormalFramebuffer = _framebuffer->getNormalFramebuffer();
auto occlusionNormalTexture = _framebuffer->getNormalTexture();
#endif
auto fullNormalTexture = linearDepthFramebuffer->getNormalTexture();
// Update sample rotation
const int SSAO_RANDOM_SAMPLE_COUNT = int(_randomSamples.size() / SSAO_SPLIT_COUNT);
for (int splitId=0 ; splitId < SSAO_SPLIT_COUNT ; splitId++) {
auto& sample = _aoFrameParametersBuffer[splitId].edit();
sample._angleInfo.x = _randomSamples[_frameId + SSAO_RANDOM_SAMPLE_COUNT * splitId] * M_PI;
sample._angleInfo.x = _randomSamples[splitId + SSAO_RANDOM_SAMPLE_COUNT * _frameId];
}
_frameId = (_frameId + 1) % SSAO_RANDOM_SAMPLE_COUNT;
// TEMPO OP _frameId = (_frameId + 1) % SSAO_RANDOM_SAMPLE_COUNT;
gpu::doInBatch("AmbientOcclusionEffect::run", args->_context, [=](gpu::Batch& batch) {
PROFILE_RANGE_BATCH(batch, "AmbientOcclusion");
@ -480,7 +517,6 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
_gpuTimer->begin(batch);
batch.setProjectionTransform(glm::mat4());
batch.resetViewTransform();
Transform model;
@ -490,53 +526,67 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
// We need this with the mips levels
batch.pushProfileRange("Depth mip creation");
#if SSAO_USE_HORIZON_BASED
batch.setPipeline(mipCreationPipeline);
batch.generateTextureMipsWithPipeline(occlusionDepthTexture);
batch.setPipeline(mipCreationPipeline);
batch.generateTextureMipsWithPipeline(occlusionDepthTexture);
#else
batch.generateTextureMips(occlusionDepthTexture);
batch.generateTextureMips(occlusionDepthTexture);
#endif
batch.popProfileRange();
#if SSAO_USE_QUAD_SPLIT
// Build derivative normals pass
batch.pushProfileRange("Build Normals");
batch.setViewportTransform(sourceViewport);
batch.setPipeline(buildNormalsPipeline);
batch.setUniformBuffer(render_utils::slot::buffer::DeferredFrameTransform, frameTransform->getFrameTransformBuffer());
batch.setUniformBuffer(render_utils::slot::buffer::SsaoParams, _aoParametersBuffer);
batch.setFramebuffer(occlusionNormalFramebuffer);
batch.setResourceTexture(render_utils::slot::texture::SsaoDepth, linearDepthTexture);
batch.draw(gpu::TRIANGLE_STRIP, 4);
batch.popProfileRange();
#endif
// Occlusion pass
batch.pushProfileRange("Occlusion");
batch.setUniformBuffer(render_utils::slot::buffer::DeferredFrameTransform, frameTransform->getFrameTransformBuffer());
batch.setUniformBuffer(render_utils::slot::buffer::SsaoParams, _aoParametersBuffer);
batch.setUniformBuffer(render_utils::slot::buffer::DeferredFrameTransform, frameTransform->getFrameTransformBuffer());
batch.setUniformBuffer(render_utils::slot::buffer::SsaoParams, _aoParametersBuffer);
#if SSAO_USE_QUAD_SPLIT
batch.setFramebuffer(occlusionBlurredFBO);
batch.setFramebuffer(occlusionBlurredFBO);
#else
batch.setFramebuffer(occlusionFBO);
batch.setFramebuffer(occlusionFBO);
#endif
batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, glm::vec4(1.0f));
batch.setPipeline(occlusionPipeline);
batch.setResourceTexture(render_utils::slot::texture::SsaoDepth, occlusionDepthTexture);
batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, glm::vec4(1.0f));
batch.setPipeline(occlusionPipeline);
batch.setResourceTexture(render_utils::slot::texture::SsaoDepth, occlusionDepthTexture);
#if SSAO_USE_QUAD_SPLIT
{
auto splitViewport = occlusionViewport >> SSAO_USE_QUAD_SPLIT;
batch.setResourceTexture(render_utils::slot::texture::SsaoNormal, occlusionNormalTexture);
{
auto splitViewport = occlusionViewport >> SSAO_USE_QUAD_SPLIT;
batch.setViewportTransform(splitViewport);
batch.setViewportTransform(splitViewport);
batch.setUniformBuffer(render_utils::slot::buffer::SsaoFrameParams, _aoFrameParametersBuffer[0]);
batch.draw(gpu::TRIANGLE_STRIP, 4);
splitViewport.x += splitViewport.z;
batch.setViewportTransform(splitViewport);
batch.setUniformBuffer(render_utils::slot::buffer::SsaoFrameParams, _aoFrameParametersBuffer[1]);
batch.draw(gpu::TRIANGLE_STRIP, 4);
splitViewport.y += splitViewport.w;
batch.setViewportTransform(splitViewport);
batch.setUniformBuffer(render_utils::slot::buffer::SsaoFrameParams, _aoFrameParametersBuffer[2]);
batch.draw(gpu::TRIANGLE_STRIP, 4);
splitViewport.x = 0;
batch.setViewportTransform(splitViewport);
batch.setUniformBuffer(render_utils::slot::buffer::SsaoFrameParams, _aoFrameParametersBuffer[3]);
batch.draw(gpu::TRIANGLE_STRIP, 4);
}
#else
batch.setUniformBuffer(render_utils::slot::buffer::SsaoFrameParams, _aoFrameParametersBuffer[0]);
batch.draw(gpu::TRIANGLE_STRIP, 4);
splitViewport.x += splitViewport.z;
batch.setViewportTransform(splitViewport);
batch.setUniformBuffer(render_utils::slot::buffer::SsaoFrameParams, _aoFrameParametersBuffer[1]);
batch.draw(gpu::TRIANGLE_STRIP, 4);
splitViewport.y += splitViewport.w;
batch.setViewportTransform(splitViewport);
batch.setUniformBuffer(render_utils::slot::buffer::SsaoFrameParams, _aoFrameParametersBuffer[2]);
batch.draw(gpu::TRIANGLE_STRIP, 4);
splitViewport.x = 0;
batch.setViewportTransform(splitViewport);
batch.setUniformBuffer(render_utils::slot::buffer::SsaoFrameParams, _aoFrameParametersBuffer[3]);
batch.draw(gpu::TRIANGLE_STRIP, 4);
}
#else
batch.setUniformBuffer(render_utils::slot::buffer::SsaoFrameParams, _aoFrameParametersBuffer[0]);
batch.draw(gpu::TRIANGLE_STRIP, 4);
#endif
batch.popProfileRange();
@ -544,11 +594,11 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
#if SSAO_USE_QUAD_SPLIT
// Gather back the four separate renders into one interleaved one
batch.pushProfileRange("Gather");
batch.setViewportTransform(occlusionViewport);
batch.setFramebuffer(occlusionFBO);
batch.setPipeline(gatherPipeline);
batch.setResourceTexture(render_utils::slot::texture::SsaoOcclusion, occlusionBlurredFBO->getRenderBuffer(0));
batch.draw(gpu::TRIANGLE_STRIP, 4);
batch.setViewportTransform(occlusionViewport);
batch.setFramebuffer(occlusionFBO);
batch.setPipeline(gatherPipeline);
batch.setResourceTexture(render_utils::slot::texture::SsaoOcclusion, occlusionBlurredFBO->getRenderBuffer(0));
batch.draw(gpu::TRIANGLE_STRIP, 4);
batch.popProfileRange();
#endif
@ -561,6 +611,7 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
batch.setFramebuffer(occlusionBlurredFBO);
// Use full resolution depth and normal for bilateral upscaling and blur
batch.setResourceTexture(render_utils::slot::texture::SsaoDepth, linearDepthTexture);
batch.setResourceTexture(render_utils::slot::texture::SsaoNormal, fullNormalTexture);
batch.setUniformBuffer(render_utils::slot::buffer::SsaoBlurParams, _hblurParametersBuffer);
batch.setPipeline(firstHBlurPipeline);
batch.setResourceTexture(render_utils::slot::texture::SsaoOcclusion, occlusionFBO->getRenderBuffer(0));

View file

@ -30,7 +30,10 @@ public:
gpu::FramebufferPointer getOcclusionBlurredFramebuffer();
gpu::TexturePointer getOcclusionBlurredTexture();
gpu::FramebufferPointer getNormalFramebuffer();
gpu::TexturePointer getNormalTexture();
// Update the source framebuffer size which will drive the allocation of all the other resources.
bool updateLinearDepth(const gpu::TexturePointer& linearDepthBuffer);
gpu::TexturePointer getLinearDepthTexture();
@ -44,10 +47,13 @@ protected:
gpu::FramebufferPointer _occlusionFramebuffer;
gpu::TexturePointer _occlusionTexture;
gpu::FramebufferPointer _occlusionBlurredFramebuffer;
gpu::TexturePointer _occlusionBlurredTexture;
gpu::FramebufferPointer _normalFramebuffer;
gpu::TexturePointer _normalTexture;
glm::ivec2 _frameSize;
};
@ -168,12 +174,14 @@ private:
static const gpu::PipelinePointer& getVBlurPipeline(); // second
static const gpu::PipelinePointer& getMipCreationPipeline();
static const gpu::PipelinePointer& getGatherPipeline();
static const gpu::PipelinePointer& getBuildNormalsPipeline();
static gpu::PipelinePointer _occlusionPipeline;
static gpu::PipelinePointer _hBlurPipeline;
static gpu::PipelinePointer _vBlurPipeline;
static gpu::PipelinePointer _mipCreationPipeline;
static gpu::PipelinePointer _gatherPipeline;
static gpu::PipelinePointer _buildNormalsPipeline;
AmbientOcclusionFramebufferPointer _framebuffer;
std::array<float, 16 * SSAO_SPLIT_COUNT> _randomSamples;

View file

@ -28,11 +28,12 @@ namespace ru {
LinearDepthFramebuffer::LinearDepthFramebuffer() {
}
void LinearDepthFramebuffer::update(const gpu::TexturePointer& depthBuffer) {
void LinearDepthFramebuffer::update(const gpu::TexturePointer& depthBuffer, const gpu::TexturePointer& normalTexture) {
//If the depth buffer or size changed, we need to delete our FBOs
bool reset = false;
if (_primaryDepthTexture != depthBuffer) {
if (_primaryDepthTexture != depthBuffer || _normalTexture != normalTexture) {
_primaryDepthTexture = depthBuffer;
_normalTexture = normalTexture;
reset = true;
}
if (_primaryDepthTexture) {
@ -100,6 +101,10 @@ gpu::TexturePointer LinearDepthFramebuffer::getLinearDepthTexture() {
return _linearDepthTexture;
}
gpu::TexturePointer LinearDepthFramebuffer::getNormalTexture() {
return _normalTexture;
}
gpu::FramebufferPointer LinearDepthFramebuffer::getDownsampleFramebuffer() {
if (!_downsampleFramebuffer) {
allocate();
@ -148,7 +153,7 @@ void LinearDepthPass::run(const render::RenderContextPointer& renderContext, con
auto depthBuffer = deferredFramebuffer->getPrimaryDepthTexture();
auto normalTexture = deferredFramebuffer->getDeferredNormalTexture();
_linearDepthFramebuffer->update(depthBuffer);
_linearDepthFramebuffer->update(depthBuffer, normalTexture);
auto linearDepthFBO = _linearDepthFramebuffer->getLinearDepthFramebuffer();
auto linearDepthTexture = _linearDepthFramebuffer->getLinearDepthTexture();

View file

@ -28,13 +28,14 @@ public:
gpu::FramebufferPointer getLinearDepthFramebuffer();
gpu::TexturePointer getLinearDepthTexture();
gpu::TexturePointer getNormalTexture();
gpu::FramebufferPointer getDownsampleFramebuffer();
gpu::TexturePointer getHalfLinearDepthTexture();
gpu::TexturePointer getHalfNormalTexture();
// Update the depth buffer which will drive the allocation of all the other resources according to its size.
void update(const gpu::TexturePointer& depthBuffer);
void update(const gpu::TexturePointer& depthBuffer, const gpu::TexturePointer& normalTexture);
const glm::ivec2& getDepthFrameSize() const { return _frameSize; }
void setResolutionLevel(int level) { _resolutionLevel = std::max(0, level); }
@ -48,6 +49,7 @@ protected:
gpu::FramebufferPointer _linearDepthFramebuffer;
gpu::TexturePointer _linearDepthTexture;
gpu::TexturePointer _normalTexture;
gpu::FramebufferPointer _downsampleFramebuffer;
gpu::TexturePointer _halfLinearDepthTexture;

View file

@ -89,6 +89,7 @@
#define RENDER_UTILS_BUFFER_SSAO_BLUR_PARAMS 4
#define RENDER_UTILS_BUFFER_SSAO_FRAME_PARAMS 5
#define RENDER_UTILS_TEXTURE_SSAO_DEPTH 1
#define RENDER_UTILS_TEXTURE_SSAO_NORMAL 2
#define RENDER_UTILS_TEXTURE_SSAO_OCCLUSION 0
// Temporal anti-aliasing
@ -196,6 +197,7 @@ enum Texture {
TaaNext = RENDER_UTILS_TEXTURE_TAA_NEXT,
SsaoOcclusion = RENDER_UTILS_TEXTURE_SSAO_OCCLUSION,
SsaoDepth = RENDER_UTILS_TEXTURE_SSAO_DEPTH,
SsaoNormal = RENDER_UTILS_TEXTURE_SSAO_NORMAL,
HighlightSceneDepth = RENDER_UTILS_TEXTURE_HIGHLIGHT_SCENE_DEPTH,
HighlightDepth = RENDER_UTILS_TEXTURE_HIGHLIGHT_DEPTH,
SurfaceGeometryDepth = RENDER_UTILS_TEXTURE_SG_DEPTH,

View file

@ -0,0 +1 @@
VERTEX gpu::vertex::DrawViewportQuadTransformTexcoord

View file

@ -98,32 +98,13 @@ float getBlurEdgeSharpness() {
return params._blurInfo.x;
}
#ifdef CONSTANT_GAUSSIAN
const int BLUR_RADIUS = 4;
const float gaussian[BLUR_RADIUS + 1] =
// KEEP this dead code for eventual performance improvment
// float[](0.356642, 0.239400, 0.072410, 0.009869);
// float[](0.398943, 0.241971, 0.053991, 0.004432, 0.000134); // stddev = 1.0
float[](0.153170, 0.144893, 0.122649, 0.092902, 0.062970); // stddev = 2.0
//float[](0.197413, 0.17467, 0.12098,0.065591,0.040059);
// float[](0.111220, 0.107798, 0.098151, 0.083953, 0.067458, 0.050920, 0.036108); // stddev = 3.0
int getBlurRadius() {
return BLUR_RADIUS;
}
float getBlurCoef(int c) {
return gaussian[c];
}
#else
int getBlurRadius() {
return int(params._blurInfo.y);
}
float getBlurCoef(int c) {
return params._gaussianCoefs[c];
return params._blurFilterTaps[c];
}
#endif
<@endfunc@>
@ -219,6 +200,7 @@ vec3 getTapLocationClampedSSAO(int sampleNumber, float spinAngle, float outerRad
// the depth pyramid texture
layout(binding=RENDER_UTILS_TEXTURE_SSAO_DEPTH) uniform sampler2D depthPyramidTex;
layout(binding=RENDER_UTILS_TEXTURE_SSAO_NORMAL) uniform sampler2D normalTex;
float getZEyeAtPixel(ivec2 pixel, int level) {
return -texelFetch(depthPyramidTex, pixel, level).x;
@ -228,8 +210,12 @@ float getZEyeAtUV(vec2 texCoord, int level) {
return -texture(depthPyramidTex, texCoord, level).x;
}
vec3 getNormalEyeAtUV(vec2 texCoord, int level) {
return normalize(texture(normalTex, texCoord, level).xyz*2.0 - vec3(1.0));
}
int evalMipFromRadius(float radius) {
const int LOG_MAX_OFFSET = 1;
const int LOG_MAX_OFFSET = 2;
const int MAX_MIP_LEVEL = 5;
return clamp(findMSB(int(radius)) - LOG_MAX_OFFSET, 0, MAX_MIP_LEVEL);
}
@ -406,24 +392,22 @@ float fetchOcclusion(vec2 coords) {
return raw.x;
}
const float BLUR_WEIGHT_OFFSET = 0.01;
const float BLUR_EDGE_DISTANCE_SCALE = 300.0;
vec2 evalTapWeightedValue(ivec3 side, int r, ivec2 destPixelCoord, vec2 scaledTexCoord, vec2 fullTexCoord, float fragDepth) {
ivec2 tapOffset = <$axis$> * r;
ivec2 tapPixelCoord = destPixelCoord + tapOffset;
ivec2 tapPixelCoord = destPixelCoord + ivec2(tapOffset);
if ((tapPixelCoord.x < side.y || tapPixelCoord.x >= side.z + side.y) || (tapPixelCoord.y < 0 || tapPixelCoord.y >= getBlurImageHeight())) {
return vec2(0.0);
}
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));
float weight = getBlurCoef(abs(r));
// range domain (the "bilateral" weight). As depth difference increases, decrease weight.
float zDistance = tapDepth - fragDepth;
@ -441,6 +425,7 @@ vec3 getBlurredOcclusion(ivec2 destPixelCoord, vec2 scaledTexCoord, vec2 fullTex
// 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, destPixelCoord, scaledTexCoord, fullTexCoord, fragDepth);

View file

@ -0,0 +1,45 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
//
// ssao_buildNormals.frag
//
// Created by Olivier Prat on 09/19/18.
// 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 ssao.slh@>
<$declareAmbientOcclusion()$>
<$declareFetchDepthPyramidMap()$>
layout(location=0) out vec4 outFragColor;
void main(void) {
vec2 sideImageSize = getSideImageSize(0);
// Pixel being shaded
vec2 fragCoord = gl_FragCoord.xy;
ivec2 fragPixelPos = ivec2(fragCoord.xy);
// Stereo side info
ivec4 side = getStereoSideInfo(fragPixelPos.x, 0);
// From now on, fragPixelPos is the pixel pos in the side
fragPixelPos.x -= side.y;
vec2 fragUVPos = (vec2(fragPixelPos) + vec2(0.5)) / sideImageSize;
// 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);
vec3 absFragNormalES = abs(fragNormalES);
// Maximize encoding precision
fragNormalES /= max(max(absFragNormalES.x, absFragNormalES.y), absFragNormalES.z);
outFragColor = vec4(vec3(fragNormalES)*0.5 + vec3(0.5), 1.0);
}

View file

@ -46,7 +46,11 @@ void main(void) {
// The position and normal of the pixel fragment in Eye space
vec3 fragPositionES = evalEyePositionFromZeye(side.x, Zeye, fragUVPos);
#if SSAO_USE_QUAD_SPLIT
vec3 fragNormalES = getNormalEyeAtUV(fragUVPos, 0);
#else
vec3 fragNormalES = evalEyeNormal(fragPositionES);
#endif
// Choose the screen-space sample radius
float diskPixelRadius = evalDiskRadius(fragPositionES.z, sideImageSize);

View file

@ -39,7 +39,7 @@ struct AmbientOcclusionParams {
SSAO_VEC4 _ditheringInfo;
SSAO_VEC4 _sampleInfo;
SSAO_VEC4 _blurInfo;
float _gaussianCoefs[SSAO_BLUR_GAUSSIAN_COEFS_COUNT];
float _blurFilterTaps[SSAO_BLUR_GAUSSIAN_COEFS_COUNT];
};
struct AmbientOcclusionFrameParams {

View file

@ -35,11 +35,12 @@ Rectangle {
model: [
"Radius:radius:2.0:false",
"Level:obscuranceLevel:1.0:false",
"Num Taps:numSamples:32:true",
"Num Taps:numSamples:16:true",
"Taps Spiral:numSpiralTurns:10.0:false",
"Falloff Angle:falloffAngle:0.5:false",
"Blur Edge Sharpness:edgeSharpness:1.0:false",
"Blur Radius:blurRadius:15.0:false",
"Blur Radius:blurRadius:15.0:true",
"Resolution Downscale:resolutionLevel:2:true",
]
ConfigSlider {
label: qsTr(modelData.split(":")[0])
@ -57,7 +58,6 @@ Rectangle {
Column {
Repeater {
model: [
"resolutionLevel:resolutionLevel",
"ditheringEnabled:ditheringEnabled",
"fetchMipsEnabled:fetchMipsEnabled",
"borderingEnabled:borderingEnabled"