<@include gpu/Config.slh@> <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // // 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()$> <$declarePackOcclusionDepth()$> <@include gpu/color.slh@> <$declareColorWheel()$> struct DebugParams{ vec4 pixelInfo; }; uniform debugAmbientOcclusionBuffer { DebugParams debugParams; }; vec2 getDebugCursorTexcoord(){ return debugParams.pixelInfo.xy; } out vec4 outFragColor; uniform sampler2D normalMap; float evalAO(in vec3 C, in vec3 n_C, vec3 Q) { vec3 v = Q - C; float vv = dot(v, v); float vn = dot(v, n_C); // Fall off function as recommended in SAO paper const float epsilon = 0.01; float f = max(getRadius2() - vv, 0.0); return f * f * f * max((vn - getFalloffBias()) / (epsilon + vv), 0.0); } void main(void) { // Pixel Debugged vec2 cursorUV = getDebugCursorTexcoord(); vec2 imageSize = getSideImageSize(getResolutionLevel()); vec2 cursorPixelPos = cursorUV * imageSize; ivec2 ssC = ivec2(cursorPixelPos); // Pixel being shaded //ivec2 ssC = ivec2(gl_FragCoord.xy); // Fetch the z under the pixel (stereo or not) float Zeye = getZEye(ssC); // Stereo side info ivec4 side = getStereoSideInfo(ssC.x, getResolutionLevel()); // From now on, ssC is the pixel pos in the side ssC.x -= side.y; vec2 fragPos = (vec2(ssC) + vec2(0.5)) / imageSize; // The position and normal of the pixel fragment in Eye space vec3 Cp = evalEyePositionFromZeye(side.x, Zeye, fragPos); vec3 Cn = evalEyeNormal(Cp); // Choose the screen-space sample radius float ssDiskRadius = evalDiskRadius(Cp.z, imageSize); vec2 fragToCursor = cursorPixelPos - gl_FragCoord.xy; if (dot(fragToCursor,fragToCursor) > ssDiskRadius * ssDiskRadius) { discard; } // Let's make noise // float randomPatternRotationAngle = getAngleDithering(ssC); float randomPatternRotationAngle = getAngleDitheringWorldPos(Cp); // Accumulate the Obscurance for each samples float sum = 0.0; float keepTapRadius = 1.0; int keepedMip = -1; bool keep = false; for (int i = 0; i < getNumSamples(); ++i) { vec3 tap = getTapLocationClamped(i, randomPatternRotationAngle, ssDiskRadius, cursorPixelPos, imageSize); // The occluding point in camera space vec2 fragToTap = vec2(ssC) + tap.xy - gl_FragCoord.xy; if (dot(fragToTap,fragToTap) < keepTapRadius) { keep = true; keepedMip = evalMipFromRadius(tap.z); } vec3 Q = getOffsetPosition(side.xyz, ssC, tap, imageSize); sum += evalAO(Cp, Cn, Q); } float A = max(0.0, 1.0 - sum * getObscuranceScaling() * 5.0 * getInvNumSamples()); outFragColor = vec4(packOcclusionDepth(A, CSZToDephtKey(Cp.z)), 1.0); // KEEP IT for Debugging // Debug Normal: outFragColor = vec4((Cn + vec3(1.0))* 0.5, 1.0); // Debug Radius outFragColor = vec4(vec3(ssDiskRadius / 100.0), 1.0); // Debug MaxMiplevel outFragColor = vec4(1.0 - vec3(float(clamp(findMSB(int(ssDiskRadius)) - LOG_MAX_OFFSET, 0, MAX_MIP_LEVEL))/ float(MAX_MIP_LEVEL)), 1.0); // Debug OffsetPosition // float ssR; // vec2 unitOffset = tapLocation(int(getNumSamples() - 1), 0, ssR); // vec3 Q = getOffsetPosition(side, ssC, unitOffset, ssR * ssDiskRadius); //outFragColor = vec4(vec3(Q.x / 10.0, Q.y / 2.0, -Q.z/ 3.0), 1.0); // vec3 v = normalize(Q - Cp); //outFragColor = vec4((v + vec3(1.0))* 0.5, 1.0); // outFragColor = vec4((Cn + vec3(1.0))* 0.5, 1.0); //outFragColor = vec4(vec3(ssDiskRadius / 100.0), 1.0); if ((dot(fragToCursor,fragToCursor) < (4.0 * keepTapRadius * keepTapRadius) )) { outFragColor = vec4(vec3(A), 1.0); return; } if (!keep) { outFragColor = vec4(0.1); } else { outFragColor.rgb = colorWheel(float(keepedMip)/float(MAX_MIP_LEVEL)); } }