mirror of
https://github.com/overte-org/overte.git
synced 2025-04-15 16:02:08 +02:00
Preparing for support of multiple concurrent outlines by adding mask id buffer
This commit is contained in:
parent
4dcce6ef45
commit
049e3d47b6
6 changed files with 110 additions and 44 deletions
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 };
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue