mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 15:23:56 +02:00
Preparing for multiple outline groups in shader
This commit is contained in:
parent
e42699c0ea
commit
1b67223e0e
5 changed files with 210 additions and 117 deletions
|
@ -21,11 +21,13 @@ uniform outlineParamsBuffer {
|
|||
|
||||
uniform sampler2D sceneDepthMap;
|
||||
uniform sampler2D outlinedDepthMap;
|
||||
uniform sampler2D outlinedIdMap;
|
||||
|
||||
in vec2 varTexCoord0;
|
||||
out vec4 outFragColor;
|
||||
|
||||
const float FAR_Z = 1.0;
|
||||
const float ID_THRESHOLD = 1.f/64.f;
|
||||
const float LINEAR_DEPTH_BIAS = 5e-3;
|
||||
const float OPACITY_EPSILON = 5e-3;
|
||||
|
||||
|
@ -37,10 +39,11 @@ void main(void) {
|
|||
// sides of the silhouette
|
||||
vec2 halfTexel = getInvWidthHeight() / 2;
|
||||
vec2 texCoord0 = varTexCoord0+halfTexel;
|
||||
vec4 outlinedIdColor = texture(outlinedIdMap, texCoord0);
|
||||
float outlinedDepth = texture(outlinedDepthMap, texCoord0).x;
|
||||
float intensity = 0.0;
|
||||
|
||||
if (outlinedDepth < FAR_Z) {
|
||||
if (outlinedDepth < FAR_Z && distance(outlinedIdColor, params._idColor) < ID_THRESHOLD) {
|
||||
// We're not on the far plane so we are on the outlined object, thus no outline to do!
|
||||
<@if IS_FILLED@>
|
||||
// But we need to fill the interior
|
||||
|
@ -75,7 +78,8 @@ void main(void) {
|
|||
if (uv.x>=0.0 && uv.x<=1.0)
|
||||
{
|
||||
outlinedDepth = texture(outlinedDepthMap, uv).x;
|
||||
intensity += (outlinedDepth < FAR_Z) ? 1.0 : 0.0;
|
||||
outlinedIdColor = texture(outlinedIdMap, uv);
|
||||
intensity += (outlinedDepth < FAR_Z && distance(outlinedIdColor, params._idColor) < ID_THRESHOLD) ? 1.0 : 0.0;
|
||||
weight += 1.f;
|
||||
}
|
||||
uv.x += deltaUv.x;
|
||||
|
|
|
@ -83,81 +83,139 @@ gpu::TexturePointer OutlineRessources::getIdTexture() {
|
|||
return _idTexture;
|
||||
}
|
||||
|
||||
glm::vec4 encodeIdToColor(unsigned int id) {
|
||||
union {
|
||||
struct {
|
||||
unsigned int r : 2;
|
||||
unsigned int g : 2;
|
||||
unsigned int b : 2;
|
||||
unsigned int a : 2;
|
||||
};
|
||||
unsigned char id;
|
||||
} groupId;
|
||||
|
||||
assert(id < 254);
|
||||
groupId.id = id+1;
|
||||
|
||||
glm::vec4 idColor{ groupId.r, groupId.g, groupId.b, groupId.a };
|
||||
|
||||
// Normalize. Since we put 2 bits into each color component, each component has a maximum
|
||||
// value of 3.
|
||||
idColor /= 3.f;
|
||||
return idColor;
|
||||
}
|
||||
|
||||
void DrawOutlineMask::run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& output) {
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->hasViewFrustum());
|
||||
auto& inShapes = inputs.get0();
|
||||
auto& groups = inputs.get0();
|
||||
auto& deferredFrameBuffer = inputs.get1();
|
||||
|
||||
if (!inShapes.empty()) {
|
||||
RenderArgs* args = renderContext->args;
|
||||
ShapeKey::Builder defaultKeyBuilder;
|
||||
RenderArgs* args = renderContext->args;
|
||||
ShapeKey::Builder defaultKeyBuilder;
|
||||
auto hasOutline = false;
|
||||
|
||||
if (!_outlineRessources) {
|
||||
_outlineRessources = std::make_shared<OutlineRessources>();
|
||||
if (!_outlineRessources) {
|
||||
_outlineRessources = std::make_shared<OutlineRessources>();
|
||||
}
|
||||
_outlineRessources->update(deferredFrameBuffer->getDeferredColorTexture());
|
||||
|
||||
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
|
||||
args->_batch = &batch;
|
||||
|
||||
auto maskPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder);
|
||||
auto maskSkinnedPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder.withSkinned());
|
||||
auto colorLoc = maskPipeline.get()->pipeline->getProgram()->getUniforms().findLocation("color");
|
||||
auto skinnedColorLoc = maskSkinnedPipeline.get()->pipeline->getProgram()->getUniforms().findLocation("color");
|
||||
unsigned int groupId = 0;
|
||||
|
||||
for (auto& inShapeBounds : groups) {
|
||||
if (!inShapeBounds.isNull()) {
|
||||
auto& inShapes = inShapeBounds.get<render::ShapeBounds>();
|
||||
|
||||
if (!inShapes.empty()) {
|
||||
if (!hasOutline) {
|
||||
batch.setFramebuffer(_outlineRessources->getFramebuffer());
|
||||
// Clear it only if it hasn't been done before
|
||||
batch.clearFramebuffer(
|
||||
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);
|
||||
batch.setStateScissorRect(args->_viewport);
|
||||
|
||||
glm::mat4 projMat;
|
||||
Transform viewMat;
|
||||
args->getViewFrustum().evalProjectionMatrix(projMat);
|
||||
args->getViewFrustum().evalViewTransform(viewMat);
|
||||
|
||||
batch.setProjectionTransform(projMat);
|
||||
batch.setViewTransform(viewMat);
|
||||
hasOutline = true;
|
||||
}
|
||||
|
||||
std::vector<ShapeKey> skinnedShapeKeys{};
|
||||
// Encode group id in quantized color
|
||||
glm::vec4 idColor = encodeIdToColor(groupId);
|
||||
|
||||
// Iterate through all inShapes and render the unskinned
|
||||
args->_shapePipeline = maskPipeline;
|
||||
batch.setPipeline(maskPipeline->pipeline);
|
||||
batch._glUniform4f(colorLoc, idColor.r, idColor.g, idColor.b, idColor.a);
|
||||
for (auto items : inShapes) {
|
||||
if (items.first.isSkinned()) {
|
||||
skinnedShapeKeys.push_back(items.first);
|
||||
} else {
|
||||
renderItems(renderContext, items.second);
|
||||
}
|
||||
}
|
||||
|
||||
// Reiterate to render the skinned
|
||||
args->_shapePipeline = maskSkinnedPipeline;
|
||||
batch.setPipeline(maskSkinnedPipeline->pipeline);
|
||||
batch._glUniform4f(skinnedColorLoc, idColor.r, idColor.g, idColor.b, idColor.a);
|
||||
for (const auto& key : skinnedShapeKeys) {
|
||||
renderItems(renderContext, inShapes.at(key));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
++groupId;
|
||||
}
|
||||
_outlineRessources->update(deferredFrameBuffer->getDeferredColorTexture());
|
||||
|
||||
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
|
||||
args->_batch = &batch;
|
||||
|
||||
batch.setFramebuffer(_outlineRessources->getFramebuffer());
|
||||
// Clear it
|
||||
batch.clearFramebuffer(
|
||||
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);
|
||||
batch.setStateScissorRect(args->_viewport);
|
||||
|
||||
glm::mat4 projMat;
|
||||
Transform viewMat;
|
||||
args->getViewFrustum().evalProjectionMatrix(projMat);
|
||||
args->getViewFrustum().evalViewTransform(viewMat);
|
||||
|
||||
batch.setProjectionTransform(projMat);
|
||||
batch.setViewTransform(viewMat);
|
||||
|
||||
auto maskPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder);
|
||||
auto maskSkinnedPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder.withSkinned());
|
||||
|
||||
std::vector<ShapeKey> skinnedShapeKeys{};
|
||||
auto colorLoc = maskPipeline.get()->pipeline->getProgram()->getUniforms().findLocation("color");
|
||||
glm::vec4 idColor{ 1.0f, 0.0f, 0.0f, 0.0f };
|
||||
|
||||
// Iterate through all inShapes and render the unskinned
|
||||
args->_shapePipeline = maskPipeline;
|
||||
batch.setPipeline(maskPipeline->pipeline);
|
||||
batch._glUniform4f(colorLoc, idColor.r, idColor.g, idColor.b, idColor.a);
|
||||
for (auto items : inShapes) {
|
||||
if (items.first.isSkinned()) {
|
||||
skinnedShapeKeys.push_back(items.first);
|
||||
}
|
||||
else {
|
||||
renderItems(renderContext, items.second);
|
||||
}
|
||||
}
|
||||
|
||||
colorLoc = maskSkinnedPipeline.get()->pipeline->getProgram()->getUniforms().findLocation("color");
|
||||
// Reiterate to render the skinned
|
||||
args->_shapePipeline = maskSkinnedPipeline;
|
||||
batch.setPipeline(maskSkinnedPipeline->pipeline);
|
||||
batch._glUniform4f(colorLoc, idColor.r, idColor.g, idColor.b, idColor.a);
|
||||
for (const auto& key : skinnedShapeKeys) {
|
||||
renderItems(renderContext, inShapes.at(key));
|
||||
}
|
||||
|
||||
args->_shapePipeline = nullptr;
|
||||
args->_batch = nullptr;
|
||||
});
|
||||
args->_shapePipeline = nullptr;
|
||||
args->_batch = nullptr;
|
||||
});
|
||||
|
||||
if (hasOutline) {
|
||||
output = _outlineRessources;
|
||||
} else {
|
||||
output = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
PrepareDrawOutline::PrepareDrawOutline() {
|
||||
|
||||
}
|
||||
|
||||
void PrepareDrawOutline::run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs) {
|
||||
auto destinationFrameBuffer = inputs;
|
||||
auto framebufferSize = destinationFrameBuffer->getSize();
|
||||
|
||||
if (!_primaryWithoutDepthBuffer || framebufferSize != _frameBufferSize) {
|
||||
// Failing to recreate this frame buffer when the screen has been resized creates a bug on Mac
|
||||
_primaryWithoutDepthBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("primaryWithoutDepth"));
|
||||
_primaryWithoutDepthBuffer->setRenderBuffer(0, destinationFrameBuffer->getRenderBuffer(0));
|
||||
_frameBufferSize = framebufferSize;
|
||||
}
|
||||
|
||||
outputs = _primaryWithoutDepthBuffer;
|
||||
}
|
||||
|
||||
gpu::PipelinePointer DrawOutline::_pipeline;
|
||||
gpu::PipelinePointer DrawOutline::_pipelineFilled;
|
||||
|
||||
DrawOutline::DrawOutline() {
|
||||
}
|
||||
|
||||
|
@ -170,6 +228,7 @@ void DrawOutline::configure(const Config& config) {
|
|||
_fillOpacityOccluded = config.fillOpacityOccluded;
|
||||
_threshold = config.glow ? 1.f : 1e-3f;
|
||||
_intensity = config.intensity * (config.glow ? 2.f : 1.f);
|
||||
_hasConfigurationChanged = true;
|
||||
}
|
||||
|
||||
void DrawOutline::run(const render::RenderContextPointer& renderContext, const Inputs& inputs) {
|
||||
|
@ -179,20 +238,16 @@ void DrawOutline::run(const render::RenderContextPointer& renderContext, const I
|
|||
auto sceneDepthBuffer = inputs.get2();
|
||||
const auto frameTransform = inputs.get0();
|
||||
auto outlinedDepthTexture = outlineFrameBuffer->getDepthTexture();
|
||||
auto outlinedIdTexture = outlineFrameBuffer->getIdTexture();
|
||||
auto destinationFrameBuffer = inputs.get3();
|
||||
auto framebufferSize = glm::ivec2(outlinedDepthTexture->getDimensions());
|
||||
|
||||
if (!_primaryWithoutDepthBuffer || framebufferSize!=_frameBufferSize) {
|
||||
// Failing to recreate this frame buffer when the screen has been resized creates a bug on Mac
|
||||
_primaryWithoutDepthBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("primaryWithoutDepth"));
|
||||
_primaryWithoutDepthBuffer->setRenderBuffer(0, destinationFrameBuffer->getRenderBuffer(0));
|
||||
_frameBufferSize = framebufferSize;
|
||||
}
|
||||
|
||||
if (sceneDepthBuffer) {
|
||||
const auto OPACITY_EPSILON = 5e-3f;
|
||||
auto pipeline = getPipeline(_fillOpacityUnoccluded>OPACITY_EPSILON || _fillOpacityOccluded>OPACITY_EPSILON);
|
||||
auto args = renderContext->args;
|
||||
|
||||
if (_hasConfigurationChanged)
|
||||
{
|
||||
auto& configuration = _configuration.edit();
|
||||
configuration._color = _color;
|
||||
|
@ -201,24 +256,27 @@ void DrawOutline::run(const render::RenderContextPointer& renderContext, const I
|
|||
configuration._fillOpacityOccluded = _fillOpacityOccluded;
|
||||
configuration._threshold = _threshold;
|
||||
configuration._blurKernelSize = _blurKernelSize;
|
||||
configuration._size.x = _size * _frameBufferSize.y / _frameBufferSize.x;
|
||||
configuration._size.x = (_size * framebufferSize.y) / framebufferSize.x;
|
||||
configuration._size.y = _size;
|
||||
configuration._idColor = encodeIdToColor(0);
|
||||
_hasConfigurationChanged = false;
|
||||
}
|
||||
|
||||
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
|
||||
batch.enableStereo(false);
|
||||
batch.setFramebuffer(_primaryWithoutDepthBuffer);
|
||||
batch.setFramebuffer(destinationFrameBuffer);
|
||||
|
||||
batch.setViewportTransform(args->_viewport);
|
||||
batch.setProjectionTransform(glm::mat4());
|
||||
batch.resetViewTransform();
|
||||
batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(_frameBufferSize, args->_viewport));
|
||||
batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(framebufferSize, args->_viewport));
|
||||
batch.setPipeline(pipeline);
|
||||
|
||||
batch.setUniformBuffer(OUTLINE_PARAMS_SLOT, _configuration);
|
||||
batch.setUniformBuffer(FRAME_TRANSFORM_SLOT, frameTransform->getFrameTransformBuffer());
|
||||
batch.setResourceTexture(SCENE_DEPTH_SLOT, sceneDepthBuffer->getPrimaryDepthTexture());
|
||||
batch.setResourceTexture(OUTLINED_DEPTH_SLOT, outlinedDepthTexture);
|
||||
batch.setResourceTexture(OUTLINED_ID_SLOT, outlinedIdTexture);
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
|
||||
// Restore previous frame buffer
|
||||
|
@ -239,6 +297,7 @@ const gpu::PipelinePointer& DrawOutline::getPipeline(bool isFilled) {
|
|||
slotBindings.insert(gpu::Shader::Binding("deferredFrameTransformBuffer", FRAME_TRANSFORM_SLOT));
|
||||
slotBindings.insert(gpu::Shader::Binding("sceneDepthMap", SCENE_DEPTH_SLOT));
|
||||
slotBindings.insert(gpu::Shader::Binding("outlinedDepthMap", OUTLINED_DEPTH_SLOT));
|
||||
slotBindings.insert(gpu::Shader::Binding("outlinedIdMap", OUTLINED_ID_SLOT));
|
||||
gpu::Shader::makeProgram(*program, slotBindings);
|
||||
|
||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||
|
@ -400,7 +459,6 @@ void DrawOutlineTask::configure(const Config& config) {
|
|||
|
||||
void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs) {
|
||||
const auto groups = inputs.getN<Inputs>(0).get<Groups>();
|
||||
const auto selectedMetas = groups[0];
|
||||
const auto sceneFrameBuffer = inputs.getN<Inputs>(1);
|
||||
const auto primaryFramebuffer = inputs.getN<Inputs>(2);
|
||||
const auto deferredFrameTransform = inputs.getN<Inputs>(3);
|
||||
|
@ -415,19 +473,26 @@ void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, rende
|
|||
initMaskPipelines(*shapePlumber, state);
|
||||
}
|
||||
|
||||
const auto outlinedItemIDs = task.addJob<render::MetaToSubItems>("OutlineMetaToSubItemIDs", selectedMetas);
|
||||
const auto outlinedItems = task.addJob<render::IDsToBounds>("OutlineMetaToSubItems", outlinedItemIDs, true);
|
||||
DrawOutlineMask::Groups sortedBounds;
|
||||
for (auto i = 0; i < DrawOutline::MAX_GROUP_COUNT; i++) {
|
||||
const auto groupItems = groups[i];
|
||||
const auto outlinedItemIDs = task.addJob<render::MetaToSubItems>("OutlineMetaToSubItemIDs", groupItems);
|
||||
const auto outlinedItems = task.addJob<render::IDsToBounds>("OutlineMetaToSubItems", outlinedItemIDs, true);
|
||||
|
||||
// Sort
|
||||
const auto sortedPipelines = task.addJob<render::PipelineSortShapes>("OutlinePipelineSort", outlinedItems);
|
||||
const auto sortedShapes = task.addJob<render::DepthSortShapes>("OutlineDepthSort", sortedPipelines);
|
||||
// Sort
|
||||
const auto sortedPipelines = task.addJob<render::PipelineSortShapes>("OutlinePipelineSort", outlinedItems);
|
||||
sortedBounds[i] = task.addJob<render::DepthSortShapes>("OutlineDepthSort", sortedPipelines);
|
||||
}
|
||||
|
||||
// Draw depth of outlined objects in separate buffer
|
||||
const auto drawMaskInputs = DrawOutlineMask::Inputs(sortedShapes, sceneFrameBuffer).asVarying();
|
||||
const auto drawMaskInputs = DrawOutlineMask::Inputs(sortedBounds, sceneFrameBuffer).asVarying();
|
||||
const auto outlinedFrameBuffer = task.addJob<DrawOutlineMask>("OutlineMask", drawMaskInputs, shapePlumber);
|
||||
|
||||
// Prepare for outline group rendering.
|
||||
const auto destFrameBuffer = task.addJob<PrepareDrawOutline>("PrepareOutline", primaryFramebuffer);
|
||||
|
||||
// Draw outline
|
||||
const auto drawOutlineInputs = DrawOutline::Inputs(deferredFrameTransform, outlinedFrameBuffer, sceneFrameBuffer, primaryFramebuffer).asVarying();
|
||||
const auto drawOutlineInputs = DrawOutline::Inputs(deferredFrameTransform, outlinedFrameBuffer, sceneFrameBuffer, destFrameBuffer).asVarying();
|
||||
task.addJob<DrawOutline>("OutlineEffect", drawOutlineInputs);
|
||||
|
||||
// Debug outline
|
||||
|
|
|
@ -42,22 +42,22 @@ protected:
|
|||
|
||||
using OutlineRessourcesPointer = std::shared_ptr<OutlineRessources>;
|
||||
|
||||
class DrawOutlineMask {
|
||||
class PrepareDrawOutline {
|
||||
public:
|
||||
using Inputs = gpu::FramebufferPointer;
|
||||
using Outputs = gpu::FramebufferPointer;
|
||||
using Config = render::Job::Config;
|
||||
using JobModel = render::Job::ModelIO<PrepareDrawOutline, Inputs, Outputs, Config>;
|
||||
|
||||
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 = OutlineRessourcesPointer;
|
||||
using JobModel = render::Job::ModelIO<DrawOutlineMask, Inputs, Outputs>;
|
||||
PrepareDrawOutline();
|
||||
|
||||
DrawOutlineMask(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {}
|
||||
void run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs);
|
||||
|
||||
void run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& output);
|
||||
private:
|
||||
|
||||
protected:
|
||||
gpu::FramebufferPointer _primaryWithoutDepthBuffer;
|
||||
gpu::Vec2u _frameBufferSize{ 0, 0 };
|
||||
|
||||
render::ShapePlumberPointer _shapePlumber;
|
||||
OutlineRessourcesPointer _outlineRessources;
|
||||
};
|
||||
|
||||
class DrawOutlineConfig : public render::Job::Config {
|
||||
|
@ -95,6 +95,10 @@ signals:
|
|||
|
||||
class DrawOutline {
|
||||
public:
|
||||
enum {
|
||||
MAX_GROUP_COUNT = 7
|
||||
};
|
||||
|
||||
using Inputs = render::VaryingSet4<DeferredFrameTransformPointer, OutlineRessourcesPointer, DeferredFramebufferPointer, gpu::FramebufferPointer>;
|
||||
using Config = DrawOutlineConfig;
|
||||
using JobModel = render::Job::ModelI<DrawOutline, Inputs, Config>;
|
||||
|
@ -109,6 +113,7 @@ private:
|
|||
enum {
|
||||
SCENE_DEPTH_SLOT = 0,
|
||||
OUTLINED_DEPTH_SLOT,
|
||||
OUTLINED_ID_SLOT,
|
||||
|
||||
OUTLINE_PARAMS_SLOT = 0,
|
||||
FRAME_TRANSFORM_SLOT
|
||||
|
@ -118,12 +123,10 @@ private:
|
|||
|
||||
using OutlineConfigurationBuffer = gpu::StructBuffer<OutlineParameters>;
|
||||
|
||||
const gpu::PipelinePointer& getPipeline(bool isFilled);
|
||||
static const gpu::PipelinePointer& getPipeline(bool isFilled);
|
||||
|
||||
gpu::FramebufferPointer _primaryWithoutDepthBuffer;
|
||||
glm::ivec2 _frameBufferSize {0, 0};
|
||||
gpu::PipelinePointer _pipeline;
|
||||
gpu::PipelinePointer _pipelineFilled;
|
||||
static gpu::PipelinePointer _pipeline;
|
||||
static gpu::PipelinePointer _pipelineFilled;
|
||||
OutlineConfigurationBuffer _configuration;
|
||||
glm::vec3 _color;
|
||||
float _size;
|
||||
|
@ -132,6 +135,44 @@ private:
|
|||
float _fillOpacityUnoccluded;
|
||||
float _fillOpacityOccluded;
|
||||
float _threshold;
|
||||
bool _hasConfigurationChanged{ true };
|
||||
};
|
||||
|
||||
class DrawOutlineTask {
|
||||
public:
|
||||
|
||||
using Groups = render::VaryingArray<render::ItemBounds, DrawOutline::MAX_GROUP_COUNT>;
|
||||
using Inputs = render::VaryingSet4<Groups, DeferredFramebufferPointer, gpu::FramebufferPointer, DeferredFrameTransformPointer>;
|
||||
using Config = render::Task::Config;
|
||||
using JobModel = render::Task::ModelI<DrawOutlineTask, Inputs, Config>;
|
||||
|
||||
DrawOutlineTask();
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
class DrawOutlineMask {
|
||||
public:
|
||||
|
||||
using Groups = render::VaryingArray<render::ShapeBounds, DrawOutline::MAX_GROUP_COUNT>;
|
||||
using Inputs = render::VaryingSet2<Groups, DeferredFramebufferPointer>;
|
||||
// Output will contain outlined objects only z-depth texture and the input primary buffer but without the primary depth buffer
|
||||
using Outputs = OutlineRessourcesPointer;
|
||||
using JobModel = render::Job::ModelIO<DrawOutlineMask, Inputs, Outputs>;
|
||||
|
||||
DrawOutlineMask(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {}
|
||||
|
||||
void run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& output);
|
||||
|
||||
protected:
|
||||
|
||||
render::ShapePlumberPointer _shapePlumber;
|
||||
OutlineRessourcesPointer _outlineRessources;
|
||||
};
|
||||
|
||||
class DebugOutlineConfig : public render::Job::Config {
|
||||
|
@ -171,27 +212,6 @@ private:
|
|||
void initializePipelines();
|
||||
};
|
||||
|
||||
class DrawOutlineTask {
|
||||
public:
|
||||
|
||||
enum {
|
||||
MAX_GROUP_COUNT = 7
|
||||
};
|
||||
|
||||
using Groups = render::VaryingArray<render::ItemBounds, MAX_GROUP_COUNT>;
|
||||
using Inputs = render::VaryingSet4<Groups, DeferredFramebufferPointer, gpu::FramebufferPointer, DeferredFrameTransformPointer>;
|
||||
using Config = render::Task::Config;
|
||||
using JobModel = render::Task::ModelI<DrawOutlineTask, Inputs, Config>;
|
||||
|
||||
DrawOutlineTask();
|
||||
|
||||
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
|
||||
|
||||
|
|
|
@ -2,9 +2,11 @@
|
|||
#ifdef __cplusplus
|
||||
# define VEC2 glm::vec2
|
||||
# define VEC3 glm::vec3
|
||||
# define VEC4 glm::vec4
|
||||
#else
|
||||
# define VEC2 vec2
|
||||
# define VEC3 vec3
|
||||
# define VEC4 vec4
|
||||
#endif
|
||||
|
||||
struct OutlineParameters
|
||||
|
@ -16,6 +18,8 @@ struct OutlineParameters
|
|||
float _fillOpacityUnoccluded;
|
||||
float _fillOpacityOccluded;
|
||||
|
||||
VEC4 _idColor;
|
||||
|
||||
float _threshold;
|
||||
int _blurKernelSize;
|
||||
float padding2;
|
||||
|
|
|
@ -181,7 +181,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
|
|||
const auto selectedItems = addSelectItemJobs(task, selectionBaseName, metas, opaques, transparents);
|
||||
DrawOutlineTask::Groups outlineGroups;
|
||||
outlineGroups[0] = selectedItems;
|
||||
for (auto i = 1; i < DrawOutlineTask::MAX_GROUP_COUNT; i++) {
|
||||
for (auto i = 1; i < DrawOutline::MAX_GROUP_COUNT; i++) {
|
||||
std::ostringstream selectionName;
|
||||
selectionName << selectionBaseName;
|
||||
selectionName << i;
|
||||
|
|
Loading…
Reference in a new issue