From 049e3d47b67802e99e0de9215374f08131873683 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Fri, 13 Oct 2017 10:23:42 +0200 Subject: [PATCH] Preparing for support of multiple concurrent outlines by adding mask id buffer --- libraries/gpu-gl/src/gpu/gl/GLShared.h | 1 + libraries/gpu-gl/src/gpu/gl/GLTexelFormat.cpp | 7 ++ libraries/gpu/src/gpu/Format.cpp | 2 + libraries/gpu/src/gpu/Format.h | 2 + libraries/render-utils/src/OutlineEffect.cpp | 113 +++++++++++++----- libraries/render-utils/src/OutlineEffect.h | 29 +++-- 6 files changed, 110 insertions(+), 44 deletions(-) diff --git a/libraries/gpu-gl/src/gpu/gl/GLShared.h b/libraries/gpu-gl/src/gpu/gl/GLShared.h index 1b898e5c22..a1cf27afa6 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLShared.h +++ b/libraries/gpu-gl/src/gpu/gl/GLShared.h @@ -110,6 +110,7 @@ static const GLenum ELEMENT_TYPE_TO_GL[gpu::NUM_TYPES] = { GL_SHORT, GL_UNSIGNED_SHORT, GL_BYTE, + GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE }; diff --git a/libraries/gpu-gl/src/gpu/gl/GLTexelFormat.cpp b/libraries/gpu-gl/src/gpu/gl/GLTexelFormat.cpp index 192a82dafc..27319e1696 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLTexelFormat.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLTexelFormat.cpp @@ -212,6 +212,9 @@ GLenum GLTexelFormat::evalGLTexelFormatInternal(const gpu::Element& dstFormat) { case gpu::NUINT8: result = GL_RGBA8; break; + case gpu::NUINT2: + result = GL_RGBA2; + break; case gpu::NINT8: result = GL_RGBA8_SNORM; break; @@ -660,6 +663,10 @@ GLTexelFormat GLTexelFormat::evalGLTexelFormat(const Element& dstFormat, const E texel.format = GL_RGBA; texel.internalFormat = GL_RGBA8_SNORM; break; + case gpu::NUINT2: + texel.format = GL_RGBA; + texel.internalFormat = GL_RGBA2; + break; case gpu::NUINT32: case gpu::NINT32: case gpu::COMPRESSED: diff --git a/libraries/gpu/src/gpu/Format.cpp b/libraries/gpu/src/gpu/Format.cpp index 7efe4d3ed6..3b153097cf 100644 --- a/libraries/gpu/src/gpu/Format.cpp +++ b/libraries/gpu/src/gpu/Format.cpp @@ -19,6 +19,8 @@ const Element Element::COLOR_SRGBA_32{ VEC4, NUINT8, SRGBA }; const Element Element::COLOR_BGRA_32{ VEC4, NUINT8, BGRA }; const Element Element::COLOR_SBGRA_32{ VEC4, NUINT8, SBGRA }; +const Element Element::COLOR_RGBA_2{ VEC4, NUINT2, RGBA }; + const Element Element::COLOR_COMPRESSED_RED{ TILE4x4, COMPRESSED, COMPRESSED_BC4_RED }; const Element Element::COLOR_COMPRESSED_SRGB { TILE4x4, COMPRESSED, COMPRESSED_BC1_SRGB }; const Element Element::COLOR_COMPRESSED_SRGBA_MASK { TILE4x4, COMPRESSED, COMPRESSED_BC1_SRGBA }; diff --git a/libraries/gpu/src/gpu/Format.h b/libraries/gpu/src/gpu/Format.h index 0654b23581..9d5d2fc49d 100644 --- a/libraries/gpu/src/gpu/Format.h +++ b/libraries/gpu/src/gpu/Format.h @@ -38,6 +38,7 @@ enum Type : uint8_t { NUINT16, NINT8, NUINT8, + NUINT2, COMPRESSED, @@ -309,6 +310,7 @@ public: static const Element COLOR_SRGBA_32; static const Element COLOR_BGRA_32; static const Element COLOR_SBGRA_32; + static const Element COLOR_RGBA_2; static const Element COLOR_R11G11B10; static const Element COLOR_RGB9E5; static const Element COLOR_COMPRESSED_RED; diff --git a/libraries/render-utils/src/OutlineEffect.cpp b/libraries/render-utils/src/OutlineEffect.cpp index d5b3b1c3bb..375ba462b9 100644 --- a/libraries/render-utils/src/OutlineEffect.cpp +++ b/libraries/render-utils/src/OutlineEffect.cpp @@ -27,12 +27,10 @@ using namespace render; -extern void initZPassPipelines(ShapePlumber& plumber, gpu::StatePointer state); - -OutlineFramebuffer::OutlineFramebuffer() { +OutlineRessources::OutlineRessources() { } -void OutlineFramebuffer::update(const gpu::TexturePointer& colorBuffer) { +void OutlineRessources::update(const gpu::TexturePointer& colorBuffer) { // If the depth buffer or size changed, we need to delete our FBOs and recreate them at the // new correct dimensions. if (_depthTexture) { @@ -44,37 +42,48 @@ void OutlineFramebuffer::update(const gpu::TexturePointer& colorBuffer) { } } -void OutlineFramebuffer::clear() { - _depthFramebuffer.reset(); +void OutlineRessources::clear() { + _frameBuffer.reset(); _depthTexture.reset(); + _idTexture.reset(); } -void OutlineFramebuffer::allocate() { +void OutlineRessources::allocate() { auto width = _frameSize.x; auto height = _frameSize.y; - auto format = gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::DEPTH); + auto depthFormat = gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::DEPTH); - _depthTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(format, width, height)); - _depthFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("outlineDepth")); - _depthFramebuffer->setDepthStencilBuffer(_depthTexture, format); + _idTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(gpu::Element::COLOR_RGBA_2, width, height)); + _depthTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(depthFormat, width, height)); + + _frameBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("outlineDepth")); + _frameBuffer->setDepthStencilBuffer(_depthTexture, depthFormat); + _frameBuffer->setRenderBuffer(0, _idTexture); } -gpu::FramebufferPointer OutlineFramebuffer::getDepthFramebuffer() { - if (!_depthFramebuffer) { +gpu::FramebufferPointer OutlineRessources::getFramebuffer() { + if (!_frameBuffer) { allocate(); } - return _depthFramebuffer; + return _frameBuffer; } -gpu::TexturePointer OutlineFramebuffer::getDepthTexture() { +gpu::TexturePointer OutlineRessources::getDepthTexture() { if (!_depthTexture) { allocate(); } return _depthTexture; } -void DrawOutlineDepth::run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& output) { +gpu::TexturePointer OutlineRessources::getIDTexture() { + if (!_idTexture) { + allocate(); + } + return _idTexture; +} + +void DrawOutlineMask::run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& output) { assert(renderContext->args); assert(renderContext->args->hasViewFrustum()); auto& inShapes = inputs.get0(); @@ -84,19 +93,19 @@ void DrawOutlineDepth::run(const render::RenderContextPointer& renderContext, co RenderArgs* args = renderContext->args; ShapeKey::Builder defaultKeyBuilder; - if (!_outlineFramebuffer) { - _outlineFramebuffer = std::make_shared(); + if (!_outlineRessources) { + _outlineRessources = std::make_shared(); } - _outlineFramebuffer->update(deferredFrameBuffer->getDeferredColorTexture()); + _outlineRessources->update(deferredFrameBuffer->getDeferredColorTexture()); gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { args->_batch = &batch; - batch.setFramebuffer(_outlineFramebuffer->getDepthFramebuffer()); + batch.setFramebuffer(_outlineRessources->getFramebuffer()); // Clear it batch.clearFramebuffer( - gpu::Framebuffer::BUFFER_DEPTH, - vec4(vec3(1.0, 1.0, 1.0), 0.0), 1.0, 0, false); + gpu::Framebuffer::BUFFER_COLOR0 | gpu::Framebuffer::BUFFER_DEPTH, + vec4(0.0f, 0.0f, 0.0f, 0.0f), 1.0f, 0, false); // Setup camera, projection and viewport for all items batch.setViewportTransform(args->_viewport); @@ -110,14 +119,14 @@ void DrawOutlineDepth::run(const render::RenderContextPointer& renderContext, co batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); - auto shadowPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder); - auto shadowSkinnedPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder.withSkinned()); + auto maskPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder); + auto maskSkinnedPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder.withSkinned()); std::vector skinnedShapeKeys{}; // Iterate through all inShapes and render the unskinned - args->_shapePipeline = shadowPipeline; - batch.setPipeline(shadowPipeline->pipeline); + args->_shapePipeline = maskPipeline; + batch.setPipeline(maskPipeline->pipeline); for (auto items : inShapes) { if (items.first.isSkinned()) { skinnedShapeKeys.push_back(items.first); @@ -128,8 +137,8 @@ void DrawOutlineDepth::run(const render::RenderContextPointer& renderContext, co } // Reiterate to render the skinned - args->_shapePipeline = shadowSkinnedPipeline; - batch.setPipeline(shadowSkinnedPipeline->pipeline); + args->_shapePipeline = maskSkinnedPipeline; + batch.setPipeline(maskSkinnedPipeline->pipeline); for (const auto& key : skinnedShapeKeys) { renderItems(renderContext, inShapes.at(key)); } @@ -138,7 +147,7 @@ void DrawOutlineDepth::run(const render::RenderContextPointer& renderContext, co args->_batch = nullptr; }); - output = _outlineFramebuffer; + output = _outlineRessources; } else { output = nullptr; } @@ -348,7 +357,7 @@ void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, rende state->setDepthTest(true, true, gpu::LESS_EQUAL); state->setColorWriteMask(false, false, false, false); - initZPassPipelines(*shapePlumberZPass, state); + initMaskPipelines(*shapePlumberZPass, state); } const auto outlinedItemIDs = task.addJob("OutlineMetaToSubItemIDs", selectedMetas); @@ -359,8 +368,8 @@ void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, rende const auto sortedShapes = task.addJob("OutlineDepthSort", sortedPipelines); // Draw depth of outlined objects in separate buffer - const auto drawOutlineDepthInputs = DrawOutlineDepth::Inputs(sortedShapes, sceneFrameBuffer).asVarying(); - const auto outlinedFrameBuffer = task.addJob("OutlineDepth", drawOutlineDepthInputs, shapePlumberZPass); + const auto drawMaskInputs = DrawOutlineMask::Inputs(sortedShapes, sceneFrameBuffer).asVarying(); + const auto outlinedFrameBuffer = task.addJob("OutlineMask", drawMaskInputs, shapePlumberZPass); // Draw outline const auto drawOutlineInputs = DrawOutline::Inputs(deferredFrameTransform, outlinedFrameBuffer, sceneFrameBuffer, primaryFramebuffer).asVarying(); @@ -369,3 +378,43 @@ void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, rende // Debug outline task.addJob("OutlineDebug", outlinedFrameBuffer); } + +#include "model_shadow_vert.h" +#include "model_shadow_fade_vert.h" +#include "skin_model_shadow_vert.h" +#include "skin_model_shadow_fade_vert.h" + +#include "model_shadow_frag.h" +#include "model_shadow_fade_frag.h" +#include "skin_model_shadow_frag.h" +#include "skin_model_shadow_fade_frag.h" + +void DrawOutlineTask::initMaskPipelines(render::ShapePlumber& shapePlumber, gpu::StatePointer state) { + auto modelVertex = gpu::Shader::createVertex(std::string(model_shadow_vert)); + auto modelPixel = gpu::Shader::createPixel(std::string(model_shadow_frag)); + gpu::ShaderPointer modelProgram = gpu::Shader::createProgram(modelVertex, modelPixel); + shapePlumber.addPipeline( + ShapeKey::Filter::Builder().withoutSkinned().withoutFade(), + modelProgram, state); + + auto skinVertex = gpu::Shader::createVertex(std::string(skin_model_shadow_vert)); + auto skinPixel = gpu::Shader::createPixel(std::string(skin_model_shadow_frag)); + gpu::ShaderPointer skinProgram = gpu::Shader::createProgram(skinVertex, skinPixel); + shapePlumber.addPipeline( + ShapeKey::Filter::Builder().withSkinned().withoutFade(), + skinProgram, state); + + auto modelFadeVertex = gpu::Shader::createVertex(std::string(model_shadow_fade_vert)); + auto modelFadePixel = gpu::Shader::createPixel(std::string(model_shadow_fade_frag)); + gpu::ShaderPointer modelFadeProgram = gpu::Shader::createProgram(modelFadeVertex, modelFadePixel); + shapePlumber.addPipeline( + ShapeKey::Filter::Builder().withoutSkinned().withFade(), + modelFadeProgram, state); + + auto skinFadeVertex = gpu::Shader::createVertex(std::string(skin_model_shadow_fade_vert)); + auto skinFadePixel = gpu::Shader::createPixel(std::string(skin_model_shadow_fade_frag)); + gpu::ShaderPointer skinFadeProgram = gpu::Shader::createProgram(skinFadeVertex, skinFadePixel); + shapePlumber.addPipeline( + ShapeKey::Filter::Builder().withSkinned().withFade(), + skinFadeProgram, state); +} diff --git a/libraries/render-utils/src/OutlineEffect.h b/libraries/render-utils/src/OutlineEffect.h index f88092429f..b04f102a83 100644 --- a/libraries/render-utils/src/OutlineEffect.h +++ b/libraries/render-utils/src/OutlineEffect.h @@ -16,11 +16,12 @@ #include "DeferredFramebuffer.h" #include "DeferredFrameTransform.h" -class OutlineFramebuffer { +class OutlineRessources { public: - OutlineFramebuffer(); + OutlineRessources(); - gpu::FramebufferPointer getDepthFramebuffer(); + gpu::FramebufferPointer getFramebuffer(); + gpu::TexturePointer getIDTexture(); gpu::TexturePointer getDepthTexture(); // Update the source framebuffer size which will drive the allocation of all the other resources. @@ -32,30 +33,31 @@ protected: void clear(); void allocate(); - gpu::FramebufferPointer _depthFramebuffer; + gpu::FramebufferPointer _frameBuffer; gpu::TexturePointer _depthTexture; + gpu::TexturePointer _idTexture; glm::ivec2 _frameSize; }; -using OutlineFramebufferPointer = std::shared_ptr; +using OutlineRessourcesPointer = std::shared_ptr; -class DrawOutlineDepth { +class DrawOutlineMask { public: using Inputs = render::VaryingSet2; // Output will contain outlined objects only z-depth texture and the input primary buffer but without the primary depth buffer - using Outputs = OutlineFramebufferPointer; - using JobModel = render::Job::ModelIO; + using Outputs = OutlineRessourcesPointer; + using JobModel = render::Job::ModelIO; - DrawOutlineDepth(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {} + DrawOutlineMask(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {} void run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& output); protected: render::ShapePlumberPointer _shapePlumber; - OutlineFramebufferPointer _outlineFramebuffer; + OutlineRessourcesPointer _outlineRessources; }; class DrawOutlineConfig : public render::Job::Config { @@ -93,7 +95,7 @@ signals: class DrawOutline { public: - using Inputs = render::VaryingSet4; + using Inputs = render::VaryingSet4; using Config = DrawOutlineConfig; using JobModel = render::Job::ModelI; @@ -146,7 +148,7 @@ signals: class DebugOutline { public: - using Inputs = OutlineFramebufferPointer; + using Inputs = OutlineRessourcesPointer; using Config = DebugOutlineConfig; using JobModel = render::Job::ModelI; @@ -176,6 +178,9 @@ public: void configure(const Config& config); void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs); +private: + + static void initMaskPipelines(render::ShapePlumber& plumber, gpu::StatePointer state); }; #endif // hifi_render_utils_OutlineEffect_h