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_UNSIGNED_SHORT,
GL_BYTE,
GL_UNSIGNED_BYTE,
GL_UNSIGNED_BYTE
};

View file

@ -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:

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_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 };

View file

@ -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;

View file

@ -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<OutlineFramebuffer>();
if (!_outlineRessources) {
_outlineRessources = std::make_shared<OutlineRessources>();
}
_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<ShapeKey> 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<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);
// Draw depth of outlined objects in separate buffer
const auto drawOutlineDepthInputs = DrawOutlineDepth::Inputs(sortedShapes, sceneFrameBuffer).asVarying();
const auto outlinedFrameBuffer = task.addJob<DrawOutlineDepth>("OutlineDepth", drawOutlineDepthInputs, shapePlumberZPass);
const auto drawMaskInputs = DrawOutlineMask::Inputs(sortedShapes, sceneFrameBuffer).asVarying();
const auto outlinedFrameBuffer = task.addJob<DrawOutlineMask>("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<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 "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<OutlineFramebuffer>;
using OutlineRessourcesPointer = std::shared_ptr<OutlineRessources>;
class DrawOutlineDepth {
class DrawOutlineMask {
public:
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
using Outputs = OutlineFramebufferPointer;
using JobModel = render::Job::ModelIO<DrawOutlineDepth, Inputs, Outputs>;
using Outputs = OutlineRessourcesPointer;
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);
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<DeferredFrameTransformPointer, OutlineFramebufferPointer, DeferredFramebufferPointer, gpu::FramebufferPointer>;
using Inputs = render::VaryingSet4<DeferredFrameTransformPointer, OutlineRessourcesPointer, DeferredFramebufferPointer, gpu::FramebufferPointer>;
using Config = DrawOutlineConfig;
using JobModel = render::Job::ModelI<DrawOutline, Inputs, Config>;
@ -146,7 +148,7 @@ signals:
class DebugOutline {
public:
using Inputs = OutlineFramebufferPointer;
using Inputs = OutlineRessourcesPointer;
using Config = DebugOutlineConfig;
using JobModel = render::Job::ModelI<DebugOutline, Inputs, Config>;
@ -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