From 0580c8477e1c3a89879176e21702765fe2e7eae0 Mon Sep 17 00:00:00 2001 From: Niraj Venkat Date: Fri, 17 Jul 2015 16:42:03 -0700 Subject: [PATCH] 3-step groundwork for AO in the pipeline --- interface/src/Application.cpp | 1 - libraries/gpu/src/gpu/GLBackendTexture.cpp | 32 ++++ .../src/AmbientOcclusionEffect.cpp | 149 ++++++++++++++++-- .../render-utils/src/AmbientOcclusionEffect.h | 18 ++- .../render-utils/src/ambient_occlusion.slf | 3 - .../render-utils/src/ambient_occlusion.slv | 4 +- libraries/render-utils/src/gaussian_blur.slf | 42 +++++ .../src/gaussian_blur_horizontal.slv | 41 +++++ .../src/gaussian_blur_vertical.slv | 41 +++++ 9 files changed, 306 insertions(+), 25 deletions(-) create mode 100644 libraries/render-utils/src/gaussian_blur.slf create mode 100644 libraries/render-utils/src/gaussian_blur_horizontal.slv create mode 100644 libraries/render-utils/src/gaussian_blur_vertical.slv diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8b04223463..537003ec02 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -274,7 +274,6 @@ bool setupEssentials(int& argc, char** argv) { auto audio = DependencyManager::set(); auto audioScope = DependencyManager::set(); auto deferredLightingEffect = DependencyManager::set(); - auto ambientOcclusionEffect = DependencyManager::set(); auto textureCache = DependencyManager::set(); auto animationCache = DependencyManager::set(); auto ddeFaceTracker = DependencyManager::set(); diff --git a/libraries/gpu/src/gpu/GLBackendTexture.cpp b/libraries/gpu/src/gpu/GLBackendTexture.cpp index 72c7de8504..2696d17596 100755 --- a/libraries/gpu/src/gpu/GLBackendTexture.cpp +++ b/libraries/gpu/src/gpu/GLBackendTexture.cpp @@ -144,6 +144,38 @@ public: case gpu::RGB: case gpu::RGBA: texel.internalFormat = GL_RED; + /* switch (dstFormat.getType()) { + case gpu::UINT32: + case gpu::INT32: + case gpu::NUINT32: + case gpu::NINT32: { + texel.internalFormat = GL_DEPTH_COMPONENT32; + break; + } + case gpu::NFLOAT: + case gpu::FLOAT: { + texel.internalFormat = GL_DEPTH_COMPONENT32F; + break; + } + case gpu::UINT16: + case gpu::INT16: + case gpu::NUINT16: + case gpu::NINT16: + case gpu::HALF: + case gpu::NHALF: { + texel.internalFormat = GL_DEPTH_COMPONENT16; + break; + } + case gpu::UINT8: + case gpu::INT8: + case gpu::NUINT8: + case gpu::NINT8: { + texel.internalFormat = GL_DEPTH_COMPONENT24; + break; + } + case gpu::NUM_TYPES: { // quiet compiler + Q_UNREACHABLE(); + }*/ break; case gpu::DEPTH: texel.format = GL_DEPTH_COMPONENT; // It's depth component to load it diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.cpp b/libraries/render-utils/src/AmbientOcclusionEffect.cpp index 07832179cc..7e6b5c7e75 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.cpp +++ b/libraries/render-utils/src/AmbientOcclusionEffect.cpp @@ -31,12 +31,16 @@ #include "ambient_occlusion_vert.h" #include "ambient_occlusion_frag.h" +#include "gaussian_blur_vertical_vert.h" +#include "gaussian_blur_horizontal_vert.h" +#include "gaussian_blur_frag.h" const int ROTATION_WIDTH = 4; const int ROTATION_HEIGHT = 4; - + +/* void AmbientOcclusionEffect::init(AbstractViewStateInterface* viewState) { - /*_viewState = viewState; // we will use this for view state services + _viewState = viewState; // we will use this for view state services _occlusionProgram = new ProgramObject(); _occlusionProgram->addShaderFromSourceFile(QGLShader::Vertex, PathUtils::resourcesPath() @@ -99,11 +103,11 @@ void AmbientOcclusionEffect::init(AbstractViewStateInterface* viewState) { _blurProgram->setUniformValue("originalTexture", 0); _blurProgram->release(); - _blurScaleLocation = _blurProgram->uniformLocation("blurScale");*/ + _blurScaleLocation = _blurProgram->uniformLocation("blurScale"); } void AmbientOcclusionEffect::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext){ - /*glDisable(GL_BLEND); + glDisable(GL_BLEND); glDisable(GL_DEPTH_TEST); glDepthMask(GL_FALSE); @@ -170,15 +174,15 @@ void AmbientOcclusionEffect::run(const render::SceneContextPointer& sceneContext glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); glEnable(GL_DEPTH_TEST); - glDepthMask(GL_TRUE);*/ + glDepthMask(GL_TRUE) } - +*/ AmbientOcclusion::AmbientOcclusion() { } -const gpu::PipelinePointer& AmbientOcclusion::getAOPipeline() { - if (!_AOPipeline) { +const gpu::PipelinePointer& AmbientOcclusion::getOcclusionPipeline() { + if (!_occlusionPipeline) { auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(ambient_occlusion_vert))); auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(ambient_occlusion_frag))); gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps)); @@ -198,10 +202,85 @@ const gpu::PipelinePointer& AmbientOcclusion::getAOPipeline() { gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, gpu::State::DEST_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ZERO); + // Link the occlusion FBO to texture + _occlusionBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create(gpu::Element::COLOR_RGBA_32, + DependencyManager::get()->getFrameBufferSize().width(), DependencyManager::get()->getFrameBufferSize().height())); + auto format = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA); + auto width = _occlusionBuffer->getWidth(); + auto height = _occlusionBuffer->getHeight(); + auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT); + _occlusionTexture = gpu::TexturePointer(gpu::Texture::create2D(format, width, height, defaultSampler)); + // Good to go add the brand new pipeline - _AOPipeline.reset(gpu::Pipeline::create(program, state)); + _occlusionPipeline.reset(gpu::Pipeline::create(program, state)); } - return _AOPipeline; + return _occlusionPipeline; +} + +const gpu::PipelinePointer& AmbientOcclusion::getVBlurPipeline() { + if (!_vBlurPipeline) { + auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(gaussian_blur_vertical_vert))); + auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(gaussian_blur_frag))); + gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps)); + + gpu::Shader::BindingSet slotBindings; + gpu::Shader::makeProgram(*program, slotBindings); + + gpu::StatePointer state = gpu::StatePointer(new gpu::State()); + + state->setDepthTest(false, false, gpu::LESS_EQUAL); + + // Blend on transparent + state->setBlendFunction(false, + gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, + gpu::State::DEST_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ZERO); + + // Link the horizontal blur FBO to texture + _vBlurBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create(gpu::Element::COLOR_RGBA_32, + DependencyManager::get()->getFrameBufferSize().width(), DependencyManager::get()->getFrameBufferSize().height())); + auto format = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA); + auto width = _vBlurBuffer->getWidth(); + auto height = _vBlurBuffer->getHeight(); + auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT); + _vBlurTexture = gpu::TexturePointer(gpu::Texture::create2D(format, width, height, defaultSampler)); + + // Good to go add the brand new pipeline + _vBlurPipeline.reset(gpu::Pipeline::create(program, state)); + } + return _vBlurPipeline; +} + +const gpu::PipelinePointer& AmbientOcclusion::getHBlurPipeline() { + if (!_hBlurPipeline) { + auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(gaussian_blur_horizontal_vert))); + auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(gaussian_blur_frag))); + gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps)); + + gpu::Shader::BindingSet slotBindings; + gpu::Shader::makeProgram(*program, slotBindings); + + gpu::StatePointer state = gpu::StatePointer(new gpu::State()); + + state->setDepthTest(false, false, gpu::LESS_EQUAL); + + // Blend on transparent + state->setBlendFunction(false, + gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, + gpu::State::DEST_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ZERO); + + // Link the horizontal blur FBO to texture + _hBlurBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create(gpu::Element::COLOR_RGBA_32, + DependencyManager::get()->getFrameBufferSize().width(), DependencyManager::get()->getFrameBufferSize().height())); + auto format = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA); + auto width = _hBlurBuffer->getWidth(); + auto height = _hBlurBuffer->getHeight(); + auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT); + _hBlurTexture = gpu::TexturePointer(gpu::Texture::create2D(format, width, height, defaultSampler)); + + // Good to go add the brand new pipeline + _hBlurPipeline.reset(gpu::Pipeline::create(program, state)); + } + return _hBlurPipeline; } void AmbientOcclusion::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext) { @@ -226,18 +305,57 @@ void AmbientOcclusion::run(const render::SceneContextPointer& sceneContext, cons batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); batch.setModelTransform(Transform()); - batch.setResourceTexture(0, DependencyManager::get()->getPrimaryDepthTexture()); - // bind the one gpu::Pipeline we need - batch.setPipeline(getAOPipeline()); + // Occlusion step + getOcclusionPipeline(); + batch.setResourceTexture(0, DependencyManager::get()->getPrimaryDepthTexture()); + _occlusionBuffer->setRenderBuffer(0, _occlusionTexture); + batch.setFramebuffer(_occlusionBuffer); + + // bind the first gpu::Pipeline we need - for calculating occlusion buffer + batch.setPipeline(getOcclusionPipeline()); glm::vec4 color(0.0f, 0.0f, 0.0f, 1.0f); - glm::vec2 bottomLeft(0.5f, -1.0f); - glm::vec2 topRight(1.0f, -0.5f); + glm::vec2 bottomLeft(-1.0f, -1.0f); + glm::vec2 topRight(1.0f, 1.0f); glm::vec2 texCoordTopLeft(0.0f, 0.0f); glm::vec2 texCoordBottomRight(1.0f, 1.0f); DependencyManager::get()->renderQuad(batch, bottomLeft, topRight, texCoordTopLeft, texCoordBottomRight, color); + // Vertical blur step + getVBlurPipeline(); + batch.setResourceTexture(0, _occlusionTexture); + _vBlurBuffer->setRenderBuffer(0, _vBlurTexture); + batch.setFramebuffer(_vBlurBuffer); + + // bind the second gpu::Pipeline we need - for calculating blur buffer + batch.setPipeline(getVBlurPipeline()); + + DependencyManager::get()->renderQuad(batch, bottomLeft, topRight, texCoordTopLeft, texCoordBottomRight, color); + + // Horizontal blur step + getHBlurPipeline(); + batch.setResourceTexture(0, _vBlurTexture); + _hBlurBuffer->setRenderBuffer(0, _hBlurTexture); + batch.setFramebuffer(_hBlurBuffer); + + // bind the second gpu::Pipeline we need - for calculating blur buffer + batch.setPipeline(getHBlurPipeline()); + + DependencyManager::get()->renderQuad(batch, bottomLeft, topRight, texCoordTopLeft, texCoordBottomRight, color); + + // "Blend" step + batch.setResourceTexture(0, _hBlurTexture); + batch.setFramebuffer(DependencyManager::get()->getPrimaryFramebuffer()); + + // bind the second gpu::Pipeline we need + batch.setPipeline(getOcclusionPipeline()); + + glm::vec2 bottomLeftSmall(0.5f, -1.0f); + glm::vec2 topRightSmall(1.0f, -0.5f); + DependencyManager::get()->renderQuad(batch, bottomLeftSmall, topRightSmall, texCoordTopLeft, texCoordBottomRight, color); + + // Ready to render args->_context->syncCache(); renderContext->args->_context->syncCache(); args->_context->render((batch)); @@ -247,4 +365,3 @@ void AmbientOcclusion::run(const render::SceneContextPointer& sceneContext, cons } - diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.h b/libraries/render-utils/src/AmbientOcclusionEffect.h index fbe4a09214..8fce5e3d0c 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.h +++ b/libraries/render-utils/src/AmbientOcclusionEffect.h @@ -22,6 +22,7 @@ class ProgramObject; /// A screen space ambient occlusion effect. See John Chapman's tutorial at /// http://john-chapman-graphics.blogspot.co.uk/2013/01/ssao-tutorial.html for reference. +/* class AmbientOcclusionEffect : public Dependency { SINGLETON_DEPENDENCY @@ -53,6 +54,7 @@ private: GLuint _rotationTextureID; AbstractViewStateInterface* _viewState; }; +*/ class AmbientOcclusion { public: @@ -62,11 +64,23 @@ public: void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); typedef render::Job::Model JobModel; - const gpu::PipelinePointer& AmbientOcclusion::getAOPipeline(); + const gpu::PipelinePointer& AmbientOcclusion::getOcclusionPipeline(); + const gpu::PipelinePointer& AmbientOcclusion::getHBlurPipeline(); + const gpu::PipelinePointer& AmbientOcclusion::getVBlurPipeline(); private: - gpu::PipelinePointer _AOPipeline; + gpu::PipelinePointer _occlusionPipeline; + gpu::PipelinePointer _hBlurPipeline; + gpu::PipelinePointer _vBlurPipeline; + + gpu::FramebufferPointer _occlusionBuffer; + gpu::FramebufferPointer _hBlurBuffer; + gpu::FramebufferPointer _vBlurBuffer; + + gpu::TexturePointer _occlusionTexture; + gpu::TexturePointer _hBlurTexture; + gpu::TexturePointer _vBlurTexture; }; #endif // hifi_AmbientOcclusionEffect_h diff --git a/libraries/render-utils/src/ambient_occlusion.slf b/libraries/render-utils/src/ambient_occlusion.slf index b56e0eb9d5..bdeb59e82a 100644 --- a/libraries/render-utils/src/ambient_occlusion.slf +++ b/libraries/render-utils/src/ambient_occlusion.slf @@ -14,9 +14,6 @@ <@include DeferredBufferWrite.slh@> -// the interpolated normal -//varying vec4 interpolatedNormal; - varying vec2 varTexcoord; uniform sampler2D depthTexture; diff --git a/libraries/render-utils/src/ambient_occlusion.slv b/libraries/render-utils/src/ambient_occlusion.slv index 54cc608129..81f196dd46 100644 --- a/libraries/render-utils/src/ambient_occlusion.slv +++ b/libraries/render-utils/src/ambient_occlusion.slv @@ -16,11 +16,9 @@ <$declareStandardTransform()$> -// the interpolated normal -//varying vec4 interpolatedNormal; varying vec2 varTexcoord; void main(void) { varTexcoord = gl_MultiTexCoord0.xy; gl_Position = gl_Vertex; -} \ No newline at end of file +} diff --git a/libraries/render-utils/src/gaussian_blur.slf b/libraries/render-utils/src/gaussian_blur.slf new file mode 100644 index 0000000000..5b66a0b751 --- /dev/null +++ b/libraries/render-utils/src/gaussian_blur.slf @@ -0,0 +1,42 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// gaussian_blur.frag +// fragment shader +// +// Created by Niraj Venkat on 7/17/15. +// Copyright 2015 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 +// + +<@include DeferredBufferWrite.slh@> + +// the interpolated normal +//varying vec4 interpolatedNormal; + +varying vec2 varTexcoord; +varying vec2 varBlurTexcoords[14]; + +uniform sampler2D occlusionTexture; + +void main(void) { + gl_FragColor = vec4(0.0); + gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[ 0])*0.0044299121055113265; + gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[ 1])*0.00895781211794; + gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[ 2])*0.0215963866053; + gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[ 3])*0.0443683338718; + gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[ 4])*0.0776744219933; + gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[ 5])*0.115876621105; + gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[ 6])*0.147308056121; + gl_FragColor += texture2D(occlusionTexture, varTexcoord )*0.159576912161; + gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[ 7])*0.147308056121; + gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[ 8])*0.115876621105; + gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[ 9])*0.0776744219933; + gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[10])*0.0443683338718; + gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[11])*0.0215963866053; + gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[12])*0.00895781211794; + gl_FragColor += texture2D(occlusionTexture, varBlurTexcoords[13])*0.0044299121055113265; +} diff --git a/libraries/render-utils/src/gaussian_blur_horizontal.slv b/libraries/render-utils/src/gaussian_blur_horizontal.slv new file mode 100644 index 0000000000..94631b4b08 --- /dev/null +++ b/libraries/render-utils/src/gaussian_blur_horizontal.slv @@ -0,0 +1,41 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// guassian_blur_horizontal.vert +// vertex shader +// +// Created by Niraj Venkat on 7/17/15. +// Copyright 2015 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 +// + +<@include gpu/Transform.slh@> + +<$declareStandardTransform()$> + +varying vec2 varTexcoord; +varying vec2 varBlurTexcoords[14]; + +void main(void) { + varTexcoord = gl_MultiTexCoord0.xy; + gl_Position = gl_Vertex; + + varBlurTexcoords[ 0] = varTexcoord + vec2(-0.028, 0.0); + varBlurTexcoords[ 1] = varTexcoord + vec2(-0.024, 0.0); + varBlurTexcoords[ 2] = varTexcoord + vec2(-0.020, 0.0); + varBlurTexcoords[ 3] = varTexcoord + vec2(-0.016, 0.0); + varBlurTexcoords[ 4] = varTexcoord + vec2(-0.012, 0.0); + varBlurTexcoords[ 5] = varTexcoord + vec2(-0.008, 0.0); + varBlurTexcoords[ 6] = varTexcoord + vec2(-0.004, 0.0); + varBlurTexcoords[ 7] = varTexcoord + vec2( 0.004, 0.0); + varBlurTexcoords[ 8] = varTexcoord + vec2( 0.008, 0.0); + varBlurTexcoords[ 9] = varTexcoord + vec2( 0.012, 0.0); + varBlurTexcoords[10] = varTexcoord + vec2( 0.016, 0.0); + varBlurTexcoords[11] = varTexcoord + vec2( 0.020, 0.0); + varBlurTexcoords[12] = varTexcoord + vec2( 0.024, 0.0); + varBlurTexcoords[13] = varTexcoord + vec2( 0.028, 0.0); +} + \ No newline at end of file diff --git a/libraries/render-utils/src/gaussian_blur_vertical.slv b/libraries/render-utils/src/gaussian_blur_vertical.slv new file mode 100644 index 0000000000..0d6de35b85 --- /dev/null +++ b/libraries/render-utils/src/gaussian_blur_vertical.slv @@ -0,0 +1,41 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// guassian_blur_vertical.vert +// vertex shader +// +// Created by Niraj Venkat on 7/17/15. +// Copyright 2015 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 +// + +<@include gpu/Transform.slh@> + +<$declareStandardTransform()$> + +varying vec2 varTexcoord; +varying vec2 varBlurTexcoords[14]; + +void main(void) { + varTexcoord = gl_MultiTexCoord0.xy; + gl_Position = gl_Vertex; + + varBlurTexcoords[ 0] = varTexcoord + vec2(0.0, -0.028); + varBlurTexcoords[ 1] = varTexcoord + vec2(0.0, -0.024); + varBlurTexcoords[ 2] = varTexcoord + vec2(0.0, -0.020); + varBlurTexcoords[ 3] = varTexcoord + vec2(0.0, -0.016); + varBlurTexcoords[ 4] = varTexcoord + vec2(0.0, -0.012); + varBlurTexcoords[ 5] = varTexcoord + vec2(0.0, -0.008); + varBlurTexcoords[ 6] = varTexcoord + vec2(0.0, -0.004); + varBlurTexcoords[ 7] = varTexcoord + vec2(0.0, 0.004); + varBlurTexcoords[ 8] = varTexcoord + vec2(0.0, 0.008); + varBlurTexcoords[ 9] = varTexcoord + vec2(0.0, 0.012); + varBlurTexcoords[10] = varTexcoord + vec2(0.0, 0.016); + varBlurTexcoords[11] = varTexcoord + vec2(0.0, 0.020); + varBlurTexcoords[12] = varTexcoord + vec2(0.0, 0.024); + varBlurTexcoords[13] = varTexcoord + vec2(0.0, 0.028); +} + \ No newline at end of file