mirror of
https://github.com/overte-org/overte.git
synced 2025-08-06 18:50:00 +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() {
|
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
|
//If the depth buffer or size changed, we need to delete our FBOs
|
||||||
bool reset = false;
|
bool reset = false;
|
||||||
if ((_linearDepthTexture != linearDepthBuffer)) {
|
if ((_linearDepthTexture != linearDepthBuffer)) {
|
||||||
|
@ -59,6 +59,8 @@ void AmbientOcclusionFramebuffer::updateLinearDepth(const gpu::TexturePointer& l
|
||||||
if (reset) {
|
if (reset) {
|
||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return reset;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AmbientOcclusionFramebuffer::clear() {
|
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() {
|
AmbientOcclusionEffect::AmbientOcclusionEffect() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,11 +214,12 @@ void AmbientOcclusionEffect::configure(const Config& config) {
|
||||||
DependencyManager::get<DeferredLightingEffect>()->setAmbientOcclusionEnabled(config.enabled);
|
DependencyManager::get<DeferredLightingEffect>()->setAmbientOcclusionEnabled(config.enabled);
|
||||||
|
|
||||||
bool shouldUpdateGaussian = false;
|
bool shouldUpdateGaussian = false;
|
||||||
|
bool shouldUpdateBlurs = false;
|
||||||
|
|
||||||
const double RADIUS_POWER = 6.0;
|
const double RADIUS_POWER = 6.0;
|
||||||
const auto& radius = config.radius;
|
const auto& radius = config.radius;
|
||||||
if (radius != _parametersBuffer->getRadius()) {
|
if (radius != _aoParametersBuffer->getRadius()) {
|
||||||
auto& current = _parametersBuffer.edit().radiusInfo;
|
auto& current = _aoParametersBuffer.edit().radiusInfo;
|
||||||
current.x = radius;
|
current.x = radius;
|
||||||
current.y = radius * radius;
|
current.y = radius * radius;
|
||||||
current.z = 10.0f;
|
current.z = 10.0f;
|
||||||
|
@ -190,74 +228,97 @@ void AmbientOcclusionEffect::configure(const Config& config) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.obscuranceLevel != _parametersBuffer->getObscuranceLevel()) {
|
if (config.obscuranceLevel != _aoParametersBuffer->getObscuranceLevel()) {
|
||||||
auto& current = _parametersBuffer.edit().radiusInfo;
|
auto& current = _aoParametersBuffer.edit().radiusInfo;
|
||||||
current.w = config.obscuranceLevel;
|
current.w = config.obscuranceLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.falloffBias != _parametersBuffer->getFalloffBias()) {
|
if (config.falloffBias != _aoParametersBuffer->getFalloffBias()) {
|
||||||
auto& current = _parametersBuffer.edit().ditheringInfo;
|
auto& current = _aoParametersBuffer.edit().ditheringInfo;
|
||||||
current.z = config.falloffBias;
|
current.z = config.falloffBias;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.edgeSharpness != _parametersBuffer->getEdgeSharpness()) {
|
if (config.edgeSharpness != _aoParametersBuffer->getEdgeSharpness()) {
|
||||||
auto& current = _parametersBuffer.edit().blurInfo;
|
auto& current = _aoParametersBuffer.edit().blurInfo;
|
||||||
current.x = config.edgeSharpness;
|
current.x = config.edgeSharpness;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.blurDeviation != _parametersBuffer->getBlurDeviation()) {
|
if (config.blurDeviation != _aoParametersBuffer->getBlurDeviation()) {
|
||||||
auto& current = _parametersBuffer.edit().blurInfo;
|
auto& current = _aoParametersBuffer.edit().blurInfo;
|
||||||
current.z = config.blurDeviation;
|
current.z = config.blurDeviation;
|
||||||
shouldUpdateGaussian = true;
|
shouldUpdateGaussian = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.numSpiralTurns != _parametersBuffer->getNumSpiralTurns()) {
|
if (config.numSpiralTurns != _aoParametersBuffer->getNumSpiralTurns()) {
|
||||||
auto& current = _parametersBuffer.edit().sampleInfo;
|
auto& current = _aoParametersBuffer.edit().sampleInfo;
|
||||||
current.z = config.numSpiralTurns;
|
current.z = config.numSpiralTurns;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.numSamples != _parametersBuffer->getNumSamples()) {
|
if (config.numSamples != _aoParametersBuffer->getNumSamples()) {
|
||||||
auto& current = _parametersBuffer.edit().sampleInfo;
|
auto& current = _aoParametersBuffer.edit().sampleInfo;
|
||||||
current.x = config.numSamples;
|
current.x = config.numSamples;
|
||||||
current.y = 1.0f / config.numSamples;
|
current.y = 1.0f / config.numSamples;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.fetchMipsEnabled != _parametersBuffer->isFetchMipsEnabled()) {
|
if (config.fetchMipsEnabled != _aoParametersBuffer->isFetchMipsEnabled()) {
|
||||||
auto& current = _parametersBuffer.edit().sampleInfo;
|
auto& current = _aoParametersBuffer.edit().sampleInfo;
|
||||||
current.w = (float)config.fetchMipsEnabled;
|
current.w = (float)config.fetchMipsEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_framebuffer) {
|
if (!_framebuffer) {
|
||||||
_framebuffer = std::make_shared<AmbientOcclusionFramebuffer>();
|
_framebuffer = std::make_shared<AmbientOcclusionFramebuffer>();
|
||||||
|
shouldUpdateBlurs = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.perspectiveScale != _parametersBuffer->getPerspectiveScale()) {
|
if (config.perspectiveScale != _aoParametersBuffer->getPerspectiveScale()) {
|
||||||
_parametersBuffer.edit().resolutionInfo.z = config.perspectiveScale;
|
_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;
|
current.x = (float) config.resolutionLevel;
|
||||||
|
shouldUpdateBlurs = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.blurRadius != _parametersBuffer->getBlurRadius()) {
|
if (config.blurRadius != _aoParametersBuffer->getBlurRadius()) {
|
||||||
auto& current = _parametersBuffer.edit().blurInfo;
|
auto& current = _aoParametersBuffer.edit().blurInfo;
|
||||||
current.y = (float)config.blurRadius;
|
current.y = (float)config.blurRadius;
|
||||||
shouldUpdateGaussian = true;
|
shouldUpdateGaussian = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.ditheringEnabled != _parametersBuffer->isDitheringEnabled()) {
|
if (config.ditheringEnabled != _aoParametersBuffer->isDitheringEnabled()) {
|
||||||
auto& current = _parametersBuffer.edit().ditheringInfo;
|
auto& current = _aoParametersBuffer.edit().ditheringInfo;
|
||||||
current.x = (float)config.ditheringEnabled;
|
current.x = (float)config.ditheringEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.borderingEnabled != _parametersBuffer->isBorderingEnabled()) {
|
if (config.borderingEnabled != _aoParametersBuffer->isBorderingEnabled()) {
|
||||||
auto& current = _parametersBuffer.edit().ditheringInfo;
|
auto& current = _aoParametersBuffer.edit().ditheringInfo;
|
||||||
current.w = (float)config.borderingEnabled;
|
current.w = (float)config.borderingEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shouldUpdateGaussian) {
|
if (shouldUpdateGaussian) {
|
||||||
updateGaussianDistribution();
|
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() {
|
const gpu::PipelinePointer& AmbientOcclusionEffect::getOcclusionPipeline() {
|
||||||
|
@ -309,8 +370,8 @@ const gpu::PipelinePointer& AmbientOcclusionEffect::getMipCreationPipeline() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AmbientOcclusionEffect::updateGaussianDistribution() {
|
void AmbientOcclusionEffect::updateGaussianDistribution() {
|
||||||
auto coefs = _parametersBuffer.edit()._gaussianCoefs;
|
auto coefs = _aoParametersBuffer.edit()._gaussianCoefs;
|
||||||
GaussianDistribution::evalSampling(coefs, Parameters::GAUSSIAN_COEFS_LENGTH, _parametersBuffer->getBlurRadius(), _parametersBuffer->getBlurDeviation());
|
GaussianDistribution::evalSampling(coefs, AOParameters::GAUSSIAN_COEFS_LENGTH, _aoParametersBuffer->getBlurRadius(), _aoParametersBuffer->getBlurDeviation());
|
||||||
}
|
}
|
||||||
|
|
||||||
void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs) {
|
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 linearDepthTexture = linearDepthFramebuffer->getLinearDepthTexture();
|
||||||
auto sourceViewport = args->_viewport;
|
auto sourceViewport = args->_viewport;
|
||||||
auto occlusionViewport = sourceViewport;
|
auto occlusionViewport = sourceViewport;
|
||||||
|
auto firstBlurViewport = sourceViewport;
|
||||||
|
|
||||||
if (!_gpuTimer) {
|
if (!_gpuTimer) {
|
||||||
_gpuTimer = std::make_shared < gpu::RangeTimer>(__FUNCTION__);
|
_gpuTimer = std::make_shared < gpu::RangeTimer>(__FUNCTION__);
|
||||||
|
@ -334,18 +396,21 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
|
||||||
_framebuffer = std::make_shared<AmbientOcclusionFramebuffer>();
|
_framebuffer = std::make_shared<AmbientOcclusionFramebuffer>();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_parametersBuffer->getResolutionLevel() > 0) {
|
const auto resolutionScale = powf(0.5f, _aoParametersBuffer->getResolutionLevel());
|
||||||
linearDepthTexture = linearDepthFramebuffer->getHalfLinearDepthTexture();
|
if (_aoParametersBuffer->getResolutionLevel() > 0) {
|
||||||
occlusionViewport = occlusionViewport >> _parametersBuffer->getResolutionLevel();
|
occlusionViewport = occlusionViewport >> _aoParametersBuffer->getResolutionLevel();
|
||||||
|
firstBlurViewport.w = firstBlurViewport.w >> _aoParametersBuffer->getResolutionLevel();
|
||||||
}
|
}
|
||||||
|
|
||||||
_framebuffer->updateLinearDepth(linearDepthTexture);
|
if (_framebuffer->updateLinearDepth(linearDepthTexture)) {
|
||||||
|
updateBlurParameters();
|
||||||
|
}
|
||||||
|
|
||||||
auto occlusionFBO = _framebuffer->getOcclusionFramebuffer();
|
auto occlusionFBO = _framebuffer->getOcclusionFramebuffer();
|
||||||
auto occlusionBlurredFBO = _framebuffer->getOcclusionBlurredFramebuffer();
|
auto occlusionBlurredFBO = _framebuffer->getOcclusionBlurredFramebuffer();
|
||||||
|
|
||||||
outputs.edit0() = _framebuffer;
|
outputs.edit0() = _framebuffer;
|
||||||
outputs.edit1() = _parametersBuffer;
|
outputs.edit1() = _aoParametersBuffer;
|
||||||
|
|
||||||
auto framebufferSize = _framebuffer->getSourceFrameSize();
|
auto framebufferSize = _framebuffer->getSourceFrameSize();
|
||||||
|
|
||||||
|
@ -380,7 +445,7 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
|
||||||
batch.popProfileRange();
|
batch.popProfileRange();
|
||||||
|
|
||||||
batch.setUniformBuffer(render_utils::slot::buffer::DeferredFrameTransform, frameTransform->getFrameTransformBuffer());
|
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
|
// Occlusion pass
|
||||||
batch.setFramebuffer(occlusionFBO);
|
batch.setFramebuffer(occlusionFBO);
|
||||||
|
@ -389,16 +454,24 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
|
||||||
batch.setResourceTexture(render_utils::slot::texture::SsaoPyramid, _framebuffer->getLinearDepthTexture());
|
batch.setResourceTexture(render_utils::slot::texture::SsaoPyramid, _framebuffer->getLinearDepthTexture());
|
||||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||||
|
|
||||||
if (_parametersBuffer->getBlurRadius() > 0) {
|
/* TEMPO OP if (_aoParametersBuffer->getBlurRadius() > 0)*/ {
|
||||||
PROFILE_RANGE_BATCH(batch, "Blur");
|
PROFILE_RANGE_BATCH(batch, "Blur");
|
||||||
// Blur 1st pass
|
// Blur 1st pass
|
||||||
|
model.setScale(resolutionScale);
|
||||||
|
batch.setModelTransform(model);
|
||||||
|
batch.setViewportTransform(firstBlurViewport);
|
||||||
batch.setFramebuffer(occlusionBlurredFBO);
|
batch.setFramebuffer(occlusionBlurredFBO);
|
||||||
|
batch.setUniformBuffer(render_utils::slot::buffer::SsaoBlurParams, _hblurParametersBuffer);
|
||||||
batch.setPipeline(firstHBlurPipeline);
|
batch.setPipeline(firstHBlurPipeline);
|
||||||
batch.setResourceTexture(render_utils::slot::texture::SsaoOcclusion, occlusionFBO->getRenderBuffer(0));
|
batch.setResourceTexture(render_utils::slot::texture::SsaoOcclusion, occlusionFBO->getRenderBuffer(0));
|
||||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||||
|
|
||||||
// Blur 2nd pass
|
// Blur 2nd pass
|
||||||
|
model.setScale(glm::vec3(1.0f, resolutionScale, 1.0f));
|
||||||
|
batch.setModelTransform(model);
|
||||||
|
batch.setViewportTransform(sourceViewport);
|
||||||
batch.setFramebuffer(occlusionFBO);
|
batch.setFramebuffer(occlusionFBO);
|
||||||
|
batch.setUniformBuffer(render_utils::slot::buffer::SsaoBlurParams, _vblurParametersBuffer);
|
||||||
batch.setPipeline(lastVBlurPipeline);
|
batch.setPipeline(lastVBlurPipeline);
|
||||||
batch.setResourceTexture(render_utils::slot::texture::SsaoOcclusion, occlusionBlurredFBO->getRenderBuffer(0));
|
batch.setResourceTexture(render_utils::slot::texture::SsaoOcclusion, occlusionBlurredFBO->getRenderBuffer(0));
|
||||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||||
|
|
|
@ -32,7 +32,7 @@ public:
|
||||||
gpu::TexturePointer getOcclusionBlurredTexture();
|
gpu::TexturePointer getOcclusionBlurredTexture();
|
||||||
|
|
||||||
// Update the source framebuffer size which will drive the allocation of all the other resources.
|
// 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();
|
gpu::TexturePointer getLinearDepthTexture();
|
||||||
const glm::ivec2& getSourceFrameSize() const { return _frameSize; }
|
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)
|
Q_PROPERTY(int blurRadius MEMBER blurRadius WRITE setBlurRadius)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AmbientOcclusionEffectConfig() : render::GPUJobConfig::Persistent(QStringList() << "Render" << "Engine" << "Ambient Occlusion", false) {}
|
AmbientOcclusionEffectConfig();
|
||||||
|
|
||||||
const int MAX_RESOLUTION_LEVEL = 4;
|
const int MAX_RESOLUTION_LEVEL = 4;
|
||||||
const int MAX_BLUR_RADIUS = 6;
|
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 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(); }
|
void setBlurRadius(int radius) { blurRadius = std::max(0, std::min(MAX_BLUR_RADIUS, radius)); emit dirty(); }
|
||||||
|
|
||||||
float radius{ 0.5f };
|
float radius;
|
||||||
float perspectiveScale{ 1.0f };
|
float perspectiveScale;
|
||||||
float obscuranceLevel{ 0.5f }; // intensify or dim down the obscurance effect
|
float obscuranceLevel; // intensify or dim down the obscurance effect
|
||||||
float falloffBias{ 0.01f };
|
float falloffBias;
|
||||||
float edgeSharpness{ 1.0f };
|
float edgeSharpness;
|
||||||
float blurDeviation{ 2.5f };
|
float blurDeviation;
|
||||||
float numSpiralTurns{ 7.0f }; // defining an angle span to distribute the samples ray directions
|
float numSpiralTurns; // defining an angle span to distribute the samples ray directions
|
||||||
int numSamples{ 16 };
|
int numSamples;
|
||||||
int resolutionLevel{ 1 };
|
int resolutionLevel;
|
||||||
int blurRadius{ 4 }; // 0 means no blurring
|
int blurRadius; // 0 means no blurring
|
||||||
bool ditheringEnabled{ true }; // randomize the distribution of taps per pixel, should always be true
|
bool ditheringEnabled; // 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 borderingEnabled; // 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
|
bool fetchMipsEnabled; // fetch taps in sub mips to otpimize cache, should always be true
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void dirty();
|
void dirty();
|
||||||
|
@ -118,23 +118,23 @@ public:
|
||||||
|
|
||||||
|
|
||||||
// Class describing the uniform buffer with all the parameters common to the AO shaders
|
// Class describing the uniform buffer with all the parameters common to the AO shaders
|
||||||
class Parameters {
|
class AOParameters {
|
||||||
public:
|
public:
|
||||||
// Resolution info
|
// 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}
|
// 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
|
// Dithering info
|
||||||
glm::vec4 ditheringInfo { 0.0f, 0.0f, 0.01f, 1.0f };
|
glm::vec4 ditheringInfo;
|
||||||
// Sampling info
|
// Sampling info
|
||||||
glm::vec4 sampleInfo { 11.0f, 1.0f/11.0f, 7.0f, 1.0f };
|
glm::vec4 sampleInfo;
|
||||||
// Blurring info
|
// 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)
|
// gaussian distribution coefficients first is the sampling radius (max is 6)
|
||||||
const static int GAUSSIAN_COEFS_LENGTH = 8;
|
const static int GAUSSIAN_COEFS_LENGTH = 8;
|
||||||
float _gaussianCoefs[GAUSSIAN_COEFS_LENGTH];
|
float _gaussianCoefs[GAUSSIAN_COEFS_LENGTH];
|
||||||
|
|
||||||
Parameters() {}
|
AOParameters();
|
||||||
|
|
||||||
int getResolutionLevel() const { return resolutionInfo.x; }
|
int getResolutionLevel() const { return resolutionInfo.x; }
|
||||||
float getRadius() const { return radiusInfo.x; }
|
float getRadius() const { return radiusInfo.x; }
|
||||||
|
@ -152,12 +152,26 @@ public:
|
||||||
bool isDitheringEnabled() const { return ditheringInfo.x; }
|
bool isDitheringEnabled() const { return ditheringInfo.x; }
|
||||||
bool isBorderingEnabled() const { return ditheringInfo.w; }
|
bool isBorderingEnabled() const { return ditheringInfo.w; }
|
||||||
};
|
};
|
||||||
using ParametersBuffer = gpu::StructBuffer<Parameters>;
|
using AOParametersBuffer = gpu::StructBuffer<AOParameters>;
|
||||||
|
|
||||||
private:
|
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 updateGaussianDistribution();
|
||||||
|
void updateBlurParameters();
|
||||||
|
|
||||||
ParametersBuffer _parametersBuffer;
|
AOParametersBuffer _aoParametersBuffer;
|
||||||
|
BlurParametersBuffer _vblurParametersBuffer;
|
||||||
|
BlurParametersBuffer _hblurParametersBuffer;
|
||||||
|
|
||||||
static const gpu::PipelinePointer& getOcclusionPipeline();
|
static const gpu::PipelinePointer& getOcclusionPipeline();
|
||||||
static const gpu::PipelinePointer& getHBlurPipeline(); // first
|
static const gpu::PipelinePointer& getHBlurPipeline(); // first
|
||||||
|
@ -195,7 +209,7 @@ signals:
|
||||||
|
|
||||||
class DebugAmbientOcclusion {
|
class DebugAmbientOcclusion {
|
||||||
public:
|
public:
|
||||||
using Inputs = render::VaryingSet4<DeferredFrameTransformPointer, DeferredFramebufferPointer, LinearDepthFramebufferPointer, AmbientOcclusionEffect::ParametersBuffer>;
|
using Inputs = render::VaryingSet4<DeferredFrameTransformPointer, DeferredFramebufferPointer, LinearDepthFramebufferPointer, AmbientOcclusionEffect::AOParametersBuffer>;
|
||||||
using Config = DebugAmbientOcclusionConfig;
|
using Config = DebugAmbientOcclusionConfig;
|
||||||
using JobModel = render::Job::ModelI<DebugAmbientOcclusion, Inputs, Config>;
|
using JobModel = render::Job::ModelI<DebugAmbientOcclusion, Inputs, Config>;
|
||||||
|
|
||||||
|
|
|
@ -64,14 +64,15 @@ void LinearDepthFramebuffer::allocate() {
|
||||||
auto height = _frameSize.y;
|
auto height = _frameSize.y;
|
||||||
|
|
||||||
// For Linear Depth:
|
// 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));
|
gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT));
|
||||||
_linearDepthFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("linearDepth"));
|
_linearDepthFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("linearDepth"));
|
||||||
_linearDepthFramebuffer->setRenderBuffer(0, _linearDepthTexture);
|
_linearDepthFramebuffer->setRenderBuffer(0, _linearDepthTexture);
|
||||||
_linearDepthFramebuffer->setDepthStencilBuffer(_primaryDepthTexture, _primaryDepthTexture->getTexelFormat());
|
_linearDepthFramebuffer->setDepthStencilBuffer(_primaryDepthTexture, _primaryDepthTexture->getTexelFormat());
|
||||||
|
|
||||||
// For Downsampling:
|
// 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,
|
_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));
|
gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT));
|
||||||
|
|
||||||
|
|
|
@ -86,6 +86,7 @@
|
||||||
// Ambient occlusion
|
// Ambient occlusion
|
||||||
#define RENDER_UTILS_BUFFER_SSAO_PARAMS 2
|
#define RENDER_UTILS_BUFFER_SSAO_PARAMS 2
|
||||||
#define RENDER_UTILS_BUFFER_SSAO_DEBUG_PARAMS 3
|
#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_PYRAMID 1
|
||||||
#define RENDER_UTILS_TEXTURE_SSAO_OCCLUSION 0
|
#define RENDER_UTILS_TEXTURE_SSAO_OCCLUSION 0
|
||||||
|
|
||||||
|
@ -153,6 +154,7 @@ enum Buffer {
|
||||||
SsscParams = RENDER_UTILS_BUFFER_SSSC_PARAMS,
|
SsscParams = RENDER_UTILS_BUFFER_SSSC_PARAMS,
|
||||||
SsaoParams = RENDER_UTILS_BUFFER_SSAO_PARAMS,
|
SsaoParams = RENDER_UTILS_BUFFER_SSAO_PARAMS,
|
||||||
SsaoDebugParams = RENDER_UTILS_BUFFER_SSAO_DEBUG_PARAMS,
|
SsaoDebugParams = RENDER_UTILS_BUFFER_SSAO_DEBUG_PARAMS,
|
||||||
|
SsaoBlurParams = RENDER_UTILS_BUFFER_SSAO_BLUR_PARAMS,
|
||||||
LightIndex = RENDER_UTILS_BUFFER_LIGHT_INDEX,
|
LightIndex = RENDER_UTILS_BUFFER_LIGHT_INDEX,
|
||||||
TaaParams = RENDER_UTILS_BUFFER_TAA_PARAMS,
|
TaaParams = RENDER_UTILS_BUFFER_TAA_PARAMS,
|
||||||
HighlightParams = RENDER_UTILS_BUFFER_HIGHLIGHT_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()$>
|
<$declarePackOcclusionDepth()$>
|
||||||
<$declareAmbientOcclusion()$>
|
<$declareAmbientOcclusion()$>
|
||||||
|
<$declareFetchDepthPyramidMap()$>
|
||||||
|
|
||||||
// the source occlusion texture
|
// the source occlusion texture
|
||||||
layout(binding=RENDER_UTILS_TEXTURE_SSAO_OCCLUSION) uniform sampler2D occlusionMap;
|
layout(binding=RENDER_UTILS_TEXTURE_SSAO_OCCLUSION) uniform sampler2D occlusionMap;
|
||||||
|
|
||||||
|
struct BlurParams {
|
||||||
|
vec4 scaleHeight;
|
||||||
|
};
|
||||||
|
|
||||||
vec2 fetchOcclusionDepthRaw(ivec2 coords, out vec3 raw) {
|
layout(binding=RENDER_UTILS_BUFFER_SSAO_BLUR_PARAMS) uniform blurParamsBuffer {
|
||||||
raw = texelFetch(occlusionMap, coords, 0).xyz;
|
BlurParams blurParams;
|
||||||
return unpackOcclusionDepth(raw);
|
};
|
||||||
|
|
||||||
|
float getOcclusionBlurScale() {
|
||||||
|
return blurParams.scaleHeight.x;
|
||||||
}
|
}
|
||||||
|
|
||||||
vec2 fetchOcclusionDepth(ivec2 coords) {
|
float getDepthBlurScale() {
|
||||||
return unpackOcclusionDepth(texelFetch(occlusionMap, coords, 0).xyz);
|
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_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) {
|
vec2 evalTapWeightedValue(ivec3 side, int r, ivec2 destPixelCoord, vec2 scaledTexCoord, vec2 fullTexCoord, float key) {
|
||||||
ivec2 tapOffset = <$axis$> * (r * RADIUS_SCALE);
|
ivec2 tapOffset = <$axis$> * r;
|
||||||
ivec2 ssP = (ssC + tapOffset);
|
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);
|
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
|
// spatial domain: offset gaussian tap
|
||||||
float weight = BLUR_WEIGHT_OFFSET + getBlurCoef(abs(r));
|
float weight = BLUR_WEIGHT_OFFSET + getBlurCoef(abs(r));
|
||||||
|
|
||||||
// range domain (the "bilateral" weight). As depth difference increases, decrease weight.
|
// 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) {
|
vec3 getBlurredOcclusion(ivec2 destPixelCoord, vec2 scaledTexCoord, vec2 fullTexCoord) {
|
||||||
ivec2 ssC = ivec2(coord);
|
|
||||||
|
|
||||||
// Stereo side info
|
// Stereo side info
|
||||||
ivec4 side = getStereoSideInfo(ssC.x, getResolutionLevel());
|
ivec4 side = getStereoSideInfo(destPixelCoord.x, 0);
|
||||||
|
|
||||||
vec3 rawSample;
|
float pixelDepth = getZEyeAtUV(fullTexCoord, 0);
|
||||||
vec2 occlusionDepth = fetchOcclusionDepthRaw(ssC, rawSample);
|
vec2 weightedSums = vec2(0.0);
|
||||||
float key = occlusionDepth.y;
|
|
||||||
|
|
||||||
// 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
|
// Accumulate weighted contributions along the bluring axis in the [-radius, radius] range
|
||||||
int blurRadius = getBlurRadius();
|
int blurRadius = getBlurRadius();
|
||||||
// negative side first
|
// negative side first
|
||||||
for (int r = -blurRadius; r <= -1; ++r) {
|
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
|
// then positive side
|
||||||
for (int r = 1; r <= blurRadius; ++r) {
|
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
|
// Final normalization
|
||||||
const float epsilon = 0.0001;
|
const float epsilon = 0.0001;
|
||||||
float result = weightedSums.x / (weightedSums.y + epsilon);
|
float result = weightedSums.x / (weightedSums.y + epsilon);
|
||||||
|
|
||||||
rawSample.x = result;
|
return vec3(result);
|
||||||
return rawSample;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
<@endfunc@>
|
<@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);
|
const ivec2 horizontal = ivec2(1,0);
|
||||||
<$declareBlurPass(horizontal)$>
|
<$declareBlurPass(horizontal)$>
|
||||||
|
|
||||||
|
layout(location=0) in vec4 varTexCoord0;
|
||||||
|
|
||||||
layout(location=0) out vec4 outFragColor;
|
layout(location=0) out vec4 outFragColor;
|
||||||
|
|
||||||
void main(void) {
|
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;
|
vec2 fragCoord = gl_FragCoord.xy;
|
||||||
ivec2 centerPixelPos = ivec2(fragCoord.xy);
|
ivec2 centerPixelPos = ivec2(fragCoord.xy);
|
||||||
|
|
||||||
// Fetch the z under the pixel (stereo or not)
|
|
||||||
float Zeye = getZEyeAtPixel(centerPixelPos, 0);
|
|
||||||
|
|
||||||
// Stereo side info
|
// Stereo side info
|
||||||
ivec4 side = getStereoSideInfo(centerPixelPos.x, getResolutionLevel());
|
ivec4 side = getStereoSideInfo(centerPixelPos.x, getResolutionLevel());
|
||||||
|
|
||||||
|
@ -40,6 +37,9 @@ void main(void) {
|
||||||
centerPixelPos.x -= side.y;
|
centerPixelPos.x -= side.y;
|
||||||
vec2 fragUVPos = (vec2(centerPixelPos) + vec2(0.5)) / imageSize;
|
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
|
// The position and normal of the pixel fragment in Eye space
|
||||||
vec3 fragPositionES = evalEyePositionFromZeye(side.x, Zeye, fragUVPos);
|
vec3 fragPositionES = evalEyePositionFromZeye(side.x, Zeye, fragUVPos);
|
||||||
vec3 fragNormalES = evalEyeNormal(fragPositionES);
|
vec3 fragNormalES = evalEyeNormal(fragPositionES);
|
||||||
|
|
|
@ -15,9 +15,11 @@
|
||||||
const ivec2 vertical = ivec2(0,1);
|
const ivec2 vertical = ivec2(0,1);
|
||||||
<$declareBlurPass(vertical)$>
|
<$declareBlurPass(vertical)$>
|
||||||
|
|
||||||
|
layout(location=0) in vec4 varTexCoord0;
|
||||||
|
|
||||||
layout(location=0) out vec4 outFragColor;
|
layout(location=0) out vec4 outFragColor;
|
||||||
|
|
||||||
void main(void) {
|
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);
|
outFragColor = vec4(occlusion, 0.0, 0.0, occlusion);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue