mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 11:45:36 +02:00
Bilateral blur
This commit is contained in:
parent
6c0309402f
commit
45b4881edc
11 changed files with 251 additions and 99 deletions
|
@ -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);
|
||||
|
|
|
@ -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>;
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -1 +1 @@
|
|||
VERTEX gpu::vertex::DrawViewportQuadTransformTexcoord
|
||||
VERTEX ssao_blur
|
||||
|
|
|
@ -1 +1 @@
|
|||
VERTEX gpu::vertex::DrawViewportQuadTransformTexcoord
|
||||
VERTEX ssao_blur
|
||||
|
|
|
@ -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@>
|
||||
|
|
42
libraries/render-utils/src/ssao_blur.slv
Normal file
42
libraries/render-utils/src/ssao_blur.slv
Normal 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;
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue