Small bilateral blur optim

This commit is contained in:
Olivier Prat 2018-10-02 12:25:00 +02:00
parent 6420d96149
commit 1ed0bd68b9
4 changed files with 40 additions and 23 deletions

View file

@ -220,7 +220,7 @@ AmbientOcclusionEffectConfig::AmbientOcclusionEffectConfig() :
borderingEnabled{ true }, borderingEnabled{ true },
fetchMipsEnabled{ true }, fetchMipsEnabled{ true },
horizonBased{ true }, horizonBased{ true },
jitterEnabled{ true }{ jitterEnabled{ false }{
} }
AmbientOcclusionEffect::AOParameters::AOParameters() { AmbientOcclusionEffect::AOParameters::AOParameters() {

View file

@ -32,14 +32,20 @@ vec4 packOcclusionOutput(float occlusion, float depth, vec3 eyeNormal) {
#endif #endif
} }
void unpackOcclusionOutput(vec4 raw, out float occlusion, out float depth, out vec3 eyeNormal) { struct UnpackedOcclusion {
occlusion = raw.x; vec3 normal;
float depth;
float occlusion;
};
void unpackOcclusionOutput(vec4 raw, out UnpackedOcclusion result) {
result.occlusion = raw.x;
#if SSAO_BILATERAL_BLUR_USE_NORMAL #if SSAO_BILATERAL_BLUR_USE_NORMAL
depth = raw.y; result.depth = raw.y;
eyeNormal = normalize(vec3(raw.zw, 1.0)); result.normal = normalize(vec3(raw.zw, 1.0));
#else #else
depth = (raw.y + raw.z / 256.0); result.depth = (raw.y + raw.z / 256.0);
eyeNormal = vec3(0,0,1); result.normal = vec3(0,0,1);
#endif #endif
} }
@ -391,6 +397,7 @@ float evalVisibilitySSAO(in vec3 centerPosition, in vec3 centerNormal, in vec3 t
} }
#define HBAO_USE_COS_ANGLE 1 #define HBAO_USE_COS_ANGLE 1
#define HBAO_USE_OVERHANG_HACK 0
float computeWeightForHorizon(float horizonLimit, float distanceSquared) { float computeWeightForHorizon(float horizonLimit, float distanceSquared) {
return max(0.0, 1.0 - distanceSquared / getRadius2()); return max(0.0, 1.0 - distanceSquared / getRadius2());
@ -433,11 +440,14 @@ float computeWeightedHorizon(float horizonLimit, float distanceSquared) {
if (tapHorizonLimit > horizonLimit) { if (tapHorizonLimit > horizonLimit) {
occlusion += weight * (tapHorizonLimit - horizonLimit); occlusion += weight * (tapHorizonLimit - horizonLimit);
horizonLimit = tapHorizonLimit; horizonLimit = tapHorizonLimit;
} /*else if (dot(deltaVec, fragFrameES.tangent) < 0.0) { }
#if HBAO_USE_OVERHANG_HACK
else if (dot(deltaVec, fragFrameES.tangent) < 0.0) {
// This is a hack to try to handle the case where the occlusion angle is // This is a hack to try to handle the case where the occlusion angle is
// greater than 90° // greater than 90°
occlusion = mix(occlusion, (occlusion+1.0) * 0.5, weight); occlusion = mix(occlusion, (occlusion+1.0) * 0.5, weight);
}*/ }
#endif
#else #else
if (tapHorizonLimit < horizonLimit) { if (tapHorizonLimit < horizonLimit) {
tapHorizonLimit = computeWeightedHorizon(tapHorizonLimit, distanceSquared); tapHorizonLimit = computeWeightedHorizon(tapHorizonLimit, distanceSquared);
@ -509,13 +519,16 @@ float evalVisibilityHBAO(ivec4 side, vec2 fragUVPos, vec2 invSideImageSize, vec2
pixelSearchVec = abs(pixelSearchVec); pixelSearchVec = abs(pixelSearchVec);
int stepCount = int(ceil(max(pixelSearchVec.x, pixelSearchVec.y))); int stepCount = int(ceil(max(pixelSearchVec.x, pixelSearchVec.y)));
#if HBAO_USE_OVERHANG_HACK || !HBAO_USE_COS_ANGLE
fragFrameES.tangent = normalize(fragFrameES.tangent * deltaTap.x + fragFrameES.binormal * deltaTap.y); fragFrameES.tangent = normalize(fragFrameES.tangent * deltaTap.x + fragFrameES.binormal * deltaTap.y);
#endif
// Forward search for h1 // Forward search for h1
obscuranceH1 = computeOcclusion(side, fragUVPos, fragPositionES, fragFrameES, searchDir, diskPixelRadius, stepCount); obscuranceH1 = computeOcclusion(side, fragUVPos, fragPositionES, fragFrameES, searchDir, diskPixelRadius, stepCount);
// Backward search for h2 // Backward search for h2
#if HBAO_USE_OVERHANG_HACK || !HBAO_USE_COS_ANGLE
fragFrameES.tangent = -fragFrameES.tangent; fragFrameES.tangent = -fragFrameES.tangent;
#endif
obscuranceH2 = computeOcclusion(side, fragUVPos, fragPositionES, fragFrameES, -searchDir, diskPixelRadius, stepCount); obscuranceH2 = computeOcclusion(side, fragUVPos, fragPositionES, fragFrameES, -searchDir, diskPixelRadius, stepCount);
return obscuranceH1 + obscuranceH2; return obscuranceH1 + obscuranceH2;

View file

@ -55,29 +55,26 @@ float evalBlurCoefficient(vec3 blurScales, float radialDistance, float zDistance
const float BLUR_EDGE_NORMAL_LIMIT = 0.25; const float BLUR_EDGE_NORMAL_LIMIT = 0.25;
vec2 evalTapWeightedValue(vec3 blurScales, ivec4 side, int r, vec2 occlusionTexCoord, float fragDepth, vec3 fragNormal) { vec2 evalTapWeightedValue(vec3 blurScales, ivec4 side, int r, vec2 occlusionTexCoord, float fragDepth, vec3 fragNormal) {
vec2 tapOcclusionTexCoord = getBlurOcclusionAxis() * r + occlusionTexCoord;
vec2 occlusionTexCoordLimits = getBlurOcclusionUVLimit(); vec2 occlusionTexCoordLimits = getBlurOcclusionUVLimit();
if (any(lessThan(tapOcclusionTexCoord, vec2(0.0))) || any(greaterThanEqual(tapOcclusionTexCoord, occlusionTexCoordLimits)) ) { if (any(lessThan(occlusionTexCoord, vec2(0.0))) || any(greaterThanEqual(occlusionTexCoord, occlusionTexCoordLimits)) ) {
return vec2(0.0); return vec2(0.0);
} }
vec4 tapOcclusionPacked = fetchOcclusionPacked(side, tapOcclusionTexCoord); vec4 tapOcclusionPacked = fetchOcclusionPacked(side, occlusionTexCoord);
float tapOcclusion; UnpackedOcclusion tap;
float tapDepth; unpackOcclusionOutput(tapOcclusionPacked, tap);
vec3 tapNormal;
unpackOcclusionOutput(tapOcclusionPacked, tapOcclusion, tapDepth, tapNormal);
// range domain (the "bilateral" weight). As depth difference increases, decrease weight. // range domain (the "bilateral" weight). As depth difference increases, decrease weight.
float zDistance = tapDepth - fragDepth; float zDistance = tap.depth - fragDepth;
#if SSAO_BILATERAL_BLUR_USE_NORMAL #if SSAO_BILATERAL_BLUR_USE_NORMAL
float normalDistance = BLUR_EDGE_NORMAL_LIMIT - min(BLUR_EDGE_NORMAL_LIMIT, dot(tapNormal, fragNormal)); float normalDistance = BLUR_EDGE_NORMAL_LIMIT - min(BLUR_EDGE_NORMAL_LIMIT, dot(tap.normal, fragNormal));
#else #else
float normalDistance = 0.0; float normalDistance = 0.0;
#endif #endif
float weight = evalBlurCoefficient(blurScales, abs(r), zDistance, normalDistance); float weight = evalBlurCoefficient(blurScales, abs(r), zDistance, normalDistance);
return vec2(tapOcclusion * weight, weight); return vec2(tap.occlusion * weight, weight);
} }
vec4 getBlurredOcclusion(ivec2 destPixelCoord, vec2 occlusionTexCoord, vec2 depthTexCoord) { vec4 getBlurredOcclusion(ivec2 destPixelCoord, vec2 occlusionTexCoord, vec2 depthTexCoord) {
@ -96,24 +93,30 @@ vec4 getBlurredOcclusion(ivec2 destPixelCoord, vec2 occlusionTexCoord, vec2 dept
// 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();
vec3 blurScales = getBlurScales(); vec3 blurScales = getBlurScales();
int r;
// From now on, occlusionTexCoord is the UV pos in the side // From now on, occlusionTexCoord is the UV pos in the side
float sideTexCoord = occlusionTexCoord.x * 2.0 - getStereoSide(side) * getBlurOcclusionUVLimit().x; float sideTexCoord = occlusionTexCoord.x * 2.0 - getStereoSide(side) * getBlurOcclusionUVLimit().x;
occlusionTexCoord.x = mix(occlusionTexCoord.x, sideTexCoord, isStereo()); occlusionTexCoord.x = mix(occlusionTexCoord.x, sideTexCoord, isStereo());
occlusionTexCoord -= getBlurOcclusionAxis() * blurRadius;
// negative side first // negative side first
for (int r = -blurRadius; r <= -1; ++r) { for (r = -blurRadius; r <= -1; r++) {
weightedSums += evalTapWeightedValue(blurScales, side, r, occlusionTexCoord, fragDepthKey, fragNormal); weightedSums += evalTapWeightedValue(blurScales, side, r, occlusionTexCoord, fragDepthKey, fragNormal);
occlusionTexCoord += getBlurOcclusionAxis();
} }
// Central pixel contribution // Central pixel contribution
float mainWeight = 1.0; float mainWeight = 1.0;
float pixelOcclusion = unpackOcclusion(fetchOcclusionPacked(side, occlusionTexCoord)); float pixelOcclusion = unpackOcclusion(fetchOcclusionPacked(side, occlusionTexCoord));
weightedSums += vec2(pixelOcclusion * mainWeight, mainWeight); weightedSums += vec2(pixelOcclusion * mainWeight, mainWeight);
occlusionTexCoord += getBlurOcclusionAxis();
// then positive side // then positive side
for (int r = 1; r <= blurRadius; ++r) { for (r = 1; r <= blurRadius; ++r) {
weightedSums += evalTapWeightedValue(blurScales, side, r, occlusionTexCoord, fragDepthKey, fragNormal); weightedSums += evalTapWeightedValue(blurScales, side, r, occlusionTexCoord, fragDepthKey, fragNormal);
occlusionTexCoord += getBlurOcclusionAxis();
} }
// Final normalization // Final normalization

View file

@ -60,8 +60,9 @@ void main(void) {
fragFrameES.tangent = vec3(0.0); fragFrameES.tangent = vec3(0.0);
fragFrameES.binormal = vec3(0.0); fragFrameES.binormal = vec3(0.0);
fragFrameES.normal = fragNormalES; fragFrameES.normal = fragNormalES;
#if HBAO_USE_OVERHANG_HACK || !HBAO_USE_COS_ANGLE
buildTangentBinormal(side, fragUVPos, fragPositionES, fragNormalES, deltaDepthUV, fragFrameES.tangent, fragFrameES.binormal); buildTangentBinormal(side, fragUVPos, fragPositionES, fragNormalES, deltaDepthUV, fragFrameES.tangent, fragFrameES.binormal);
#endif
// Let's make noise // Let's make noise
float randomPatternRotationAngle = getAngleDithering(fragPixelPos); float randomPatternRotationAngle = getAngleDithering(fragPixelPos);