diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.cpp b/libraries/render-utils/src/AmbientOcclusionEffect.cpp index 8e2a25b3e6..5e6bc39253 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.cpp +++ b/libraries/render-utils/src/AmbientOcclusionEffect.cpp @@ -109,8 +109,8 @@ void AmbientOcclusionFramebuffer::allocate() { } auto width = sideSize.x; auto height = sideSize.y; - - _normalTexture = gpu::Texture::createRenderBuffer(gpu::Element::COLOR_RGBA_32, width, height, gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT, gpu::Sampler::WRAP_CLAMP)); + auto format = gpu::Element::COLOR_RGBA_32; + _normalTexture = gpu::Texture::createRenderBuffer(format, 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); } @@ -561,8 +561,8 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte } // _frameId = (_frameId + 1) % SSAO_RANDOM_SAMPLE_COUNT; - gpu::doInBatch("AmbientOcclusionEffect::run", args->_context, [=](gpu::Batch& batch) { - PROFILE_RANGE_BATCH(batch, "AmbientOcclusion"); + gpu::doInBatch("AmbientOcclusionEffect::Depth mip creation", args->_context, [=](gpu::Batch& batch) { + PROFILE_RANGE_BATCH(batch, "AO::Depth mip creation"); batch.enableStereo(false); _gpuTimer->begin(batch); @@ -574,29 +574,57 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte batch.setModelTransform(model); // We need this with the mips levels - batch.pushProfileRange("Depth mip creation"); #if SSAO_USE_HORIZON_BASED - batch.setPipeline(mipCreationPipeline); - batch.generateTextureMipsWithPipeline(occlusionDepthTexture); + batch.setPipeline(mipCreationPipeline); + batch.generateTextureMipsWithPipeline(occlusionDepthTexture); #else - batch.generateTextureMips(occlusionDepthTexture); + batch.generateTextureMips(occlusionDepthTexture); #endif - batch.popProfileRange(); + + _gpuTimer->end(batch); + }); #if SSAO_USE_QUAD_SPLIT + gpu::doInBatch("AmbientOcclusionEffect::Build Normals", args->_context, [=](gpu::Batch& batch) { + PROFILE_RANGE_BATCH(batch, "AO::Build Normals"); + batch.enableStereo(false); + + _gpuTimer->begin(batch); + + batch.resetViewTransform(); + + batch.setProjectionTransform(glm::mat4()); + Transform model; + auto depthTextureSize = linearDepthTexture->getDimensions(); + model.setScale( glm::vec3(occlusionViewport.z / (depthTextureSize.x * resolutionScale), occlusionViewport.w / (depthTextureSize.y * resolutionScale), 1.0f) ); + batch.setModelTransform(model); + // Build face normals pass - batch.pushProfileRange("Build Normals"); - 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.draw(gpu::TRIANGLE_STRIP, 4); - batch.popProfileRange(); + 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.draw(gpu::TRIANGLE_STRIP, 4); + + _gpuTimer->end(batch); + }); #endif + gpu::doInBatch("AmbientOcclusionEffect::Occlusion", args->_context, [=](gpu::Batch& batch) { + PROFILE_RANGE_BATCH(batch, "AO::Occlusion"); + batch.enableStereo(false); + + _gpuTimer->begin(batch); + + batch.resetViewTransform(); + + Transform model; + batch.setProjectionTransform(glm::mat4()); + batch.setModelTransform(model); + // Occlusion pass batch.pushProfileRange("Occlusion"); diff --git a/libraries/render-utils/src/SurfaceGeometryPass.cpp b/libraries/render-utils/src/SurfaceGeometryPass.cpp index 8f337b66da..66ac3669a4 100644 --- a/libraries/render-utils/src/SurfaceGeometryPass.cpp +++ b/libraries/render-utils/src/SurfaceGeometryPass.cpp @@ -73,19 +73,20 @@ void LinearDepthFramebuffer::allocate() { auto height = _frameSize.y; // For Linear Depth: - const uint16_t LINEAR_DEPTH_MAX_MIP_LEVEL = 5; - // Point sampling of the depth is needed for the AmbientOcclusionEffect in HBAO, as well as the clamp to edge - const auto depthSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_POINT, gpu::Sampler::WRAP_CLAMP); + const uint16_t LINEAR_DEPTH_MAX_MIP_LEVEL = 1; + const auto depthSamplerFull = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT, gpu::Sampler::WRAP_CLAMP); _linearDepthTexture = gpu::Texture::createRenderBuffer(gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::RED), width, height, LINEAR_DEPTH_MAX_MIP_LEVEL, - depthSampler); + depthSamplerFull); _linearDepthFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("linearDepth")); _linearDepthFramebuffer->setRenderBuffer(0, _linearDepthTexture); _linearDepthFramebuffer->setDepthStencilBuffer(_primaryDepthTexture, _primaryDepthTexture->getTexelFormat()); // For Downsampling: - const uint16_t HALF_LINEAR_DEPTH_MAX_MIP_LEVEL = LINEAR_DEPTH_MAX_MIP_LEVEL; + const uint16_t HALF_LINEAR_DEPTH_MAX_MIP_LEVEL = 5; + // Point sampling of the depth, as well as the clamp to edge, are needed for the AmbientOcclusionEffect with HBAO + const auto depthSamplerHalf = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_POINT, gpu::Sampler::WRAP_CLAMP); _halfLinearDepthTexture = gpu::Texture::createRenderBuffer(gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::RED), _halfFrameSize.x, _halfFrameSize.y, HALF_LINEAR_DEPTH_MAX_MIP_LEVEL, - depthSampler); + depthSamplerHalf); _halfNormalTexture = gpu::Texture::createRenderBuffer(gpu::Element::COLOR_RGBA_32, _halfFrameSize.x, _halfFrameSize.y, gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT)); @@ -183,35 +184,47 @@ void LinearDepthPass::run(const render::RenderContextPointer& renderContext, con auto halfViewport = divideRoundUp(depthViewport, 2); float clearLinearDepth = args->getViewFrustum().getFarClip() * 2.0f; - gpu::doInBatch("LinearDepthPass::run", args->_context, [=](gpu::Batch& batch) { + gpu::doInBatch("LinearDepthPass::ZtoLinearDepth", args->_context, [=](gpu::Batch& batch) { + PROFILE_RANGE_BATCH(batch, "ZtoLinearDepth"); _gpuTimer->begin(batch); batch.enableStereo(false); - batch.setViewportTransform(depthViewport); batch.setProjectionTransform(glm::mat4()); batch.resetViewTransform(); - batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(_linearDepthFramebuffer->getDepthFrameSize(), depthViewport)); batch.setUniformBuffer(ru::Buffer::DeferredFrameTransform, frameTransform->getFrameTransformBuffer()); // LinearDepth + batch.setViewportTransform(depthViewport); batch.setFramebuffer(linearDepthFBO); batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, glm::vec4(clearLinearDepth, 0.0f, 0.0f, 0.0f)); batch.setPipeline(linearDepthPipeline); + batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(_linearDepthFramebuffer->getDepthFrameSize(), depthViewport)); batch.setResourceTexture(ru::Texture::SurfaceGeometryDepth, depthBuffer); batch.draw(gpu::TRIANGLE_STRIP, 4); + _gpuTimer->end(batch); + }); + + gpu::doInBatch("LinearDepthPass::halfDepth", args->_context, [=](gpu::Batch& batch) { + PROFILE_RANGE_BATCH(batch, "LinearDepthDownsample"); + _gpuTimer->begin(batch); + batch.enableStereo(false); + + batch.setProjectionTransform(glm::mat4()); + batch.resetViewTransform(); + + batch.setUniformBuffer(ru::Buffer::DeferredFrameTransform, frameTransform->getFrameTransformBuffer()); + // Downsample batch.setViewportTransform(halfViewport); - Transform model; - model.setScale( glm::vec3((depthViewport.z >> 1) / float(halfViewport.z), (depthViewport.w >> 1) / float(halfViewport.w), 1.0f) ); - batch.setModelTransform(model); batch.setFramebuffer(downsampleFBO); batch.setResourceTexture(ru::Texture::SurfaceGeometryDepth, linearDepthTexture); batch.setResourceTexture(ru::Texture::SurfaceGeometryNormal, normalTexture); batch.setPipeline(downsamplePipeline); + batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(_linearDepthFramebuffer->getDepthFrameSize() >> 1, halfViewport)); batch.draw(gpu::TRIANGLE_STRIP, 4); - + _gpuTimer->end(batch); }); diff --git a/libraries/render-utils/src/ssao.slh b/libraries/render-utils/src/ssao.slh index 3f4d361531..f8bba54d6b 100644 --- a/libraries/render-utils/src/ssao.slh +++ b/libraries/render-utils/src/ssao.slh @@ -282,25 +282,26 @@ vec4 fetchTap(ivec4 side, vec2 tapSidePixelPos, float tapRadius, vec2 sideImageS return P; } -vec3 buildPosition(ivec4 side, vec2 fragUVPos, ivec2 depthTexFragPixelPos, ivec2 deltaDepthTexPixel, vec2 uvScale) { - depthTexFragPixelPos += deltaDepthTexPixel; - fragUVPos += deltaDepthTexPixel * uvScale; - float Zeye = getZEyeAtPixel(depthTexFragPixelPos, 0); +vec3 buildPosition(ivec4 side, vec2 fragUVPos) { + vec2 fetchUV = clamp(fragUVPos, vec2(0), vec2(1)); + fetchUV = mix(fetchUV, vec2((fetchUV.x + getStereoSide(side)) * 0.5, fetchUV.y), isStereo()); + float Zeye = getZEyeAtUV(fetchUV, 0); return evalEyePositionFromZeye(side.x, Zeye, fragUVPos); } vec3 getMinDelta(vec3 centralPoint, vec3 offsetPointPos, vec3 offsetPointNeg) { vec3 delta0 = offsetPointPos - centralPoint; vec3 delta1 = centralPoint - offsetPointNeg; - return dot(delta0, delta0) < dot(delta1, delta1) ? delta0 : delta1; + float sqrLength0 = dot(delta0, delta0); + float sqrLength1 = dot(delta1, delta1); + return sqrLength0 < sqrLength1 ? delta0 : delta1; } -vec3 buildNormal(ivec4 side, vec2 fragUVPos, ivec2 depthTexFragPixelPos, vec3 fragPosition, vec2 depthTextureSize) { - vec2 uvScale = vec2(1.0) / depthTextureSize; - vec3 fragPositionDxPos = buildPosition(side, fragUVPos, depthTexFragPixelPos, ivec2(1, 0), uvScale); - vec3 fragPositionDyPos = buildPosition(side, fragUVPos, depthTexFragPixelPos, ivec2(0, 1), uvScale); - vec3 fragPositionDxNeg = buildPosition(side, fragUVPos, depthTexFragPixelPos, ivec2(-1, 0), uvScale); - vec3 fragPositionDyNeg = buildPosition(side, fragUVPos, depthTexFragPixelPos, ivec2(0, -1), uvScale); +vec3 buildNormal(ivec4 side, vec2 fragUVPos, vec3 fragPosition, vec2 deltaDepthUV) { + vec3 fragPositionDxPos = buildPosition(side, fragUVPos + vec2(deltaDepthUV.x, 0)); + vec3 fragPositionDyPos = buildPosition(side, fragUVPos + vec2(0, deltaDepthUV.y)); + vec3 fragPositionDxNeg = buildPosition(side, fragUVPos - vec2(deltaDepthUV.x, 0)); + vec3 fragPositionDyNeg = buildPosition(side, fragUVPos - vec2(0, deltaDepthUV.y)); vec3 fragPositionDx = getMinDelta(fragPosition, fragPositionDxPos, fragPositionDxNeg); vec3 fragPositionDy = getMinDelta(fragPosition, fragPositionDyPos, fragPositionDyNeg); diff --git a/libraries/render-utils/src/ssao_buildNormals.slf b/libraries/render-utils/src/ssao_buildNormals.slf index 36066b87df..09502f2026 100644 --- a/libraries/render-utils/src/ssao_buildNormals.slf +++ b/libraries/render-utils/src/ssao_buildNormals.slf @@ -15,31 +15,28 @@ <$declareAmbientOcclusion()$> <$declareFetchDepthPyramidMap()$> +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); - - // Fetch the z under the pixel (stereo or not) from full res depth - int depthTextureRatio = 1 << getNormalsResolutionLevel(); - ivec2 depthTexFragPixelPos = fragPixelPos * depthTextureRatio; - float Zeye = getZEyeAtPixel(depthTexFragPixelPos, 0); + vec2 fragUVPos = varTexCoord0; // Stereo side info based on the real viewport size of this pass ivec2 sideNormalsSize = ivec2( getNormalsSideSize() ); ivec4 side = getStereoSideInfoFromWidth(fragPixelPos.x, sideNormalsSize.x); - // From now on, fragPixelPos is the pixel pos in the side - vec2 depthSideSize = getDepthTextureSideSize(0); - vec2 sideImageSize = depthSideSize / float(depthTextureRatio); - fragPixelPos.x -= side.y; - vec2 fragUVPos = (vec2(fragPixelPos) + vec2(0.5)) / sideImageSize; + // From now on, fragUVPos is the UV pos in the side + fragUVPos.x = mix(fragUVPos.x, fragUVPos.x - getStereoSide(side) * 0.5, isStereo()); + + vec2 deltaDepthUV = vec2(1.0) / vec2(getDepthTextureSideSize(0)); // The position and normal of the pixel fragment in Eye space - vec3 fragPositionES = evalEyePositionFromZeye(side.x, Zeye, fragUVPos); - vec3 fragNormalES = buildNormal(side, fragUVPos, depthTexFragPixelPos, fragPositionES, depthSideSize); + vec3 fragPositionES = buildPosition(side, fragUVPos); + vec3 fragNormalES = buildNormal(side, fragUVPos, fragPositionES, deltaDepthUV); vec3 absFragNormalES = abs(fragNormalES); fragNormalES /= max(absFragNormalES.z, max(absFragNormalES.x, absFragNormalES.y)); diff --git a/libraries/render-utils/src/ssao_makeOcclusion.slf b/libraries/render-utils/src/ssao_makeOcclusion.slf index f4962d8286..510ca4ea7b 100644 --- a/libraries/render-utils/src/ssao_makeOcclusion.slf +++ b/libraries/render-utils/src/ssao_makeOcclusion.slf @@ -51,9 +51,10 @@ void main(void) { vec2 fragUVPos = (vec2(fragPixelPos) + vec2(0.5)) / sideImageSize; // The position and normal of the pixel fragment in Eye space - vec3 fragPositionES = evalEyePositionFromZeye(side.x, Zeye, fragUVPos); + vec3 fragPositionES = buildPosition(side, fragUVPos); #if !SSAO_USE_QUAD_SPLIT - vec3 fragNormalES = buildNormal(side, fragUVPos, depthTexFragPixelPos, fragPositionES, depthSideSize); + vec2 deltaDepthUV = vec2(1.0) / depthSideSize; + vec3 fragNormalES = buildNormal(side, fragUVPos, fragPositionES, deltaDepthUV); #endif // Choose the screen-space sample radius