diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackendTexture.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLBackendTexture.cpp index 674fdacf0f..410c52a1f6 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackendTexture.cpp +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackendTexture.cpp @@ -105,7 +105,7 @@ void GLBackend::do_generateTextureMipsWithPipeline(const Batch& batch, size_t pa } glBindFramebuffer(GL_FRAMEBUFFER, _mipGenerationFramebufferId); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER_EXT, 0); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0); for (int level = 1; level < numMips; level++) { glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, object->_id, level); diff --git a/libraries/gpu/src/gpu/Batch.h b/libraries/gpu/src/gpu/Batch.h index 90a30f4e5e..06b1bd860e 100644 --- a/libraries/gpu/src/gpu/Batch.h +++ b/libraries/gpu/src/gpu/Batch.h @@ -213,7 +213,7 @@ public: // Generate the mips for a texture void generateTextureMips(const TexturePointer& texture); // Generate the mips for a texture using the current pipeline - void generateTextureMipsWithPipeline(const TexturePointer& texture, int numMips = -1); + void generateTextureMipsWithPipeline(const TexturePointer& destTexture, int numMips = -1); // Query Section void beginQuery(const QueryPointer& query); diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.cpp b/libraries/render-utils/src/AmbientOcclusionEffect.cpp index c526f16b75..7176135a0a 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.cpp +++ b/libraries/render-utils/src/AmbientOcclusionEffect.cpp @@ -34,6 +34,12 @@ #include "ssao_makeHorizontalBlur_frag.h" #include "ssao_makeVerticalBlur_frag.h" +#include "mip_depth_median_frag.h" + +gpu::PipelinePointer AmbientOcclusionEffect::_occlusionPipeline; +gpu::PipelinePointer AmbientOcclusionEffect::_hBlurPipeline; +gpu::PipelinePointer AmbientOcclusionEffect::_vBlurPipeline; +gpu::PipelinePointer AmbientOcclusionEffect::_mipCreationPipeline; AmbientOcclusionFramebuffer::AmbientOcclusionFramebuffer() { } @@ -333,6 +339,15 @@ const gpu::PipelinePointer& AmbientOcclusionEffect::getVBlurPipeline() { return _vBlurPipeline; } +const gpu::PipelinePointer& AmbientOcclusionEffect::getMipCreationPipeline() { + if (!_mipCreationPipeline) { + gpu::Shader::BindingSet slotBindings; + slotBindings.insert(gpu::Shader::Binding(std::string("depthTexture"), 0)); + _mipCreationPipeline = gpu::Context::createMipGenerationPipeline(mip_depth_median_frag::getShader(), slotBindings); + } + return _mipCreationPipeline; +} + void AmbientOcclusionEffect::updateGaussianDistribution() { auto coefs = _parametersBuffer.edit()._gaussianCoefs; GaussianDistribution::evalSampling(coefs, Parameters::GAUSSIAN_COEFS_LENGTH, _parametersBuffer->getBlurRadius(), _parametersBuffer->getBlurDeviation()); @@ -384,9 +399,11 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte auto occlusionPipeline = getOcclusionPipeline(); auto firstHBlurPipeline = getHBlurPipeline(); auto lastVBlurPipeline = getVBlurPipeline(); + auto mipCreationPipeline = getMipCreationPipeline(); gpu::doInBatch("AmbientOcclusionEffect::run", args->_context, [=](gpu::Batch& batch) { - batch.enableStereo(false); + PROFILE_RANGE_BATCH(batch, "AmbientOcclusion"); + batch.enableStereo(false); _gpuTimer->begin(batch); @@ -395,16 +412,18 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte batch.resetViewTransform(); Transform model; - model.setTranslation(glm::vec3(sMin, tMin, 0.0f)); + + // We need this with the mips levels + batch.setModelTransform(model); + batch.setPipeline(mipCreationPipeline); + batch.generateTextureMipsWithPipeline(_framebuffer->getLinearDepthTexture()); + + model.setTranslation(glm::vec3(sMin, tMin, 0.0f)); model.setScale(glm::vec3(sWidth, tHeight, 1.0f)); batch.setModelTransform(model); batch.setUniformBuffer(AmbientOcclusionEffect_FrameTransformSlot, frameTransform->getFrameTransformBuffer()); batch.setUniformBuffer(AmbientOcclusionEffect_ParamsSlot, _parametersBuffer); - - - // We need this with the mips levels - batch.generateTextureMips(_framebuffer->getLinearDepthTexture()); // Occlusion pass batch.setFramebuffer(occlusionFBO); @@ -413,7 +432,6 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte batch.setResourceTexture(AmbientOcclusionEffect_LinearDepthMapSlot, _framebuffer->getLinearDepthTexture()); batch.draw(gpu::TRIANGLE_STRIP, 4); - if (_parametersBuffer->getBlurRadius() > 0) { // Blur 1st pass batch.setFramebuffer(occlusionBlurredFBO); diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.h b/libraries/render-utils/src/AmbientOcclusionEffect.h index 3643e608ed..99cf4b034c 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.h +++ b/libraries/render-utils/src/AmbientOcclusionEffect.h @@ -159,13 +159,15 @@ private: ParametersBuffer _parametersBuffer; - const gpu::PipelinePointer& getOcclusionPipeline(); - const gpu::PipelinePointer& getHBlurPipeline(); // first - const gpu::PipelinePointer& getVBlurPipeline(); // second + static const gpu::PipelinePointer& getOcclusionPipeline(); + static const gpu::PipelinePointer& getHBlurPipeline(); // first + static const gpu::PipelinePointer& getVBlurPipeline(); // second + static const gpu::PipelinePointer& getMipCreationPipeline(); - gpu::PipelinePointer _occlusionPipeline; - gpu::PipelinePointer _hBlurPipeline; - gpu::PipelinePointer _vBlurPipeline; + static gpu::PipelinePointer _occlusionPipeline; + static gpu::PipelinePointer _hBlurPipeline; + static gpu::PipelinePointer _vBlurPipeline; + static gpu::PipelinePointer _mipCreationPipeline; AmbientOcclusionFramebufferPointer _framebuffer; diff --git a/libraries/render-utils/src/mip_depth_median.slf b/libraries/render-utils/src/mip_depth_median.slf new file mode 100644 index 0000000000..08813ebb5f --- /dev/null +++ b/libraries/render-utils/src/mip_depth_median.slf @@ -0,0 +1,35 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// mip_depth_median.frag +// fragment shader +// +// Created by Olivier Prat on 4/18/18. +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +uniform sampler2D depthTexture; + +in vec2 varTexCoord0; +out vec4 outFragColor; + +void main(void) { + vec4 depths = textureGather(depthTexture, varTexCoord0); + + // Order the depths from minimum to maximum + depths.xy = depths.x > depths.y ? depths.yx : depths.xy; + depths.xz = depths.x > depths.z ? depths.zx : depths.xz; + depths.xw = depths.x > depths.w ? depths.wx : depths.xw; + + depths.yz = depths.y > depths.z ? depths.zy : depths.yz; + depths.yw = depths.y > depths.w ? depths.wy : depths.yw; + + depths.zw = depths.z > depths.w ? depths.wz : depths.zw; + + float median = (depths.y + depths.z) / 2.0; + outFragColor = vec4(vec3(median), 1.0); +}