From e92e69d963f4102073dc7b268eaa3755f536c78a Mon Sep 17 00:00:00 2001 From: sam Date: Sat, 6 Aug 2016 11:54:54 -0700 Subject: [PATCH] More changes --- .../src/AmbientOcclusionEffect.cpp | 55 +++++-------------- .../render-utils/src/AmbientOcclusionEffect.h | 8 +-- .../render-utils/src/SurfaceGeometryPass.cpp | 3 +- libraries/render-utils/src/ssao.slh | 27 +++++++-- .../render-utils/src/ssao_debugOcclusion.slf | 41 ++++++-------- .../render-utils/src/ssao_makeOcclusion.slf | 47 ++++------------ .../utilities/render/ambientOcclusionPass.qml | 1 + .../utilities/render/deferredLighting.qml | 1 + 8 files changed, 68 insertions(+), 115 deletions(-) diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.cpp b/libraries/render-utils/src/AmbientOcclusionEffect.cpp index 9bdabbfb04..3899c1deb5 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.cpp +++ b/libraries/render-utils/src/AmbientOcclusionEffect.cpp @@ -111,13 +111,6 @@ gpu::TexturePointer AmbientOcclusionFramebuffer::getOcclusionBlurredTexture() { return _occlusionBlurredTexture; } -void AmbientOcclusionFramebuffer::setResolutionLevel(int resolutionLevel) { - if (resolutionLevel != getResolutionLevel()) { - clear(); - _resolutionLevel = resolutionLevel; - } -} - class GaussianDistribution { public: @@ -240,20 +233,11 @@ void AmbientOcclusionEffect::configure(const Config& config) { if (config.perspectiveScale != _parametersBuffer->getPerspectiveScale()) { _parametersBuffer->resolutionInfo.z = config.perspectiveScale; } - _framebuffer->setResolutionLevel(config.resolutionLevel); if (config.resolutionLevel != _parametersBuffer->getResolutionLevel()) { - _parametersBuffer->resolutionInfo.w = config.resolutionLevel; + auto& current = _parametersBuffer->resolutionInfo; + current.x = (float) config.resolutionLevel; } - const auto& resolutionLevel = config.resolutionLevel; - if (resolutionLevel != _parametersBuffer->getResolutionLevel()) { - auto& current = _parametersBuffer->resolutionInfo; - current.x = (float)resolutionLevel; - - // Communicate the change to the Framebuffer cache - // DependencyManager::get()->setAmbientOcclusionResolutionLevel(resolutionLevel); - } - if (config.blurRadius != _parametersBuffer->getBlurRadius()) { auto& current = _parametersBuffer->blurInfo; current.y = (float)config.blurRadius; @@ -355,17 +339,11 @@ void AmbientOcclusionEffect::run(const render::SceneContextPointer& sceneContext RenderArgs* args = renderContext->args; - // FIXME: Different render modes should have different tasks -// if (args->_renderMode != RenderArgs::DEFAULT_RENDER_MODE) { -// return; -// } - const auto frameTransform = inputs.get0(); const auto deferredFramebuffer = inputs.get1(); const auto linearDepthFramebuffer = inputs.get2(); auto linearDepthTexture = linearDepthFramebuffer->getLinearDepthTexture(); - auto normalTexture = deferredFramebuffer->getDeferredNormalTexture(); auto sourceViewport = args->_viewport; auto occlusionViewport = sourceViewport; @@ -373,10 +351,9 @@ void AmbientOcclusionEffect::run(const render::SceneContextPointer& sceneContext _framebuffer = std::make_shared(); } - if (_framebuffer->getResolutionLevel() > 0) { + if (_parametersBuffer->getResolutionLevel() > 0) { linearDepthTexture = linearDepthFramebuffer->getHalfLinearDepthTexture(); - normalTexture = linearDepthFramebuffer->getHalfNormalTexture(); - occlusionViewport = occlusionViewport >> _framebuffer->getResolutionLevel(); + occlusionViewport = occlusionViewport >> _parametersBuffer->getResolutionLevel(); } _framebuffer->updateLinearDepth(linearDepthTexture); @@ -390,10 +367,10 @@ void AmbientOcclusionEffect::run(const render::SceneContextPointer& sceneContext auto framebufferSize = _framebuffer->getSourceFrameSize(); - float sMin = args->_viewport.x / (float)framebufferSize.x; - float sWidth = args->_viewport.z / (float)framebufferSize.x; - float tMin = args->_viewport.y / (float)framebufferSize.y; - float tHeight = args->_viewport.w / (float)framebufferSize.y; + float sMin = occlusionViewport.x / (float)framebufferSize.x; + float sWidth = occlusionViewport.z / (float)framebufferSize.x; + float tMin = occlusionViewport.y / (float)framebufferSize.y; + float tHeight = occlusionViewport.w / (float)framebufferSize.y; auto resolutionLevel = _parametersBuffer->getResolutionLevel(); @@ -536,10 +513,10 @@ void DebugAmbientOcclusion::run(const render::SceneContextPointer& sceneContext, auto framebufferSize = glm::ivec2(linearDepthTexture->getDimensions()); - float sMin = args->_viewport.x / (float)framebufferSize.x; - float sWidth = args->_viewport.z / (float)framebufferSize.x; - float tMin = args->_viewport.y / (float)framebufferSize.y; - float tHeight = args->_viewport.w / (float)framebufferSize.y; + float sMin = occlusionViewport.x / (float)framebufferSize.x; + float sWidth = occlusionViewport.z / (float)framebufferSize.x; + float tMin = occlusionViewport.y / (float)framebufferSize.y; + float tHeight = occlusionViewport.w / (float)framebufferSize.y; // Running in stero ? @@ -562,19 +539,13 @@ void DebugAmbientOcclusion::run(const render::SceneContextPointer& sceneContext, batch.setUniformBuffer(AmbientOcclusionEffect_FrameTransformSlot, frameTransform->getFrameTransformBuffer()); batch.setUniformBuffer(AmbientOcclusionEffect_ParamsSlot, ambientOcclusionUniforms); batch.setUniformBuffer(2, _parametersBuffer); - - - // We need this with the mips levels - batch.generateTextureMips(linearDepthTexture); batch.setPipeline(debugPipeline); batch.setResourceTexture(AmbientOcclusionEffect_LinearDepthMapSlot, linearDepthTexture); batch.draw(gpu::TRIANGLE_STRIP, 4); - batch.setResourceTexture(AmbientOcclusionEffect_LinearDepthMapSlot, nullptr); - batch.setResourceTexture(AmbientOcclusionEffect_OcclusionMapSlot, nullptr); - + batch.setResourceTexture(AmbientOcclusionEffect_LinearDepthMapSlot, nullptr); }); } diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.h b/libraries/render-utils/src/AmbientOcclusionEffect.h index 7c2c465ba3..dd0031bee7 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.h +++ b/libraries/render-utils/src/AmbientOcclusionEffect.h @@ -34,10 +34,7 @@ public: void updateLinearDepth(const gpu::TexturePointer& linearDepthBuffer); gpu::TexturePointer getLinearDepthTexture(); const glm::ivec2& getSourceFrameSize() const { return _frameSize; } - - void setResolutionLevel(int level); - int getResolutionLevel() const { return _resolutionLevel; } - + protected: void clear(); void allocate(); @@ -52,7 +49,6 @@ protected: glm::ivec2 _frameSize; - int _resolutionLevel{ 0 }; }; using AmbientOcclusionFramebufferPointer = std::shared_ptr; @@ -98,7 +94,7 @@ public: float blurDeviation{ 2.5f }; float numSpiralTurns{ 7.0f }; // defining an angle span to distribute the samples ray directions int numSamples{ 11 }; - int resolutionLevel{ 0 }; + int resolutionLevel{ 1 }; int blurRadius{ 3 }; // 0 means no blurring bool ditheringEnabled{ true }; // randomize the distribution of taps per pixel, should always be true bool borderingEnabled{ true }; // avoid evaluating information from non existing pixels out of the frame, should always be true diff --git a/libraries/render-utils/src/SurfaceGeometryPass.cpp b/libraries/render-utils/src/SurfaceGeometryPass.cpp index 683fe69ff0..0f009990de 100644 --- a/libraries/render-utils/src/SurfaceGeometryPass.cpp +++ b/libraries/render-utils/src/SurfaceGeometryPass.cpp @@ -71,7 +71,7 @@ void LinearDepthFramebuffer::allocate() { // For Linear Depth: _linearDepthTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::RGB), width, height, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT))); - _linearDepthTexture->autoGenerateMips(1); + _linearDepthTexture->autoGenerateMips(5); _linearDepthFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create()); _linearDepthFramebuffer->setRenderBuffer(0, _linearDepthTexture); _linearDepthFramebuffer->setDepthStencilBuffer(_primaryDepthTexture, _primaryDepthTexture->getTexelFormat()); @@ -79,6 +79,7 @@ void LinearDepthFramebuffer::allocate() { // For Downsampling: _halfLinearDepthTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::RGB), _halfFrameSize.x, _halfFrameSize.y, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT))); + _halfLinearDepthTexture->autoGenerateMips(-1); _halfNormalTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::VEC3, gpu::NUINT8, gpu::RGB), _halfFrameSize.x, _halfFrameSize.y, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT))); diff --git a/libraries/render-utils/src/ssao.slh b/libraries/render-utils/src/ssao.slh index 7efcd861c7..ae3b70095e 100644 --- a/libraries/render-utils/src/ssao.slh +++ b/libraries/render-utils/src/ssao.slh @@ -133,11 +133,11 @@ float getBlurCoef(int c) { <@func declareSamplingDisk()@> float getAngleDitheringWorldPos(in vec3 pixelWorldPos) { - vec3 worldPosFract = fract(pixelWorldPos * 0.2); + vec3 worldPosFract = fract(pixelWorldPos * 0.4); ivec3 pixelPos = ivec3(worldPosFract * 256); - return isDitheringEnabled() * (3 * pixelPos.x ^ pixelPos.y + pixelPos.x * pixelPos.y) * 10 + getFrameDithering(); + return isDitheringEnabled() * ((3 * pixelPos.x ^ pixelPos.y + pixelPos.x * pixelPos.y) + (3 * pixelPos.y ^ pixelPos.z + pixelPos.x * pixelPos.z)) * 10 + getFrameDithering(); } float getAngleDithering(in ivec2 pixelPos) { @@ -217,7 +217,8 @@ vec3 getTapLocationClamped(int sampleNumber, float spinAngle, float outerRadius, if (redoTap) { tap.xy = tapPos - pixelPos; tap.z = length(tap.xy); - } + tap.z = 0; + } return tap; } @@ -231,8 +232,8 @@ vec3 getTapLocationClamped(int sampleNumber, float spinAngle, float outerRadius, // the depth pyramid texture uniform sampler2D pyramidMap; -float getZEye(ivec2 pixel) { - return -texelFetch(pyramidMap, pixel, getResolutionLevel()).x; +float getZEye(ivec2 pixel, int level) { + return -texelFetch(pyramidMap, pixel, level).x; } const int LOG_MAX_OFFSET = 3; @@ -269,6 +270,22 @@ vec3 getOffsetPosition(ivec3 side, ivec2 ssC, vec3 tap, vec2 imageSize) { <@endfunc@> + +<@func declareEvalObscurance()@> + +float evalAO(in vec3 C, in vec3 n_C, in 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); +} + +<@endfunc@> + <@func declareBlurPass(axis)@> <$declarePackOcclusionDepth()$> diff --git a/libraries/render-utils/src/ssao_debugOcclusion.slf b/libraries/render-utils/src/ssao_debugOcclusion.slf index ecb1d112b9..5db1626ab8 100644 --- a/libraries/render-utils/src/ssao_debugOcclusion.slf +++ b/libraries/render-utils/src/ssao_debugOcclusion.slf @@ -13,6 +13,7 @@ <$declareAmbientOcclusion()$> <$declareFetchDepthPyramidMap()$> <$declareSamplingDisk()$> +<$declareEvalObscurance()$> <$declarePackOcclusionDepth()$> @@ -33,32 +34,23 @@ vec2 getDebugCursorTexcoord(){ 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) { + vec2 imageSize = getSideImageSize(getResolutionLevel()); + + // In debug adjust the correct frag pixel based on base resolution + vec2 fragCoord = gl_FragCoord.xy; + if (getResolutionLevel() > 0) { + fragCoord /= float (1 << getResolutionLevel()); + } + // 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); + ivec2 ssC = ivec2(cursorPixelPos); + // Fetch the z under the pixel (stereo or not) - float Zeye = getZEye(ssC); + float Zeye = getZEye(ssC, 0); // Stereo side info ivec4 side = getStereoSideInfo(ssC.x, getResolutionLevel()); @@ -74,7 +66,7 @@ void main(void) { // Choose the screen-space sample radius float ssDiskRadius = evalDiskRadius(Cp.z, imageSize); - vec2 fragToCursor = cursorPixelPos - gl_FragCoord.xy; + vec2 fragToCursor = cursorPixelPos - fragCoord.xy; if (dot(fragToCursor,fragToCursor) > ssDiskRadius * ssDiskRadius) { discard; } @@ -93,7 +85,7 @@ void main(void) { 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; + vec2 fragToTap = vec2(ssC) + tap.xy - fragCoord.xy; if (dot(fragToTap,fragToTap) < keepTapRadius) { keep = true; keepedMip = evalMipFromRadius(tap.z); @@ -101,7 +93,7 @@ void main(void) { vec3 Q = getOffsetPosition(side.xyz, ssC, tap, imageSize); - sum += evalAO(Cp, Cn, Q); + sum += float(tap.z > 0.0) * evalAO(Cp, Cn, Q); } @@ -134,7 +126,8 @@ void main(void) { // 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) )) { + if ((dot(fragToCursor,fragToCursor) < (100.0 * keepTapRadius * keepTapRadius) )) { + // outFragColor = vec4(vec3(A), 1.0); outFragColor = vec4(vec3(A), 1.0); return; } diff --git a/libraries/render-utils/src/ssao_makeOcclusion.slf b/libraries/render-utils/src/ssao_makeOcclusion.slf index 19a6244a07..7af1feb477 100644 --- a/libraries/render-utils/src/ssao_makeOcclusion.slf +++ b/libraries/render-utils/src/ssao_makeOcclusion.slf @@ -13,41 +13,28 @@ <$declareAmbientOcclusion()$> <$declareFetchDepthPyramidMap()$> <$declareSamplingDisk()$> +<$declareEvalObscurance()$> <$declarePackOcclusionDepth()$> - out vec4 outFragColor; -uniform sampler2D normalMap; - - -float evalAO(in vec3 C, in vec3 n_C, in 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 being shaded - ivec2 ssC = ivec2(gl_FragCoord.xy); - vec2 imageSize = getSideImageSize(getResolutionLevel()); + // Pixel being shaded + vec2 fragCoord = gl_FragCoord.xy; + ivec2 ssC = ivec2(fragCoord.xy); + // Fetch the z under the pixel (stereo or not) - float Zeye = getZEye(ssC); + float Zeye = getZEye(ssC, 0); // 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)) / vec2(getStereoSideWidth(getResolutionLevel()), getStereoSideHeight(getResolutionLevel())); + 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); @@ -57,7 +44,7 @@ void main(void) { float ssDiskRadius = evalDiskRadius(Cp.z, imageSize); // Let's make noise - // float randomPatternRotationAngle = getAngleDithering(ssC); + //float randomPatternRotationAngle = getAngleDithering(ssC); float randomPatternRotationAngle = getAngleDitheringWorldPos(Cp); // Accumulate the Obscurance for each samples @@ -65,9 +52,9 @@ void main(void) { for (int i = 0; i < getNumSamples(); ++i) { vec3 tap = getTapLocationClamped(i, randomPatternRotationAngle, ssDiskRadius, ssC, imageSize); - vec3 Q = getOffsetPosition(side.xyz, ssC, tap, imageSize); + vec3 Q = getOffsetPosition(side.xyz, ssC, tap, imageSize); - sum += evalAO(Cp, Cn, Q); + sum += float(tap.z > 0.0) * evalAO(Cp, Cn, Q); } float A = max(0.0, 1.0 - sum * getObscuranceScaling() * 5.0 * getInvNumSamples()); @@ -84,18 +71,4 @@ void main(void) { !> 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); } diff --git a/scripts/developer/utilities/render/ambientOcclusionPass.qml b/scripts/developer/utilities/render/ambientOcclusionPass.qml index c4d86e544e..b6d54676e3 100644 --- a/scripts/developer/utilities/render/ambientOcclusionPass.qml +++ b/scripts/developer/utilities/render/ambientOcclusionPass.qml @@ -25,6 +25,7 @@ Column { "Level:obscuranceLevel:1.0:false", "Num Taps:numSamples:32:true", "Taps Spiral:numSpiralTurns:10.0:false", + "Falloff Bias:falloffBias:0.2:false", "Blur Radius:blurRadius:10.0:false", ] ConfigSlider { diff --git a/scripts/developer/utilities/render/deferredLighting.qml b/scripts/developer/utilities/render/deferredLighting.qml index 635d8b1471..4901be8e03 100644 --- a/scripts/developer/utilities/render/deferredLighting.qml +++ b/scripts/developer/utilities/render/deferredLighting.qml @@ -24,6 +24,7 @@ Column { "Emissive:LightingModel:enableEmissive", "Lightmap:LightingModel:enableLightmap", "Background:LightingModel:enableBackground", + "ssao:AmbientOcclusion:enabled", ] CheckBox { text: modelData.split(":")[0]