diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.cpp b/libraries/render-utils/src/AmbientOcclusionEffect.cpp index 5b27cfa41d..86de3cec04 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.cpp +++ b/libraries/render-utils/src/AmbientOcclusionEffect.cpp @@ -92,12 +92,13 @@ void AmbientOcclusionFramebuffer::allocate() { { auto width = _frameSize.x; auto height = _frameSize.y; + auto sampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR, gpu::Sampler::WRAP_CLAMP); - _occlusionTexture = gpu::Texture::createRenderBuffer(occlusionformat, width, height, gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR, gpu::Sampler::WRAP_CLAMP)); + _occlusionTexture = gpu::Texture::createRenderBuffer(occlusionformat, width, height, gpu::Texture::SINGLE_MIP, sampler); _occlusionFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("occlusion")); _occlusionFramebuffer->setRenderBuffer(0, _occlusionTexture); - _occlusionBlurredTexture = gpu::Texture::createRenderBuffer(occlusionformat, width, height, gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR, gpu::Sampler::WRAP_CLAMP)); + _occlusionBlurredTexture = gpu::Texture::createRenderBuffer(occlusionformat, width, height, gpu::Texture::SINGLE_MIP, sampler); _occlusionBlurredFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("occlusionBlurred")); _occlusionBlurredFramebuffer->setRenderBuffer(0, _occlusionBlurredTexture); } @@ -108,7 +109,7 @@ void AmbientOcclusionFramebuffer::allocate() { if (_isStereo) { sideSize.x >>= 1; } - sideSize = divideRoundUp(sideSize, 1 << _resolutionLevel); + sideSize >>= _resolutionLevel; if (_isStereo) { sideSize.x <<= 1; } @@ -127,7 +128,7 @@ void AmbientOcclusionFramebuffer::allocate() { if (_isStereo) { splitSize.x >>= 1; } - splitSize = divideRoundUp(splitSize, SSAO_SPLIT_COUNT << _resolutionLevel); + splitSize = divideRoundUp(_frameSize >> _resolutionLevel, SSAO_SPLIT_COUNT); if (_isStereo) { splitSize.x <<= 1; } @@ -355,14 +356,13 @@ void AmbientOcclusionEffect::configure(const Config& config) { void AmbientOcclusionEffect::updateBlurParameters() { const auto resolutionLevel = _aoParametersBuffer->getResolutionLevel(); - const auto resolutionScale = 1 << resolutionLevel; auto& vblur = _vblurParametersBuffer.edit(); auto& hblur = _hblurParametersBuffer.edit(); auto frameSize = _framebuffer->getSourceFrameSize(); if (_framebuffer->isStereo()) { frameSize.x >>= 1; } - const auto occlusionSize = divideRoundUp(frameSize, resolutionScale); + const auto occlusionSize = frameSize >> resolutionLevel; // Occlusion UV limit hblur._blurAxis.z = occlusionSize.x / float(frameSize.x); @@ -381,18 +381,17 @@ void AmbientOcclusionEffect::updateBlurParameters() { void AmbientOcclusionEffect::updateFramebufferSizes() { auto& params = _aoParametersBuffer.edit(); - const int widthScale = _framebuffer->isStereo() & 1; + const int stereoDivide = _framebuffer->isStereo() & 1; auto sourceFrameSideSize = _framebuffer->getSourceFrameSize(); - sourceFrameSideSize.x >>= widthScale; + sourceFrameSideSize.x >>= stereoDivide; const int resolutionLevel = _aoParametersBuffer.get().getResolutionLevel(); - // Depth is at maximum half depth const int depthResolutionLevel = getDepthResolutionLevel(); - const auto occlusionDepthFrameSize = divideRoundUp(sourceFrameSideSize, 1 << depthResolutionLevel); - const auto occlusionFrameSize = divideRoundUp(sourceFrameSideSize, 1 << resolutionLevel); + const auto occlusionDepthFrameSize = sourceFrameSideSize >> depthResolutionLevel; + const auto occlusionFrameSize = sourceFrameSideSize >> resolutionLevel; auto normalTextureSize = _framebuffer->getNormalTexture()->getDimensions(); - normalTextureSize.x >>= widthScale; + normalTextureSize.x >>= stereoDivide; params._sideSizes[0].x = normalTextureSize.x; params._sideSizes[0].y = normalTextureSize.y; @@ -485,12 +484,10 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte const auto depthResolutionScale = powf(0.5f, depthResolutionLevel); const auto isHorizonBased = _aoParametersBuffer->isHorizonBased(); - auto linearDepthTexture = linearDepthFramebuffer->getLinearDepthTexture(); - auto occlusionDepthTexture = linearDepthTexture; + auto fullResDepthTexture = linearDepthFramebuffer->getLinearDepthTexture(); + auto occlusionDepthTexture = fullResDepthTexture; auto sourceViewport = args->_viewport; - // divideRoundUp is used two compute the quarter or half resolution render sizes. - // We choose to take the rounded up resolution. - auto occlusionViewport = divideRoundUp(sourceViewport, 1 << resolutionLevel); + auto occlusionViewport = sourceViewport >> resolutionLevel; auto firstBlurViewport = sourceViewport; firstBlurViewport.w = occlusionViewport.w; @@ -506,7 +503,7 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte occlusionDepthTexture = linearDepthFramebuffer->getHalfLinearDepthTexture(); } - if (_framebuffer->update(linearDepthTexture, resolutionLevel, depthResolutionLevel, args->isStereo())) { + if (_framebuffer->update(fullResDepthTexture, resolutionLevel, depthResolutionLevel, args->isStereo())) { updateBlurParameters(); updateFramebufferSizes(); } @@ -538,7 +535,7 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte auto& sample = _aoFrameParametersBuffer[splitId].edit(); sample._angleInfo.x = _randomSamples[splitId + SSAO_RANDOM_SAMPLE_COUNT * _frameId]; } - // _frameId = (_frameId + 1) % SSAO_RANDOM_SAMPLE_COUNT; + _frameId = (_frameId + 1) % SSAO_RANDOM_SAMPLE_COUNT; gpu::doInBatch("AmbientOcclusionEffect::run", args->_context, [=](gpu::Batch& batch) { PROFILE_RANGE_BATCH(batch, "SSAO"); @@ -567,7 +564,7 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte batch.setModelTransform(Transform()); batch.setViewportTransform(normalViewport); batch.setPipeline(buildNormalsPipeline); - batch.setResourceTexture(render_utils::slot::texture::SsaoDepth, linearDepthTexture); + batch.setResourceTexture(render_utils::slot::texture::SsaoDepth, fullResDepthTexture); 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); @@ -651,8 +648,8 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte batch.setModelTransform(model); } batch.setPipeline(bilateralBlurPipeline); - // Use full resolution depth and normal for bilateral upscaling and blur - batch.setResourceTexture(render_utils::slot::texture::SsaoDepth, linearDepthTexture); + // Use full resolution depth for bilateral upscaling and blur + batch.setResourceTexture(render_utils::slot::texture::SsaoDepth, fullResDepthTexture); #if SSAO_USE_QUAD_SPLIT batch.setResourceTexture(render_utils::slot::texture::SsaoNormal, occlusionNormalTexture); #else @@ -742,18 +739,18 @@ void DebugAmbientOcclusion::run(const render::RenderContextPointer& renderContex return; } - auto linearDepthTexture = linearDepthFramebuffer->getLinearDepthTexture(); + auto fullResDepthTexture = linearDepthFramebuffer->getLinearDepthTexture(); auto sourceViewport = args->_viewport; auto occlusionViewport = sourceViewport; auto resolutionLevel = ambientOcclusionUniforms->getResolutionLevel(); if (resolutionLevel > 0) { - linearDepthTexture = linearDepthFramebuffer->getHalfLinearDepthTexture(); + fullResDepthTexture = linearDepthFramebuffer->getHalfLinearDepthTexture(); occlusionViewport = occlusionViewport >> ambientOcclusionUniforms->getResolutionLevel(); } - auto framebufferSize = glm::ivec2(linearDepthTexture->getDimensions()); + auto framebufferSize = glm::ivec2(fullResDepthTexture->getDimensions()); float sMin = occlusionViewport.x / (float)framebufferSize.x; float sWidth = occlusionViewport.z / (float)framebufferSize.x; @@ -779,7 +776,7 @@ void DebugAmbientOcclusion::run(const render::RenderContextPointer& renderContex batch.setUniformBuffer(render_utils::slot::buffer::SsaoDebugParams, _parametersBuffer); batch.setPipeline(debugPipeline); - batch.setResourceTexture(render_utils::slot::texture::SsaoDepth, linearDepthTexture); + batch.setResourceTexture(render_utils::slot::texture::SsaoDepth, fullResDepthTexture); batch.draw(gpu::TRIANGLE_STRIP, 4); diff --git a/libraries/render-utils/src/SurfaceGeometryPass.cpp b/libraries/render-utils/src/SurfaceGeometryPass.cpp index d5e0249a21..59d2198daa 100644 --- a/libraries/render-utils/src/SurfaceGeometryPass.cpp +++ b/libraries/render-utils/src/SurfaceGeometryPass.cpp @@ -45,7 +45,7 @@ void LinearDepthFramebuffer::update(const gpu::TexturePointer& depthBuffer, cons if (isStereo) { _halfFrameSize.x >>= 1; } - _halfFrameSize = divideRoundUp(_halfFrameSize, 2); + _halfFrameSize >>= 1; if (isStereo) { _halfFrameSize.x <<= 1; } @@ -182,7 +182,7 @@ void LinearDepthPass::run(const render::RenderContextPointer& renderContext, con auto downsamplePipeline = getDownsamplePipeline(renderContext); auto depthViewport = args->_viewport; - auto halfViewport = divideRoundUp(depthViewport, 2); + auto halfViewport = depthViewport >> 1; float clearLinearDepth = args->getViewFrustum().getFarClip() * 2.0f; gpu::doInBatch("LinearDepthPass::run", args->_context, [=](gpu::Batch& batch) { diff --git a/libraries/render-utils/src/ssao.slh b/libraries/render-utils/src/ssao.slh index 9590dd9277..a5bb689d06 100644 --- a/libraries/render-utils/src/ssao.slh +++ b/libraries/render-utils/src/ssao.slh @@ -260,11 +260,20 @@ float getZEyeAtUV(vec2 texCoord, int level) { return -textureLod(depthPyramidTex, texCoord, level).x; } +float getZEyeAtUV(vec2 texCoord, int level, ivec2 texelOffset) { + return -textureLodOffset(depthPyramidTex, texCoord, level, texelOffset).x; +} + float getZEyeAtUV(ivec4 side, vec2 texCoord, int level) { texCoord.x = mix(texCoord.x, (texCoord.x + getStereoSide(side)) * 0.5, isStereo()); return getZEyeAtUV(texCoord, level); } +float getZEyeAtUV(ivec4 side, vec2 texCoord, int level, ivec2 texelOffset) { + texCoord.x = mix(texCoord.x, (texCoord.x + getStereoSide(side)) * 0.5, isStereo()); + return getZEyeAtUV(texCoord, level, texelOffset); +} + vec3 getNormalEyeAtUV(vec2 texCoord, int level) { return normalize(textureLod(normalTex, texCoord, level).xyz*2.0 - vec3(1.0)); } @@ -301,20 +310,25 @@ vec3 buildPosition(ivec4 side, vec2 fragUVPos) { return evalEyePositionFromZeye(side.x, Zeye, fragUVPos); } +vec3 buildPosition(ivec4 side, vec2 fragUVPos, ivec2 texelOffset, vec2 deltaUV) { + float Zeye = getZEyeAtUV(side, fragUVPos, 0, texelOffset); + return evalEyePositionFromZeye(side.x, Zeye, fragUVPos + texelOffset*deltaUV); +} + vec3 getMinDelta(vec3 centralPoint, vec3 offsetPointPos, vec3 offsetPointNeg) { vec3 delta0 = offsetPointPos - centralPoint; vec3 delta1 = centralPoint - offsetPointNeg; float sqrLength0 = dot(delta0, delta0); float sqrLength1 = dot(delta1, delta1); - float epsilon = 1e-6; - return sqrLength0 < sqrLength1 && sqrLength0>epsilon ? delta0 : delta1; + + return sqrLength0 < sqrLength1 ? delta0 : delta1; } vec3 buildNormal(ivec4 side, vec2 fragUVPos, vec3 fragPosition, vec2 deltaDepthUV) { - vec3 fragPositionDxPos = buildPosition(side, fragUVPos + vec2(deltaDepthUV.x, 0)); - vec3 fragPositionDxNeg = buildPosition(side, fragUVPos - vec2(deltaDepthUV.x, 0)); - vec3 fragPositionDyPos = buildPosition(side, fragUVPos + vec2(0, deltaDepthUV.y)); - vec3 fragPositionDyNeg = buildPosition(side, fragUVPos - vec2(0, deltaDepthUV.y)); + vec3 fragPositionDxPos = buildPosition(side, fragUVPos, ivec2(1,0), deltaDepthUV); + vec3 fragPositionDxNeg = buildPosition(side, fragUVPos, ivec2(-1,0), deltaDepthUV); + vec3 fragPositionDyPos = buildPosition(side, fragUVPos, ivec2(0,1), deltaDepthUV); + vec3 fragPositionDyNeg = buildPosition(side, fragUVPos, ivec2(0,-1), deltaDepthUV); vec3 fragPositionDx = getMinDelta(fragPosition, fragPositionDxPos, fragPositionDxNeg); vec3 fragPositionDy = getMinDelta(fragPosition, fragPositionDyPos, fragPositionDyNeg); diff --git a/libraries/render-utils/src/ssao_bilateralBlur.slf b/libraries/render-utils/src/ssao_bilateralBlur.slf index e89d696cbb..bec6793307 100644 --- a/libraries/render-utils/src/ssao_bilateralBlur.slf +++ b/libraries/render-utils/src/ssao_bilateralBlur.slf @@ -43,7 +43,7 @@ int getBlurRadius() { } vec4 fetchOcclusionPacked(ivec4 side, vec2 texCoord) { - texCoord.x = mix(texCoord.x, (texCoord.x + getStereoSide(side)) * 0.5, isStereo()); + texCoord.x = mix(texCoord.x, (texCoord.x + getStereoSide(side) * getBlurOcclusionUVLimit().x) * 0.5, isStereo()); return textureLod(occlusionMap, texCoord, 0); } @@ -54,12 +54,11 @@ float evalBlurCoefficient(vec3 blurScales, float radialDistance, float zDistance const float BLUR_EDGE_NORMAL_LIMIT = 0.25; -vec2 evalTapWeightedValue(vec3 blurScales, ivec4 side, int r, vec2 occlusionTexCoord, vec2 depthTexCoord, float fragDepth, vec3 fragNormal) { +vec2 evalTapWeightedValue(vec3 blurScales, ivec4 side, int r, vec2 occlusionTexCoord, float fragDepth, vec3 fragNormal) { vec2 tapOcclusionTexCoord = getBlurOcclusionAxis() * r + occlusionTexCoord; vec2 occlusionTexCoordLimits = getBlurOcclusionUVLimit(); - if (tapOcclusionTexCoord.x < side.x || tapOcclusionTexCoord.x >= (side.x + occlusionTexCoordLimits.x) - || tapOcclusionTexCoord.y < 0 || tapOcclusionTexCoord.y >= occlusionTexCoordLimits.y) { + if (any(lessThan(tapOcclusionTexCoord, vec2(0.0))) || any(greaterThanEqual(tapOcclusionTexCoord, occlusionTexCoordLimits)) ) { return vec2(0.0); } @@ -85,10 +84,10 @@ vec4 getBlurredOcclusion(ivec2 destPixelCoord, vec2 occlusionTexCoord, vec2 dept // Stereo side info ivec4 side = getStereoSideInfo(destPixelCoord.x, 0); - float fragDepth = getZEyeAtUV(side, depthTexCoord, 0); + float fragDepth = getZEyeAtUV(depthTexCoord, 0); float fragDepthKey = CSZToDepthKey(fragDepth); #if SSAO_BILATERAL_BLUR_USE_NORMAL - vec3 fragNormal = getNormalEyeAtUV(side, depthTexCoord, 0); + vec3 fragNormal = getNormalEyeAtUV(depthTexCoord, 0); #else vec3 fragNormal = vec3(0, 0, 1); #endif @@ -98,9 +97,13 @@ vec4 getBlurredOcclusion(ivec2 destPixelCoord, vec2 occlusionTexCoord, vec2 dept int blurRadius = getBlurRadius(); vec3 blurScales = getBlurScales(); + // From now on, occlusionTexCoord is the UV pos in the side + float sideTexCoord = occlusionTexCoord.x * 2.0 - getStereoSide(side) * getBlurOcclusionUVLimit().x; + occlusionTexCoord.x = mix(occlusionTexCoord.x, sideTexCoord, isStereo()); + // negative side first for (int r = -blurRadius; r <= -1; ++r) { - weightedSums += evalTapWeightedValue(blurScales, side, r, occlusionTexCoord, depthTexCoord, fragDepthKey, fragNormal); + weightedSums += evalTapWeightedValue(blurScales, side, r, occlusionTexCoord, fragDepthKey, fragNormal); } // Central pixel contribution @@ -110,7 +113,7 @@ vec4 getBlurredOcclusion(ivec2 destPixelCoord, vec2 occlusionTexCoord, vec2 dept // then positive side for (int r = 1; r <= blurRadius; ++r) { - weightedSums += evalTapWeightedValue(blurScales, side, r, occlusionTexCoord, depthTexCoord, fragDepthKey, fragNormal); + weightedSums += evalTapWeightedValue(blurScales, side, r, occlusionTexCoord, fragDepthKey, fragNormal); } // Final normalization