From 03814e7653fd8106d4209fb5abd8d67ab42902d1 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Tue, 18 Sep 2018 18:33:28 +0200 Subject: [PATCH] Preparing for split rendering of HBAO directions --- .../src/AmbientOcclusionEffect.cpp | 68 +++++++++++++++++-- .../render-utils/src/AmbientOcclusionEffect.h | 4 ++ .../src/render-utils/ShaderConstants.h | 2 + libraries/render-utils/src/ssao.slh | 14 +++- .../render-utils/src/ssao_makeOcclusion.slf | 3 +- libraries/render-utils/src/ssao_shared.h | 16 ++++- 6 files changed, 99 insertions(+), 8 deletions(-) diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.cpp b/libraries/render-utils/src/AmbientOcclusionEffect.cpp index 0a7a15ecbd..c1101ad395 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.cpp +++ b/libraries/render-utils/src/AmbientOcclusionEffect.cpp @@ -260,6 +260,23 @@ void AmbientOcclusionEffect::configure(const Config& config) { auto& current = _aoParametersBuffer.edit()._sampleInfo; current.x = config.numSamples; current.y = 1.0f / config.numSamples; + + // Regenerate halton sequence + const int B = config.numSamples + 1; + const float invB = 1.0f / (float)B; + + for (int i = 0; i < _randomSamples.size(); i++) { + int index = i+1; // Indices start at 1, not 0 + float f = 1.0f; + float r = 0.0f; + + while (index > 0) { + f = f * invB; + r = r + f * (float)(index % B); + index = index / B; + } + _randomSamples[i] = r; + } } if (config.fetchMipsEnabled != _aoParametersBuffer->isFetchMipsEnabled()) { @@ -280,6 +297,13 @@ void AmbientOcclusionEffect::configure(const Config& config) { auto& current = _aoParametersBuffer.edit()._resolutionInfo; current.x = (float) config.resolutionLevel; shouldUpdateBlurs = true; + + _aoFrameParametersBuffer[0].edit()._pixelOffsets = { 0, 0, 0, 0 }; +#if SSAO_USE_QUAD_SPLIT + _aoFrameParametersBuffer[1].edit()._pixelOffsets = { 1, 0, 0, 0 }; + _aoFrameParametersBuffer[2].edit()._pixelOffsets = { 1, 1, 0, 0 }; + _aoFrameParametersBuffer[3].edit()._pixelOffsets = { 0, 1, 0, 0 }; +#endif } if (config.blurRadius != _aoParametersBuffer->getBlurRadius()) { @@ -425,21 +449,29 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte auto mipCreationPipeline = getMipCreationPipeline(); #endif + // Update sample rotation + const int SSAO_RANDOM_SAMPLE_COUNT = int(_randomSamples.size() / SSAO_SPLIT_COUNT); + for (int splitId=0 ; splitId < SSAO_SPLIT_COUNT ; splitId++) { + auto& sample = _aoFrameParametersBuffer[splitId].edit(); + sample._angleInfo.x = _randomSamples[_frameId + SSAO_RANDOM_SAMPLE_COUNT * splitId] * M_PI; + } + _frameId = (_frameId + 1) % SSAO_RANDOM_SAMPLE_COUNT; + gpu::doInBatch("AmbientOcclusionEffect::run", args->_context, [=](gpu::Batch& batch) { PROFILE_RANGE_BATCH(batch, "AmbientOcclusion"); batch.enableStereo(false); _gpuTimer->begin(batch); - batch.setViewportTransform(occlusionViewport); batch.setProjectionTransform(glm::mat4()); batch.resetViewTransform(); Transform model; + batch.setProjectionTransform(glm::mat4()); + batch.setModelTransform(model); // We need this with the mips levels batch.pushProfileRange("Depth mip creation"); - batch.setModelTransform(model); #if SSAO_USE_HORIZON_BASED batch.setPipeline(mipCreationPipeline); batch.generateTextureMipsWithPipeline(occlusionDepthTexture); @@ -450,13 +482,42 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte // Occlusion pass batch.pushProfileRange("Occlusion"); + batch.setUniformBuffer(render_utils::slot::buffer::DeferredFrameTransform, frameTransform->getFrameTransformBuffer()); - batch.setUniformBuffer(render_utils::slot::buffer::SsaoParams, _aoParametersBuffer); + batch.setUniformBuffer(render_utils::slot::buffer::SsaoParams, _aoParametersBuffer); batch.setFramebuffer(occlusionFBO); batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, glm::vec4(1.0f)); batch.setPipeline(occlusionPipeline); batch.setResourceTexture(render_utils::slot::texture::SsaoDepth, occlusionDepthTexture); + +#if SSAO_USE_QUAD_SPLIT + { + auto splitViewport = occlusionViewport >> SSAO_USE_QUAD_SPLIT; + + batch.setViewportTransform(splitViewport); + batch.setUniformBuffer(render_utils::slot::buffer::SsaoFrameParams, _aoFrameParametersBuffer[0]); + batch.draw(gpu::TRIANGLE_STRIP, 4); + + splitViewport.x += splitViewport.z; + batch.setViewportTransform(splitViewport); + batch.setUniformBuffer(render_utils::slot::buffer::SsaoFrameParams, _aoFrameParametersBuffer[1]); + batch.draw(gpu::TRIANGLE_STRIP, 4); + + splitViewport.y += splitViewport.w; + batch.setViewportTransform(splitViewport); + batch.setUniformBuffer(render_utils::slot::buffer::SsaoFrameParams, _aoFrameParametersBuffer[2]); + batch.draw(gpu::TRIANGLE_STRIP, 4); + + splitViewport.x = 0; + batch.setViewportTransform(splitViewport); + batch.setUniformBuffer(render_utils::slot::buffer::SsaoFrameParams, _aoFrameParametersBuffer[3]); + batch.draw(gpu::TRIANGLE_STRIP, 4); + } +#else + batch.setUniformBuffer(render_utils::slot::buffer::SsaoFrameParams, _aoFrameParametersBuffer[0]); batch.draw(gpu::TRIANGLE_STRIP, 4); +#endif + batch.popProfileRange(); { @@ -552,7 +613,6 @@ void DebugAmbientOcclusion::run(const render::RenderContextPointer& renderContex linearDepthTexture = linearDepthFramebuffer->getHalfLinearDepthTexture(); occlusionViewport = occlusionViewport >> ambientOcclusionUniforms->getResolutionLevel(); } - auto framebufferSize = glm::ivec2(linearDepthTexture->getDimensions()); diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.h b/libraries/render-utils/src/AmbientOcclusionEffect.h index 86754d494b..807c0b5ec8 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.h +++ b/libraries/render-utils/src/AmbientOcclusionEffect.h @@ -153,11 +153,13 @@ private: }; using BlurParametersBuffer = gpu::StructBuffer; + using FrameParametersBuffer = gpu::StructBuffer< AmbientOcclusionFrameParams>; void updateGaussianDistribution(); void updateBlurParameters(); AOParametersBuffer _aoParametersBuffer; + FrameParametersBuffer _aoFrameParametersBuffer[SSAO_SPLIT_COUNT]; BlurParametersBuffer _vblurParametersBuffer; BlurParametersBuffer _hblurParametersBuffer; @@ -172,6 +174,8 @@ private: static gpu::PipelinePointer _mipCreationPipeline; AmbientOcclusionFramebufferPointer _framebuffer; + std::array _randomSamples; + int _frameId{ 0 }; gpu::RangeTimerPointer _gpuTimer; diff --git a/libraries/render-utils/src/render-utils/ShaderConstants.h b/libraries/render-utils/src/render-utils/ShaderConstants.h index c6bdfb759c..ce4e481ce3 100644 --- a/libraries/render-utils/src/render-utils/ShaderConstants.h +++ b/libraries/render-utils/src/render-utils/ShaderConstants.h @@ -87,6 +87,7 @@ #define RENDER_UTILS_BUFFER_SSAO_PARAMS 2 #define RENDER_UTILS_BUFFER_SSAO_DEBUG_PARAMS 3 #define RENDER_UTILS_BUFFER_SSAO_BLUR_PARAMS 4 +#define RENDER_UTILS_BUFFER_SSAO_FRAME_PARAMS 5 #define RENDER_UTILS_TEXTURE_SSAO_DEPTH 1 #define RENDER_UTILS_TEXTURE_SSAO_OCCLUSION 0 @@ -153,6 +154,7 @@ enum Buffer { LightClusterContent = RENDER_UTILS_BUFFER_LIGHT_CLUSTER_CONTENT, SsscParams = RENDER_UTILS_BUFFER_SSSC_PARAMS, SsaoParams = RENDER_UTILS_BUFFER_SSAO_PARAMS, + SsaoFrameParams = RENDER_UTILS_BUFFER_SSAO_FRAME_PARAMS, SsaoDebugParams = RENDER_UTILS_BUFFER_SSAO_DEBUG_PARAMS, SsaoBlurParams = RENDER_UTILS_BUFFER_SSAO_BLUR_PARAMS, LightIndex = RENDER_UTILS_BUFFER_LIGHT_INDEX, diff --git a/libraries/render-utils/src/ssao.slh b/libraries/render-utils/src/ssao.slh index 38b7999924..fefa424bbd 100644 --- a/libraries/render-utils/src/ssao.slh +++ b/libraries/render-utils/src/ssao.slh @@ -40,9 +40,11 @@ layout(binding=RENDER_UTILS_BUFFER_SSAO_PARAMS) uniform ambientOcclusionParamsBu AmbientOcclusionParams params; }; +layout(binding=RENDER_UTILS_BUFFER_SSAO_FRAME_PARAMS) uniform ambientOcclusionFrameParamsBuffer { + AmbientOcclusionFrameParams frameParams; +}; float getPerspectiveScale() { - return (params._resolutionInfo.z); } int getResolutionLevel() { @@ -136,8 +138,16 @@ float getAngleDitheringWorldPos(in vec3 pixelWorldPos) { } float getAngleDithering(in ivec2 pixelPos) { +#if SSAO_USE_QUAD_SPLIT + return isDitheringEnabled() * frameParams._angleInfo.x; +#else // Hash function used in the AlchemyAO paper - return isDitheringEnabled() * float((3 * pixelPos.x ^ pixelPos.y + pixelPos.x * pixelPos.y) * 10); + return isDitheringEnabled() * float((3 * pixelPos.x ^ pixelPos.y + pixelPos.x * pixelPos.y) * 10); +#endif +} + +ivec2 getPixelOffset() { + return frameParams._pixelOffsets.xy; } float evalDiskRadius(float Zeye, vec2 sideImageSize) { diff --git a/libraries/render-utils/src/ssao_makeOcclusion.slf b/libraries/render-utils/src/ssao_makeOcclusion.slf index 8c8832634c..e9e8c74f7b 100644 --- a/libraries/render-utils/src/ssao_makeOcclusion.slf +++ b/libraries/render-utils/src/ssao_makeOcclusion.slf @@ -25,10 +25,11 @@ layout(location=0) out vec4 outFragColor; void main(void) { vec2 sideImageSize = getSideImageSize(getResolutionLevel()); + ivec2 splitImageSize = ivec2(getWidthHeight(getResolutionLevel() + SSAO_USE_QUAD_SPLIT)); // Pixel being shaded vec2 fragCoord = gl_FragCoord.xy; - ivec2 fragPixelPos = ivec2(fragCoord.xy); + ivec2 fragPixelPos = ((ivec2(fragCoord.xy) - getPixelOffset()*splitImageSize) << SSAO_USE_QUAD_SPLIT) + getPixelOffset(); // Stereo side info ivec4 side = getStereoSideInfo(fragPixelPos.x, getResolutionLevel()); diff --git a/libraries/render-utils/src/ssao_shared.h b/libraries/render-utils/src/ssao_shared.h index 6b71c20c43..61bf14ccf8 100644 --- a/libraries/render-utils/src/ssao_shared.h +++ b/libraries/render-utils/src/ssao_shared.h @@ -15,13 +15,22 @@ #define RENDER_UTILS_SSAO_SHARED_H #define SSAO_USE_HORIZON_BASED 1 +#define SSAO_USE_QUAD_SPLIT 1 #define SSAO_BLUR_GAUSSIAN_COEFS_COUNT 16 -// glsl / C++ compatible source as interface for Shadows +#if SSAO_USE_QUAD_SPLIT +#define SSAO_SPLIT_COUNT 4 +#else +#define SSAO_SPLIT_COUNT 1 +#endif + +// glsl / C++ compatible source as interface for ambient occlusion #ifdef __cplusplus # define SSAO_VEC4 glm::vec4 +# define SSAO_IVEC4 glm::ivec4 #else # define SSAO_VEC4 vec4 +# define SSAO_IVEC4 ivec4 #endif struct AmbientOcclusionParams { @@ -33,6 +42,11 @@ struct AmbientOcclusionParams { float _gaussianCoefs[SSAO_BLUR_GAUSSIAN_COEFS_COUNT]; }; +struct AmbientOcclusionFrameParams { + SSAO_VEC4 _angleInfo; + SSAO_IVEC4 _pixelOffsets; +}; + #endif // RENDER_UTILS_SHADER_CONSTANTS_H // <@if 1@>