diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.cpp b/libraries/render-utils/src/AmbientOcclusionEffect.cpp index 2314568720..5cb95c01b2 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.cpp +++ b/libraries/render-utils/src/AmbientOcclusionEffect.cpp @@ -87,10 +87,6 @@ void AmbientOcclusionFramebuffer::allocate() { _occlusionBlurredTexture = gpu::Texture::createRenderBuffer(format, width, height, gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR, gpu::Sampler::WRAP_CLAMP)); _occlusionBlurredFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("occlusionBlurred")); _occlusionBlurredFramebuffer->setRenderBuffer(0, _occlusionBlurredTexture); - - _normalTexture = gpu::Texture::createRenderBuffer(gpu::Element::COLOR_R11G11B10, width, height, gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT, gpu::Sampler::WRAP_CLAMP)); - _normalFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("ssaoNormals")); - _normalFramebuffer->setRenderBuffer(0, _normalTexture); } gpu::FramebufferPointer AmbientOcclusionFramebuffer::getOcclusionFramebuffer() { @@ -121,16 +117,26 @@ gpu::TexturePointer AmbientOcclusionFramebuffer::getOcclusionBlurredTexture() { return _occlusionBlurredTexture; } -gpu::FramebufferPointer AmbientOcclusionFramebuffer::getNormalFramebuffer() { - if (!_normalFramebuffer) { - allocate(); +void AmbientOcclusionFramebuffer::allocate(int resolutionLevel) { + auto width = _frameSize.x >> resolutionLevel; + auto height = _frameSize.y >> resolutionLevel; + + _normalTexture = gpu::Texture::createRenderBuffer(gpu::Element::COLOR_R11G11B10, width, height, gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT, gpu::Sampler::WRAP_CLAMP)); + _normalFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("ssaoNormals")); + _normalFramebuffer->setRenderBuffer(0, _normalTexture); + _resolutionLevel = resolutionLevel; +} + +gpu::FramebufferPointer AmbientOcclusionFramebuffer::getNormalFramebuffer(int resolutionLevel) { + if (!_normalFramebuffer || resolutionLevel != _resolutionLevel) { + allocate(resolutionLevel); } return _normalFramebuffer; } -gpu::TexturePointer AmbientOcclusionFramebuffer::getNormalTexture() { - if (!_normalTexture) { - allocate(); +gpu::TexturePointer AmbientOcclusionFramebuffer::getNormalTexture(int resolutionLevel) { + if (!_normalTexture || resolutionLevel != _resolutionLevel) { + allocate(resolutionLevel); } return _normalTexture; } @@ -208,11 +214,11 @@ AmbientOcclusionEffectConfig::AmbientOcclusionEffectConfig() : blurDeviation{ 2.5f }, numSpiralTurns{ 7.0f }, #if SSAO_USE_HORIZON_BASED - numSamples{ 2 }, + numSamples{ 3 }, #else numSamples{ 16 }, #endif - resolutionLevel{ 0 }, + resolutionLevel{ 2 }, blurRadius{ 4 }, ditheringEnabled{ true }, borderingEnabled{ true }, @@ -470,10 +476,11 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte _framebuffer = std::make_shared(); } - const auto resolutionScale = powf(0.5f, _aoParametersBuffer->getResolutionLevel()); - if (_aoParametersBuffer->getResolutionLevel() > 0) { - occlusionViewport = occlusionViewport >> _aoParametersBuffer->getResolutionLevel(); - firstBlurViewport.w = firstBlurViewport.w >> _aoParametersBuffer->getResolutionLevel(); + const int resolutionLevel = _aoParametersBuffer->getResolutionLevel(); + const auto resolutionScale = powf(0.5f, resolutionLevel); + if (resolutionLevel > 0) { + occlusionViewport = occlusionViewport >> resolutionLevel; + firstBlurViewport.w = firstBlurViewport.w >> resolutionLevel; occlusionDepthTexture = linearDepthFramebuffer->getHalfLinearDepthTexture(); } @@ -498,8 +505,8 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte #if SSAO_USE_QUAD_SPLIT auto gatherPipeline = getGatherPipeline(); auto buildNormalsPipeline = getBuildNormalsPipeline(); - auto occlusionNormalFramebuffer = _framebuffer->getNormalFramebuffer(); - auto occlusionNormalTexture = _framebuffer->getNormalTexture(); + auto occlusionNormalFramebuffer = _framebuffer->getNormalFramebuffer(resolutionLevel); + auto occlusionNormalTexture = _framebuffer->getNormalTexture(resolutionLevel); #endif auto fullNormalTexture = linearDepthFramebuffer->getNormalTexture(); @@ -536,12 +543,13 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte #if SSAO_USE_QUAD_SPLIT // Build derivative normals pass batch.pushProfileRange("Build Normals"); - batch.setViewportTransform(sourceViewport); + batch.setViewportTransform(occlusionViewport); batch.setPipeline(buildNormalsPipeline); + batch.setResourceTexture(render_utils::slot::texture::SsaoDepth, linearDepthTexture); + batch.setResourceTexture(render_utils::slot::texture::SsaoNormal, nullptr); batch.setUniformBuffer(render_utils::slot::buffer::DeferredFrameTransform, frameTransform->getFrameTransformBuffer()); batch.setUniformBuffer(render_utils::slot::buffer::SsaoParams, _aoParametersBuffer); batch.setFramebuffer(occlusionNormalFramebuffer); - batch.setResourceTexture(render_utils::slot::texture::SsaoDepth, linearDepthTexture); batch.draw(gpu::TRIANGLE_STRIP, 4); batch.popProfileRange(); #endif diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.h b/libraries/render-utils/src/AmbientOcclusionEffect.h index e04e24b4f4..1509cf6492 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.h +++ b/libraries/render-utils/src/AmbientOcclusionEffect.h @@ -31,8 +31,8 @@ public: gpu::FramebufferPointer getOcclusionBlurredFramebuffer(); gpu::TexturePointer getOcclusionBlurredTexture(); - gpu::FramebufferPointer getNormalFramebuffer(); - gpu::TexturePointer getNormalTexture(); + gpu::FramebufferPointer getNormalFramebuffer(int resolutionLevel); + gpu::TexturePointer getNormalTexture(int resolutionLevel); // Update the source framebuffer size which will drive the allocation of all the other resources. bool updateLinearDepth(const gpu::TexturePointer& linearDepthBuffer); @@ -40,8 +40,10 @@ public: const glm::ivec2& getSourceFrameSize() const { return _frameSize; } protected: + void clear(); void allocate(); + void allocate(int resolutionLevel); gpu::TexturePointer _linearDepthTexture; @@ -56,6 +58,7 @@ protected: glm::ivec2 _frameSize; + int _resolutionLevel{ 0 }; }; using AmbientOcclusionFramebufferPointer = std::shared_ptr; diff --git a/libraries/render-utils/src/ssao.slh b/libraries/render-utils/src/ssao.slh index c4efb3be89..dec0109922 100644 --- a/libraries/render-utils/src/ssao.slh +++ b/libraries/render-utils/src/ssao.slh @@ -202,6 +202,10 @@ vec3 getTapLocationClampedSSAO(int sampleNumber, float spinAngle, float outerRad layout(binding=RENDER_UTILS_TEXTURE_SSAO_DEPTH) uniform sampler2D depthPyramidTex; layout(binding=RENDER_UTILS_TEXTURE_SSAO_NORMAL) uniform sampler2D normalTex; +ivec2 getDepthTextureSize(int level) { + return textureSize(depthPyramidTex, level); +} + float getZEyeAtPixel(ivec2 pixel, int level) { return -texelFetch(depthPyramidTex, pixel, level).x; } diff --git a/libraries/render-utils/src/ssao_buildNormals.slf b/libraries/render-utils/src/ssao_buildNormals.slf index 4d7d6e6530..8e06d4ffc9 100644 --- a/libraries/render-utils/src/ssao_buildNormals.slf +++ b/libraries/render-utils/src/ssao_buildNormals.slf @@ -18,17 +18,19 @@ layout(location=0) out vec4 outFragColor; void main(void) { - vec2 sideImageSize = getStereoSideSize(0); + vec2 sideImageSize = getStereoSideSize(getResolutionLevel()); + ivec2 renderSize = ivec2(sideImageSize) << ivec2(int(isStereo()) & 1, 0); // Pixel being shaded vec2 fragCoord = gl_FragCoord.xy; ivec2 fragPixelPos = ivec2(fragCoord.xy); // Fetch the z under the pixel (stereo or not) - float Zeye = getZEyeAtPixel(fragPixelPos, 0); + ivec2 depthTexFragPixelPos = fragPixelPos * getDepthTextureSize(0) / renderSize ; + float Zeye = getZEyeAtPixel(depthTexFragPixelPos, 0); // Stereo side info - ivec4 side = getStereoSideInfo(fragPixelPos.x, 0); + ivec4 side = getStereoSideInfo(fragPixelPos.x, getResolutionLevel()); // From now on, fragPixelPos is the pixel pos in the side fragPixelPos.x -= side.y; @@ -39,7 +41,5 @@ void main(void) { vec3 fragNormalES = evalEyeNormal(fragPositionES); vec3 absFragNormalES = abs(fragNormalES); - // Maximize encoding precision - fragNormalES /= max(max(absFragNormalES.x, absFragNormalES.y), absFragNormalES.z); outFragColor = vec4(vec3(fragNormalES)*0.5 + vec3(0.5), 1.0); } diff --git a/libraries/render-utils/src/ssao_makeOcclusion.slf b/libraries/render-utils/src/ssao_makeOcclusion.slf index fee4d6f84f..3db497fdc7 100644 --- a/libraries/render-utils/src/ssao_makeOcclusion.slf +++ b/libraries/render-utils/src/ssao_makeOcclusion.slf @@ -25,6 +25,7 @@ layout(location=0) out vec4 outFragColor; void main(void) { vec2 sideImageSize = getStereoSideSize(getResolutionLevel()); + ivec2 renderSize = ivec2(sideImageSize) << ivec2(int(isStereo()) & 1, 0); // Pixel being shaded vec2 fragCoord = gl_FragCoord.xy; @@ -35,7 +36,8 @@ void main(void) { #endif // Fetch the z under the pixel (stereo or not) - float Zeye = getZEyeAtPixel(fragPixelPos, 0); + ivec2 depthTexFragPixelPos = fragPixelPos * getDepthTextureSize(0) / renderSize ; + float Zeye = getZEyeAtPixel(depthTexFragPixelPos, 0); #if SSAO_USE_QUAD_SPLIT vec3 fragNormalES = getNormalEyeAtPixel(fragPixelPos, 0); #endif