Preparing for support of multiple concurrent outlines by adding mask id buffer

This commit is contained in:
Olivier Prat 2017-10-13 10:23:42 +02:00
parent 4dcce6ef45
commit 049e3d47b6
6 changed files with 110 additions and 44 deletions

View file

@ -110,6 +110,7 @@ static const GLenum ELEMENT_TYPE_TO_GL[gpu::NUM_TYPES] = {
GL_SHORT, GL_SHORT,
GL_UNSIGNED_SHORT, GL_UNSIGNED_SHORT,
GL_BYTE, GL_BYTE,
GL_UNSIGNED_BYTE,
GL_UNSIGNED_BYTE GL_UNSIGNED_BYTE
}; };

View file

@ -212,6 +212,9 @@ GLenum GLTexelFormat::evalGLTexelFormatInternal(const gpu::Element& dstFormat) {
case gpu::NUINT8: case gpu::NUINT8:
result = GL_RGBA8; result = GL_RGBA8;
break; break;
case gpu::NUINT2:
result = GL_RGBA2;
break;
case gpu::NINT8: case gpu::NINT8:
result = GL_RGBA8_SNORM; result = GL_RGBA8_SNORM;
break; break;
@ -660,6 +663,10 @@ GLTexelFormat GLTexelFormat::evalGLTexelFormat(const Element& dstFormat, const E
texel.format = GL_RGBA; texel.format = GL_RGBA;
texel.internalFormat = GL_RGBA8_SNORM; texel.internalFormat = GL_RGBA8_SNORM;
break; break;
case gpu::NUINT2:
texel.format = GL_RGBA;
texel.internalFormat = GL_RGBA2;
break;
case gpu::NUINT32: case gpu::NUINT32:
case gpu::NINT32: case gpu::NINT32:
case gpu::COMPRESSED: case gpu::COMPRESSED:

View file

@ -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_BGRA_32{ VEC4, NUINT8, BGRA };
const Element Element::COLOR_SBGRA_32{ VEC4, NUINT8, SBGRA }; 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_RED{ TILE4x4, COMPRESSED, COMPRESSED_BC4_RED };
const Element Element::COLOR_COMPRESSED_SRGB { TILE4x4, COMPRESSED, COMPRESSED_BC1_SRGB }; const Element Element::COLOR_COMPRESSED_SRGB { TILE4x4, COMPRESSED, COMPRESSED_BC1_SRGB };
const Element Element::COLOR_COMPRESSED_SRGBA_MASK { TILE4x4, COMPRESSED, COMPRESSED_BC1_SRGBA }; const Element Element::COLOR_COMPRESSED_SRGBA_MASK { TILE4x4, COMPRESSED, COMPRESSED_BC1_SRGBA };

View file

@ -38,6 +38,7 @@ enum Type : uint8_t {
NUINT16, NUINT16,
NINT8, NINT8,
NUINT8, NUINT8,
NUINT2,
COMPRESSED, COMPRESSED,
@ -309,6 +310,7 @@ public:
static const Element COLOR_SRGBA_32; static const Element COLOR_SRGBA_32;
static const Element COLOR_BGRA_32; static const Element COLOR_BGRA_32;
static const Element COLOR_SBGRA_32; static const Element COLOR_SBGRA_32;
static const Element COLOR_RGBA_2;
static const Element COLOR_R11G11B10; static const Element COLOR_R11G11B10;
static const Element COLOR_RGB9E5; static const Element COLOR_RGB9E5;
static const Element COLOR_COMPRESSED_RED; static const Element COLOR_COMPRESSED_RED;

View file

@ -27,12 +27,10 @@
using namespace render; using namespace render;
extern void initZPassPipelines(ShapePlumber& plumber, gpu::StatePointer state); OutlineRessources::OutlineRessources() {
OutlineFramebuffer::OutlineFramebuffer() {
} }
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 // If the depth buffer or size changed, we need to delete our FBOs and recreate them at the
// new correct dimensions. // new correct dimensions.
if (_depthTexture) { if (_depthTexture) {
@ -44,37 +42,48 @@ void OutlineFramebuffer::update(const gpu::TexturePointer& colorBuffer) {
} }
} }
void OutlineFramebuffer::clear() { void OutlineRessources::clear() {
_depthFramebuffer.reset(); _frameBuffer.reset();
_depthTexture.reset(); _depthTexture.reset();
_idTexture.reset();
} }
void OutlineFramebuffer::allocate() { void OutlineRessources::allocate() {
auto width = _frameSize.x; auto width = _frameSize.x;
auto height = _frameSize.y; 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)); _idTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(gpu::Element::COLOR_RGBA_2, width, height));
_depthFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("outlineDepth")); _depthTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(depthFormat, width, height));
_depthFramebuffer->setDepthStencilBuffer(_depthTexture, format);
_frameBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("outlineDepth"));
_frameBuffer->setDepthStencilBuffer(_depthTexture, depthFormat);
_frameBuffer->setRenderBuffer(0, _idTexture);
} }
gpu::FramebufferPointer OutlineFramebuffer::getDepthFramebuffer() { gpu::FramebufferPointer OutlineRessources::getFramebuffer() {
if (!_depthFramebuffer) { if (!_frameBuffer) {
allocate(); allocate();
} }
return _depthFramebuffer; return _frameBuffer;
} }
gpu::TexturePointer OutlineFramebuffer::getDepthTexture() { gpu::TexturePointer OutlineRessources::getDepthTexture() {
if (!_depthTexture) { if (!_depthTexture) {
allocate(); allocate();
} }
return _depthTexture; 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);
assert(renderContext->args->hasViewFrustum()); assert(renderContext->args->hasViewFrustum());
auto& inShapes = inputs.get0(); auto& inShapes = inputs.get0();
@ -84,19 +93,19 @@ void DrawOutlineDepth::run(const render::RenderContextPointer& renderContext, co
RenderArgs* args = renderContext->args; RenderArgs* args = renderContext->args;
ShapeKey::Builder defaultKeyBuilder; ShapeKey::Builder defaultKeyBuilder;
if (!_outlineFramebuffer) { if (!_outlineRessources) {
_outlineFramebuffer = std::make_shared<OutlineFramebuffer>(); _outlineRessources = std::make_shared<OutlineRessources>();
} }
_outlineFramebuffer->update(deferredFrameBuffer->getDeferredColorTexture()); _outlineRessources->update(deferredFrameBuffer->getDeferredColorTexture());
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
args->_batch = &batch; args->_batch = &batch;
batch.setFramebuffer(_outlineFramebuffer->getDepthFramebuffer()); batch.setFramebuffer(_outlineRessources->getFramebuffer());
// Clear it // Clear it
batch.clearFramebuffer( batch.clearFramebuffer(
gpu::Framebuffer::BUFFER_DEPTH, gpu::Framebuffer::BUFFER_COLOR0 | gpu::Framebuffer::BUFFER_DEPTH,
vec4(vec3(1.0, 1.0, 1.0), 0.0), 1.0, 0, false); vec4(0.0f, 0.0f, 0.0f, 0.0f), 1.0f, 0, false);
// Setup camera, projection and viewport for all items // Setup camera, projection and viewport for all items
batch.setViewportTransform(args->_viewport); batch.setViewportTransform(args->_viewport);
@ -110,14 +119,14 @@ void DrawOutlineDepth::run(const render::RenderContextPointer& renderContext, co
batch.setProjectionTransform(projMat); batch.setProjectionTransform(projMat);
batch.setViewTransform(viewMat); batch.setViewTransform(viewMat);
auto shadowPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder); auto maskPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder);
auto shadowSkinnedPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder.withSkinned()); auto maskSkinnedPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder.withSkinned());
std::vector<ShapeKey> skinnedShapeKeys{}; std::vector<ShapeKey> skinnedShapeKeys{};
// Iterate through all inShapes and render the unskinned // Iterate through all inShapes and render the unskinned
args->_shapePipeline = shadowPipeline; args->_shapePipeline = maskPipeline;
batch.setPipeline(shadowPipeline->pipeline); batch.setPipeline(maskPipeline->pipeline);
for (auto items : inShapes) { for (auto items : inShapes) {
if (items.first.isSkinned()) { if (items.first.isSkinned()) {
skinnedShapeKeys.push_back(items.first); skinnedShapeKeys.push_back(items.first);
@ -128,8 +137,8 @@ void DrawOutlineDepth::run(const render::RenderContextPointer& renderContext, co
} }
// Reiterate to render the skinned // Reiterate to render the skinned
args->_shapePipeline = shadowSkinnedPipeline; args->_shapePipeline = maskSkinnedPipeline;
batch.setPipeline(shadowSkinnedPipeline->pipeline); batch.setPipeline(maskSkinnedPipeline->pipeline);
for (const auto& key : skinnedShapeKeys) { for (const auto& key : skinnedShapeKeys) {
renderItems(renderContext, inShapes.at(key)); renderItems(renderContext, inShapes.at(key));
} }
@ -138,7 +147,7 @@ void DrawOutlineDepth::run(const render::RenderContextPointer& renderContext, co
args->_batch = nullptr; args->_batch = nullptr;
}); });
output = _outlineFramebuffer; output = _outlineRessources;
} else { } else {
output = nullptr; output = nullptr;
} }
@ -348,7 +357,7 @@ void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, rende
state->setDepthTest(true, true, gpu::LESS_EQUAL); state->setDepthTest(true, true, gpu::LESS_EQUAL);
state->setColorWriteMask(false, false, false, false); state->setColorWriteMask(false, false, false, false);
initZPassPipelines(*shapePlumberZPass, state); initMaskPipelines(*shapePlumberZPass, state);
} }
const auto outlinedItemIDs = task.addJob<render::MetaToSubItems>("OutlineMetaToSubItemIDs", selectedMetas); const auto outlinedItemIDs = task.addJob<render::MetaToSubItems>("OutlineMetaToSubItemIDs", selectedMetas);
@ -359,8 +368,8 @@ void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, rende
const auto sortedShapes = task.addJob<render::DepthSortShapes>("OutlineDepthSort", sortedPipelines); const auto sortedShapes = task.addJob<render::DepthSortShapes>("OutlineDepthSort", sortedPipelines);
// Draw depth of outlined objects in separate buffer // Draw depth of outlined objects in separate buffer
const auto drawOutlineDepthInputs = DrawOutlineDepth::Inputs(sortedShapes, sceneFrameBuffer).asVarying(); const auto drawMaskInputs = DrawOutlineMask::Inputs(sortedShapes, sceneFrameBuffer).asVarying();
const auto outlinedFrameBuffer = task.addJob<DrawOutlineDepth>("OutlineDepth", drawOutlineDepthInputs, shapePlumberZPass); const auto outlinedFrameBuffer = task.addJob<DrawOutlineMask>("OutlineMask", drawMaskInputs, shapePlumberZPass);
// Draw outline // Draw outline
const auto drawOutlineInputs = DrawOutline::Inputs(deferredFrameTransform, outlinedFrameBuffer, sceneFrameBuffer, primaryFramebuffer).asVarying(); 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 // Debug outline
task.addJob<DebugOutline>("OutlineDebug", outlinedFrameBuffer); task.addJob<DebugOutline>("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);
}

