overte-thingvellir/libraries/render-utils/src/ssao_makeOcclusion.slf
2018-11-16 10:25:02 -08:00

109 lines
4 KiB
Text

<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
//
// ssao_makeOcclusion.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@>
<$declareAmbientOcclusion()$>
<$declareFetchDepthPyramidMap()$>
<$declareSamplingDisk()$>
<$declareEvalObscurance()$>
<$declarePackOcclusionDepth()$>
#define SSAO_HBAO_MAX_RADIUS 300.0
layout(location=0) in vec2 varTexCoord0;
layout(location=0) out vec4 outFragColor;
void main(void) {
// Pixel being shaded
vec2 fragCoord = gl_FragCoord.xy;
ivec2 fragPixelPos = ivec2(fragCoord.xy);
vec2 fragUVPos = varTexCoord0;
#if SSAO_USE_QUAD_SPLIT
vec3 fragNormalES = getNormalEyeAtUV(fragUVPos, 0.0);
#endif
// Stereo side info based on the real viewport size of this pass
vec2 sideDepthSize = getDepthTextureSideSize(0);
ivec2 sideOcclusionSize;
if (isHorizonBased()) {
sideOcclusionSize = ivec2( getOcclusionSplitSideSize() );
} else {
sideOcclusionSize = ivec2( getOcclusionSideSize() );
}
ivec4 side = getStereoSideInfoFromWidth(fragPixelPos.x, sideOcclusionSize.x);
// From now on, fragUVPos is the UV pos in the side
fragUVPos = getSideUVFromFramebufferUV(side, fragUVPos);
fragUVPos = snapToTexel(fragUVPos, sideDepthSize);
// The position and normal of the pixel fragment in Eye space
vec2 deltaDepthUV = vec2(2.0) / sideDepthSize;
vec3 fragPositionES = buildPosition(side, fragUVPos);
#if !SSAO_USE_QUAD_SPLIT
vec3 fragNormalES = buildNormal(side, fragUVPos, fragPositionES, deltaDepthUV);
#endif
float occlusion = 1.0;
if (fragPositionES.z > (1.0-getPosLinearDepthFar())) {
// Choose the screen-space sample radius
float diskPixelRadius = evalDiskRadius(fragPositionES.z, sideDepthSize);
if (isHorizonBased()) {
diskPixelRadius = min(diskPixelRadius, SSAO_HBAO_MAX_RADIUS);
}
// Let's make noise
float randomPatternRotationAngle = 0.0;
// Accumulate the obscurance for each samples
float obscuranceSum = 0.0;
int numSamples = int(getNumSamples());
float invNumSamples = getInvNumSamples();
if (isHorizonBased()) {
randomPatternRotationAngle = getAngleDithering(fragPixelPos);
for (int i = 0; i < numSamples; ++i) {
vec3 deltaTap = getUnitTapLocation(i, 1.0, randomPatternRotationAngle, PI);
obscuranceSum += evalVisibilityHBAO(side, fragUVPos, deltaDepthUV, deltaTap.xy, diskPixelRadius, fragPositionES, fragNormalES);
}
obscuranceSum *= invNumSamples;
#if HBAO_USE_COS_ANGLE
obscuranceSum = 1.0 - obscuranceSum * getObscuranceScaling();
#else
obscuranceSum = mix(1.0, obscuranceSum, getObscuranceScaling());
#endif
} else {
// Steps are in the depth texture resolution
vec2 depthTexFragPixelPos = fragUVPos * sideDepthSize;
randomPatternRotationAngle = getAngleDitheringPixelPos(fragPixelPos) + getAngleDitheringSplit();
for (int i = 0; i < numSamples; ++i) {
vec3 tap = getTapLocationClampedSSAO(i, randomPatternRotationAngle, diskPixelRadius, depthTexFragPixelPos, sideDepthSize);
vec2 tapUV = fragUVPos + tap.xy * deltaDepthUV;
vec2 tapMipZ = fetchTap(side, tapUV, tap.z);
vec3 tapPositionES = evalEyePositionFromZeye(side.x, tapMipZ.y, tapUV);
obscuranceSum += float(tap.z > 0.0) * evalVisibilitySSAO(fragPositionES, fragNormalES, tapPositionES);
}
obscuranceSum *= invNumSamples;
obscuranceSum = 1.0 - obscuranceSum * getObscuranceScaling();
}
occlusion = clamp(obscuranceSum, 0.0, 1.0);
}
outFragColor = packOcclusionOutput(occlusion, fragPositionES.z, fragNormalES);
}