From 4ff2b85e1a87f14fb4cce2f80396c182aaec5722 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Mon, 11 Jan 2016 16:00:08 -0800 Subject: [PATCH] Replace ShapePipelineLib abstract with ShapePlumber instanced class --- .../render-utils/src/DeferredPipelineLib.cpp | 204 ------------------ .../render-utils/src/DeferredPipelineLib.h | 32 --- libraries/render-utils/src/Model.cpp | 12 +- libraries/render-utils/src/Model.h | 1 + .../render-utils/src/RenderDeferredTask.cpp | 169 ++++++++++++++- .../render-utils/src/RenderDeferredTask.h | 11 +- libraries/render/src/render/DrawTask.cpp | 6 +- libraries/render/src/render/DrawTask.h | 4 +- libraries/render/src/render/ShapePipeline.cpp | 128 ++++++----- libraries/render/src/render/ShapePipeline.h | 110 +++++++--- 10 files changed, 339 insertions(+), 338 deletions(-) delete mode 100644 libraries/render-utils/src/DeferredPipelineLib.cpp delete mode 100644 libraries/render-utils/src/DeferredPipelineLib.h diff --git a/libraries/render-utils/src/DeferredPipelineLib.cpp b/libraries/render-utils/src/DeferredPipelineLib.cpp deleted file mode 100644 index 70f8d13a07..0000000000 --- a/libraries/render-utils/src/DeferredPipelineLib.cpp +++ /dev/null @@ -1,204 +0,0 @@ -// -// DeferredPipelineLib.cpp -// render-utils/src -// -// Created by Zach Pomerantz on 1/4/2015. -// Copyright 2015 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include "DeferredPipelineLib.h" - -#include - -#include - -#include "DeferredLightingEffect.h" - -#include "model_vert.h" -#include "model_shadow_vert.h" -#include "model_normal_map_vert.h" -#include "model_lightmap_vert.h" -#include "model_lightmap_normal_map_vert.h" -#include "skin_model_vert.h" -#include "skin_model_shadow_vert.h" -#include "skin_model_normal_map_vert.h" - -#include "model_frag.h" -#include "model_shadow_frag.h" -#include "model_normal_map_frag.h" -#include "model_normal_specular_map_frag.h" -#include "model_specular_map_frag.h" -#include "model_lightmap_frag.h" -#include "model_lightmap_normal_map_frag.h" -#include "model_lightmap_normal_specular_map_frag.h" -#include "model_lightmap_specular_map_frag.h" -#include "model_translucent_frag.h" - -DeferredPipelineLib::DeferredPipelineLib() { - if (!_isInitPipeline) { - initPipeline(); - } -} - -const DeferredPipelineLib::PipelinePointer DeferredPipelineLib::pickPipeline(RenderArgs* args, const Key& key) const { - PerformanceTimer perfTimer("DeferredPipelineLib::pickPipeline"); - - auto pipeline = _pickPipeline(args, key); - if (!pipeline) { - return pipeline; - } - - if ((pipeline->locations->normalFittingMapUnit > -1)) { - args->_batch->setResourceTexture(pipeline->locations->normalFittingMapUnit, - DependencyManager::get()->getNormalFittingTexture()); - } - - return pipeline; -} - -bool DeferredPipelineLib::_isInitPipeline { false }; - -void DeferredPipelineLib::initPipeline() { - assert(_pipelineLib.empty()); - - // Vertex shaders - auto modelVertex = gpu::Shader::createVertex(std::string(model_vert)); - auto modelNormalMapVertex = gpu::Shader::createVertex(std::string(model_normal_map_vert)); - auto modelLightmapVertex = gpu::Shader::createVertex(std::string(model_lightmap_vert)); - auto modelLightmapNormalMapVertex = gpu::Shader::createVertex(std::string(model_lightmap_normal_map_vert)); - auto modelShadowVertex = gpu::Shader::createVertex(std::string(model_shadow_vert)); - auto skinModelVertex = gpu::Shader::createVertex(std::string(skin_model_vert)); - auto skinModelNormalMapVertex = gpu::Shader::createVertex(std::string(skin_model_normal_map_vert)); - auto skinModelShadowVertex = gpu::Shader::createVertex(std::string(skin_model_shadow_vert)); - - // Pixel shaders - auto modelPixel = gpu::Shader::createPixel(std::string(model_frag)); - auto modelNormalMapPixel = gpu::Shader::createPixel(std::string(model_normal_map_frag)); - auto modelSpecularMapPixel = gpu::Shader::createPixel(std::string(model_specular_map_frag)); - auto modelNormalSpecularMapPixel = gpu::Shader::createPixel(std::string(model_normal_specular_map_frag)); - auto modelTranslucentPixel = gpu::Shader::createPixel(std::string(model_translucent_frag)); - auto modelShadowPixel = gpu::Shader::createPixel(std::string(model_shadow_frag)); - auto modelLightmapPixel = gpu::Shader::createPixel(std::string(model_lightmap_frag)); - auto modelLightmapNormalMapPixel = gpu::Shader::createPixel(std::string(model_lightmap_normal_map_frag)); - auto modelLightmapSpecularMapPixel = gpu::Shader::createPixel(std::string(model_lightmap_specular_map_frag)); - auto modelLightmapNormalSpecularMapPixel = gpu::Shader::createPixel(std::string(model_lightmap_normal_specular_map_frag)); - - // Fill the pipelineLib - - _pipelineLib.addPipeline( - Key::Builder(), - modelVertex, modelPixel); - - _pipelineLib.addPipeline( - Key::Builder().withTangents(), - modelNormalMapVertex, modelNormalMapPixel); - - _pipelineLib.addPipeline( - Key::Builder().withSpecular(), - modelVertex, modelSpecularMapPixel); - - _pipelineLib.addPipeline( - Key::Builder().withTangents().withSpecular(), - modelNormalMapVertex, modelNormalSpecularMapPixel); - - - _pipelineLib.addPipeline( - Key::Builder().withTranslucent(), - modelVertex, modelTranslucentPixel); - // FIXME Ignore lightmap for translucents meshpart - _pipelineLib.addPipeline( - Key::Builder().withTranslucent().withLightmap(), - modelVertex, modelTranslucentPixel); - - _pipelineLib.addPipeline( - Key::Builder().withTangents().withTranslucent(), - modelNormalMapVertex, modelTranslucentPixel); - - _pipelineLib.addPipeline( - Key::Builder().withSpecular().withTranslucent(), - modelVertex, modelTranslucentPixel); - - _pipelineLib.addPipeline( - Key::Builder().withTangents().withSpecular().withTranslucent(), - modelNormalMapVertex, modelTranslucentPixel); - - - _pipelineLib.addPipeline( - Key::Builder().withLightmap(), - modelLightmapVertex, modelLightmapPixel); - - _pipelineLib.addPipeline( - Key::Builder().withLightmap().withTangents(), - modelLightmapNormalMapVertex, modelLightmapNormalMapPixel); - - _pipelineLib.addPipeline( - Key::Builder().withLightmap().withSpecular(), - modelLightmapVertex, modelLightmapSpecularMapPixel); - - _pipelineLib.addPipeline( - Key::Builder().withLightmap().withTangents().withSpecular(), - modelLightmapNormalMapVertex, modelLightmapNormalSpecularMapPixel); - - - _pipelineLib.addPipeline( - Key::Builder().withSkinned(), - skinModelVertex, modelPixel); - - _pipelineLib.addPipeline( - Key::Builder().withSkinned().withTangents(), - skinModelNormalMapVertex, modelNormalMapPixel); - - _pipelineLib.addPipeline( - Key::Builder().withSkinned().withSpecular(), - skinModelVertex, modelSpecularMapPixel); - - _pipelineLib.addPipeline( - Key::Builder().withSkinned().withTangents().withSpecular(), - skinModelNormalMapVertex, modelNormalSpecularMapPixel); - - - _pipelineLib.addPipeline( - Key::Builder().withSkinned().withTranslucent(), - skinModelVertex, modelTranslucentPixel); - - _pipelineLib.addPipeline( - Key::Builder().withSkinned().withTangents().withTranslucent(), - skinModelNormalMapVertex, modelTranslucentPixel); - - _pipelineLib.addPipeline( - Key::Builder().withSkinned().withSpecular().withTranslucent(), - skinModelVertex, modelTranslucentPixel); - - _pipelineLib.addPipeline( - Key::Builder().withSkinned().withTangents().withSpecular().withTranslucent(), - skinModelNormalMapVertex, modelTranslucentPixel); - - - _pipelineLib.addPipeline( - Key::Builder().withDepthOnly().withShadow(), - modelShadowVertex, modelShadowPixel); - - - _pipelineLib.addPipeline( - Key::Builder().withSkinned().withDepthOnly().withShadow(), - skinModelShadowVertex, modelShadowPixel); - - _isInitPipeline = true; -} - -model::MaterialPointer DeferredPipelineLib::_collisionHullMaterial; - -model::MaterialPointer DeferredPipelineLib::getCollisionHullMaterial() { - if (!_collisionHullMaterial) { - _collisionHullMaterial = std::make_shared(); - _collisionHullMaterial->setDiffuse(glm::vec3(1.0f, 0.5f, 0.0f)); - _collisionHullMaterial->setMetallic(0.02f); - _collisionHullMaterial->setGloss(1.0f); - } - - return _collisionHullMaterial; -} - diff --git a/libraries/render-utils/src/DeferredPipelineLib.h b/libraries/render-utils/src/DeferredPipelineLib.h deleted file mode 100644 index 4ea891c58c..0000000000 --- a/libraries/render-utils/src/DeferredPipelineLib.h +++ /dev/null @@ -1,32 +0,0 @@ -// -// DeferredPipelineLib.h -// render-utils/src -// -// Created by Zach Pomerantz on 1/4/2015. -// Copyright 2015 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_render_utils_DeferredPipelineLib_h -#define hifi_render_utils_DeferredPipelineLib_h - -#include -#include - -class DeferredPipelineLib : public render::ShapePipelineLib { -public: - DeferredPipelineLib(); - const PipelinePointer pickPipeline(RenderArgs* args, const Key& key) const override; - - static model::MaterialPointer getCollisionHullMaterial(); - -protected: - static bool _isInitPipeline; - static void initPipeline(); - - static model::MaterialPointer _collisionHullMaterial; -}; - -#endif // hifi_render_utils_DeferredPipelineLib_h diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 40352a1bc3..e2d0d02af7 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -22,7 +22,6 @@ #include #include "AbstractViewStateInterface.h" -#include "DeferredPipelineLib.h" #include "MeshPartPayload.h" #include "Model.h" @@ -36,6 +35,8 @@ static int vec3VectorTypeId = qRegisterMetaType >(); float Model::FAKE_DIMENSION_PLACEHOLDER = -1.0f; #define HTTP_INVALID_COM "http://invalid.com" +model::MaterialPointer Model::_collisionHullMaterial; + Model::Model(RigPointer rig, QObject* parent) : QObject(parent), _translation(0.0f), @@ -1194,8 +1195,13 @@ void Model::segregateMeshGroups() { int totalParts = mesh.parts.size(); for (int partIndex = 0; partIndex < totalParts; partIndex++) { if (showingCollisionHull) { - _renderItemsSet << std::make_shared(networkMesh._mesh, partIndex, DeferredPipelineLib::getCollisionHullMaterial(), transform, offset); - + if (!_collisionHullMaterial) { + _collisionHullMaterial = std::make_shared(); + _collisionHullMaterial->setDiffuse(glm::vec3(1.0f, 0.5f, 0.0f)); + _collisionHullMaterial->setMetallic(0.02f); + _collisionHullMaterial->setGloss(1.0f); + } + _renderItemsSet << std::make_shared(networkMesh._mesh, partIndex, _collisionHullMaterial, transform, offset); } else { _renderItemsSet << std::make_shared(this, i, partIndex, shapeID, transform, offset); } diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 3416a9b71e..157c6dbf70 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -347,6 +347,7 @@ protected: void recalculateMeshBoxes(bool pickAgainstTriangles = false); void segregateMeshGroups(); // used to calculate our list of translucent vs opaque meshes + static model::MaterialPointer _collisionHullMaterial; bool _meshGroupsKnown; bool _isWireframe; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index b68108d6f1..1ad0bb4abf 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -28,6 +28,26 @@ #include "AmbientOcclusionEffect.h" #include "AntialiasingEffect.h" +#include "model_vert.h" +#include "model_shadow_vert.h" +#include "model_normal_map_vert.h" +#include "model_lightmap_vert.h" +#include "model_lightmap_normal_map_vert.h" +#include "skin_model_vert.h" +#include "skin_model_shadow_vert.h" +#include "skin_model_normal_map_vert.h" + +#include "model_frag.h" +#include "model_shadow_frag.h" +#include "model_normal_map_frag.h" +#include "model_normal_specular_map_frag.h" +#include "model_specular_map_frag.h" +#include "model_lightmap_frag.h" +#include "model_lightmap_normal_map_frag.h" +#include "model_lightmap_normal_specular_map_frag.h" +#include "model_lightmap_specular_map_frag.h" +#include "model_translucent_frag.h" + #include "overlay3D_vert.h" #include "overlay3D_frag.h" @@ -35,6 +55,7 @@ using namespace render; +void initDeferredPipelines(render::ShapePlumber& plumber); void PrepareDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { DependencyManager::get()->prepare(renderContext->getArgs()); @@ -50,6 +71,15 @@ void ToneMappingDeferred::run(const SceneContextPointer& sceneContext, const Ren } RenderDeferredTask::RenderDeferredTask() : Task() { + // Prepare the ShapePipelines + ShapePlumberPointer shapePlumber = std::make_shared([](gpu::Batch& batch, ShapePipelinePointer pipeline) { + if ((pipeline->locations->normalFittingMapUnit > -1)) { + batch.setResourceTexture(pipeline->locations->normalFittingMapUnit, + DependencyManager::get()->getNormalFittingTexture()); + } + }); + initDeferredPipelines(*shapePlumber); + // CPU only, create the list of renderedOpaques items _jobs.push_back(Job(new FetchItems::JobModel("FetchOpaque", FetchItems([](const RenderContextPointer& context, int count) { @@ -75,7 +105,7 @@ RenderDeferredTask::RenderDeferredTask() : Task() { _jobs.push_back(Job(new PrepareDeferred::JobModel("PrepareDeferred"))); // Render opaque objects in DeferredBuffer - _jobs.push_back(Job(new DrawOpaqueDeferred::JobModel("DrawOpaqueDeferred", renderedOpaques))); + _jobs.push_back(Job(new DrawOpaqueDeferred::JobModel("DrawOpaqueDeferred", renderedOpaques, DrawOpaqueDeferred(shapePlumber)))); // Once opaque is all rendered create stencil background _jobs.push_back(Job(new DrawStencilDeferred::JobModel("DrawOpaqueStencil"))); @@ -100,7 +130,7 @@ RenderDeferredTask::RenderDeferredTask() : Task() { _antialiasingJobIndex = (int)_jobs.size() - 1; // Render transparent objects forward in LigthingBuffer - _jobs.push_back(Job(new DrawTransparentDeferred::JobModel("TransparentDeferred", renderedTransparents))); + _jobs.push_back(Job(new DrawTransparentDeferred::JobModel("TransparentDeferred", renderedTransparents, DrawTransparentDeferred(shapePlumber)))); // Lighting Buffer ready for tone mapping _jobs.push_back(Job(new ToneMappingDeferred::JobModel("ToneMapping"))); @@ -121,7 +151,7 @@ RenderDeferredTask::RenderDeferredTask() : Task() { _drawStatusJobIndex = (int)_jobs.size() - 1; } - _jobs.push_back(Job(new DrawOverlay3D::JobModel("DrawOverlay3D"))); + _jobs.push_back(Job(new DrawOverlay3D::JobModel("DrawOverlay3D", DrawOverlay3D(shapePlumber)))); _jobs.push_back(Job(new HitEffect::JobModel("HitEffect"))); _jobs.back().setEnabled(false); @@ -193,7 +223,7 @@ void DrawOpaqueDeferred::run(const SceneContextPointer& sceneContext, const Rend batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); - renderShapes(sceneContext, renderContext, _deferredPipelineLib, inItems, opaque.maxDrawn); + renderShapes(sceneContext, renderContext, _shapePlumber, inItems, opaque.maxDrawn); args->_batch = nullptr; }); } @@ -219,11 +249,12 @@ void DrawTransparentDeferred::run(const SceneContextPointer& sceneContext, const batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); - renderShapes(sceneContext, renderContext, _deferredPipelineLib, inItems, transparent.maxDrawn); + renderShapes(sceneContext, renderContext, _shapePlumber, inItems, transparent.maxDrawn); args->_batch = nullptr; }); } +// TODO: Move this to the shapePlumber gpu::PipelinePointer DrawOverlay3D::_opaquePipeline; const gpu::PipelinePointer& DrawOverlay3D::getOpaquePipeline() { if (!_opaquePipeline) { @@ -292,7 +323,7 @@ void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderCon batch.setPipeline(getOpaquePipeline()); batch.setResourceTexture(0, args->_whiteTexture); - renderShapes(sceneContext, renderContext, _deferredPipelineLib, inItems, renderContext->getItemsConfig().overlay3D.maxDrawn); + renderShapes(sceneContext, renderContext, _shapePlumber, inItems, renderContext->getItemsConfig().overlay3D.maxDrawn); }); args->_batch = nullptr; args->_whiteTexture.reset(); @@ -485,3 +516,129 @@ int RenderDeferredTask::getToneMappingToneCurve() const { } } +void initDeferredPipelines(render::ShapePlumber& plumber) { + using Key = render::ShapeKey; + + // Vertex shaders + auto modelVertex = gpu::Shader::createVertex(std::string(model_vert)); + auto modelNormalMapVertex = gpu::Shader::createVertex(std::string(model_normal_map_vert)); + auto modelLightmapVertex = gpu::Shader::createVertex(std::string(model_lightmap_vert)); + auto modelLightmapNormalMapVertex = gpu::Shader::createVertex(std::string(model_lightmap_normal_map_vert)); + auto modelShadowVertex = gpu::Shader::createVertex(std::string(model_shadow_vert)); + auto skinModelVertex = gpu::Shader::createVertex(std::string(skin_model_vert)); + auto skinModelNormalMapVertex = gpu::Shader::createVertex(std::string(skin_model_normal_map_vert)); + auto skinModelShadowVertex = gpu::Shader::createVertex(std::string(skin_model_shadow_vert)); + + // Pixel shaders + auto modelPixel = gpu::Shader::createPixel(std::string(model_frag)); + auto modelNormalMapPixel = gpu::Shader::createPixel(std::string(model_normal_map_frag)); + auto modelSpecularMapPixel = gpu::Shader::createPixel(std::string(model_specular_map_frag)); + auto modelNormalSpecularMapPixel = gpu::Shader::createPixel(std::string(model_normal_specular_map_frag)); + auto modelTranslucentPixel = gpu::Shader::createPixel(std::string(model_translucent_frag)); + auto modelShadowPixel = gpu::Shader::createPixel(std::string(model_shadow_frag)); + auto modelLightmapPixel = gpu::Shader::createPixel(std::string(model_lightmap_frag)); + auto modelLightmapNormalMapPixel = gpu::Shader::createPixel(std::string(model_lightmap_normal_map_frag)); + auto modelLightmapSpecularMapPixel = gpu::Shader::createPixel(std::string(model_lightmap_specular_map_frag)); + auto modelLightmapNormalSpecularMapPixel = gpu::Shader::createPixel(std::string(model_lightmap_normal_specular_map_frag)); + + // Fill the pipelineLib + + plumber.addPipeline( + Key::Builder(), + modelVertex, modelPixel); + + plumber.addPipeline( + Key::Builder().withTangents(), + modelNormalMapVertex, modelNormalMapPixel); + + plumber.addPipeline( + Key::Builder().withSpecular(), + modelVertex, modelSpecularMapPixel); + + plumber.addPipeline( + Key::Builder().withTangents().withSpecular(), + modelNormalMapVertex, modelNormalSpecularMapPixel); + + + plumber.addPipeline( + Key::Builder().withTranslucent(), + modelVertex, modelTranslucentPixel); + // FIXME Ignore lightmap for translucents meshpart + plumber.addPipeline( + Key::Builder().withTranslucent().withLightmap(), + modelVertex, modelTranslucentPixel); + + plumber.addPipeline( + Key::Builder().withTangents().withTranslucent(), + modelNormalMapVertex, modelTranslucentPixel); + + plumber.addPipeline( + Key::Builder().withSpecular().withTranslucent(), + modelVertex, modelTranslucentPixel); + + plumber.addPipeline( + Key::Builder().withTangents().withSpecular().withTranslucent(), + modelNormalMapVertex, modelTranslucentPixel); + + + plumber.addPipeline( + Key::Builder().withLightmap(), + modelLightmapVertex, modelLightmapPixel); + + plumber.addPipeline( + Key::Builder().withLightmap().withTangents(), + modelLightmapNormalMapVertex, modelLightmapNormalMapPixel); + + plumber.addPipeline( + Key::Builder().withLightmap().withSpecular(), + modelLightmapVertex, modelLightmapSpecularMapPixel); + + plumber.addPipeline( + Key::Builder().withLightmap().withTangents().withSpecular(), + modelLightmapNormalMapVertex, modelLightmapNormalSpecularMapPixel); + + + plumber.addPipeline( + Key::Builder().withSkinned(), + skinModelVertex, modelPixel); + + plumber.addPipeline( + Key::Builder().withSkinned().withTangents(), + skinModelNormalMapVertex, modelNormalMapPixel); + + plumber.addPipeline( + Key::Builder().withSkinned().withSpecular(), + skinModelVertex, modelSpecularMapPixel); + + plumber.addPipeline( + Key::Builder().withSkinned().withTangents().withSpecular(), + skinModelNormalMapVertex, modelNormalSpecularMapPixel); + + + plumber.addPipeline( + Key::Builder().withSkinned().withTranslucent(), + skinModelVertex, modelTranslucentPixel); + + plumber.addPipeline( + Key::Builder().withSkinned().withTangents().withTranslucent(), + skinModelNormalMapVertex, modelTranslucentPixel); + + plumber.addPipeline( + Key::Builder().withSkinned().withSpecular().withTranslucent(), + skinModelVertex, modelTranslucentPixel); + + plumber.addPipeline( + Key::Builder().withSkinned().withTangents().withSpecular().withTranslucent(), + skinModelNormalMapVertex, modelTranslucentPixel); + + + plumber.addPipeline( + Key::Builder().withDepthOnly(), + modelShadowVertex, modelShadowPixel); + + + plumber.addPipeline( + Key::Builder().withSkinned().withDepthOnly(), + skinModelShadowVertex, modelShadowPixel); +} + diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index 171fe843da..b93cd0ec02 100755 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -13,10 +13,10 @@ #define hifi_RenderDeferredTask_h #include "render/DrawTask.h" +#include "render/ShapePipeline.h" #include "gpu/Pipeline.h" -#include "DeferredPipelineLib.h" #include "ToneMappingEffect.h" class SetupDeferred { @@ -52,22 +52,24 @@ public: class DrawOpaqueDeferred { public: + DrawOpaqueDeferred(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {} void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const render::ItemIDsBounds& inItems); typedef render::Job::ModelI JobModel; protected: - DeferredPipelineLib _deferredPipelineLib; + render::ShapePlumberPointer _shapePlumber; }; class DrawTransparentDeferred { public: + DrawTransparentDeferred(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {} void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const render::ItemIDsBounds& inItems); typedef render::Job::ModelI JobModel; protected: - DeferredPipelineLib _deferredPipelineLib; + render::ShapePlumberPointer _shapePlumber; }; class DrawStencilDeferred { @@ -91,6 +93,7 @@ public: class DrawOverlay3D { public: + DrawOverlay3D(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {} static const gpu::PipelinePointer& getOpaquePipeline(); void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); @@ -99,7 +102,7 @@ public: protected: static gpu::PipelinePointer _opaquePipeline; //lazy evaluation hence mutable - DeferredPipelineLib _deferredPipelineLib; + render::ShapePlumberPointer _shapePlumber; }; class Blit { diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index 27cd2011d8..4791324002 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -195,11 +195,11 @@ void render::renderLights(const SceneContextPointer& sceneContext, const RenderC } } -void renderShape(RenderArgs* args, const ShapePipelineLib& shapeContext, const Item& item) { +void renderShape(RenderArgs* args, const ShapePlumberPointer& shapeContext, const Item& item) { assert(item.getKey().isShape()); const auto& key = item.getShapeKey(); if (key.isValid() && !key.hasOwnPipeline()) { - args->_pipeline = shapeContext.pickPipeline(args, key); + args->_pipeline = shapeContext->pickPipeline(args, key); if (args->_pipeline) { item.render(args); } @@ -211,7 +211,7 @@ void renderShape(RenderArgs* args, const ShapePipelineLib& shapeContext, const I } void render::renderShapes(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, - const ShapePipelineLib& shapeContext, const ItemIDsBounds& inItems, int maxDrawnItems) { + const ShapePlumberPointer& shapeContext, const ItemIDsBounds& inItems, int maxDrawnItems) { auto& scene = sceneContext->_scene; RenderArgs* args = renderContext->getArgs(); diff --git a/libraries/render/src/render/DrawTask.h b/libraries/render/src/render/DrawTask.h index ef9508365c..f2eb6920cf 100755 --- a/libraries/render/src/render/DrawTask.h +++ b/libraries/render/src/render/DrawTask.h @@ -134,7 +134,7 @@ public: Model() {} Model(const std::string& name): Concept(name) {} Model(Data data): _data(data) {} - Model(Data data, const std::string& name): Concept(name), _data(data) {} + Model(const std::string& name, Data data): Concept(name), _data(data) {} void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { if (isEnabled()) { @@ -222,7 +222,7 @@ typedef std::vector Jobs; void cullItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outITems); void depthSortItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, bool frontToBack, const ItemIDsBounds& inItems, ItemIDsBounds& outITems); void renderLights(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems); -void renderShapes(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ShapePipelineLib& shapeContext, const ItemIDsBounds& inItems, int maxDrawnItems = -1); +void renderShapes(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ShapePlumberPointer& shapeContext, const ItemIDsBounds& inItems, int maxDrawnItems = -1); class FetchItems { diff --git a/libraries/render/src/render/ShapePipeline.cpp b/libraries/render/src/render/ShapePipeline.cpp index b766fb8695..4044750673 100644 --- a/libraries/render/src/render/ShapePipeline.cpp +++ b/libraries/render/src/render/ShapePipeline.cpp @@ -9,41 +9,67 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "DependencyManager.h" + #include "ShapePipeline.h" #include using namespace render; -ShapePipelineLib::PipelineLib ShapePipelineLib::_pipelineLib; - -void ShapePipelineLib::addPipeline(Key key, gpu::ShaderPointer& vertexShader, gpu::ShaderPointer& pixelShader) { - _pipelineLib.addPipeline(key, vertexShader, pixelShader); +ShapeKey::Filter::Builder::Builder() { + _mask.set(OWN_PIPELINE); + _mask.set(INVALID); } -const ShapePipelineLib::PipelinePointer ShapePipelineLib::_pickPipeline(RenderArgs* args, const Key& key) { - assert(!_pipelineLib.empty()); - assert(args); - assert(args->_batch); +void defaultStateSetter(ShapeKey key, gpu::State& state) { + // Cull backface + state.setCullMode(gpu::State::CULL_BACK); - PerformanceTimer perfTimer("ShapePipelineLib::getPipeline"); + // Z test depends on transparency + state.setDepthTest(true, !key.isTranslucent(), gpu::LESS_EQUAL); - const auto& pipelineIterator = _pipelineLib.find(key); - if (pipelineIterator == _pipelineLib.end()) { - qDebug() << "Couldn't find a pipeline from ShapeKey ?" << key; - return PipelinePointer(nullptr); + // Blend if transparent + state.setBlendFunction(key.isTranslucent(), + // For transparency, keep the highlight intensity + gpu::State::ONE, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, + gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); + + // Add a wireframe version + if (!key.isWireFrame()) { + state.setFillMode(gpu::State::FILL_LINE); } - - PipelinePointer shapePipeline(pipelineIterator->second); - auto& batch = args->_batch; - - // Setup the one pipeline (to rule them all) - batch->setPipeline(shapePipeline->pipeline); - - return shapePipeline; } -void ShapePipelineLib::PipelineLib::addPipeline(Key key, gpu::ShaderPointer& vertexShader, gpu::ShaderPointer& pixelShader) { +void defaultBatchSetter(gpu::Batch& batch, ShapePipelinePointer pipeline) { +} + +ShapePlumber::ShapePlumber() : _stateSetter{ defaultStateSetter }, _batchSetter{ defaultBatchSetter } {} +ShapePlumber::ShapePlumber(BatchSetter batchSetter) : _stateSetter{ defaultStateSetter }, _batchSetter{ batchSetter } {} + +void ShapePlumber::addPipelineHelper(const Filter& filter, ShapeKey key, int bit, gpu::ShaderPointer program, LocationsPointer locations) { + // Iterate over all keys, toggling only bits set as significant in filter._mask + if (bit < (int)ShapeKey::FlagBit::NUM_FLAGS) { + addPipelineHelper(filter, key, ++bit, program, locations); + if (filter._mask[bit]) { + key._flags.flip(bit); + addPipelineHelper(filter, key, ++bit, program, locations); + } + } else { + auto state = std::make_shared(); + _stateSetter(key, *state); + + // Add the brand new pipeline and cache its location in the lib + auto pipeline = gpu::Pipeline::create(program, state); + _pipelineMap.insert(PipelineMap::value_type(key, std::make_shared(pipeline, locations))); + } +} + +void ShapePlumber::addPipeline(const Key& key, gpu::ShaderPointer& vertexShader, gpu::ShaderPointer& pixelShader) { + addPipeline(Filter{key}, vertexShader, pixelShader); +} + +void ShapePlumber::addPipeline(const Filter& filter, gpu::ShaderPointer& vertexShader, gpu::ShaderPointer& pixelShader) { gpu::Shader::BindingSet slotBindings; slotBindings.insert(gpu::Shader::Binding(std::string("skinClusterBuffer"), Slot::SKINNING_GPU)); slotBindings.insert(gpu::Shader::Binding(std::string("materialBuffer"), Slot::MATERIAL_GPU)); @@ -69,37 +95,29 @@ void ShapePipelineLib::PipelineLib::addPipeline(Key key, gpu::ShaderPointer& ver locations->materialBufferUnit = program->getBuffers().findLocation("materialBuffer"); locations->lightBufferUnit = program->getBuffers().findLocation("lightBuffer"); - auto state = std::make_shared(); - - // Backface on shadow - if (key.isShadow()) { - state->setCullMode(gpu::State::CULL_FRONT); - state->setDepthBias(1.0f); - state->setDepthBiasSlopeScale(4.0f); - } else { - state->setCullMode(gpu::State::CULL_BACK); - } - - // Z test depends on transparency - state->setDepthTest(true, !key.isTranslucent(), gpu::LESS_EQUAL); - - // Blend if transparent - state->setBlendFunction(key.isTranslucent(), - gpu::State::ONE, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, // For transparent only, this keep the highlight intensity - gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); - - // Add the brand new pipeline and cache its location in the lib - auto pipeline = gpu::Pipeline::create(program, state); - insert(value_type(key, std::make_shared(pipeline, locations))); - - // Add a wireframe version - if (!key.isWireFrame()) { - ShapeKey wireframeKey(ShapeKey::Builder(key).withWireframe()); - - auto wireframeState = std::make_shared(state->getValues()); - wireframeState->setFillMode(gpu::State::FILL_LINE); - - auto wireframePipeline = gpu::Pipeline::create(program, wireframeState); - insert(value_type(wireframeKey, std::make_shared(wireframePipeline, locations))); - } + ShapeKey key{filter._flags}; + addPipelineHelper(filter, key, 0, program, locations); +} + +const ShapePipelinePointer ShapePlumber::pickPipeline(RenderArgs* args, const Key& key) const { + assert(!_pipelineMap.empty()); + assert(args); + assert(args->_batch); + + PerformanceTimer perfTimer("ShapePlumber::pickPipeline"); + + const auto& pipelineIterator = _pipelineMap.find(key); + if (pipelineIterator == _pipelineMap.end()) { + qDebug() << "Couldn't find a pipeline from ShapeKey ?" << key; + return PipelinePointer(nullptr); + } + + PipelinePointer shapePipeline(pipelineIterator->second); + auto& batch = args->_batch; + _batchSetter(*batch, shapePipeline); + + // Setup the one pipeline (to rule them all) + batch->setPipeline(shapePipeline->pipeline); + + return shapePipeline; } diff --git a/libraries/render/src/render/ShapePipeline.h b/libraries/render/src/render/ShapePipeline.h index 1f293cfb93..04f9e0daa7 100644 --- a/libraries/render/src/render/ShapePipeline.h +++ b/libraries/render/src/render/ShapePipeline.h @@ -28,29 +28,26 @@ public: SKINNED, STEREO, DEPTH_ONLY, - SHADOW, WIREFRAME, OWN_PIPELINE, INVALID, - NUM_FLAGS, // Not a valid flag + NUM_FLAGS, // Not a valid flag }; using Flags = std::bitset; Flags _flags; - ShapeKey() : _flags{ 0 } {} - ShapeKey(const Flags& flags) : _flags(flags) {} + ShapeKey() : _flags{0} {} + ShapeKey(const Flags& flags) : _flags{flags} {} class Builder { - friend class ShapeKey; - Flags _flags{ 0 }; public: Builder() {} - Builder(ShapeKey key) : _flags{ key._flags } {} + Builder(ShapeKey key) : _flags{key._flags} {} - ShapeKey build() const { return ShapeKey(_flags); } + ShapeKey build() const { return ShapeKey{_flags}; } Builder& withTranslucent() { _flags.set(TRANSLUCENT); return (*this); } Builder& withLightmap() { _flags.set(LIGHTMAP); return (*this); } @@ -60,15 +57,70 @@ public: Builder& withSkinned() { _flags.set(SKINNED); return (*this); } Builder& withStereo() { _flags.set(STEREO); return (*this); } Builder& withDepthOnly() { _flags.set(DEPTH_ONLY); return (*this); } - Builder& withShadow() { _flags.set(SHADOW); return (*this); } Builder& withWireframe() { _flags.set(WIREFRAME); return (*this); } + Builder& withOwnPipeline() { _flags.set(OWN_PIPELINE); return (*this); } Builder& invalidate() { _flags.set(INVALID); return (*this); } static const ShapeKey ownPipeline() { return Builder().withOwnPipeline(); } static const ShapeKey invalid() { return Builder().invalidate(); } + + protected: + friend class ShapeKey; + Flags _flags{0}; + }; + ShapeKey(const Builder& builder) : ShapeKey{builder._flags} {} + + class Filter { + public: + Filter(Flags flags, Flags mask) : _flags{flags}, _mask{mask} {} + Filter(const ShapeKey& key) : _flags{ key._flags } { _mask.set(); } + + // Build a standard filter (will always exclude OWN_PIPELINE, INVALID) + class Builder { + public: + Builder(); + + Filter build() const { return Filter(_flags, _mask); } + + Builder& withOpaque() { _flags.reset(TRANSLUCENT); _mask.set(TRANSLUCENT); return (*this); } + Builder& withTranslucent() { _flags.set(TRANSLUCENT); _mask.set(TRANSLUCENT); return (*this); } + + Builder& withLightmap() { _flags.reset(LIGHTMAP); _mask.set(LIGHTMAP); return (*this); } + Builder& withoutLightmap() { _flags.set(LIGHTMAP); _mask.set(LIGHTMAP); return (*this); } + + Builder& withTangents() { _flags.reset(TANGENTS); _mask.set(TANGENTS); return (*this); } + Builder& withoutTangents() { _flags.set(TANGENTS); _mask.set(TANGENTS); return (*this); } + + Builder& withSpecular() { _flags.reset(SPECULAR); _mask.set(SPECULAR); return (*this); } + Builder& withoutSpecular() { _flags.set(SPECULAR); _mask.set(SPECULAR); return (*this); } + + Builder& withEmissive() { _flags.reset(EMISSIVE); _mask.set(EMISSIVE); return (*this); } + Builder& withoutEmissive() { _flags.set(EMISSIVE); _mask.set(EMISSIVE); return (*this); } + + Builder& withSkinned() { _flags.reset(SKINNED); _mask.set(SKINNED); return (*this); } + Builder& withoutSkinned() { _flags.set(SKINNED); _mask.set(SKINNED); return (*this); } + + Builder& withStereo() { _flags.reset(STEREO); _mask.set(STEREO); return (*this); } + Builder& withoutStereo() { _flags.set(STEREO); _mask.set(STEREO); return (*this); } + + Builder& withDepthOnly() { _flags.reset(DEPTH_ONLY); _mask.set(DEPTH_ONLY); return (*this); } + Builder& withoutDepthOnly() { _flags.set(DEPTH_ONLY); _mask.set(DEPTH_ONLY); return (*this); } + + Builder& withWireframe() { _flags.reset(WIREFRAME); _mask.set(WIREFRAME); return (*this); } + Builder& withoutWireframe() { _flags.set(WIREFRAME); _mask.set(WIREFRAME); return (*this); } + + protected: + friend class Filter; + Flags _flags{0}; + Flags _mask{0}; + }; + Filter(const Filter::Builder& builder) : Filter(builder._flags, builder._mask) {} + protected: + friend class ShapePlumber; + Flags _flags{0}; + Flags _mask{0}; }; - ShapeKey(const Builder& builder) : ShapeKey(builder._flags) {} bool hasLightmap() const { return _flags[LIGHTMAP]; } bool hasTangents() const { return _flags[TANGENTS]; } @@ -78,7 +130,6 @@ public: bool isSkinned() const { return _flags[SKINNED]; } bool isStereo() const { return _flags[STEREO]; } bool isDepthOnly() const { return _flags[DEPTH_ONLY]; } - bool isShadow() const { return _flags[SHADOW]; } bool isWireFrame() const { return _flags[WIREFRAME]; } bool hasOwnPipeline() const { return _flags[OWN_PIPELINE]; } @@ -113,7 +164,6 @@ inline QDebug operator<<(QDebug debug, const ShapeKey& renderKey) { << "isSkinned:" << renderKey.isSkinned() << "isStereo:" << renderKey.isStereo() << "isDepthOnly:" << renderKey.isDepthOnly() - << "isShadow:" << renderKey.isShadow() << "isWireFrame:" << renderKey.isWireFrame() << "]"; } @@ -124,6 +174,7 @@ inline QDebug operator<<(QDebug debug, const ShapeKey& renderKey) { } // Rendering abstraction over gpu::Pipeline and map locations +// Meta-information (pipeline and locations) to render a shape class ShapePipeline { public: class Slot { @@ -162,32 +213,33 @@ public: }; using ShapePipelinePointer = std::shared_ptr; -// Meta-information (pipeline and locations) to render a shape -class ShapePipelineLib { +class ShapePlumber { public: using Key = ShapeKey; + using Filter = Key::Filter; using Pipeline = ShapePipeline; using PipelinePointer = ShapePipelinePointer; - using Slot = ShapePipeline::Slot; - using Locations = ShapePipeline::Locations; + using PipelineMap = std::unordered_map; + using Slot = Pipeline::Slot; + using Locations = Pipeline::Locations; + using LocationsPointer = Pipeline::LocationsPointer; + using StateSetter = std::function; + using BatchSetter = std::function; - virtual ~ShapePipelineLib() = default; + ShapePlumber(); + explicit ShapePlumber(BatchSetter batchSetter); - static void addPipeline(Key key, gpu::ShaderPointer& vertexShader, gpu::ShaderPointer& pixelShader); - virtual const PipelinePointer pickPipeline(RenderArgs* args, const Key& key) const { - return ShapePipelineLib::_pickPipeline(args, key); - } + void addPipeline(const Key& key, gpu::ShaderPointer& vertexShader, gpu::ShaderPointer& pixelShader); + void addPipeline(const Filter& filter, gpu::ShaderPointer& vertexShader, gpu::ShaderPointer& pixelShader); + const PipelinePointer pickPipeline(RenderArgs* args, const Key& key) const; protected: - using PipelineMap = std::unordered_map; - class PipelineLib : public PipelineMap { - public: - void addPipeline(Key key, gpu::ShaderPointer& vertexShader, gpu::ShaderPointer& pixelShader); - }; - - static PipelineLib _pipelineLib; - static const PipelinePointer _pickPipeline(RenderArgs* args, const Key& key); + void addPipelineHelper(const Filter& filter, Key key, int bit, gpu::ShaderPointer pipeline, LocationsPointer locations); + PipelineMap _pipelineMap; + StateSetter _stateSetter; + BatchSetter _batchSetter; }; +using ShapePlumberPointer = std::shared_ptr; }