View file

@ -16,11 +16,12 @@
#include "DeferredFramebuffer.h" #include "DeferredFramebuffer.h"
#include "DeferredFrameTransform.h" #include "DeferredFrameTransform.h"
class OutlineFramebuffer { class OutlineRessources {
public: public:
OutlineFramebuffer(); OutlineRessources();
gpu::FramebufferPointer getDepthFramebuffer(); gpu::FramebufferPointer getFramebuffer();
gpu::TexturePointer getIDTexture();
gpu::TexturePointer getDepthTexture(); gpu::TexturePointer getDepthTexture();
// Update the source framebuffer size which will drive the allocation of all the other resources. // Update the source framebuffer size which will drive the allocation of all the other resources.
@ -32,30 +33,31 @@ protected:
void clear(); void clear();
void allocate(); void allocate();
gpu::FramebufferPointer _depthFramebuffer; gpu::FramebufferPointer _frameBuffer;
gpu::TexturePointer _depthTexture; gpu::TexturePointer _depthTexture;
gpu::TexturePointer _idTexture;
glm::ivec2 _frameSize; glm::ivec2 _frameSize;
}; };
using OutlineFramebufferPointer = std::shared_ptr<OutlineFramebuffer>; using OutlineRessourcesPointer = std::shared_ptr<OutlineRessources>;
class DrawOutlineDepth { class DrawOutlineMask {
public: public:
using Inputs = render::VaryingSet2<render::ShapeBounds, DeferredFramebufferPointer>; using Inputs = render::VaryingSet2<render::ShapeBounds, DeferredFramebufferPointer>;
// Output will contain outlined objects only z-depth texture and the input primary buffer but without the primary depth buffer // Output will contain outlined objects only z-depth texture and the input primary buffer but without the primary depth buffer
using Outputs = OutlineFramebufferPointer; using Outputs = OutlineRessourcesPointer;
using JobModel = render::Job::ModelIO<DrawOutlineDepth, Inputs, Outputs>; using JobModel = render::Job::ModelIO<DrawOutlineMask, Inputs, Outputs>;
DrawOutlineDepth(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {} DrawOutlineMask(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {}
void run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& output); void run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& output);
protected: protected:
render::ShapePlumberPointer _shapePlumber; render::ShapePlumberPointer _shapePlumber;
OutlineFramebufferPointer _outlineFramebuffer; OutlineRessourcesPointer _outlineRessources;
}; };
class DrawOutlineConfig : public render::Job::Config { class DrawOutlineConfig : public render::Job::Config {
@ -93,7 +95,7 @@ signals:
class DrawOutline { class DrawOutline {
public: public:
using Inputs = render::VaryingSet4<DeferredFrameTransformPointer, OutlineFramebufferPointer, DeferredFramebufferPointer, gpu::FramebufferPointer>; using Inputs = render::VaryingSet4<DeferredFrameTransformPointer, OutlineRessourcesPointer, DeferredFramebufferPointer, gpu::FramebufferPointer>;
using Config = DrawOutlineConfig; using Config = DrawOutlineConfig;
using JobModel = render::Job::ModelI<DrawOutline, Inputs, Config>; using JobModel = render::Job::ModelI<DrawOutline, Inputs, Config>;
@ -146,7 +148,7 @@ signals:
class DebugOutline { class DebugOutline {
public: public:
using Inputs = OutlineFramebufferPointer; using Inputs = OutlineRessourcesPointer;
using Config = DebugOutlineConfig; using Config = DebugOutlineConfig;
using JobModel = render::Job::ModelI<DebugOutline, Inputs, Config>; using JobModel = render::Job::ModelI<DebugOutline, Inputs, Config>;
@ -176,6 +178,9 @@ public:
void configure(const Config& config); void configure(const Config& config);
void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs); 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 #endif // hifi_render_utils_OutlineEffect_h