From 8006d7c0522ac787f7f242a8715e195ce71e01d3 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 13 Sep 2018 15:33:44 +0200 Subject: [PATCH] Blur is now at occlusion resolution and added some bias to prevent AO on silhouettes --- .../src/AmbientOcclusionEffect.cpp | 14 +++++++++---- .../render-utils/src/AmbientOcclusionEffect.h | 4 ++++ libraries/render-utils/src/ssao.slh | 20 +++++++++++-------- .../utilities/render/ambientOcclusionPass.qml | 3 ++- 4 files changed, 28 insertions(+), 13 deletions(-) diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.cpp b/libraries/render-utils/src/AmbientOcclusionEffect.cpp index 8d28fae760..fe9f4fc46b 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.cpp +++ b/libraries/render-utils/src/AmbientOcclusionEffect.cpp @@ -182,6 +182,7 @@ AmbientOcclusionEffectConfig::AmbientOcclusionEffectConfig() : perspectiveScale{ 1.0f }, obscuranceLevel{ 0.5f }, falloffBias{ 0.01f }, + silhouetteRadius{ 0.3f }, edgeSharpness{ 1.0f }, blurDeviation{ 2.5f }, numSpiralTurns{ 7.0f }, @@ -296,6 +297,11 @@ void AmbientOcclusionEffect::configure(const Config& config) { current.w = (float)config.borderingEnabled; } + if (config.silhouetteRadius != _aoParametersBuffer->getSilhouetteRadius()) { + auto& current = _aoParametersBuffer.edit().ditheringInfo; + current.y = (float)config.silhouetteRadius; + } + if (shouldUpdateGaussian) { updateGaussianDistribution(); } @@ -312,12 +318,12 @@ void AmbientOcclusionEffect::updateBlurParameters() { 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.x = 1.0f / frameSize.x; + hblur.scaleHeight.y = float(resolutionScale) / 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.x = 1.0f / frameSize.y; + vblur.scaleHeight.y = float(resolutionScale) / frameSize.y; vblur.scaleHeight.z = frameSize.y; } diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.h b/libraries/render-utils/src/AmbientOcclusionEffect.h index b44569eb89..48752ba3b6 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.h +++ b/libraries/render-utils/src/AmbientOcclusionEffect.h @@ -63,6 +63,7 @@ class AmbientOcclusionEffectConfig : public render::GPUJobConfig::Persistent { Q_PROPERTY(float radius MEMBER radius WRITE setRadius) Q_PROPERTY(float obscuranceLevel MEMBER obscuranceLevel WRITE setObscuranceLevel) Q_PROPERTY(float falloffBias MEMBER falloffBias WRITE setFalloffBias) + Q_PROPERTY(float silhouetteRadius MEMBER silhouetteRadius WRITE setSilhouetteRadius) Q_PROPERTY(float edgeSharpness MEMBER edgeSharpness WRITE setEdgeSharpness) Q_PROPERTY(float blurDeviation MEMBER blurDeviation WRITE setBlurDeviation) Q_PROPERTY(float numSpiralTurns MEMBER numSpiralTurns WRITE setNumSpiralTurns) @@ -79,6 +80,7 @@ public: void setRadius(float newRadius) { radius = std::max(0.01f, newRadius); emit dirty(); } void setObscuranceLevel(float level) { obscuranceLevel = std::max(0.01f, level); emit dirty(); } void setFalloffBias(float bias) { falloffBias = std::max(0.0f, std::min(bias, 0.2f)); emit dirty(); } + void setSilhouetteRadius(float value) { silhouetteRadius = std::max(0.0f, value); emit dirty(); } void setEdgeSharpness(float sharpness) { edgeSharpness = std::max(0.0f, (float)sharpness); emit dirty(); } void setBlurDeviation(float deviation) { blurDeviation = std::max(0.0f, deviation); emit dirty(); } void setNumSpiralTurns(float turns) { numSpiralTurns = std::max(0.0f, (float)turns); emit dirty(); } @@ -90,6 +92,7 @@ public: float perspectiveScale; float obscuranceLevel; // intensify or dim down the obscurance effect float falloffBias; + float silhouetteRadius; float edgeSharpness; float blurDeviation; float numSpiralTurns; // defining an angle span to distribute the samples ray directions @@ -143,6 +146,7 @@ public: float getFalloffBias() const { return (float)ditheringInfo.z; } float getEdgeSharpness() const { return (float)blurInfo.x; } float getBlurDeviation() const { return blurInfo.z; } + float getSilhouetteRadius() const { return ditheringInfo.y; } float getNumSpiralTurns() const { return sampleInfo.z; } int getNumSamples() const { return (int)sampleInfo.x; } diff --git a/libraries/render-utils/src/ssao.slh b/libraries/render-utils/src/ssao.slh index d974a83104..71ad578485 100644 --- a/libraries/render-utils/src/ssao.slh +++ b/libraries/render-utils/src/ssao.slh @@ -67,6 +67,7 @@ float getRadius2() { float getInvRadius6() { return params._radiusInfo.z; } + float getObscuranceScaling() { return params._radiusInfo.z * params._radiusInfo.w; } @@ -74,7 +75,7 @@ float getObscuranceScaling() { float isDitheringEnabled() { return params._ditheringInfo.x; } -float getFrameDithering() { +float getSilhouetteRadius() { return params._ditheringInfo.y; } float isBorderingEnabled() { @@ -139,12 +140,12 @@ float getAngleDitheringWorldPos(in vec3 pixelWorldPos) { ivec3 pixelPos = ivec3(worldPosFract * 256.0); - return isDitheringEnabled() * float(((3 * pixelPos.x ^ pixelPos.y + pixelPos.x * pixelPos.y) + (3 * pixelPos.y ^ pixelPos.z + pixelPos.x * pixelPos.z)) * 10) + getFrameDithering(); + return isDitheringEnabled() * float(((3 * pixelPos.x ^ pixelPos.y + pixelPos.x * pixelPos.y) + (3 * pixelPos.y ^ pixelPos.z + pixelPos.x * pixelPos.z)) * 10); } float getAngleDithering(in ivec2 pixelPos) { // Hash function used in the AlchemyAO paper - return isDitheringEnabled() * float((3 * pixelPos.x ^ pixelPos.y + pixelPos.x * pixelPos.y) * 10) + getFrameDithering(); + return isDitheringEnabled() * float((3 * pixelPos.x ^ pixelPos.y + pixelPos.x * pixelPos.y) * 10); } float evalDiskRadius(float Zeye, vec2 imageSize) { @@ -304,10 +305,13 @@ float evalVisibilitySSAO(in vec3 centerPosition, in vec3 centerNormal, in vec3 t vec3 tap = vec3(tapPixelPos, radius); vec3 tapUVZ = fetchTap(side, centerPixelPos, tap, imageSize); vec3 tapPositionES = evalEyePositionFromZeye(side.x, tapUVZ.z, tapUVZ.xy); - vec3 deltaVec = normalize(tapPositionES - fragPositionES); - float rawHorizon = dot(deltaVec, fragNormalES); + vec3 deltaVec = tapPositionES - fragPositionES; + float deltaVecHeight = dot(deltaVec, fragNormalES); + float rawHorizon = dot(normalize(deltaVec), fragNormalES); + float falloff = max(0.0, 1.0 - deltaVecHeight / getSilhouetteRadius()); - rawHorizon *= 1.0 - radius / ssDiskRadius; + rawHorizon = rawHorizon < getFalloffBias() ? 0.0f : rawHorizon; + rawHorizon *= falloff * falloff; <$horizon$> = max(<$horizon$>, rawHorizon); } @@ -455,8 +459,8 @@ float fetchOcclusion(vec2 coords) { return raw.x; } -const float BLUR_WEIGHT_OFFSET = 0.05; -const float BLUR_EDGE_SCALE = 100.0; +const float BLUR_WEIGHT_OFFSET = 0.01; +const float BLUR_EDGE_SCALE = 10.0; vec2 evalTapWeightedValue(ivec3 side, int r, ivec2 destPixelCoord, vec2 scaledTexCoord, vec2 fullTexCoord, float key) { ivec2 tapOffset = <$axis$> * r; diff --git a/scripts/developer/utilities/render/ambientOcclusionPass.qml b/scripts/developer/utilities/render/ambientOcclusionPass.qml index 179fc8341c..1e5a46f115 100644 --- a/scripts/developer/utilities/render/ambientOcclusionPass.qml +++ b/scripts/developer/utilities/render/ambientOcclusionPass.qml @@ -38,7 +38,8 @@ Rectangle { "Num Taps:numSamples:32:true", "Taps Spiral:numSpiralTurns:10.0:false", "Falloff Bias:falloffBias:0.2:false", - "Edge Sharpness:edgeSharpness:1.0:false", + "Silhouette Radius:silhouetteRadius:1.0:false", + "Blur Edge Sharpness:edgeSharpness:1.0:false", "Blur Radius:blurRadius:10.0:false", ] ConfigSlider {