overte-HifiExperiments/libraries/render-utils/src/ssao_bilateralBlur.slf
Olivier Prat 40b7b42f5b Bis
2018-11-08 12:29:01 +01:00

135 lines
4.5 KiB
Text

<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
//
// ssao_bilateralBlur.frag
//
// Created by Sam Gateau on 1/1/16.
// Copyright 2016 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@>
// Hack comment
<$declareAmbientOcclusion()$>
<$declareFetchDepthPyramidMap()$>
<$declarePackOcclusionDepth()$>
// the source occlusion texture
LAYOUT(binding=RENDER_UTILS_TEXTURE_SSAO_OCCLUSION) uniform sampler2D occlusionMap;
LAYOUT(binding=RENDER_UTILS_BUFFER_SSAO_BLUR_PARAMS) uniform blurParamsBuffer {
AmbientOcclusionBlurParams blurParams;
};
vec2 getBlurOcclusionAxis() {
return blurParams._blurAxis.xy;
}
vec2 getBlurOcclusionUVLimit() {
return blurParams._blurAxis.zw;
}
vec3 getBlurScales() {
return blurParams._blurInfo.xyz;
}
int getBlurRadius() {
return int(blurParams._blurInfo.w);
}
vec4 fetchOcclusionPacked(ivec4 side, vec2 texCoord) {
texCoord.x = isStereo() ? (texCoord.x + float(getStereoSide(side)) * getBlurOcclusionUVLimit().x) * 0.5 : texCoord.x;
return textureLod(occlusionMap, texCoord, 0.0);
}
float evalBlurCoefficient(vec3 blurScales, float radialDistance, float zDistance, float normalDistance) {
vec3 distances = vec3(radialDistance, zDistance, normalDistance);
return exp2(dot(blurScales, distances*distances));
}
const float BLUR_EDGE_NORMAL_LIMIT = 0.25;
vec2 evalTapWeightedValue(vec3 blurScales, ivec4 side, int r, vec2 occlusionTexCoord, float fragDepth, vec3 fragNormal) {
vec2 occlusionTexCoordLimits = getBlurOcclusionUVLimit();
if (any(lessThan(occlusionTexCoord, vec2(0.0))) || any(greaterThanEqual(occlusionTexCoord, occlusionTexCoordLimits)) ) {
return vec2(0.0);
}
vec4 tapOcclusionPacked = fetchOcclusionPacked(side, occlusionTexCoord);
UnpackedOcclusion tap;
unpackOcclusionOutput(tapOcclusionPacked, tap);
// range domain (the "bilateral" weight). As depth difference increases, decrease weight.
float zDistance = tap.depth - fragDepth;
#if SSAO_BILATERAL_BLUR_USE_NORMAL
float normalDistance = BLUR_EDGE_NORMAL_LIMIT - min(BLUR_EDGE_NORMAL_LIMIT, dot(tap.normal, fragNormal));
#else
float normalDistance = 0.0;
#endif
float weight = evalBlurCoefficient(blurScales, float(abs(r)), zDistance, normalDistance);
return vec2(tap.occlusion * weight, weight);
}
vec4 getBlurredOcclusion(ivec2 destPixelCoord, vec2 occlusionTexCoord, vec2 depthTexCoord) {
// Stereo side info
ivec4 side = getStereoSideInfo(destPixelCoord.x, 0);
float fragDepth = getZEyeAtUV(depthTexCoord, 0.0);
float fragDepthKey = CSZToDepthKey(fragDepth);
#if SSAO_BILATERAL_BLUR_USE_NORMAL
vec3 fragNormal = getNormalEyeAtUV(depthTexCoord, 0.0);
#else
vec3 fragNormal = vec3(0.0, 0.0, 1.0);
#endif
vec2 weightedSums = vec2(0.0);
// Accumulate weighted contributions along the bluring axis in the [-radius, radius] range
int blurRadius = getBlurRadius();
vec3 blurScales = getBlurScales();
int r;
// From now on, occlusionTexCoord is the UV pos in the side
float sideTexCoord = occlusionTexCoord.x * 2.0 - float(getStereoSide(side)) * getBlurOcclusionUVLimit().x;
occlusionTexCoord.x = mix(occlusionTexCoord.x, sideTexCoord, isStereo());
occlusionTexCoord -= getBlurOcclusionAxis() * float(blurRadius);
// negative side first
for (r = -blurRadius; r <= -1; r++) {
weightedSums += evalTapWeightedValue(blurScales, side, r, occlusionTexCoord, fragDepthKey, fragNormal);
occlusionTexCoord += getBlurOcclusionAxis();
}
// Central pixel contribution
float mainWeight = 1.0;
float pixelOcclusion = unpackOcclusion(fetchOcclusionPacked(side, occlusionTexCoord));
weightedSums += vec2(pixelOcclusion * mainWeight, mainWeight);
occlusionTexCoord += getBlurOcclusionAxis();
// then positive side
for (r = 1; r <= blurRadius; ++r) {
weightedSums += evalTapWeightedValue(blurScales, side, r, occlusionTexCoord, fragDepthKey, fragNormal);
occlusionTexCoord += getBlurOcclusionAxis();
}
// Final normalization
const float epsilon = 0.0001;
float result = weightedSums.x / (weightedSums.y + epsilon);
return packOcclusionOutput(result, fragDepth, fragNormal);
}
layout(location=0) in vec4 varTexCoord0;
layout(location=0) out vec4 outFragColor;
void main(void) {
outFragColor = getBlurredOcclusion(ivec2(gl_FragCoord.xy), varTexCoord0.xy, varTexCoord0.zw);
}