From 16bb861046681ed99fefdf2b2f421a65f52c980e Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Thu, 31 Dec 2015 15:52:28 -0800 Subject: [PATCH 01/39] Add render::Shape to abstract ModelRender --- libraries/render/src/render/Shape.cpp | 101 +++++++++++++++ libraries/render/src/render/Shape.h | 169 ++++++++++++++++++++++++++ 2 files changed, 270 insertions(+) create mode 100644 libraries/render/src/render/Shape.cpp create mode 100644 libraries/render/src/render/Shape.h diff --git a/libraries/render/src/render/Shape.cpp b/libraries/render/src/render/Shape.cpp new file mode 100644 index 0000000000..cbff84d068 --- /dev/null +++ b/libraries/render/src/render/Shape.cpp @@ -0,0 +1,101 @@ +// +// Shape.cpp +// render/src/render +// +// Created by Zach Pomerantz on 12/31/15. +// 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 "Shape.h" + +#include + +using namespace render; + +Shape::PipelineLib _pipelineLip; + +const Shape::Pipeline& Shape::_pickPipeline(RenderArgs* args, const Key& key) { + assert(!_pipelineLib.empty()); + assert(args); + assert(args->_batch); + + PerformanceTimer perfTimer("Shape::getPipeline"); + + const auto& pipelineIterator = _pipelineLib.find(key); + if (pipelineIterator == _pipelineLib.end()) { + qDebug() << "Couldn't find a pipeline from ShapeKey ?" << key; + return Shape::Pipeline(); // uninitialized _pipeline == nullptr + } + + const auto& shapePipeline = pipelineIterator->second; + auto& batch = args->_batch; + + // Setup the one pipeline (to rule them all) + batch->setPipeline(shapePipeline.pipeline); + + return shapePipeline; +} + +void Shape::PipelineLib::addPipeline(Key key, gpu::ShaderPointer& vertexShader, gpu::ShaderPointer& pixelShader) { + gpu::Shader::BindingSet slotBindings; + slotBindings.insert(gpu::Shader::Binding(std::string("skinClusterBuffer"), Shape::Slots::SKINNING_GPU)); + slotBindings.insert(gpu::Shader::Binding(std::string("materialBuffer"), Shape::Slots::MATERIAL_GPU)); + slotBindings.insert(gpu::Shader::Binding(std::string("diffuseMap"), Shape::Slots::DIFFUSE_MAP)); + slotBindings.insert(gpu::Shader::Binding(std::string("normalMap"), Shape::Slots::NORMAL_MAP)); + slotBindings.insert(gpu::Shader::Binding(std::string("specularMap"), Shape::Slots::SPECULAR_MAP)); + slotBindings.insert(gpu::Shader::Binding(std::string("emissiveMap"), Shape::Slots::LIGHTMAP_MAP)); + slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), Shape::Slots::LIGHT_BUFFER)); + slotBindings.insert(gpu::Shader::Binding(std::string("normalFittingMap"), Shape::Slots::NORMAL_FITTING_MAP)); + + gpu::ShaderPointer program = gpu::Shader::createProgram(vertexShader, pixelShader); + gpu::Shader::makeProgram(*program, slotBindings); + + auto locations = std::make_shared(); + locations->texcoordMatrices = program->getUniforms().findLocation("texcoordMatrices"); + locations->emissiveParams = program->getUniforms().findLocation("emissiveParams"); + locations->normalFittingMapUnit = program->getTextures().findLocation("normalFittingMap"); + locations->diffuseTextureUnit = program->getTextures().findLocation("diffuseMap"); + locations->normalTextureUnit = program->getTextures().findLocation("normalMap"); + locations->specularTextureUnit = program->getTextures().findLocation("specularMap"); + locations->emissiveTextureUnit = program->getTextures().findLocation("emissiveMap"); + locations->skinClusterBufferUnit = program->getBuffers().findLocation("skinClusterBuffer"); + 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, Shape::Pipeline(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, Shape::Pipeline(wireframePipeline, locations))); + } +} diff --git a/libraries/render/src/render/Shape.h b/libraries/render/src/render/Shape.h new file mode 100644 index 0000000000..cad4475da4 --- /dev/null +++ b/libraries/render/src/render/Shape.h @@ -0,0 +1,169 @@ +// +// Shape.h +// render/src/render +// +// Created by Zach Pomerantz on 12/31/15. +// 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_Shape_h +#define hifi_render_Shape_h + +#include +#include + +namespace render { + +class ShapeKey { +public: + enum FlagBit { + TRANSLUCENT = 0, + LIGHTMAP, + TANGENTS, + SPECULAR, + EMISSIVE, + SKINNED, + STEREO, + DEPTH_ONLY, + SHADOW, + WIREFRAME, + + NUM_FLAGS, // Not a valid flag + }; + using Flags = std::bitset; + + 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 } {} + + ShapeKey build() const { return ShapeKey(_flags); } + + Builder& withTranslucent() { _flags.set(TRANSLUCENT); return (*this); } + Builder& withLightmap() { _flags.set(LIGHTMAP); return (*this); } + Builder& withTangents() { _flags.set(TANGENTS); return (*this); } + Builder& withSpecular() { _flags.set(SPECULAR); return (*this); } + Builder& withEmissive() { _flags.set(EMISSIVE); return (*this); } + 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); } + }; + ShapeKey(const Builder& builder) : ShapeKey(builder._flags) {} + + bool hasLightmap() const { return _flags[LIGHTMAP]; } + bool hasTangents() const { return _flags[TANGENTS]; } + bool hasSpecular() const { return _flags[SPECULAR]; } + bool hasEmissive() const { return _flags[EMISSIVE]; } + bool isTranslucent() const { return _flags[TRANSLUCENT]; } + 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]; } + + // Hasher for use in unordered_maps + class Hash { + public: + size_t operator() (const ShapeKey& key) { + return std::hash()(key._flags); + } + }; + + // Comparator for use in unordered_maps + class KeyEqual { + public: + bool operator()(const ShapeKey& lhs, const ShapeKey& rhs) const { return lhs._flags == rhs._flags; } + }; +}; + +inline QDebug operator<<(QDebug debug, const ShapeKey& renderKey) { + debug << "[ShapeKey:" + << "hasLightmap:" << renderKey.hasLightmap() + << "hasTangents:" << renderKey.hasTangents() + << "hasSpecular:" << renderKey.hasSpecular() + << "hasEmissive:" << renderKey.hasEmissive() + << "isTranslucent:" << renderKey.isTranslucent() + << "isSkinned:" << renderKey.isSkinned() + << "isStereo:" << renderKey.isStereo() + << "isDepthOnly:" << renderKey.isDepthOnly() + << "isShadow:" << renderKey.isShadow() + << "isWireFrame:" << renderKey.isWireFrame() + << "]"; + return debug; +} + +// Meta-information (pipeline and locations) to render a shape +class Shape { +public: + using Key = ShapeKey; + + class Slots { + public: + static const int SKINNING_GPU = 2; + static const int MATERIAL_GPU = 3; + static const int DIFFUSE_MAP = 0; + static const int NORMAL_MAP = 1; + static const int SPECULAR_MAP = 2; + static const int LIGHTMAP_MAP = 3; + static const int LIGHT_BUFFER = 4; + static const int NORMAL_FITTING_MAP = 10; + }; + + class Locations { + public: + int texcoordMatrices; + int diffuseTextureUnit; + int normalTextureUnit; + int specularTextureUnit; + int emissiveTextureUnit; + int emissiveParams; + int normalFittingMapUnit; + int skinClusterBufferUnit; + int materialBufferUnit; + int lightBufferUnit; + }; + + // Rendering abstraction over gpu::Pipeline and map locations + class Pipeline { + public: + gpu::PipelinePointer pipeline; + std::shared_ptr locations; + + Pipeline() : Pipeline(nullptr, nullptr) {} + Pipeline(gpu::PipelinePointer pipeline, std::shared_ptr locations) : + pipeline(pipeline), locations(locations) {} + }; + + using PipelineMap = std::unordered_map; + class PipelineLib : public PipelineMap { + public: + void addPipeline(Key key, gpu::ShaderPointer& vertexShader, gpu::ShaderPointer& pixelShader); + }; + + static void addPipeline(Key key, gpu::ShaderPointer& vertexShader, gpu::ShaderPointer& pixelShader) { + _pipelineLib.addPipeline(key, vertexShader, pixelShader); + } + virtual const Pipeline& pickPipeline(RenderArgs* args, const Key& key) { + return Shape::_pickPipeline(args, key); + } + +protected: + static const Pipeline& _pickPipeline(RenderArgs* args, const Key& key); + static PipelineLib _pipelineLib; +}; + +} + +#endif // hifi_render_Shape_h \ No newline at end of file From 59a354ea8ca2d28b1e9e276319ff82025920ec83 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 1 Jan 2016 17:05:38 -0800 Subject: [PATCH 02/39] Change payload interface to return ShapeKey, not MaterialKey --- .../render-utils/src/MeshPartPayload.cpp | 237 ++++++++++-------- libraries/render-utils/src/MeshPartPayload.h | 6 +- libraries/render/src/render/Scene.h | 9 +- libraries/render/src/render/Shape.h | 37 +-- libraries/shared/src/RenderArgs.h | 6 + 5 files changed, 173 insertions(+), 122 deletions(-) diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 414ad9cf97..a1e512bb24 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -14,30 +14,36 @@ #include #include "DeferredLightingEffect.h" - #include "Model.h" -namespace render { - template <> const ItemKey payloadGetKey(const MeshPartPayload::Pointer& payload) { - if (payload) { - return payload->getKey(); - } - // Return opaque for lack of a better idea - return ItemKey::Builder::opaqueShape(); - } +using namespace render; - template <> const Item::Bound payloadGetBound(const MeshPartPayload::Pointer& payload) { - if (payload) { - return payload->getBound(); - } - return render::Item::Bound(); - } - template <> void payloadRender(const MeshPartPayload::Pointer& payload, RenderArgs* args) { - return payload->render(args); +namespace render { +template <> const ItemKey payloadGetKey(const MeshPartPayload::Pointer& payload) { + if (payload) { + return payload->getKey(); } + return ItemKey::Builder::opaqueShape(); // for lack of a better idea } -using namespace render; +template <> const Item::Bound payloadGetBound(const MeshPartPayload::Pointer& payload) { + if (payload) { + return payload->getBound(); + } + return Item::Bound(); +} + +template <> const ShapeKey shapeGetShapeKey(const MeshPartPayload::Pointer& payload) { + if (payload) { + return payload->getShapeKey(); + } + return ShapeKey::Builder::invalid(); +} + +template <> void payloadRender(const MeshPartPayload::Pointer& payload, RenderArgs* args) { + return payload->render(args); +} +} MeshPartPayload::MeshPartPayload(model::MeshPointer mesh, int partIndex, model::MaterialPointer material, const Transform& transform, const Transform& offsetTransform) { @@ -69,7 +75,7 @@ void MeshPartPayload::updateMaterial(model::MaterialPointer drawMaterial) { _drawMaterial = drawMaterial; } -render::ItemKey MeshPartPayload::getKey() const { +ItemKey MeshPartPayload::getKey() const { ItemKey::Builder builder; builder.withTypeShape(); @@ -83,10 +89,29 @@ render::ItemKey MeshPartPayload::getKey() const { return builder.build(); } -render::Item::Bound MeshPartPayload::getBound() const { +Item::Bound MeshPartPayload::getBound() const { return _worldBound; } +ShapeKey MeshPartPayload::getShapeKey() const { + model::MaterialKey drawMaterialKey; + if (_drawMaterial) { + drawMaterialKey = _drawMaterial->getKey(); + } + + bool isTranslucent = drawMaterialKey.isTransparent() || drawMaterialKey.isTransparentMap(); + bool hasTangents = drawMaterialKey.isNormalMap(); + bool hasSpecular = drawMaterialKey.isGlossMap(); + bool hasLightmap = drawMaterialKey.isLightmapMap(); + + ShapeKey::Builder builder; + if (isTranslucent) { builder.withTranslucent(); } + if (hasTangents) { builder.withTangents(); } + if (hasSpecular) { builder.withSpecular(); } + if (hasLightmap) { builder.withLightmap(); } + return builder.build(); +} + void MeshPartPayload::drawCall(gpu::Batch& batch) const { batch.drawIndexed(gpu::TRIANGLES, _drawPart._numIndices, _drawPart._startIndex); } @@ -195,27 +220,13 @@ void MeshPartPayload::bindTransform(gpu::Batch& batch, const ModelRender::Locati void MeshPartPayload::render(RenderArgs* args) const { PerformanceTimer perfTimer("MeshPartPayload::render"); - gpu::Batch& batch = *(args->_batch); auto mode = args->_renderMode; - model::MaterialKey drawMaterialKey; - if (_drawMaterial) { - drawMaterialKey = _drawMaterial->getKey(); - } - bool translucentMesh = drawMaterialKey.isTransparent() || drawMaterialKey.isTransparentMap(); - - bool hasTangents = drawMaterialKey.isNormalMap(); - bool hasSpecular = drawMaterialKey.isGlossMap(); - bool hasLightmap = drawMaterialKey.isLightmapMap(); - bool isSkinned = false; - bool wireframe = false; - if (wireframe) { - translucentMesh = hasTangents = hasSpecular = hasLightmap = isSkinned = false; - } + ShapeKey key = getShapeKey(); ModelRender::Locations* locations = nullptr; - ModelRender::pickPrograms(batch, mode, translucentMesh, hasLightmap, hasTangents, hasSpecular, isSkinned, wireframe, + ModelRender::pickPrograms(batch, mode, key.isTranslucent(), key.hasLightmap(), key.hasTangents(), key.hasSpecular(), key.isSkinned(), key.isWireFrame(), args, locations); @@ -230,7 +241,7 @@ void MeshPartPayload::render(RenderArgs* args) const { // TODO: We should be able to do that just in the renderTransparentJob - if (translucentMesh && locations->lightBufferUnit >= 0) { + if (key.isTranslucent() && locations->lightBufferUnit >= 0) { PerformanceTimer perfTimer("DLE->setupTransparent()"); DependencyManager::get()->setupTransparent(args, locations->lightBufferUnit); @@ -251,29 +262,32 @@ void MeshPartPayload::render(RenderArgs* args) const { } } - - namespace render { - template <> const ItemKey payloadGetKey(const ModelMeshPartPayload::Pointer& payload) { - if (payload) { - return payload->getKey(); - } - // Return opaque for lack of a better idea - return ItemKey::Builder::opaqueShape(); - } - - template <> const Item::Bound payloadGetBound(const ModelMeshPartPayload::Pointer& payload) { - if (payload) { - return payload->getBound(); - } - return render::Item::Bound(); - } - template <> void payloadRender(const ModelMeshPartPayload::Pointer& payload, RenderArgs* args) { - return payload->render(args); +template <> const ItemKey payloadGetKey(const ModelMeshPartPayload::Pointer& payload) { + if (payload) { + return payload->getKey(); } + return ItemKey::Builder::opaqueShape(); // for lack of a better idea } -using namespace render; +template <> const Item::Bound payloadGetBound(const ModelMeshPartPayload::Pointer& payload) { + if (payload) { + return payload->getBound(); + } + return Item::Bound(); +} + +template <> const ShapeKey shapeGetShapeKey(const ModelMeshPartPayload::Pointer& payload) { + if (payload) { + return payload->getShapeKey(); + } + return ShapeKey::Builder::invalid(); +} + +template <> void payloadRender(const ModelMeshPartPayload::Pointer& payload, RenderArgs* args) { + return payload->render(args); +} +} ModelMeshPartPayload::ModelMeshPartPayload(Model* model, int _meshIndex, int partIndex, int shapeIndex, const Transform& transform, const Transform& offsetTransform) : _model(model), @@ -310,7 +324,7 @@ void ModelMeshPartPayload::notifyLocationChanged() { _model->_needsUpdateClusterMatrices = true; } -render::ItemKey ModelMeshPartPayload::getKey() const { +ItemKey ModelMeshPartPayload::getKey() const { ItemKey::Builder builder; builder.withTypeShape(); @@ -332,12 +346,70 @@ render::ItemKey ModelMeshPartPayload::getKey() const { return builder.build(); } -render::Item::Bound ModelMeshPartPayload::getBound() const { +Item::Bound ModelMeshPartPayload::getBound() const { // NOTE: we can't cache this bounds because we need to handle the case of a moving // entity or mesh part. return _model->getPartBounds(_meshIndex, _partIndex, _transform.getTranslation(), _transform.getRotation()); } +ShapeKey ModelMeshPartPayload::getShapeKey() const { + const FBXGeometry& geometry = _model->_geometry->getFBXGeometry(); + const std::vector>& networkMeshes = _model->_geometry->getMeshes(); + + // guard against partially loaded meshes + if (_meshIndex >= (int)networkMeshes.size() || _meshIndex >= (int)geometry.meshes.size() || _meshIndex >= (int)_model->_meshStates.size()) { + return ShapeKey::Builder::invalid(); + } + + // Back to model to update the cluster matrices right now + _model->updateClusterMatrices(_transform.getTranslation(), _transform.getRotation()); + + const FBXMesh& mesh = geometry.meshes.at(_meshIndex); + + // if our index is ever out of range for either meshes or networkMeshes, then skip it, and set our _meshGroupsKnown + // to false to rebuild out mesh groups. + if (_meshIndex < 0 || _meshIndex >= (int)networkMeshes.size() || _meshIndex > geometry.meshes.size()) { + _model->_meshGroupsKnown = false; // regenerate these lists next time around. + _model->_readyWhenAdded = false; // in case any of our users are using scenes + _model->invalidCalculatedMeshBoxes(); // if we have to reload, we need to assume our mesh boxes are all invalid + return ShapeKey::Builder::invalid(); + } + + + int vertexCount = mesh.vertices.size(); + if (vertexCount == 0) { + // sanity check + return ShapeKey::Builder::invalid(); + } + + + model::MaterialKey drawMaterialKey; + if (_drawMaterial) { + drawMaterialKey = _drawMaterial->getKey(); + } + + bool isTranslucent = drawMaterialKey.isTransparent() || drawMaterialKey.isTransparentMap(); + bool hasTangents = drawMaterialKey.isNormalMap() && !mesh.tangents.isEmpty(); + bool hasSpecular = drawMaterialKey.isGlossMap(); + bool hasLightmap = drawMaterialKey.isLightmapMap(); + + bool isSkinned = _isSkinned; + bool wireframe = _model->isWireframe(); + + if (wireframe) { + isTranslucent = hasTangents = hasSpecular = hasLightmap = isSkinned = false; + } + + ShapeKey::Builder builder; + if (isTranslucent) { builder.withTranslucent(); } + if (hasTangents) { builder.withTangents(); } + if (hasSpecular) { builder.withSpecular(); } + if (hasLightmap) { builder.withLightmap(); } + if (isSkinned) { builder.withSkinned(); } + if (wireframe) { builder.withWireframe(); } + return builder.build(); +} + void ModelMeshPartPayload::bindMesh(gpu::Batch& batch) const { if (!_isBlendShaped) { batch.setIndexBuffer(gpu::UINT32, (_drawMesh->getIndexBuffer()._buffer), 0); @@ -387,6 +459,7 @@ void ModelMeshPartPayload::bindTransform(gpu::Batch& batch, const ModelRender::L void ModelMeshPartPayload::render(RenderArgs* args) const { PerformanceTimer perfTimer("ModelMeshPartPayload::render"); + if (!_model->_readyWhenAdded || !_model->_isVisible) { return; // bail asap } @@ -394,47 +467,11 @@ void ModelMeshPartPayload::render(RenderArgs* args) const { gpu::Batch& batch = *(args->_batch); auto mode = args->_renderMode; - const FBXGeometry& geometry = _model->_geometry->getFBXGeometry(); - const std::vector>& networkMeshes = _model->_geometry->getMeshes(); - - // guard against partially loaded meshes - if (_meshIndex >= (int)networkMeshes.size() || _meshIndex >= (int)geometry.meshes.size() || _meshIndex >= (int)_model->_meshStates.size() ) { + ShapeKey key = getShapeKey(); + if (!key.isValid()) { return; } - - // Back to model to update the cluster matrices right now - _model->updateClusterMatrices(_transform.getTranslation(), _transform.getRotation()); - - const FBXMesh& mesh = geometry.meshes.at(_meshIndex); - - // if our index is ever out of range for either meshes or networkMeshes, then skip it, and set our _meshGroupsKnown - // to false to rebuild out mesh groups. - if (_meshIndex < 0 || _meshIndex >= (int)networkMeshes.size() || _meshIndex > geometry.meshes.size()) { - _model->_meshGroupsKnown = false; // regenerate these lists next time around. - _model->_readyWhenAdded = false; // in case any of our users are using scenes - _model->invalidCalculatedMeshBoxes(); // if we have to reload, we need to assume our mesh boxes are all invalid - return; // FIXME! - } - - - int vertexCount = mesh.vertices.size(); - if (vertexCount == 0) { - // sanity check - return; // FIXME! - } - model::MaterialKey drawMaterialKey; - if (_drawMaterial) { - drawMaterialKey = _drawMaterial->getKey(); - } - bool translucentMesh = drawMaterialKey.isTransparent() || drawMaterialKey.isTransparentMap(); - - bool hasTangents = drawMaterialKey.isNormalMap() && !mesh.tangents.isEmpty(); - bool hasSpecular = drawMaterialKey.isGlossMap(); - bool hasLightmap = drawMaterialKey.isLightmapMap(); - bool isSkinned = _isSkinned; - bool wireframe = _model->isWireframe(); - // render the part bounding box #ifdef DEBUG_BOUNDING_PARTS { @@ -458,12 +495,8 @@ void ModelMeshPartPayload::render(RenderArgs* args) const { } #endif //def DEBUG_BOUNDING_PARTS - if (wireframe) { - translucentMesh = hasTangents = hasSpecular = hasLightmap = isSkinned = false; - } - ModelRender::Locations* locations = nullptr; - ModelRender::pickPrograms(batch, mode, translucentMesh, hasLightmap, hasTangents, hasSpecular, isSkinned, wireframe, + ModelRender::pickPrograms(batch, mode, key.isTranslucent(), key.hasLightmap(), key.hasTangents(), key.hasSpecular(), key.isSkinned(), key.isWireFrame(), args, locations); if (!locations) { // the pipeline could not be found @@ -481,7 +514,7 @@ void ModelMeshPartPayload::render(RenderArgs* args) const { // TODO: We should be able to do that just in the renderTransparentJob - if (translucentMesh && locations->lightBufferUnit >= 0) { + if (key.isTranslucent() && locations->lightBufferUnit >= 0) { PerformanceTimer perfTimer("DLE->setupTransparent()"); DependencyManager::get()->setupTransparent(args, locations->lightBufferUnit); diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index e03d1c8a68..27312eb064 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -40,6 +40,7 @@ public: // Render Item interface virtual render::ItemKey getKey() const; virtual render::Item::Bound getBound() const; + virtual render::ShapeKey getShapeKey() const; // shape interface virtual void render(RenderArgs* args) const; // ModelMeshPartPayload functions to perform render @@ -67,10 +68,10 @@ public: namespace render { template <> const ItemKey payloadGetKey(const MeshPartPayload::Pointer& payload); template <> const Item::Bound payloadGetBound(const MeshPartPayload::Pointer& payload); + template <> const ShapeKey shapeGetShapeKey(const MeshPartPayload::Pointer& payload); template <> void payloadRender(const MeshPartPayload::Pointer& payload, RenderArgs* args); } - class ModelMeshPartPayload : public MeshPartPayload { public: ModelMeshPartPayload(Model* model, int meshIndex, int partIndex, int shapeIndex, const Transform& transform, const Transform& offsetTransform); @@ -83,8 +84,9 @@ public: // Render Item interface render::ItemKey getKey() const override; render::Item::Bound getBound() const override; + render::ShapeKey getShapeKey() const override; // shape interface void render(RenderArgs* args) const override; - + // ModelMeshPartPayload functions to perform render void bindMesh(gpu::Batch& batch) const override; void bindTransform(gpu::Batch& batch, const ModelRender::Locations* locations) const override; diff --git a/libraries/render/src/render/Scene.h b/libraries/render/src/render/Scene.h index 1976801c96..e71f088538 100644 --- a/libraries/render/src/render/Scene.h +++ b/libraries/render/src/render/Scene.h @@ -25,6 +25,7 @@ #include #include "model/Material.h" +#include "Shape.h" namespace render { @@ -264,7 +265,7 @@ public: virtual void render(RenderArgs* args) = 0; - virtual const model::MaterialKey getMaterialKey() const = 0; + virtual const ShapeKey getShapeKey() const = 0; ~PayloadInterface() {} @@ -304,7 +305,7 @@ public: void render(RenderArgs* args) { _payload->render(args); } // Shape Type Interface - const model::MaterialKey getMaterialKey() const { return _payload->getMaterialKey(); } + const ShapeKey getShapeKey() const { return _payload->getShapeKey(); } // Access the status const StatusPointer& getStatus() const { return _payload->getStatus(); } @@ -346,7 +347,7 @@ template int payloadGetLayer(const std::shared_ptr& payloadData) { template void payloadRender(const std::shared_ptr& payloadData, RenderArgs* args) { } // Shape type interface -template const model::MaterialKey shapeGetMaterialKey(const std::shared_ptr& payloadData) { return model::MaterialKey(); } +template const ShapeKey shapeGetShapeKey(const std::shared_ptr& payloadData) { return ShapeKey::Builder::invalid(); } template class Payload : public Item::PayloadInterface { public: @@ -364,7 +365,7 @@ public: virtual void render(RenderArgs* args) { payloadRender(_data, args); } // Shape Type interface - virtual const model::MaterialKey getMaterialKey() const { return shapeGetMaterialKey(_data); } + virtual const ShapeKey getShapeKey() const { return shapeGetShapeKey(_data); } protected: DataPointer _data; diff --git a/libraries/render/src/render/Shape.h b/libraries/render/src/render/Shape.h index cad4475da4..a4ae500bfc 100644 --- a/libraries/render/src/render/Shape.h +++ b/libraries/render/src/render/Shape.h @@ -31,6 +31,8 @@ public: SHADOW, WIREFRAME, + INVALID, + NUM_FLAGS, // Not a valid flag }; using Flags = std::bitset; @@ -59,6 +61,9 @@ public: Builder& withDepthOnly() { _flags.set(DEPTH_ONLY); return (*this); } Builder& withShadow() { _flags.set(SHADOW); return (*this); } Builder& withWireframe() { _flags.set(WIREFRAME); return (*this); } + Builder& invalidate() { _flags.set(INVALID); return (*this); } + + static const ShapeKey& invalid() { return Builder().invalidate(); } }; ShapeKey(const Builder& builder) : ShapeKey(builder._flags) {} @@ -72,6 +77,7 @@ public: bool isDepthOnly() const { return _flags[DEPTH_ONLY]; } bool isShadow() const { return _flags[SHADOW]; } bool isWireFrame() const { return _flags[WIREFRAME]; } + bool isValid() const { return !_flags[INVALID]; } // Hasher for use in unordered_maps class Hash { @@ -104,11 +110,9 @@ inline QDebug operator<<(QDebug debug, const ShapeKey& renderKey) { return debug; } -// Meta-information (pipeline and locations) to render a shape -class Shape { +// Rendering abstraction over gpu::Pipeline and map locations +class ShapePipeline { public: - using Key = ShapeKey; - class Slots { public: static const int SKINNING_GPU = 2; @@ -135,16 +139,21 @@ public: int lightBufferUnit; }; - // Rendering abstraction over gpu::Pipeline and map locations - class Pipeline { - public: - gpu::PipelinePointer pipeline; - std::shared_ptr locations; + gpu::PipelinePointer pipeline; + std::shared_ptr locations; - Pipeline() : Pipeline(nullptr, nullptr) {} - Pipeline(gpu::PipelinePointer pipeline, std::shared_ptr locations) : - pipeline(pipeline), locations(locations) {} - }; + ShapePipeline() : ShapePipeline(nullptr, nullptr) {} + ShapePipeline(gpu::PipelinePointer pipeline, std::shared_ptr locations) : + pipeline(pipeline), locations(locations) {} +}; + +// Meta-information (pipeline and locations) to render a shape +class Shape { +public: + using Key = ShapeKey; + using Pipeline = ShapePipeline; + using Slots = ShapePipeline::Slots; + using Locations = ShapePipeline::Locations; using PipelineMap = std::unordered_map; class PipelineLib : public PipelineMap { @@ -166,4 +175,4 @@ protected: } -#endif // hifi_render_Shape_h \ No newline at end of file +#endif // hifi_render_Shape_h diff --git a/libraries/shared/src/RenderArgs.h b/libraries/shared/src/RenderArgs.h index 640ccdcb1f..789033b826 100644 --- a/libraries/shared/src/RenderArgs.h +++ b/libraries/shared/src/RenderArgs.h @@ -20,6 +20,7 @@ class AABox; class OctreeRenderer; class ViewFrustum; + namespace gpu { class Batch; class Context; @@ -27,6 +28,10 @@ class Texture; class Framebuffer; } +namespace render { +class ShapePipeline; +} + class RenderDetails { public: enum Type { @@ -103,6 +108,7 @@ public: std::shared_ptr _context = nullptr; std::shared_ptr _blitFramebuffer = nullptr; + std::shared_ptr _pipeline = nullptr; OctreeRenderer* _renderer = nullptr; ViewFrustum* _viewFrustum = nullptr; glm::ivec4 _viewport{ 0, 0, 1, 1 }; From 1a3a9be605d497fae364ecd5ca1299a5f75f35d5 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 1 Jan 2016 17:53:58 -0800 Subject: [PATCH 03/39] Use PipelinePointer for rendering Shape --- libraries/render/src/render/Scene.h | 3 +++ libraries/render/src/render/Shape.cpp | 8 ++++---- libraries/render/src/render/Shape.h | 5 +++-- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/libraries/render/src/render/Scene.h b/libraries/render/src/render/Scene.h index e71f088538..1d8744c1a7 100644 --- a/libraries/render/src/render/Scene.h +++ b/libraries/render/src/render/Scene.h @@ -83,6 +83,9 @@ public: }; ItemKey(const Builder& builder) : ItemKey(builder._flags) {} + bool isShape() const { return _flags[TYPE_SHAPE]; } + bool isLight() const { return _flags[TYPE_LIGHT]; } + bool isOpaque() const { return !_flags[TRANSLUCENT]; } bool isTransparent() const { return _flags[TRANSLUCENT]; } diff --git a/libraries/render/src/render/Shape.cpp b/libraries/render/src/render/Shape.cpp index cbff84d068..79cb07ddf1 100644 --- a/libraries/render/src/render/Shape.cpp +++ b/libraries/render/src/render/Shape.cpp @@ -17,7 +17,7 @@ using namespace render; Shape::PipelineLib _pipelineLip; -const Shape::Pipeline& Shape::_pickPipeline(RenderArgs* args, const Key& key) { +const Shape::PipelinePointer& Shape::_pickPipeline(RenderArgs* args, const Key& key) { assert(!_pipelineLib.empty()); assert(args); assert(args->_batch); @@ -27,14 +27,14 @@ const Shape::Pipeline& Shape::_pickPipeline(RenderArgs* args, const Key& key) { const auto& pipelineIterator = _pipelineLib.find(key); if (pipelineIterator == _pipelineLib.end()) { qDebug() << "Couldn't find a pipeline from ShapeKey ?" << key; - return Shape::Pipeline(); // uninitialized _pipeline == nullptr + return std::make_shared(); } - const auto& shapePipeline = pipelineIterator->second; + Shape::PipelinePointer shapePipeline(&(pipelineIterator->second)); auto& batch = args->_batch; // Setup the one pipeline (to rule them all) - batch->setPipeline(shapePipeline.pipeline); + batch->setPipeline(shapePipeline->pipeline); return shapePipeline; } diff --git a/libraries/render/src/render/Shape.h b/libraries/render/src/render/Shape.h index a4ae500bfc..590075ccca 100644 --- a/libraries/render/src/render/Shape.h +++ b/libraries/render/src/render/Shape.h @@ -152,6 +152,7 @@ class Shape { public: using Key = ShapeKey; using Pipeline = ShapePipeline; + using PipelinePointer = std::shared_ptr; using Slots = ShapePipeline::Slots; using Locations = ShapePipeline::Locations; @@ -164,12 +165,12 @@ public: static void addPipeline(Key key, gpu::ShaderPointer& vertexShader, gpu::ShaderPointer& pixelShader) { _pipelineLib.addPipeline(key, vertexShader, pixelShader); } - virtual const Pipeline& pickPipeline(RenderArgs* args, const Key& key) { + virtual const PipelinePointer& pickPipeline(RenderArgs* args, const Key& key) { return Shape::_pickPipeline(args, key); } protected: - static const Pipeline& _pickPipeline(RenderArgs* args, const Key& key); + static const PipelinePointer& _pickPipeline(RenderArgs* args, const Key& key); static PipelineLib _pipelineLib; }; From 74c49300342f16316d3545c1dc6311e583c06392 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 1 Jan 2016 17:57:37 -0800 Subject: [PATCH 04/39] Remove DrawBackround task --- libraries/render/src/render/DrawTask.cpp | 34 ------------------------ libraries/render/src/render/DrawTask.h | 9 ------- 2 files changed, 43 deletions(-) diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index 44ba57143f..e6a3e024ad 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -264,40 +264,6 @@ void DrawLight::run(const SceneContextPointer& sceneContext, const RenderContext args->_batch = nullptr; } -void DrawBackground::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - assert(renderContext->getArgs()); - assert(renderContext->getArgs()->_viewFrustum); - - // render backgrounds - auto& scene = sceneContext->_scene; - auto& items = scene->getMasterBucket().at(ItemFilter::Builder::background()); - - - ItemIDsBounds inItems; - inItems.reserve(items.size()); - for (auto id : items) { - inItems.emplace_back(id); - } - RenderArgs* args = renderContext->getArgs(); - doInBatch(args->_context, [=](gpu::Batch& batch) { - args->_batch = &batch; - batch.enableSkybox(true); - batch.setViewportTransform(args->_viewport); - batch.setStateScissorRect(args->_viewport); - - glm::mat4 projMat; - Transform viewMat; - args->_viewFrustum->evalProjectionMatrix(projMat); - args->_viewFrustum->evalViewTransform(viewMat); - - batch.setProjectionTransform(projMat); - batch.setViewTransform(viewMat); - - renderItems(sceneContext, renderContext, inItems); - }); - args->_batch = nullptr; -} - void ItemMaterialBucketMap::insert(const ItemID& id, const model::MaterialKey& key) { // Insert the itemID in every bucket where it filters true for (auto& bucket : (*this)) { diff --git a/libraries/render/src/render/DrawTask.h b/libraries/render/src/render/DrawTask.h index ab102e32a7..b06223035d 100755 --- a/libraries/render/src/render/DrawTask.h +++ b/libraries/render/src/render/DrawTask.h @@ -275,15 +275,6 @@ public: typedef Job::Model JobModel; }; -class DrawBackground { -public: - void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext); - - - typedef Job::Model JobModel; -}; - - class DrawSceneTask : public Task { public: From e96b1fa881ba116bf7f17666bd13bcb8dfe80e1f Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Mon, 4 Jan 2016 10:48:33 -0800 Subject: [PATCH 05/39] Return copies of local vars in Shape --- libraries/render/src/render/Shape.cpp | 2 +- libraries/render/src/render/Shape.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/render/src/render/Shape.cpp b/libraries/render/src/render/Shape.cpp index 79cb07ddf1..a6b8e09126 100644 --- a/libraries/render/src/render/Shape.cpp +++ b/libraries/render/src/render/Shape.cpp @@ -17,7 +17,7 @@ using namespace render; Shape::PipelineLib _pipelineLip; -const Shape::PipelinePointer& Shape::_pickPipeline(RenderArgs* args, const Key& key) { +const Shape::PipelinePointer Shape::_pickPipeline(RenderArgs* args, const Key& key) { assert(!_pipelineLib.empty()); assert(args); assert(args->_batch); diff --git a/libraries/render/src/render/Shape.h b/libraries/render/src/render/Shape.h index 590075ccca..f8b2f77b5a 100644 --- a/libraries/render/src/render/Shape.h +++ b/libraries/render/src/render/Shape.h @@ -63,7 +63,7 @@ public: Builder& withWireframe() { _flags.set(WIREFRAME); return (*this); } Builder& invalidate() { _flags.set(INVALID); return (*this); } - static const ShapeKey& invalid() { return Builder().invalidate(); } + static const ShapeKey invalid() { return Builder().invalidate(); } }; ShapeKey(const Builder& builder) : ShapeKey(builder._flags) {} @@ -165,12 +165,12 @@ public: static void addPipeline(Key key, gpu::ShaderPointer& vertexShader, gpu::ShaderPointer& pixelShader) { _pipelineLib.addPipeline(key, vertexShader, pixelShader); } - virtual const PipelinePointer& pickPipeline(RenderArgs* args, const Key& key) { + virtual const PipelinePointer pickPipeline(RenderArgs* args, const Key& key) { return Shape::_pickPipeline(args, key); } protected: - static const PipelinePointer& _pickPipeline(RenderArgs* args, const Key& key); + static const PipelinePointer _pickPipeline(RenderArgs* args, const Key& key); static PipelineLib _pipelineLib; }; From c0800abdc5180e03fd4f035c48d98ad2d3978757 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Mon, 4 Jan 2016 12:23:06 -0800 Subject: [PATCH 06/39] Add virtual ~Shape --- libraries/render/src/render/Shape.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries/render/src/render/Shape.h b/libraries/render/src/render/Shape.h index f8b2f77b5a..c3bf06f0ee 100644 --- a/libraries/render/src/render/Shape.h +++ b/libraries/render/src/render/Shape.h @@ -169,6 +169,8 @@ public: return Shape::_pickPipeline(args, key); } + virtual ~Shape() {}; + protected: static const PipelinePointer _pickPipeline(RenderArgs* args, const Key& key); static PipelineLib _pipelineLib; From c725fd1520d0a0c93e8980e309adc2d030740317 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Mon, 4 Jan 2016 12:33:06 -0800 Subject: [PATCH 07/39] Add specialized ShapeRender for deferred --- libraries/render-utils/src/ShapeRender.cpp | 195 +++++++++++++++++++++ libraries/render-utils/src/ShapeRender.h | 28 +++ 2 files changed, 223 insertions(+) create mode 100644 libraries/render-utils/src/ShapeRender.cpp create mode 100644 libraries/render-utils/src/ShapeRender.h diff --git a/libraries/render-utils/src/ShapeRender.cpp b/libraries/render-utils/src/ShapeRender.cpp new file mode 100644 index 0000000000..31db3b010e --- /dev/null +++ b/libraries/render-utils/src/ShapeRender.cpp @@ -0,0 +1,195 @@ +// +// ModelRender.cpp +// interface/src/renderer +// +// Created by Sam Gateau on 10/3/15. +// 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 "ShapeRender.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" + +void ShapeRender::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( + RenderKey(0), + modelVertex, modelPixel); + + _pipelineLib.addPipeline( + RenderKey(RenderKey::HAS_TANGENTS), + modelNormalMapVertex, modelNormalMapPixel); + + _pipelineLib.addPipeline( + RenderKey(RenderKey::HAS_SPECULAR), + modelVertex, modelSpecularMapPixel); + + _pipelineLib.addPipeline( + RenderKey(RenderKey::HAS_TANGENTS | RenderKey::HAS_SPECULAR), + modelNormalMapVertex, modelNormalSpecularMapPixel); + + + _pipelineLib.addPipeline( + RenderKey(RenderKey::IS_TRANSLUCENT), + modelVertex, modelTranslucentPixel); + // FIXME Ignore lightmap for translucents meshpart + _pipelineLib.addPipeline( + RenderKey(RenderKey::IS_TRANSLUCENT | RenderKey::HAS_LIGHTMAP), + modelVertex, modelTranslucentPixel); + + _pipelineLib.addPipeline( + RenderKey(RenderKey::HAS_TANGENTS | RenderKey::IS_TRANSLUCENT), + modelNormalMapVertex, modelTranslucentPixel); + + _pipelineLib.addPipeline( + RenderKey(RenderKey::HAS_SPECULAR | RenderKey::IS_TRANSLUCENT), + modelVertex, modelTranslucentPixel); + + _pipelineLib.addPipeline( + RenderKey(RenderKey::HAS_TANGENTS | RenderKey::HAS_SPECULAR | RenderKey::IS_TRANSLUCENT), + modelNormalMapVertex, modelTranslucentPixel); + + + _pipelineLib.addPipeline( + RenderKey(RenderKey::HAS_LIGHTMAP), + modelLightmapVertex, modelLightmapPixel); + _pipelineLib.addPipeline( + RenderKey(RenderKey::HAS_LIGHTMAP | RenderKey::HAS_TANGENTS), + modelLightmapNormalMapVertex, modelLightmapNormalMapPixel); + + _pipelineLib.addPipeline( + RenderKey(RenderKey::HAS_LIGHTMAP | RenderKey::HAS_SPECULAR), + modelLightmapVertex, modelLightmapSpecularMapPixel); + + _pipelineLib.addPipeline( + RenderKey(RenderKey::HAS_LIGHTMAP | RenderKey::HAS_TANGENTS | RenderKey::HAS_SPECULAR), + modelLightmapNormalMapVertex, modelLightmapNormalSpecularMapPixel); + + + _pipelineLib.addPipeline( + RenderKey(RenderKey::IS_SKINNED), + skinModelVertex, modelPixel); + + _pipelineLib.addPipeline( + RenderKey(RenderKey::IS_SKINNED | RenderKey::HAS_TANGENTS), + skinModelNormalMapVertex, modelNormalMapPixel); + + _pipelineLib.addPipeline( + RenderKey(RenderKey::IS_SKINNED | RenderKey::HAS_SPECULAR), + skinModelVertex, modelSpecularMapPixel); + + _pipelineLib.addPipeline( + RenderKey(RenderKey::IS_SKINNED | RenderKey::HAS_TANGENTS | RenderKey::HAS_SPECULAR), + skinModelNormalMapVertex, modelNormalSpecularMapPixel); + + + _pipelineLib.addPipeline( + RenderKey(RenderKey::IS_SKINNED | RenderKey::IS_TRANSLUCENT), + skinModelVertex, modelTranslucentPixel); + + _pipelineLib.addPipeline( + RenderKey(RenderKey::IS_SKINNED | RenderKey::HAS_TANGENTS | RenderKey::IS_TRANSLUCENT), + skinModelNormalMapVertex, modelTranslucentPixel); + + _pipelineLib.addPipeline( + RenderKey(RenderKey::IS_SKINNED | RenderKey::HAS_SPECULAR | RenderKey::IS_TRANSLUCENT), + skinModelVertex, modelTranslucentPixel); + + _pipelineLib.addPipeline( + RenderKey(RenderKey::IS_SKINNED | RenderKey::HAS_TANGENTS | RenderKey::HAS_SPECULAR | RenderKey::IS_TRANSLUCENT), + skinModelNormalMapVertex, modelTranslucentPixel); + + + _pipelineLib.addPipeline( + RenderKey(RenderKey::IS_DEPTH_ONLY | RenderKey::IS_SHADOW), + modelShadowVertex, modelShadowPixel); + + + _pipelineLib.addPipeline( + RenderKey(RenderKey::IS_SKINNED | RenderKey::IS_DEPTH_ONLY | RenderKey::IS_SHADOW), + skinModelShadowVertex, modelShadowPixel); +} + +const render::PipelinePointer ShapeRender::pickPipeline(RenderArgs* args, Key& key) { + PerformanceTimer perfTimer("ShapeRender::pickPipeline"); + // TODO: There is probably a cleaner way to init the pipeline that in a derived class + if (_pipelineLib.empty()) { + initPipeline(); + } + + auto pipeline = _pickPipeline(args, key); + if (!pipeline) { + return pipeline; + } + + if ((pipeline->locations->normalFittingMapUnit > -1)) { + batch.setResourceTexture(pipeline->locations->normalFittingMapUnit, + DependencyManager::get()->getNormalFittingTexture()); + } +} + +model::MaterialPointer ShapeRender::_collisionHullMaterial; + +model::MaterialPointer ShapeRender::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/ShapeRender.h b/libraries/render-utils/src/ShapeRender.h new file mode 100644 index 0000000000..047f300dc0 --- /dev/null +++ b/libraries/render-utils/src/ShapeRender.h @@ -0,0 +1,28 @@ +// +// ModelRender.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_Shape_h +#define hifi_render_utils_Shape_h + +#include + +class ShapeRender : public render::Shape { + static model::MaterialPointer _collisionHullMaterial; + +public: + static void initPipeline(); + const render::PipelinePointer pickPipeline(RenderArgs* args, Key& key) override; + + static model::MaterialPointer getCollisionHullMaterial(); +}; + +#endif // hifi_render_utils_Shape_h + From 7913ca7f3b45812d0ea8ddbbc8e0d23b89921775 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Mon, 4 Jan 2016 12:33:38 -0800 Subject: [PATCH 08/39] Render using ShapeRender, pickPipeline in renderItems --- .../render-utils/src/MeshPartPayload.cpp | 51 ++-- libraries/render-utils/src/MeshPartPayload.h | 8 +- libraries/render-utils/src/ModelRender.cpp | 284 ------------------ libraries/render-utils/src/ModelRender.h | 157 ---------- .../render-utils/src/RenderDeferredTask.cpp | 9 +- .../render-utils/src/RenderDeferredTask.h | 7 +- libraries/render-utils/src/ShapeRender.cpp | 6 +- libraries/render-utils/src/ShapeRender.h | 2 +- libraries/render/src/render/DrawTask.cpp | 22 +- libraries/render/src/render/DrawTask.h | 4 +- 10 files changed, 57 insertions(+), 493 deletions(-) delete mode 100644 libraries/render-utils/src/ModelRender.cpp delete mode 100644 libraries/render-utils/src/ModelRender.h diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index a1e512bb24..f50deb0e43 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -129,14 +129,14 @@ void MeshPartPayload::bindMesh(gpu::Batch& batch) const { } } -void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ModelRender::Locations* locations) const { +void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locations* locations) const { if (!_drawMaterial) { return; } auto textureCache = DependencyManager::get(); - batch.setUniformBuffer(ModelRender::MATERIAL_GPU_SLOT, _drawMaterial->getSchemaBuffer()); + batch.setUniformBuffer(ShapePipeline::Slots::MATERIAL_GPU, _drawMaterial->getSchemaBuffer()); auto materialKey = _drawMaterial->getKey(); auto textureMaps = _drawMaterial->getTextureMaps(); @@ -146,44 +146,44 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ModelRender::Locatio if (materialKey.isDiffuseMap()) { auto diffuseMap = textureMaps[model::MaterialKey::DIFFUSE_MAP]; if (diffuseMap && diffuseMap->isDefined()) { - batch.setResourceTexture(ModelRender::DIFFUSE_MAP_SLOT, diffuseMap->getTextureView()); + batch.setResourceTexture(ShapePipeline::Slots::DIFFUSE_MAP, diffuseMap->getTextureView()); if (!diffuseMap->getTextureTransform().isIdentity()) { diffuseMap->getTextureTransform().getMatrix(texcoordTransform[0]); } } else { - batch.setResourceTexture(ModelRender::DIFFUSE_MAP_SLOT, textureCache->getGrayTexture()); + batch.setResourceTexture(ShapePipeline::Slots::DIFFUSE_MAP, textureCache->getGrayTexture()); } } else { - batch.setResourceTexture(ModelRender::DIFFUSE_MAP_SLOT, textureCache->getWhiteTexture()); + batch.setResourceTexture(ShapePipeline::Slots::DIFFUSE_MAP, textureCache->getWhiteTexture()); } // Normal map if (materialKey.isNormalMap()) { auto normalMap = textureMaps[model::MaterialKey::NORMAL_MAP]; if (normalMap && normalMap->isDefined()) { - batch.setResourceTexture(ModelRender::NORMAL_MAP_SLOT, normalMap->getTextureView()); + batch.setResourceTexture(ShapePipeline::Slots::::NORMAL_MAP, normalMap->getTextureView()); // texcoord are assumed to be the same has diffuse } else { - batch.setResourceTexture(ModelRender::NORMAL_MAP_SLOT, textureCache->getBlueTexture()); + batch.setResourceTexture(ShapePipeline::Slots::NORMAL_MAP, textureCache->getBlueTexture()); } } else { - batch.setResourceTexture(ModelRender::NORMAL_MAP_SLOT, nullptr); + batch.setResourceTexture(ShapePipeline::Slots::NORMAL_MAP, nullptr); } // TODO: For now gloss map is used as the "specular map in the shading, we ll need to fix that if (materialKey.isGlossMap()) { auto specularMap = textureMaps[model::MaterialKey::GLOSS_MAP]; if (specularMap && specularMap->isDefined()) { - batch.setResourceTexture(ModelRender::SPECULAR_MAP_SLOT, specularMap->getTextureView()); + batch.setResourceTexture(ShapePipeline::Slots::SPECULAR_MAP, specularMap->getTextureView()); // texcoord are assumed to be the same has diffuse } else { - batch.setResourceTexture(ModelRender::SPECULAR_MAP_SLOT, textureCache->getBlackTexture()); + batch.setResourceTexture(ShapePipeline::Slots::SPECULAR_MAP, textureCache->getBlackTexture()); } } else { - batch.setResourceTexture(ModelRender::SPECULAR_MAP_SLOT, nullptr); + batch.setResourceTexture(ShapePipeline::SPECULAR_MAP, nullptr); } // TODO: For now lightmaop is piped into the emissive map unit, we need to fix that and support for real emissive too @@ -191,7 +191,7 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ModelRender::Locatio auto lightmapMap = textureMaps[model::MaterialKey::LIGHTMAP_MAP]; if (lightmapMap && lightmapMap->isDefined()) { - batch.setResourceTexture(ModelRender::LIGHTMAP_MAP_SLOT, lightmapMap->getTextureView()); + batch.setResourceTexture(ShapePipeline::LIGHTMAP_MAP, lightmapMap->getTextureView()); auto lightmapOffsetScale = lightmapMap->getLightmapOffsetScale(); batch._glUniform2f(locations->emissiveParams, lightmapOffsetScale.x, lightmapOffsetScale.y); @@ -200,10 +200,10 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ModelRender::Locatio lightmapMap->getTextureTransform().getMatrix(texcoordTransform[1]); } } else { - batch.setResourceTexture(ModelRender::LIGHTMAP_MAP_SLOT, textureCache->getGrayTexture()); + batch.setResourceTexture(ShapePipeline::LIGHTMAP_MAP, textureCache->getGrayTexture()); } } else { - batch.setResourceTexture(ModelRender::LIGHTMAP_MAP_SLOT, nullptr); + batch.setResourceTexture(ShapePipeline::LIGHTMAP_MAP, nullptr); } // Texcoord transforms ? @@ -212,7 +212,7 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ModelRender::Locatio } } -void MeshPartPayload::bindTransform(gpu::Batch& batch, const ModelRender::Locations* locations) const { +void MeshPartPayload::bindTransform(gpu::Batch& batch, const ShapePipeline::Locations* locations) const { batch.setModelTransform(_drawTransform); } @@ -225,10 +225,8 @@ void MeshPartPayload::render(RenderArgs* args) const { ShapeKey key = getShapeKey(); - ModelRender::Locations* locations = nullptr; - ModelRender::pickPrograms(batch, mode, key.isTranslucent(), key.hasLightmap(), key.hasTangents(), key.hasSpecular(), key.isSkinned(), key.isWireFrame(), - args, locations); - + auto locations = args->_pipeline->locations; + assert(locations); // Bind the model transform and the skinCLusterMatrices if needed bindTransform(batch, locations); @@ -433,16 +431,16 @@ void ModelMeshPartPayload::bindMesh(gpu::Batch& batch) const { } } -void ModelMeshPartPayload::bindTransform(gpu::Batch& batch, const ModelRender::Locations* locations) const { +void ModelMeshPartPayload::bindTransform(gpu::Batch& batch, const ShapePipeline::Locations* locations) const { // Still relying on the raw data from the model const Model::MeshState& state = _model->_meshStates.at(_meshIndex); Transform transform; if (state.clusterBuffer) { if (_model->_cauterizeBones) { - batch.setUniformBuffer(ModelRender::SKINNING_GPU_SLOT, state.cauterizedClusterBuffer); + batch.setUniformBuffer(ShapePipeline::SKINNING_GPU, state.cauterizedClusterBuffer); } else { - batch.setUniformBuffer(ModelRender::SKINNING_GPU_SLOT, state.clusterBuffer); + batch.setUniformBuffer(ShapePipeline::SKINNING_GPU, state.clusterBuffer); } } else { if (_model->_cauterizeBones) { @@ -495,13 +493,8 @@ void ModelMeshPartPayload::render(RenderArgs* args) const { } #endif //def DEBUG_BOUNDING_PARTS - ModelRender::Locations* locations = nullptr; - ModelRender::pickPrograms(batch, mode, key.isTranslucent(), key.hasLightmap(), key.hasTangents(), key.hasSpecular(), key.isSkinned(), key.isWireFrame(), - args, locations); - - if (!locations) { // the pipeline could not be found - return; - } + auto locations = args->_pipeline->locations; + assert(locations); // Bind the model transform and the skinCLusterMatrices if needed bindTransform(batch, locations); diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index 27312eb064..cb7e1fd386 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -18,7 +18,7 @@ #include -#include "ModelRender.h" +#include "ShapeRender.h" class Model; @@ -46,8 +46,8 @@ public: // ModelMeshPartPayload functions to perform render void drawCall(gpu::Batch& batch) const; virtual void bindMesh(gpu::Batch& batch) const; - virtual void bindMaterial(gpu::Batch& batch, const ModelRender::Locations* locations) const; - virtual void bindTransform(gpu::Batch& batch, const ModelRender::Locations* locations) const; + virtual void bindMaterial(gpu::Batch& batch, const render::ShapePipeline::Locations* locations) const; + virtual void bindTransform(gpu::Batch& batch, const render::ShapePipeline::Locations* locations) const; // Payload resource cached values model::MeshPointer _drawMesh; @@ -89,7 +89,7 @@ public: // ModelMeshPartPayload functions to perform render void bindMesh(gpu::Batch& batch) const override; - void bindTransform(gpu::Batch& batch, const ModelRender::Locations* locations) const override; + void bindTransform(gpu::Batch& batch, const render::ShapePipeline::Locations* locations) const override; void initCache(); diff --git a/libraries/render-utils/src/ModelRender.cpp b/libraries/render-utils/src/ModelRender.cpp deleted file mode 100644 index 312d34e41b..0000000000 --- a/libraries/render-utils/src/ModelRender.cpp +++ /dev/null @@ -1,284 +0,0 @@ -// -// ModelRender.cpp -// interface/src/renderer -// -// Created by Sam Gateau on 10/3/15. -// 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 "ModelRender.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" - -ModelRender::RenderPipelineLib ModelRender::_renderPipelineLib; - -const ModelRender::RenderPipelineLib& ModelRender::getRenderPipelineLib() { - if (_renderPipelineLib.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 renderPipelineLib - - _renderPipelineLib.addRenderPipeline( - RenderKey(0), - modelVertex, modelPixel); - - _renderPipelineLib.addRenderPipeline( - RenderKey(RenderKey::HAS_TANGENTS), - modelNormalMapVertex, modelNormalMapPixel); - - _renderPipelineLib.addRenderPipeline( - RenderKey(RenderKey::HAS_SPECULAR), - modelVertex, modelSpecularMapPixel); - - _renderPipelineLib.addRenderPipeline( - RenderKey(RenderKey::HAS_TANGENTS | RenderKey::HAS_SPECULAR), - modelNormalMapVertex, modelNormalSpecularMapPixel); - - - _renderPipelineLib.addRenderPipeline( - RenderKey(RenderKey::IS_TRANSLUCENT), - modelVertex, modelTranslucentPixel); - // FIXME Ignore lightmap for translucents meshpart - _renderPipelineLib.addRenderPipeline( - RenderKey(RenderKey::IS_TRANSLUCENT | RenderKey::HAS_LIGHTMAP), - modelVertex, modelTranslucentPixel); - - _renderPipelineLib.addRenderPipeline( - RenderKey(RenderKey::HAS_TANGENTS | RenderKey::IS_TRANSLUCENT), - modelNormalMapVertex, modelTranslucentPixel); - - _renderPipelineLib.addRenderPipeline( - RenderKey(RenderKey::HAS_SPECULAR | RenderKey::IS_TRANSLUCENT), - modelVertex, modelTranslucentPixel); - - _renderPipelineLib.addRenderPipeline( - RenderKey(RenderKey::HAS_TANGENTS | RenderKey::HAS_SPECULAR | RenderKey::IS_TRANSLUCENT), - modelNormalMapVertex, modelTranslucentPixel); - - - _renderPipelineLib.addRenderPipeline( - RenderKey(RenderKey::HAS_LIGHTMAP), - modelLightmapVertex, modelLightmapPixel); - _renderPipelineLib.addRenderPipeline( - RenderKey(RenderKey::HAS_LIGHTMAP | RenderKey::HAS_TANGENTS), - modelLightmapNormalMapVertex, modelLightmapNormalMapPixel); - - _renderPipelineLib.addRenderPipeline( - RenderKey(RenderKey::HAS_LIGHTMAP | RenderKey::HAS_SPECULAR), - modelLightmapVertex, modelLightmapSpecularMapPixel); - - _renderPipelineLib.addRenderPipeline( - RenderKey(RenderKey::HAS_LIGHTMAP | RenderKey::HAS_TANGENTS | RenderKey::HAS_SPECULAR), - modelLightmapNormalMapVertex, modelLightmapNormalSpecularMapPixel); - - - _renderPipelineLib.addRenderPipeline( - RenderKey(RenderKey::IS_SKINNED), - skinModelVertex, modelPixel); - - _renderPipelineLib.addRenderPipeline( - RenderKey(RenderKey::IS_SKINNED | RenderKey::HAS_TANGENTS), - skinModelNormalMapVertex, modelNormalMapPixel); - - _renderPipelineLib.addRenderPipeline( - RenderKey(RenderKey::IS_SKINNED | RenderKey::HAS_SPECULAR), - skinModelVertex, modelSpecularMapPixel); - - _renderPipelineLib.addRenderPipeline( - RenderKey(RenderKey::IS_SKINNED | RenderKey::HAS_TANGENTS | RenderKey::HAS_SPECULAR), - skinModelNormalMapVertex, modelNormalSpecularMapPixel); - - - _renderPipelineLib.addRenderPipeline( - RenderKey(RenderKey::IS_SKINNED | RenderKey::IS_TRANSLUCENT), - skinModelVertex, modelTranslucentPixel); - - _renderPipelineLib.addRenderPipeline( - RenderKey(RenderKey::IS_SKINNED | RenderKey::HAS_TANGENTS | RenderKey::IS_TRANSLUCENT), - skinModelNormalMapVertex, modelTranslucentPixel); - - _renderPipelineLib.addRenderPipeline( - RenderKey(RenderKey::IS_SKINNED | RenderKey::HAS_SPECULAR | RenderKey::IS_TRANSLUCENT), - skinModelVertex, modelTranslucentPixel); - - _renderPipelineLib.addRenderPipeline( - RenderKey(RenderKey::IS_SKINNED | RenderKey::HAS_TANGENTS | RenderKey::HAS_SPECULAR | RenderKey::IS_TRANSLUCENT), - skinModelNormalMapVertex, modelTranslucentPixel); - - - _renderPipelineLib.addRenderPipeline( - RenderKey(RenderKey::IS_DEPTH_ONLY | RenderKey::IS_SHADOW), - modelShadowVertex, modelShadowPixel); - - - _renderPipelineLib.addRenderPipeline( - RenderKey(RenderKey::IS_SKINNED | RenderKey::IS_DEPTH_ONLY | RenderKey::IS_SHADOW), - skinModelShadowVertex, modelShadowPixel); - } - - return _renderPipelineLib; -} - - -void ModelRender::RenderPipelineLib::addRenderPipeline(ModelRender::RenderKey key, - gpu::ShaderPointer& vertexShader, - gpu::ShaderPointer& pixelShader) { - - gpu::Shader::BindingSet slotBindings; - slotBindings.insert(gpu::Shader::Binding(std::string("skinClusterBuffer"), ModelRender::SKINNING_GPU_SLOT)); - slotBindings.insert(gpu::Shader::Binding(std::string("materialBuffer"), ModelRender::MATERIAL_GPU_SLOT)); - slotBindings.insert(gpu::Shader::Binding(std::string("diffuseMap"), ModelRender::DIFFUSE_MAP_SLOT)); - slotBindings.insert(gpu::Shader::Binding(std::string("normalMap"), ModelRender::NORMAL_MAP_SLOT)); - slotBindings.insert(gpu::Shader::Binding(std::string("specularMap"), ModelRender::SPECULAR_MAP_SLOT)); - slotBindings.insert(gpu::Shader::Binding(std::string("emissiveMap"), ModelRender::LIGHTMAP_MAP_SLOT)); - slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), ModelRender::LIGHT_BUFFER_SLOT)); - slotBindings.insert(gpu::Shader::Binding(std::string("normalFittingMap"), DeferredLightingEffect::NORMAL_FITTING_MAP_SLOT)); - - gpu::ShaderPointer program = gpu::Shader::createProgram(vertexShader, pixelShader); - gpu::Shader::makeProgram(*program, slotBindings); - - - auto locations = std::make_shared(); - initLocations(program, *locations); - - - 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 if transparent or not - state->setDepthTest(true, !key.isTranslucent(), gpu::LESS_EQUAL); - - // Blend on 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); - - // Good to go add the brand new pipeline - auto pipeline = gpu::Pipeline::create(program, state); - insert(value_type(key.getRaw(), RenderPipeline(pipeline, locations))); - - - if (!key.isWireFrame()) { - - RenderKey wireframeKey(key.getRaw() | RenderKey::IS_WIREFRAME); - auto wireframeState = std::make_shared(state->getValues()); - - wireframeState->setFillMode(gpu::State::FILL_LINE); - - // create a new RenderPipeline with the same shader side and the wireframe state - auto wireframePipeline = gpu::Pipeline::create(program, wireframeState); - insert(value_type(wireframeKey.getRaw(), RenderPipeline(wireframePipeline, locations))); - } -} - - -void ModelRender::RenderPipelineLib::initLocations(gpu::ShaderPointer& program, ModelRender::Locations& locations) { - locations.texcoordMatrices = program->getUniforms().findLocation("texcoordMatrices"); - locations.emissiveParams = program->getUniforms().findLocation("emissiveParams"); - locations.normalFittingMapUnit = program->getTextures().findLocation("normalFittingMap"); - locations.diffuseTextureUnit = program->getTextures().findLocation("diffuseMap"); - locations.normalTextureUnit = program->getTextures().findLocation("normalMap"); - locations.specularTextureUnit = program->getTextures().findLocation("specularMap"); - locations.emissiveTextureUnit = program->getTextures().findLocation("emissiveMap"); - locations.skinClusterBufferUnit = program->getBuffers().findLocation("skinClusterBuffer"); - locations.materialBufferUnit = program->getBuffers().findLocation("materialBuffer"); - locations.lightBufferUnit = program->getBuffers().findLocation("lightBuffer"); - -} - - -void ModelRender::pickPrograms(gpu::Batch& batch, RenderArgs::RenderMode mode, bool translucent, - bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, bool isWireframe, RenderArgs* args, - Locations*& locations) { - - PerformanceTimer perfTimer("Model::pickPrograms"); - getRenderPipelineLib(); - - RenderKey key(mode, translucent, hasLightmap, hasTangents, hasSpecular, isSkinned, isWireframe); - auto pipeline = _renderPipelineLib.find(key.getRaw()); - if (pipeline == _renderPipelineLib.end()) { - qDebug() << "No good, couldn't find a pipeline from the key ?" << key.getRaw(); - locations = 0; - return; - } - - gpu::ShaderPointer program = (*pipeline).second._pipeline->getProgram(); - locations = (*pipeline).second._locations.get(); - - - // Setup the One pipeline - batch.setPipeline((*pipeline).second._pipeline); - - if ((locations->normalFittingMapUnit > -1)) { - batch.setResourceTexture(locations->normalFittingMapUnit, - DependencyManager::get()->getNormalFittingTexture()); - } -} - -model::MaterialPointer ModelRender::_collisionHullMaterial; - -model::MaterialPointer ModelRender::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/ModelRender.h b/libraries/render-utils/src/ModelRender.h deleted file mode 100644 index 8331440fb0..0000000000 --- a/libraries/render-utils/src/ModelRender.h +++ /dev/null @@ -1,157 +0,0 @@ -// -// ModelRender.h -// interface/src/renderer -// -// Created by Sam Gateau on 10/3/15. -// 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_ModelRender_h -#define hifi_ModelRender_h - -#include - -#include - -class ModelRender { -public: - - static const int SKINNING_GPU_SLOT = 2; - static const int MATERIAL_GPU_SLOT = 3; - static const int DIFFUSE_MAP_SLOT = 0; - static const int NORMAL_MAP_SLOT = 1; - static const int SPECULAR_MAP_SLOT = 2; - static const int LIGHTMAP_MAP_SLOT = 3; - static const int LIGHT_BUFFER_SLOT = 4; - - class Locations { - public: - int texcoordMatrices; - int diffuseTextureUnit; - int normalTextureUnit; - int specularTextureUnit; - int emissiveTextureUnit; - int emissiveParams; - int normalFittingMapUnit; - int skinClusterBufferUnit; - int materialBufferUnit; - int lightBufferUnit; - }; - - static void pickPrograms(gpu::Batch& batch, RenderArgs::RenderMode mode, bool translucent, - bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, bool isWireframe, RenderArgs* args, - Locations*& locations); - - class RenderKey { - public: - enum FlagBit { - IS_TRANSLUCENT_FLAG = 0, - HAS_LIGHTMAP_FLAG, - HAS_TANGENTS_FLAG, - HAS_SPECULAR_FLAG, - HAS_EMISSIVE_FLAG, - IS_SKINNED_FLAG, - IS_STEREO_FLAG, - IS_DEPTH_ONLY_FLAG, - IS_SHADOW_FLAG, - IS_WIREFRAME_FLAG, - - NUM_FLAGS, - }; - - enum Flag { - IS_TRANSLUCENT = (1 << IS_TRANSLUCENT_FLAG), - HAS_LIGHTMAP = (1 << HAS_LIGHTMAP_FLAG), - HAS_TANGENTS = (1 << HAS_TANGENTS_FLAG), - HAS_SPECULAR = (1 << HAS_SPECULAR_FLAG), - HAS_EMISSIVE = (1 << HAS_EMISSIVE_FLAG), - IS_SKINNED = (1 << IS_SKINNED_FLAG), - IS_STEREO = (1 << IS_STEREO_FLAG), - IS_DEPTH_ONLY = (1 << IS_DEPTH_ONLY_FLAG), - IS_SHADOW = (1 << IS_SHADOW_FLAG), - IS_WIREFRAME = (1 << IS_WIREFRAME_FLAG), - }; - typedef unsigned short Flags; - - - - bool isFlag(short flagNum) const { return bool((_flags & flagNum) != 0); } - - bool isTranslucent() const { return isFlag(IS_TRANSLUCENT); } - bool hasLightmap() const { return isFlag(HAS_LIGHTMAP); } - bool hasTangents() const { return isFlag(HAS_TANGENTS); } - bool hasSpecular() const { return isFlag(HAS_SPECULAR); } - bool hasEmissive() const { return isFlag(HAS_EMISSIVE); } - bool isSkinned() const { return isFlag(IS_SKINNED); } - bool isStereo() const { return isFlag(IS_STEREO); } - bool isDepthOnly() const { return isFlag(IS_DEPTH_ONLY); } - bool isShadow() const { return isFlag(IS_SHADOW); } // = depth only but with back facing - bool isWireFrame() const { return isFlag(IS_WIREFRAME); } - - Flags _flags = 0; - short _spare = 0; - - int getRaw() { return *reinterpret_cast(this); } - - - RenderKey( - bool translucent, bool hasLightmap, - bool hasTangents, bool hasSpecular, bool isSkinned, bool isWireframe) : - RenderKey((translucent ? IS_TRANSLUCENT : 0) - | (hasLightmap ? HAS_LIGHTMAP : 0) - | (hasTangents ? HAS_TANGENTS : 0) - | (hasSpecular ? HAS_SPECULAR : 0) - | (isSkinned ? IS_SKINNED : 0) - | (isWireframe ? IS_WIREFRAME : 0) - ) {} - - RenderKey(RenderArgs::RenderMode mode, - bool translucent, bool hasLightmap, - bool hasTangents, bool hasSpecular, bool isSkinned, bool isWireframe) : - RenderKey(((translucent && (mode != RenderArgs::SHADOW_RENDER_MODE)) ? IS_TRANSLUCENT : 0) - | (hasLightmap && (mode != RenderArgs::SHADOW_RENDER_MODE) ? HAS_LIGHTMAP : 0) // Lightmap, tangents and specular don't matter for depthOnly - | (hasTangents && (mode != RenderArgs::SHADOW_RENDER_MODE) ? HAS_TANGENTS : 0) - | (hasSpecular && (mode != RenderArgs::SHADOW_RENDER_MODE) ? HAS_SPECULAR : 0) - | (isSkinned ? IS_SKINNED : 0) - | (isWireframe ? IS_WIREFRAME : 0) - | ((mode == RenderArgs::SHADOW_RENDER_MODE) ? IS_DEPTH_ONLY : 0) - | ((mode == RenderArgs::SHADOW_RENDER_MODE) ? IS_SHADOW : 0) - ) {} - - RenderKey(int bitmask) : _flags(bitmask) {} - }; - - - class RenderPipeline { - public: - gpu::PipelinePointer _pipeline; - std::shared_ptr _locations; - RenderPipeline(gpu::PipelinePointer pipeline, std::shared_ptr locations) : - _pipeline(pipeline), _locations(locations) {} - }; - - typedef std::unordered_map BaseRenderPipelineMap; - class RenderPipelineLib : public BaseRenderPipelineMap { - public: - typedef RenderKey Key; - - - void addRenderPipeline(Key key, gpu::ShaderPointer& vertexShader, gpu::ShaderPointer& pixelShader); - - void initLocations(gpu::ShaderPointer& program, Locations& locations); - }; - static RenderPipelineLib _renderPipelineLib; - - static const RenderPipelineLib& getRenderPipelineLib(); - - // Collision hull Material - static model::MaterialPointer _collisionHullMaterial; - - static model::MaterialPointer getCollisionHullMaterial(); - -}; - -#endif // hifi_ModelRender_h \ No newline at end of file diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 1b1d08f353..90bc1486f2 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -193,7 +193,7 @@ void DrawOpaqueDeferred::run(const SceneContextPointer& sceneContext, const Rend batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); - renderItems(sceneContext, renderContext, inItems, opaque.maxDrawn); + renderItems(sceneContext, renderContext, this, inItems, opaque.maxDrawn); args->_batch = nullptr; }); } @@ -219,7 +219,7 @@ void DrawTransparentDeferred::run(const SceneContextPointer& sceneContext, const batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); - renderItems(sceneContext, renderContext, inItems, transparent.maxDrawn); + renderItems(sceneContext, renderContext, this, inItems, transparent.maxDrawn); args->_batch = nullptr; }); } @@ -292,7 +292,7 @@ void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderCon batch.setPipeline(getOpaquePipeline()); batch.setResourceTexture(0, args->_whiteTexture); - renderItems(sceneContext, renderContext, inItems, renderContext->getItemsConfig().overlay3D.maxDrawn); + renderItems(sceneContext, renderContext, this, inItems, renderContext->getItemsConfig().overlay3D.maxDrawn); }); args->_batch = nullptr; args->_whiteTexture.reset(); @@ -381,8 +381,7 @@ void DrawBackgroundDeferred::run(const SceneContextPointer& sceneContext, const batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); - renderItems(sceneContext, renderContext, inItems); - + renderItems(sceneContext, renderContext, nullptr, inItems); }); args->_batch = nullptr; } diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index 051faa3238..2c4102ef92 100755 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -16,6 +16,7 @@ #include "gpu/Pipeline.h" +#include "ShapeRender.h" #include "ToneMappingEffect.h" class SetupDeferred { @@ -49,14 +50,14 @@ public: typedef render::Job::Model JobModel; }; -class DrawOpaqueDeferred { +class DrawOpaqueDeferred : public ShapeRender { public: void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const render::ItemIDsBounds& inItems); typedef render::Job::ModelI JobModel; }; -class DrawTransparentDeferred { +class DrawTransparentDeferred : public ShapeRender { public: void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const render::ItemIDsBounds& inItems); @@ -80,7 +81,7 @@ public: typedef render::Job::Model JobModel; }; -class DrawOverlay3D { +class DrawOverlay3D : public ShapeRender { static gpu::PipelinePointer _opaquePipeline; //lazy evaluation hence mutable public: static const gpu::PipelinePointer& getOpaquePipeline(); diff --git a/libraries/render-utils/src/ShapeRender.cpp b/libraries/render-utils/src/ShapeRender.cpp index 31db3b010e..720cc5edad 100644 --- a/libraries/render-utils/src/ShapeRender.cpp +++ b/libraries/render-utils/src/ShapeRender.cpp @@ -1,8 +1,8 @@ // -// ModelRender.cpp -// interface/src/renderer +// ShapeRender.cpp +// render-utils/src // -// Created by Sam Gateau on 10/3/15. +// Created by Zach Pomerantz on 1/4/2015. // Copyright 2015 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. diff --git a/libraries/render-utils/src/ShapeRender.h b/libraries/render-utils/src/ShapeRender.h index 047f300dc0..7f7390992b 100644 --- a/libraries/render-utils/src/ShapeRender.h +++ b/libraries/render-utils/src/ShapeRender.h @@ -1,5 +1,5 @@ // -// ModelRender.h +// ShapeRender.h // render-utils/src // // Created by Zach Pomerantz on 1/4/2015. diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index e6a3e024ad..5bb8662149 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -209,24 +209,36 @@ void DepthSortItems::run(const SceneContextPointer& sceneContext, const RenderCo depthSortItems(sceneContext, renderContext, _frontToBack, inItems, outItems); } -void render::renderItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, int maxDrawnItems) { +void render::renderItem(RenderArgs* args, const Shape* shapeContext, Item& item) { + if (item.isShape()) { + assert(shapeContext); + const auto& key = item._payload.getShapeKey(); + args->_pipeline = shapeContext->pickPipeline(args, key); + if (!args->pipeline) { + return; + } + } + item.render(args); +} + +void render::renderItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const Shape* shapeContext, const ItemIDsBounds& inItems, int maxDrawnItems) { auto& scene = sceneContext->_scene; RenderArgs* args = renderContext->getArgs(); // render if ((maxDrawnItems < 0) || (maxDrawnItems > (int) inItems.size())) { for (auto itemDetails : inItems) { auto item = scene->getItem(itemDetails.id); - item.render(args); + renderItem(args, shapeContext, item); } } else { int numItems = 0; for (auto itemDetails : inItems) { auto item = scene->getItem(itemDetails.id); if (numItems + 1 >= maxDrawnItems) { - item.render(args); + renderItem(args, shapeContext, item); return; } - item.render(args); + renderItem(args, jobContext, item); numItems++; if (numItems >= maxDrawnItems) { return; @@ -259,7 +271,7 @@ void DrawLight::run(const SceneContextPointer& sceneContext, const RenderContext gpu::doInBatch(args->_context, [=](gpu::Batch& batch) { args->_batch = &batch; - renderItems(sceneContext, renderContext, culledItems); + renderItems(sceneContext, renderContext, this, culledItems); }); args->_batch = nullptr; } diff --git a/libraries/render/src/render/DrawTask.h b/libraries/render/src/render/DrawTask.h index b06223035d..8a1d84404e 100755 --- a/libraries/render/src/render/DrawTask.h +++ b/libraries/render/src/render/DrawTask.h @@ -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 renderItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, int maxDrawnItems = -1); +void renderItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const Shape* shapeContext, const ItemIDsBounds& inItems, int maxDrawnItems = -1); class FetchItems { @@ -268,7 +268,7 @@ public: typedef Job::ModelIO JobModel; }; -class DrawLight { +class DrawLight : public Shape { public: void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext); From dfcb74c3beff3013b00c6d63bda5d7d1f5f45c56 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Mon, 4 Jan 2016 13:12:06 -0800 Subject: [PATCH 09/39] Split renderItems to Lights/Shapes --- .../render-utils/src/RenderDeferredTask.cpp | 8 +-- libraries/render/src/render/DrawTask.cpp | 59 ++++++++++--------- libraries/render/src/render/DrawTask.h | 3 +- 3 files changed, 37 insertions(+), 33 deletions(-) diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 90bc1486f2..27aeebc173 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -193,7 +193,7 @@ void DrawOpaqueDeferred::run(const SceneContextPointer& sceneContext, const Rend batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); - renderItems(sceneContext, renderContext, this, inItems, opaque.maxDrawn); + renderShapes(sceneContext, renderContext, this, inItems, opaque.maxDrawn); args->_batch = nullptr; }); } @@ -219,7 +219,7 @@ void DrawTransparentDeferred::run(const SceneContextPointer& sceneContext, const batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); - renderItems(sceneContext, renderContext, this, inItems, transparent.maxDrawn); + renderShapes(sceneContext, renderContext, this, inItems, transparent.maxDrawn); args->_batch = nullptr; }); } @@ -292,7 +292,7 @@ void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderCon batch.setPipeline(getOpaquePipeline()); batch.setResourceTexture(0, args->_whiteTexture); - renderItems(sceneContext, renderContext, this, inItems, renderContext->getItemsConfig().overlay3D.maxDrawn); + renderShapes(sceneContext, renderContext, this, inItems, renderContext->getItemsConfig().overlay3D.maxDrawn); }); args->_batch = nullptr; args->_whiteTexture.reset(); @@ -381,7 +381,7 @@ void DrawBackgroundDeferred::run(const SceneContextPointer& sceneContext, const batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); - renderItems(sceneContext, renderContext, nullptr, inItems); + renderLights(sceneContext, renderContext, inItems); }); args->_batch = nullptr; } diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index 5bb8662149..729c72ad6f 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -209,39 +209,43 @@ void DepthSortItems::run(const SceneContextPointer& sceneContext, const RenderCo depthSortItems(sceneContext, renderContext, _frontToBack, inItems, outItems); } -void render::renderItem(RenderArgs* args, const Shape* shapeContext, Item& item) { - if (item.isShape()) { - assert(shapeContext); - const auto& key = item._payload.getShapeKey(); - args->_pipeline = shapeContext->pickPipeline(args, key); - if (!args->pipeline) { - return; - } - } - item.render(args); -} - -void render::renderItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const Shape* shapeContext, const ItemIDsBounds& inItems, int maxDrawnItems) { +void render::renderLights(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const Shape* shapeContext, const ItemIDsBounds& inItems) { auto& scene = sceneContext->_scene; RenderArgs* args = renderContext->getArgs(); - // render - if ((maxDrawnItems < 0) || (maxDrawnItems > (int) inItems.size())) { - for (auto itemDetails : inItems) { - auto item = scene->getItem(itemDetails.id); - renderItem(args, shapeContext, item); + + for (const auto& itemDetails : inItems) { + const auto& item = scene->getItem(itemDetails.id); + item.render(args); + } +} + +void renderShape(RenderArgs* args, const Item& item, const ShapeKey& lastKey) { + assert(item.isShape()); + const auto& key = item._payload.getShapeKey(); + args->_pipeline = shapeContext->pickPipeline(args, key); + // only render with a pipeline + if (args->_pipeline) { + item.render(args); + } +} + +void render::renderShapes(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const Shape* shapeContext, const ItemIDsBounds& inItems, int maxDrawnItems) { + auto& scene = sceneContext->_scene; + RenderArgs* args = renderContext->getArgs(); + + if ((maxDrawnItems < 0) || (maxDrawnItems > (int)inItems.size())) { + for (const auto& itemDetails : inItems) { + const auto& item = scene->getItem(itemDetails.id); + renderShape(args, item); } } else { int numItems = 0; - for (auto itemDetails : inItems) { - auto item = scene->getItem(itemDetails.id); - if (numItems + 1 >= maxDrawnItems) { - renderItem(args, shapeContext, item); - return; - } - renderItem(args, jobContext, item); + for (const auto& itemDetails : inItems) { numItems++; + const auto& item = scene->getItem(itemDetails.id); + renderShape(args, item); if (numItems >= maxDrawnItems) { - return; + break; } } } @@ -255,7 +259,6 @@ void DrawLight::run(const SceneContextPointer& sceneContext, const RenderContext auto& scene = sceneContext->_scene; auto& items = scene->getMasterBucket().at(ItemFilter::Builder::light()); - ItemIDsBounds inItems; inItems.reserve(items.size()); for (auto id : items) { @@ -271,7 +274,7 @@ void DrawLight::run(const SceneContextPointer& sceneContext, const RenderContext gpu::doInBatch(args->_context, [=](gpu::Batch& batch) { args->_batch = &batch; - renderItems(sceneContext, renderContext, this, culledItems); + renderLights(sceneContext, renderContext, culledItems); }); args->_batch = nullptr; } diff --git a/libraries/render/src/render/DrawTask.h b/libraries/render/src/render/DrawTask.h index 8a1d84404e..870a7d6ea7 100755 --- a/libraries/render/src/render/DrawTask.h +++ b/libraries/render/src/render/DrawTask.h @@ -222,7 +222,8 @@ 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 renderItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const Shape* shapeContext, const ItemIDsBounds& inItems, int maxDrawnItems = -1); +void renderLights(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems); +void renderShapes(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const Shape* shapeContext, const ItemIDsBounds& inItems, int maxDrawnItems = -1); class FetchItems { From cf35974f0275061b961ab458ad9828b4dba4699b Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 5 Jan 2016 01:18:57 -0800 Subject: [PATCH 10/39] Move shapeContext to jobContext --- .../render-utils/src/RenderDeferredTask.cpp | 6 +++--- libraries/render-utils/src/RenderDeferredTask.h | 14 +++++++++----- libraries/render-utils/src/ShapeRender.cpp | 11 +++++++---- libraries/render-utils/src/ShapeRender.h | 1 + libraries/render/src/render/DrawTask.cpp | 12 ++++++------ libraries/render/src/render/DrawTask.h | 16 ++++++++++------ 6 files changed, 36 insertions(+), 24 deletions(-) diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 27aeebc173..456736e76c 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -193,7 +193,7 @@ void DrawOpaqueDeferred::run(const SceneContextPointer& sceneContext, const Rend batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); - renderShapes(sceneContext, renderContext, this, inItems, opaque.maxDrawn); + renderShapes(sceneContext, renderContext, _context, inItems, opaque.maxDrawn); args->_batch = nullptr; }); } @@ -219,7 +219,7 @@ void DrawTransparentDeferred::run(const SceneContextPointer& sceneContext, const batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); - renderShapes(sceneContext, renderContext, this, inItems, transparent.maxDrawn); + renderShapes(sceneContext, renderContext, _context, inItems, transparent.maxDrawn); args->_batch = nullptr; }); } @@ -292,7 +292,7 @@ void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderCon batch.setPipeline(getOpaquePipeline()); batch.setResourceTexture(0, args->_whiteTexture); - renderShapes(sceneContext, renderContext, this, inItems, renderContext->getItemsConfig().overlay3D.maxDrawn); + renderShapes(sceneContext, renderContext, _context, inItems, renderContext->getItemsConfig().overlay3D.maxDrawn); }); args->_batch = nullptr; args->_whiteTexture.reset(); diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index 2c4102ef92..240d693de3 100755 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -50,14 +50,16 @@ public: typedef render::Job::Model JobModel; }; -class DrawOpaqueDeferred : public ShapeRender { +class DrawOpaqueDeferred { + class JobContext : public render::Job::Context, public ShapeRender {} _context; public: void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const render::ItemIDsBounds& inItems); typedef render::Job::ModelI JobModel; }; -class DrawTransparentDeferred : public ShapeRender { +class DrawTransparentDeferred { + class JobContext : public render::Job::Context, public ShapeRender {} _context; public: void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const render::ItemIDsBounds& inItems); @@ -81,13 +83,15 @@ public: typedef render::Job::Model JobModel; }; -class DrawOverlay3D : public ShapeRender { +class DrawOverlay3D { static gpu::PipelinePointer _opaquePipeline; //lazy evaluation hence mutable + + class JobContext : public render::Job::Context, public ShapeRender {} _context; public: static const gpu::PipelinePointer& getOpaquePipeline(); - + void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); - + typedef render::Job::Model JobModel; }; diff --git a/libraries/render-utils/src/ShapeRender.cpp b/libraries/render-utils/src/ShapeRender.cpp index 720cc5edad..6ede4ea897 100644 --- a/libraries/render-utils/src/ShapeRender.cpp +++ b/libraries/render-utils/src/ShapeRender.cpp @@ -37,6 +37,13 @@ #include "model_lightmap_specular_map_frag.h" #include "model_translucent_frag.h" +void ShapeRender::ShapeRender() { + // TODO: There is probably a cleaner way to init the pipeline that in a derived class + if (_pipelineLib.empty()) { + initPipeline(); + } +} + void ShapeRender::initPipeline() { assert(_pipelineLib.empty()); @@ -164,10 +171,6 @@ void ShapeRender::initPipeline() { const render::PipelinePointer ShapeRender::pickPipeline(RenderArgs* args, Key& key) { PerformanceTimer perfTimer("ShapeRender::pickPipeline"); - // TODO: There is probably a cleaner way to init the pipeline that in a derived class - if (_pipelineLib.empty()) { - initPipeline(); - } auto pipeline = _pickPipeline(args, key); if (!pipeline) { diff --git a/libraries/render-utils/src/ShapeRender.h b/libraries/render-utils/src/ShapeRender.h index 7f7390992b..1eef35d736 100644 --- a/libraries/render-utils/src/ShapeRender.h +++ b/libraries/render-utils/src/ShapeRender.h @@ -18,6 +18,7 @@ class ShapeRender : public render::Shape { static model::MaterialPointer _collisionHullMaterial; public: + ShapeRender(); static void initPipeline(); const render::PipelinePointer pickPipeline(RenderArgs* args, Key& key) override; diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index 729c72ad6f..adf3395cba 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -209,7 +209,7 @@ void DepthSortItems::run(const SceneContextPointer& sceneContext, const RenderCo depthSortItems(sceneContext, renderContext, _frontToBack, inItems, outItems); } -void render::renderLights(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const Shape* shapeContext, const ItemIDsBounds& inItems) { +void render::renderLights(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const Job::ContextPointer& jobContext, const ItemIDsBounds& inItems) { auto& scene = sceneContext->_scene; RenderArgs* args = renderContext->getArgs(); @@ -219,31 +219,31 @@ void render::renderLights(const SceneContextPointer& sceneContext, const RenderC } } -void renderShape(RenderArgs* args, const Item& item, const ShapeKey& lastKey) { +void renderShape(RenderArgs* args, const Job::ContextPointer& jobContext, const Item& item) { assert(item.isShape()); const auto& key = item._payload.getShapeKey(); - args->_pipeline = shapeContext->pickPipeline(args, key); + args->_pipeline = jobContext->pickPipeline(args, key); // only render with a pipeline if (args->_pipeline) { item.render(args); } } -void render::renderShapes(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const Shape* shapeContext, const ItemIDsBounds& inItems, int maxDrawnItems) { +void render::renderShapes(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const Job::ContextPointer& jobContext, const ItemIDsBounds& inItems, int maxDrawnItems) { auto& scene = sceneContext->_scene; RenderArgs* args = renderContext->getArgs(); if ((maxDrawnItems < 0) || (maxDrawnItems > (int)inItems.size())) { for (const auto& itemDetails : inItems) { const auto& item = scene->getItem(itemDetails.id); - renderShape(args, item); + renderShape(args, jobContext, item); } } else { int numItems = 0; for (const auto& itemDetails : inItems) { numItems++; const auto& item = scene->getItem(itemDetails.id); - renderShape(args, item); + renderShape(args, jobContext, item); if (numItems >= maxDrawnItems) { break; } diff --git a/libraries/render/src/render/DrawTask.h b/libraries/render/src/render/DrawTask.h index 870a7d6ea7..3cf701117c 100755 --- a/libraries/render/src/render/DrawTask.h +++ b/libraries/render/src/render/DrawTask.h @@ -57,7 +57,7 @@ public: void addJobConsumer(const std::shared_ptr& job) { _consumerJobs.push_back(job); } - + class Concept { public: virtual ~Concept() = default; @@ -101,8 +101,12 @@ public: _concept->run(sceneContext, renderContext); } -protected: public: + class Context { + public: + virtual ShapePipeline pickPipeline(RenderArgs* args, const ShapeKey& key) = 0; + }; + using ContextPointer = std::shared_ptr; class Concept { std::string _name; @@ -111,7 +115,7 @@ public: Concept() : _name() {} Concept(const std::string& name) : _name(name) {} virtual ~Concept() = default; - + void setName(const std::string& name) { _name = name; } const std::string& getName() const { return _name; } @@ -175,7 +179,7 @@ public: const Varying getOutput() const { return _output; } ModelO(const std::string& name): Concept(name), _output(Output()) { - + } ModelO(const std::string& name, Data data): Concept(name), _data(data), _output(Output()) {} @@ -223,7 +227,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 Shape* shapeContext, const ItemIDsBounds& inItems, int maxDrawnItems = -1); +void renderShapes(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const Job::ContextPointer& jobContext, const ItemIDsBounds& inItems, int maxDrawnItems = -1); class FetchItems { @@ -290,7 +294,7 @@ public: // A map of ItemIDs allowing to create bucket lists of SHAPE type items which are filtered by their -// Material +// Material class ItemMaterialBucketMap : public std::map { public: From 63444aac725b74fb1dfe1a3fd20976b3254c11a3 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 5 Jan 2016 11:35:28 -0800 Subject: [PATCH 11/39] Back to shapeContext, compiling --- .../render-utils/src/MeshPartPayload.cpp | 20 +++---- libraries/render-utils/src/MeshPartPayload.h | 6 +- libraries/render-utils/src/Model.cpp | 2 +- .../render-utils/src/RenderDeferredTask.cpp | 12 ++-- .../render-utils/src/RenderDeferredTask.h | 7 +-- libraries/render-utils/src/ShapeRender.cpp | 55 ++++++++++--------- libraries/render-utils/src/ShapeRender.h | 4 +- libraries/render/src/render/DrawTask.cpp | 24 ++++---- libraries/render/src/render/DrawTask.h | 5 +- libraries/render/src/render/Shape.cpp | 2 +- libraries/render/src/render/Shape.h | 3 +- 11 files changed, 73 insertions(+), 67 deletions(-) diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index f50deb0e43..28a341a872 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -129,7 +129,7 @@ void MeshPartPayload::bindMesh(gpu::Batch& batch) const { } } -void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locations* locations) const { +void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::LocationsPointer locations) const { if (!_drawMaterial) { return; } @@ -162,7 +162,7 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat if (materialKey.isNormalMap()) { auto normalMap = textureMaps[model::MaterialKey::NORMAL_MAP]; if (normalMap && normalMap->isDefined()) { - batch.setResourceTexture(ShapePipeline::Slots::::NORMAL_MAP, normalMap->getTextureView()); + batch.setResourceTexture(ShapePipeline::Slots::NORMAL_MAP, normalMap->getTextureView()); // texcoord are assumed to be the same has diffuse } else { @@ -183,7 +183,7 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat batch.setResourceTexture(ShapePipeline::Slots::SPECULAR_MAP, textureCache->getBlackTexture()); } } else { - batch.setResourceTexture(ShapePipeline::SPECULAR_MAP, nullptr); + batch.setResourceTexture(ShapePipeline::Slots::SPECULAR_MAP, nullptr); } // TODO: For now lightmaop is piped into the emissive map unit, we need to fix that and support for real emissive too @@ -191,7 +191,7 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat auto lightmapMap = textureMaps[model::MaterialKey::LIGHTMAP_MAP]; if (lightmapMap && lightmapMap->isDefined()) { - batch.setResourceTexture(ShapePipeline::LIGHTMAP_MAP, lightmapMap->getTextureView()); + batch.setResourceTexture(ShapePipeline::Slots::LIGHTMAP_MAP, lightmapMap->getTextureView()); auto lightmapOffsetScale = lightmapMap->getLightmapOffsetScale(); batch._glUniform2f(locations->emissiveParams, lightmapOffsetScale.x, lightmapOffsetScale.y); @@ -200,10 +200,10 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat lightmapMap->getTextureTransform().getMatrix(texcoordTransform[1]); } } else { - batch.setResourceTexture(ShapePipeline::LIGHTMAP_MAP, textureCache->getGrayTexture()); + batch.setResourceTexture(ShapePipeline::Slots::LIGHTMAP_MAP, textureCache->getGrayTexture()); } } else { - batch.setResourceTexture(ShapePipeline::LIGHTMAP_MAP, nullptr); + batch.setResourceTexture(ShapePipeline::Slots::LIGHTMAP_MAP, nullptr); } // Texcoord transforms ? @@ -212,7 +212,7 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat } } -void MeshPartPayload::bindTransform(gpu::Batch& batch, const ShapePipeline::Locations* locations) const { +void MeshPartPayload::bindTransform(gpu::Batch& batch, const ShapePipeline::LocationsPointer locations) const { batch.setModelTransform(_drawTransform); } @@ -431,16 +431,16 @@ void ModelMeshPartPayload::bindMesh(gpu::Batch& batch) const { } } -void ModelMeshPartPayload::bindTransform(gpu::Batch& batch, const ShapePipeline::Locations* locations) const { +void ModelMeshPartPayload::bindTransform(gpu::Batch& batch, const ShapePipeline::LocationsPointer locations) const { // Still relying on the raw data from the model const Model::MeshState& state = _model->_meshStates.at(_meshIndex); Transform transform; if (state.clusterBuffer) { if (_model->_cauterizeBones) { - batch.setUniformBuffer(ShapePipeline::SKINNING_GPU, state.cauterizedClusterBuffer); + batch.setUniformBuffer(ShapePipeline::Slots::SKINNING_GPU, state.cauterizedClusterBuffer); } else { - batch.setUniformBuffer(ShapePipeline::SKINNING_GPU, state.clusterBuffer); + batch.setUniformBuffer(ShapePipeline::Slots::SKINNING_GPU, state.clusterBuffer); } } else { if (_model->_cauterizeBones) { diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index cb7e1fd386..7d693dcbe9 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -46,8 +46,8 @@ public: // ModelMeshPartPayload functions to perform render void drawCall(gpu::Batch& batch) const; virtual void bindMesh(gpu::Batch& batch) const; - virtual void bindMaterial(gpu::Batch& batch, const render::ShapePipeline::Locations* locations) const; - virtual void bindTransform(gpu::Batch& batch, const render::ShapePipeline::Locations* locations) const; + virtual void bindMaterial(gpu::Batch& batch, const render::ShapePipeline::LocationsPointer locations) const; + virtual void bindTransform(gpu::Batch& batch, const render::ShapePipeline::LocationsPointer locations) const; // Payload resource cached values model::MeshPointer _drawMesh; @@ -89,7 +89,7 @@ public: // ModelMeshPartPayload functions to perform render void bindMesh(gpu::Batch& batch) const override; - void bindTransform(gpu::Batch& batch, const render::ShapePipeline::Locations* locations) const override; + void bindTransform(gpu::Batch& batch, const render::ShapePipeline::LocationsPointer locations) const override; void initCache(); diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index ef9a837b27..b40d2565c3 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -1193,7 +1193,7 @@ void Model::segregateMeshGroups() { int totalParts = mesh.parts.size(); for (int partIndex = 0; partIndex < totalParts; partIndex++) { if (showingCollisionHull) { - _renderItemsSet << std::make_shared(networkMesh._mesh, partIndex, ModelRender::getCollisionHullMaterial(), transform, offset); + _renderItemsSet << std::make_shared(networkMesh._mesh, partIndex, ShapeRender::getCollisionHullMaterial(), transform, offset); } else { _renderItemsSet << std::make_shared(this, i, partIndex, shapeID, transform, offset); diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 456736e76c..a35447cd05 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -177,7 +177,7 @@ void DrawOpaqueDeferred::run(const SceneContextPointer& sceneContext, const Rend assert(renderContext->getArgs()->_viewFrustum); RenderArgs* args = renderContext->getArgs(); - gpu::doInBatch(args->_context, [=](gpu::Batch& batch) { + gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { batch.setViewportTransform(args->_viewport); batch.setStateScissorRect(args->_viewport); args->_batch = &batch; @@ -193,7 +193,7 @@ void DrawOpaqueDeferred::run(const SceneContextPointer& sceneContext, const Rend batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); - renderShapes(sceneContext, renderContext, _context, inItems, opaque.maxDrawn); + renderShapes(sceneContext, renderContext, _renderer, inItems, opaque.maxDrawn); args->_batch = nullptr; }); } @@ -203,7 +203,7 @@ void DrawTransparentDeferred::run(const SceneContextPointer& sceneContext, const assert(renderContext->getArgs()->_viewFrustum); RenderArgs* args = renderContext->getArgs(); - gpu::doInBatch(args->_context, [=](gpu::Batch& batch) { + gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { batch.setViewportTransform(args->_viewport); batch.setStateScissorRect(args->_viewport); args->_batch = &batch; @@ -219,7 +219,7 @@ void DrawTransparentDeferred::run(const SceneContextPointer& sceneContext, const batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); - renderShapes(sceneContext, renderContext, _context, inItems, transparent.maxDrawn); + renderShapes(sceneContext, renderContext, _renderer, inItems, transparent.maxDrawn); args->_batch = nullptr; }); } @@ -276,7 +276,7 @@ void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderCon } // Render the items - gpu::doInBatch(args->_context, [=](gpu::Batch& batch) { + gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { args->_batch = &batch; args->_whiteTexture = DependencyManager::get()->getWhiteTexture(); @@ -292,7 +292,7 @@ void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderCon batch.setPipeline(getOpaquePipeline()); batch.setResourceTexture(0, args->_whiteTexture); - renderShapes(sceneContext, renderContext, _context, inItems, renderContext->getItemsConfig().overlay3D.maxDrawn); + renderShapes(sceneContext, renderContext, _renderer, inItems, renderContext->getItemsConfig().overlay3D.maxDrawn); }); args->_batch = nullptr; args->_whiteTexture.reset(); diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index 240d693de3..051f19c133 100755 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -51,7 +51,7 @@ public: }; class DrawOpaqueDeferred { - class JobContext : public render::Job::Context, public ShapeRender {} _context; + ShapeRender _renderer; public: void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const render::ItemIDsBounds& inItems); @@ -59,7 +59,7 @@ public: }; class DrawTransparentDeferred { - class JobContext : public render::Job::Context, public ShapeRender {} _context; + ShapeRender _renderer; public: void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const render::ItemIDsBounds& inItems); @@ -85,8 +85,7 @@ public: class DrawOverlay3D { static gpu::PipelinePointer _opaquePipeline; //lazy evaluation hence mutable - - class JobContext : public render::Job::Context, public ShapeRender {} _context; + ShapeRender _renderer; public: static const gpu::PipelinePointer& getOpaquePipeline(); diff --git a/libraries/render-utils/src/ShapeRender.cpp b/libraries/render-utils/src/ShapeRender.cpp index 6ede4ea897..c68664b69a 100644 --- a/libraries/render-utils/src/ShapeRender.cpp +++ b/libraries/render-utils/src/ShapeRender.cpp @@ -37,7 +37,7 @@ #include "model_lightmap_specular_map_frag.h" #include "model_translucent_frag.h" -void ShapeRender::ShapeRender() { +ShapeRender::ShapeRender() { // TODO: There is probably a cleaner way to init the pipeline that in a derived class if (_pipelineLib.empty()) { initPipeline(); @@ -72,104 +72,105 @@ void ShapeRender::initPipeline() { // Fill the pipelineLib _pipelineLib.addPipeline( - RenderKey(0), + Key::Builder(), modelVertex, modelPixel); _pipelineLib.addPipeline( - RenderKey(RenderKey::HAS_TANGENTS), + Key::Builder().withTangents(), modelNormalMapVertex, modelNormalMapPixel); _pipelineLib.addPipeline( - RenderKey(RenderKey::HAS_SPECULAR), + Key::Builder().withSpecular(), modelVertex, modelSpecularMapPixel); _pipelineLib.addPipeline( - RenderKey(RenderKey::HAS_TANGENTS | RenderKey::HAS_SPECULAR), + Key::Builder().withTangents().withSpecular(), modelNormalMapVertex, modelNormalSpecularMapPixel); _pipelineLib.addPipeline( - RenderKey(RenderKey::IS_TRANSLUCENT), + Key::Builder().withTranslucent(), modelVertex, modelTranslucentPixel); // FIXME Ignore lightmap for translucents meshpart _pipelineLib.addPipeline( - RenderKey(RenderKey::IS_TRANSLUCENT | RenderKey::HAS_LIGHTMAP), + Key::Builder().withTranslucent().withLightmap(), modelVertex, modelTranslucentPixel); _pipelineLib.addPipeline( - RenderKey(RenderKey::HAS_TANGENTS | RenderKey::IS_TRANSLUCENT), + Key::Builder().withTangents().withTranslucent(), modelNormalMapVertex, modelTranslucentPixel); _pipelineLib.addPipeline( - RenderKey(RenderKey::HAS_SPECULAR | RenderKey::IS_TRANSLUCENT), + Key::Builder().withSpecular().withTranslucent(), modelVertex, modelTranslucentPixel); _pipelineLib.addPipeline( - RenderKey(RenderKey::HAS_TANGENTS | RenderKey::HAS_SPECULAR | RenderKey::IS_TRANSLUCENT), + Key::Builder().withTangents().withSpecular().withTranslucent(), modelNormalMapVertex, modelTranslucentPixel); _pipelineLib.addPipeline( - RenderKey(RenderKey::HAS_LIGHTMAP), + Key::Builder().withLightmap(), modelLightmapVertex, modelLightmapPixel); + _pipelineLib.addPipeline( - RenderKey(RenderKey::HAS_LIGHTMAP | RenderKey::HAS_TANGENTS), + Key::Builder().withLightmap().withTangents(), modelLightmapNormalMapVertex, modelLightmapNormalMapPixel); _pipelineLib.addPipeline( - RenderKey(RenderKey::HAS_LIGHTMAP | RenderKey::HAS_SPECULAR), + Key::Builder().withLightmap().withSpecular(), modelLightmapVertex, modelLightmapSpecularMapPixel); _pipelineLib.addPipeline( - RenderKey(RenderKey::HAS_LIGHTMAP | RenderKey::HAS_TANGENTS | RenderKey::HAS_SPECULAR), + Key::Builder().withLightmap().withTangents().withSpecular(), modelLightmapNormalMapVertex, modelLightmapNormalSpecularMapPixel); _pipelineLib.addPipeline( - RenderKey(RenderKey::IS_SKINNED), + Key::Builder().withSkinned(), skinModelVertex, modelPixel); _pipelineLib.addPipeline( - RenderKey(RenderKey::IS_SKINNED | RenderKey::HAS_TANGENTS), + Key::Builder().withSkinned().withTangents(), skinModelNormalMapVertex, modelNormalMapPixel); _pipelineLib.addPipeline( - RenderKey(RenderKey::IS_SKINNED | RenderKey::HAS_SPECULAR), + Key::Builder().withSkinned().withSpecular(), skinModelVertex, modelSpecularMapPixel); _pipelineLib.addPipeline( - RenderKey(RenderKey::IS_SKINNED | RenderKey::HAS_TANGENTS | RenderKey::HAS_SPECULAR), + Key::Builder().withSkinned().withTangents().withSpecular(), skinModelNormalMapVertex, modelNormalSpecularMapPixel); _pipelineLib.addPipeline( - RenderKey(RenderKey::IS_SKINNED | RenderKey::IS_TRANSLUCENT), + Key::Builder().withSkinned().withTranslucent(), skinModelVertex, modelTranslucentPixel); _pipelineLib.addPipeline( - RenderKey(RenderKey::IS_SKINNED | RenderKey::HAS_TANGENTS | RenderKey::IS_TRANSLUCENT), + Key::Builder().withSkinned().withTangents().withTranslucent(), skinModelNormalMapVertex, modelTranslucentPixel); _pipelineLib.addPipeline( - RenderKey(RenderKey::IS_SKINNED | RenderKey::HAS_SPECULAR | RenderKey::IS_TRANSLUCENT), + Key::Builder().withSkinned().withSpecular().withTranslucent(), skinModelVertex, modelTranslucentPixel); _pipelineLib.addPipeline( - RenderKey(RenderKey::IS_SKINNED | RenderKey::HAS_TANGENTS | RenderKey::HAS_SPECULAR | RenderKey::IS_TRANSLUCENT), + Key::Builder().withSkinned().withTangents().withSpecular().withTranslucent(), skinModelNormalMapVertex, modelTranslucentPixel); _pipelineLib.addPipeline( - RenderKey(RenderKey::IS_DEPTH_ONLY | RenderKey::IS_SHADOW), + Key::Builder().withDepthOnly().withShadow(), modelShadowVertex, modelShadowPixel); _pipelineLib.addPipeline( - RenderKey(RenderKey::IS_SKINNED | RenderKey::IS_DEPTH_ONLY | RenderKey::IS_SHADOW), + Key::Builder().withSkinned().withDepthOnly().withShadow(), skinModelShadowVertex, modelShadowPixel); } -const render::PipelinePointer ShapeRender::pickPipeline(RenderArgs* args, Key& key) { +const ShapeRender::PipelinePointer ShapeRender::pickPipeline(RenderArgs* args, const Key& key) const { PerformanceTimer perfTimer("ShapeRender::pickPipeline"); auto pipeline = _pickPipeline(args, key); @@ -178,9 +179,11 @@ const render::PipelinePointer ShapeRender::pickPipeline(RenderArgs* args, Key& k } if ((pipeline->locations->normalFittingMapUnit > -1)) { - batch.setResourceTexture(pipeline->locations->normalFittingMapUnit, + args->_batch->setResourceTexture(pipeline->locations->normalFittingMapUnit, DependencyManager::get()->getNormalFittingTexture()); } + + return pipeline; } model::MaterialPointer ShapeRender::_collisionHullMaterial; diff --git a/libraries/render-utils/src/ShapeRender.h b/libraries/render-utils/src/ShapeRender.h index 1eef35d736..a3f131f21d 100644 --- a/libraries/render-utils/src/ShapeRender.h +++ b/libraries/render-utils/src/ShapeRender.h @@ -13,6 +13,7 @@ #define hifi_render_utils_Shape_h #include +#include class ShapeRender : public render::Shape { static model::MaterialPointer _collisionHullMaterial; @@ -20,10 +21,9 @@ class ShapeRender : public render::Shape { public: ShapeRender(); static void initPipeline(); - const render::PipelinePointer pickPipeline(RenderArgs* args, Key& key) override; + const PipelinePointer pickPipeline(RenderArgs* args, const Key& key) const override; static model::MaterialPointer getCollisionHullMaterial(); }; #endif // hifi_render_utils_Shape_h - diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index adf3395cba..9636ba7d86 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -209,41 +209,43 @@ void DepthSortItems::run(const SceneContextPointer& sceneContext, const RenderCo depthSortItems(sceneContext, renderContext, _frontToBack, inItems, outItems); } -void render::renderLights(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const Job::ContextPointer& jobContext, const ItemIDsBounds& inItems) { +void render::renderLights(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems) { auto& scene = sceneContext->_scene; RenderArgs* args = renderContext->getArgs(); for (const auto& itemDetails : inItems) { - const auto& item = scene->getItem(itemDetails.id); + // FIXME: Every item is copied because item.render cannot mutate a const + auto item = scene->getItem(itemDetails.id); item.render(args); } } -void renderShape(RenderArgs* args, const Job::ContextPointer& jobContext, const Item& item) { - assert(item.isShape()); - const auto& key = item._payload.getShapeKey(); - args->_pipeline = jobContext->pickPipeline(args, key); +void renderShape(RenderArgs* args, const Shape& shapeContext, Item& item) { + assert(item.getKey().isShape()); + const auto& key = item.getShapeKey(); + args->_pipeline = shapeContext.pickPipeline(args, key); // only render with a pipeline if (args->_pipeline) { item.render(args); } } -void render::renderShapes(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const Job::ContextPointer& jobContext, const ItemIDsBounds& inItems, int maxDrawnItems) { +void render::renderShapes(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const Shape& shapeContext, const ItemIDsBounds& inItems, int maxDrawnItems) { auto& scene = sceneContext->_scene; RenderArgs* args = renderContext->getArgs(); if ((maxDrawnItems < 0) || (maxDrawnItems > (int)inItems.size())) { for (const auto& itemDetails : inItems) { - const auto& item = scene->getItem(itemDetails.id); - renderShape(args, jobContext, item); + // FIXME: Every item is copied because item.render cannot mutate a const + auto item = scene->getItem(itemDetails.id); + renderShape(args, shapeContext, item); } } else { int numItems = 0; for (const auto& itemDetails : inItems) { numItems++; - const auto& item = scene->getItem(itemDetails.id); - renderShape(args, jobContext, item); + auto item = scene->getItem(itemDetails.id); + renderShape(args, shapeContext, item); if (numItems >= maxDrawnItems) { break; } diff --git a/libraries/render/src/render/DrawTask.h b/libraries/render/src/render/DrawTask.h index 3cf701117c..d3741a07a7 100755 --- a/libraries/render/src/render/DrawTask.h +++ b/libraries/render/src/render/DrawTask.h @@ -13,6 +13,7 @@ #define hifi_render_Task_h #include "Engine.h" +#include "Shape.h" #include "gpu/Batch.h" #include @@ -104,7 +105,7 @@ public: public: class Context { public: - virtual ShapePipeline pickPipeline(RenderArgs* args, const ShapeKey& key) = 0; + virtual const ShapePipeline pickPipeline(RenderArgs* args, const ShapeKey& key) = 0; }; using ContextPointer = std::shared_ptr; @@ -227,7 +228,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 Job::ContextPointer& jobContext, const ItemIDsBounds& inItems, int maxDrawnItems = -1); +void renderShapes(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const Shape& shapeContext, const ItemIDsBounds& inItems, int maxDrawnItems = -1); class FetchItems { diff --git a/libraries/render/src/render/Shape.cpp b/libraries/render/src/render/Shape.cpp index a6b8e09126..e596082e4f 100644 --- a/libraries/render/src/render/Shape.cpp +++ b/libraries/render/src/render/Shape.cpp @@ -15,7 +15,7 @@ using namespace render; -Shape::PipelineLib _pipelineLip; +Shape::PipelineLib Shape::_pipelineLib; const Shape::PipelinePointer Shape::_pickPipeline(RenderArgs* args, const Key& key) { assert(!_pipelineLib.empty()); diff --git a/libraries/render/src/render/Shape.h b/libraries/render/src/render/Shape.h index c3bf06f0ee..56bfa1e036 100644 --- a/libraries/render/src/render/Shape.h +++ b/libraries/render/src/render/Shape.h @@ -138,6 +138,7 @@ public: int materialBufferUnit; int lightBufferUnit; }; + using LocationsPointer = std::shared_ptr; gpu::PipelinePointer pipeline; std::shared_ptr locations; @@ -165,7 +166,7 @@ public: static void addPipeline(Key key, gpu::ShaderPointer& vertexShader, gpu::ShaderPointer& pixelShader) { _pipelineLib.addPipeline(key, vertexShader, pixelShader); } - virtual const PipelinePointer pickPipeline(RenderArgs* args, const Key& key) { + virtual const PipelinePointer pickPipeline(RenderArgs* args, const Key& key) const { return Shape::_pickPipeline(args, key); } From ad329a933191aac0b18823d40e93d5deff780bcf Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 5 Jan 2016 12:14:02 -0800 Subject: [PATCH 12/39] Return nullptr if no pipeline is found --- libraries/render/src/render/Shape.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/libraries/render/src/render/Shape.cpp b/libraries/render/src/render/Shape.cpp index e596082e4f..faa562e28e 100644 --- a/libraries/render/src/render/Shape.cpp +++ b/libraries/render/src/render/Shape.cpp @@ -27,10 +27,10 @@ const Shape::PipelinePointer Shape::_pickPipeline(RenderArgs* args, const Key& k const auto& pipelineIterator = _pipelineLib.find(key); if (pipelineIterator == _pipelineLib.end()) { qDebug() << "Couldn't find a pipeline from ShapeKey ?" << key; - return std::make_shared(); + return PipelinePointer(nullptr); } - Shape::PipelinePointer shapePipeline(&(pipelineIterator->second)); + PipelinePointer shapePipeline(&(pipelineIterator->second)); auto& batch = args->_batch; // Setup the one pipeline (to rule them all) @@ -41,14 +41,14 @@ const Shape::PipelinePointer Shape::_pickPipeline(RenderArgs* args, const Key& k void Shape::PipelineLib::addPipeline(Key key, gpu::ShaderPointer& vertexShader, gpu::ShaderPointer& pixelShader) { gpu::Shader::BindingSet slotBindings; - slotBindings.insert(gpu::Shader::Binding(std::string("skinClusterBuffer"), Shape::Slots::SKINNING_GPU)); - slotBindings.insert(gpu::Shader::Binding(std::string("materialBuffer"), Shape::Slots::MATERIAL_GPU)); - slotBindings.insert(gpu::Shader::Binding(std::string("diffuseMap"), Shape::Slots::DIFFUSE_MAP)); - slotBindings.insert(gpu::Shader::Binding(std::string("normalMap"), Shape::Slots::NORMAL_MAP)); - slotBindings.insert(gpu::Shader::Binding(std::string("specularMap"), Shape::Slots::SPECULAR_MAP)); - slotBindings.insert(gpu::Shader::Binding(std::string("emissiveMap"), Shape::Slots::LIGHTMAP_MAP)); - slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), Shape::Slots::LIGHT_BUFFER)); - slotBindings.insert(gpu::Shader::Binding(std::string("normalFittingMap"), Shape::Slots::NORMAL_FITTING_MAP)); + slotBindings.insert(gpu::Shader::Binding(std::string("skinClusterBuffer"), Slots::SKINNING_GPU)); + slotBindings.insert(gpu::Shader::Binding(std::string("materialBuffer"), Slots::MATERIAL_GPU)); + slotBindings.insert(gpu::Shader::Binding(std::string("diffuseMap"), Slots::DIFFUSE_MAP)); + slotBindings.insert(gpu::Shader::Binding(std::string("normalMap"), Slots::NORMAL_MAP)); + slotBindings.insert(gpu::Shader::Binding(std::string("specularMap"), Slots::SPECULAR_MAP)); + slotBindings.insert(gpu::Shader::Binding(std::string("emissiveMap"), Slots::LIGHTMAP_MAP)); + slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), Slots::LIGHT_BUFFER)); + slotBindings.insert(gpu::Shader::Binding(std::string("normalFittingMap"), Slots::NORMAL_FITTING_MAP)); gpu::ShaderPointer program = gpu::Shader::createProgram(vertexShader, pixelShader); gpu::Shader::makeProgram(*program, slotBindings); @@ -86,7 +86,7 @@ void Shape::PipelineLib::addPipeline(Key key, gpu::ShaderPointer& vertexShader, // Add the brand new pipeline and cache its location in the lib auto pipeline = gpu::Pipeline::create(program, state); - insert(value_type(key, Shape::Pipeline(pipeline, locations))); + insert(value_type(key, Pipeline(pipeline, locations))); // Add a wireframe version if (!key.isWireFrame()) { @@ -96,6 +96,6 @@ void Shape::PipelineLib::addPipeline(Key key, gpu::ShaderPointer& vertexShader, wireframeState->setFillMode(gpu::State::FILL_LINE); auto wireframePipeline = gpu::Pipeline::create(program, wireframeState); - insert(value_type(wireframeKey, Shape::Pipeline(wireframePipeline, locations))); + insert(value_type(wireframeKey, Pipeline(wireframePipeline, locations))); } } From df54d1dcc92c9e37833d31c74df03e48845cf4ab Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 5 Jan 2016 14:22:00 -0800 Subject: [PATCH 13/39] Fix render::Shape::Pipeline ownership by storing shared_ptr in map --- libraries/render/src/render/Shape.cpp | 6 +++--- libraries/render/src/render/Shape.h | 30 +++++++++++++++------------ 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/libraries/render/src/render/Shape.cpp b/libraries/render/src/render/Shape.cpp index faa562e28e..2177a71138 100644 --- a/libraries/render/src/render/Shape.cpp +++ b/libraries/render/src/render/Shape.cpp @@ -30,7 +30,7 @@ const Shape::PipelinePointer Shape::_pickPipeline(RenderArgs* args, const Key& k return PipelinePointer(nullptr); } - PipelinePointer shapePipeline(&(pipelineIterator->second)); + PipelinePointer shapePipeline(pipelineIterator->second); auto& batch = args->_batch; // Setup the one pipeline (to rule them all) @@ -86,7 +86,7 @@ void Shape::PipelineLib::addPipeline(Key key, gpu::ShaderPointer& vertexShader, // Add the brand new pipeline and cache its location in the lib auto pipeline = gpu::Pipeline::create(program, state); - insert(value_type(key, Pipeline(pipeline, locations))); + insert(value_type(key, std::make_shared(pipeline, locations))); // Add a wireframe version if (!key.isWireFrame()) { @@ -96,6 +96,6 @@ void Shape::PipelineLib::addPipeline(Key key, gpu::ShaderPointer& vertexShader, wireframeState->setFillMode(gpu::State::FILL_LINE); auto wireframePipeline = gpu::Pipeline::create(program, wireframeState); - insert(value_type(wireframeKey, Pipeline(wireframePipeline, locations))); + insert(value_type(wireframeKey, std::make_shared(wireframePipeline, locations))); } } diff --git a/libraries/render/src/render/Shape.h b/libraries/render/src/render/Shape.h index 56bfa1e036..1613904fd7 100644 --- a/libraries/render/src/render/Shape.h +++ b/libraries/render/src/render/Shape.h @@ -95,18 +95,22 @@ public: }; inline QDebug operator<<(QDebug debug, const ShapeKey& renderKey) { - debug << "[ShapeKey:" - << "hasLightmap:" << renderKey.hasLightmap() - << "hasTangents:" << renderKey.hasTangents() - << "hasSpecular:" << renderKey.hasSpecular() - << "hasEmissive:" << renderKey.hasEmissive() - << "isTranslucent:" << renderKey.isTranslucent() - << "isSkinned:" << renderKey.isSkinned() - << "isStereo:" << renderKey.isStereo() - << "isDepthOnly:" << renderKey.isDepthOnly() - << "isShadow:" << renderKey.isShadow() - << "isWireFrame:" << renderKey.isWireFrame() - << "]"; + if (renderKey.isValid()) { + debug << "[ShapeKey:" + << "hasLightmap:" << renderKey.hasLightmap() + << "hasTangents:" << renderKey.hasTangents() + << "hasSpecular:" << renderKey.hasSpecular() + << "hasEmissive:" << renderKey.hasEmissive() + << "isTranslucent:" << renderKey.isTranslucent() + << "isSkinned:" << renderKey.isSkinned() + << "isStereo:" << renderKey.isStereo() + << "isDepthOnly:" << renderKey.isDepthOnly() + << "isShadow:" << renderKey.isShadow() + << "isWireFrame:" << renderKey.isWireFrame() + << "]"; + } else { + debug << "[ShapeKey: INVALID]"; + } return debug; } @@ -157,7 +161,7 @@ public: using Slots = ShapePipeline::Slots; using Locations = ShapePipeline::Locations; - using PipelineMap = std::unordered_map; + using PipelineMap = std::unordered_map; class PipelineLib : public PipelineMap { public: void addPipeline(Key key, gpu::ShaderPointer& vertexShader, gpu::ShaderPointer& pixelShader); From 258a414404c0f8d7bce1ce3658ff206a3df5799f Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 5 Jan 2016 15:54:47 -0800 Subject: [PATCH 14/39] Add ShapeKey::NO_PIPELINE for shapes without Shape::Pipeline --- libraries/render/src/render/DrawTask.cpp | 9 ++++++--- libraries/render/src/render/Scene.h | 2 +- libraries/render/src/render/Shape.h | 5 +++++ 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index 9636ba7d86..2fa96efdd4 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -223,9 +223,12 @@ void render::renderLights(const SceneContextPointer& sceneContext, const RenderC void renderShape(RenderArgs* args, const Shape& shapeContext, Item& item) { assert(item.getKey().isShape()); const auto& key = item.getShapeKey(); - args->_pipeline = shapeContext.pickPipeline(args, key); - // only render with a pipeline - if (args->_pipeline) { + if (key.isValid() && key.hasPipeline()) { + args->_pipeline = shapeContext.pickPipeline(args, key); + if (args->_pipeline) { + item.render(args); + } + } else if (!key.hasPipeline()) { item.render(args); } } diff --git a/libraries/render/src/render/Scene.h b/libraries/render/src/render/Scene.h index 1d8744c1a7..90625dfd14 100644 --- a/libraries/render/src/render/Scene.h +++ b/libraries/render/src/render/Scene.h @@ -350,7 +350,7 @@ template int payloadGetLayer(const std::shared_ptr& payloadData) { template void payloadRender(const std::shared_ptr& payloadData, RenderArgs* args) { } // Shape type interface -template const ShapeKey shapeGetShapeKey(const std::shared_ptr& payloadData) { return ShapeKey::Builder::invalid(); } +template const ShapeKey shapeGetShapeKey(const std::shared_ptr& payloadData) { return ShapeKey::Builder::noPipeline(); } template class Payload : public Item::PayloadInterface { public: diff --git a/libraries/render/src/render/Shape.h b/libraries/render/src/render/Shape.h index 1613904fd7..394b54858c 100644 --- a/libraries/render/src/render/Shape.h +++ b/libraries/render/src/render/Shape.h @@ -31,6 +31,7 @@ public: SHADOW, WIREFRAME, + NO_PIPELINE, INVALID, NUM_FLAGS, // Not a valid flag @@ -61,8 +62,10 @@ public: Builder& withDepthOnly() { _flags.set(DEPTH_ONLY); return (*this); } Builder& withShadow() { _flags.set(SHADOW); return (*this); } Builder& withWireframe() { _flags.set(WIREFRAME); return (*this); } + Builder& withoutPipeline() { _flags.set(NO_PIPELINE); return (*this); } Builder& invalidate() { _flags.set(INVALID); return (*this); } + static const ShapeKey noPipeline() { return Builder().withoutPipeline(); } static const ShapeKey invalid() { return Builder().invalidate(); } }; ShapeKey(const Builder& builder) : ShapeKey(builder._flags) {} @@ -77,6 +80,8 @@ public: bool isDepthOnly() const { return _flags[DEPTH_ONLY]; } bool isShadow() const { return _flags[SHADOW]; } bool isWireFrame() const { return _flags[WIREFRAME]; } + + bool hasPipeline() const { return !_flags[NO_PIPELINE]; } bool isValid() const { return !_flags[INVALID]; } // Hasher for use in unordered_maps From 4eff377258a24a86c8b68a986e1bdac394e75314 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 5 Jan 2016 16:27:02 -0800 Subject: [PATCH 15/39] Change Slots->Slot to be congruous with gpu --- .../render-utils/src/DeferredLightingEffect.h | 4 ++- .../render-utils/src/MeshPartPayload.cpp | 30 +++++++++---------- libraries/render/src/render/Shape.cpp | 16 +++++----- libraries/render/src/render/Shape.h | 4 +-- 4 files changed, 28 insertions(+), 26 deletions(-) diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index dfb0ecbffb..40800258de 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -21,6 +21,8 @@ #include "model/Stage.h" #include "model/Geometry.h" +#include "render/Shape.h" + class RenderArgs; class SimpleProgramKey; struct LightLocations; @@ -30,7 +32,7 @@ class DeferredLightingEffect : public Dependency { SINGLETON_DEPENDENCY public: - static const int NORMAL_FITTING_MAP_SLOT = 10; + static const int NORMAL_FITTING_MAP_SLOT = render::Shape::Slot::NORMAL_FITTING_MAP; static const int DEFERRED_TRANSFORM_BUFFER_SLOT = 2; void init(); diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 28a341a872..53feaa5a44 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -136,7 +136,7 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat auto textureCache = DependencyManager::get(); - batch.setUniformBuffer(ShapePipeline::Slots::MATERIAL_GPU, _drawMaterial->getSchemaBuffer()); + batch.setUniformBuffer(ShapePipeline::Slot::MATERIAL_GPU, _drawMaterial->getSchemaBuffer()); auto materialKey = _drawMaterial->getKey(); auto textureMaps = _drawMaterial->getTextureMaps(); @@ -146,44 +146,44 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat if (materialKey.isDiffuseMap()) { auto diffuseMap = textureMaps[model::MaterialKey::DIFFUSE_MAP]; if (diffuseMap && diffuseMap->isDefined()) { - batch.setResourceTexture(ShapePipeline::Slots::DIFFUSE_MAP, diffuseMap->getTextureView()); + batch.setResourceTexture(ShapePipeline::Slot::DIFFUSE_MAP, diffuseMap->getTextureView()); if (!diffuseMap->getTextureTransform().isIdentity()) { diffuseMap->getTextureTransform().getMatrix(texcoordTransform[0]); } } else { - batch.setResourceTexture(ShapePipeline::Slots::DIFFUSE_MAP, textureCache->getGrayTexture()); + batch.setResourceTexture(ShapePipeline::Slot::DIFFUSE_MAP, textureCache->getGrayTexture()); } } else { - batch.setResourceTexture(ShapePipeline::Slots::DIFFUSE_MAP, textureCache->getWhiteTexture()); + batch.setResourceTexture(ShapePipeline::Slot::DIFFUSE_MAP, textureCache->getWhiteTexture()); } // Normal map if (materialKey.isNormalMap()) { auto normalMap = textureMaps[model::MaterialKey::NORMAL_MAP]; if (normalMap && normalMap->isDefined()) { - batch.setResourceTexture(ShapePipeline::Slots::NORMAL_MAP, normalMap->getTextureView()); + batch.setResourceTexture(ShapePipeline::Slot::NORMAL_MAP, normalMap->getTextureView()); // texcoord are assumed to be the same has diffuse } else { - batch.setResourceTexture(ShapePipeline::Slots::NORMAL_MAP, textureCache->getBlueTexture()); + batch.setResourceTexture(ShapePipeline::Slot::NORMAL_MAP, textureCache->getBlueTexture()); } } else { - batch.setResourceTexture(ShapePipeline::Slots::NORMAL_MAP, nullptr); + batch.setResourceTexture(ShapePipeline::Slot::NORMAL_MAP, nullptr); } // TODO: For now gloss map is used as the "specular map in the shading, we ll need to fix that if (materialKey.isGlossMap()) { auto specularMap = textureMaps[model::MaterialKey::GLOSS_MAP]; if (specularMap && specularMap->isDefined()) { - batch.setResourceTexture(ShapePipeline::Slots::SPECULAR_MAP, specularMap->getTextureView()); + batch.setResourceTexture(ShapePipeline::Slot::SPECULAR_MAP, specularMap->getTextureView()); // texcoord are assumed to be the same has diffuse } else { - batch.setResourceTexture(ShapePipeline::Slots::SPECULAR_MAP, textureCache->getBlackTexture()); + batch.setResourceTexture(ShapePipeline::Slot::SPECULAR_MAP, textureCache->getBlackTexture()); } } else { - batch.setResourceTexture(ShapePipeline::Slots::SPECULAR_MAP, nullptr); + batch.setResourceTexture(ShapePipeline::Slot::SPECULAR_MAP, nullptr); } // TODO: For now lightmaop is piped into the emissive map unit, we need to fix that and support for real emissive too @@ -191,7 +191,7 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat auto lightmapMap = textureMaps[model::MaterialKey::LIGHTMAP_MAP]; if (lightmapMap && lightmapMap->isDefined()) { - batch.setResourceTexture(ShapePipeline::Slots::LIGHTMAP_MAP, lightmapMap->getTextureView()); + batch.setResourceTexture(ShapePipeline::Slot::LIGHTMAP_MAP, lightmapMap->getTextureView()); auto lightmapOffsetScale = lightmapMap->getLightmapOffsetScale(); batch._glUniform2f(locations->emissiveParams, lightmapOffsetScale.x, lightmapOffsetScale.y); @@ -200,10 +200,10 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat lightmapMap->getTextureTransform().getMatrix(texcoordTransform[1]); } } else { - batch.setResourceTexture(ShapePipeline::Slots::LIGHTMAP_MAP, textureCache->getGrayTexture()); + batch.setResourceTexture(ShapePipeline::Slot::LIGHTMAP_MAP, textureCache->getGrayTexture()); } } else { - batch.setResourceTexture(ShapePipeline::Slots::LIGHTMAP_MAP, nullptr); + batch.setResourceTexture(ShapePipeline::Slot::LIGHTMAP_MAP, nullptr); } // Texcoord transforms ? @@ -438,9 +438,9 @@ void ModelMeshPartPayload::bindTransform(gpu::Batch& batch, const ShapePipeline: Transform transform; if (state.clusterBuffer) { if (_model->_cauterizeBones) { - batch.setUniformBuffer(ShapePipeline::Slots::SKINNING_GPU, state.cauterizedClusterBuffer); + batch.setUniformBuffer(ShapePipeline::Slot::SKINNING_GPU, state.cauterizedClusterBuffer); } else { - batch.setUniformBuffer(ShapePipeline::Slots::SKINNING_GPU, state.clusterBuffer); + batch.setUniformBuffer(ShapePipeline::Slot::SKINNING_GPU, state.clusterBuffer); } } else { if (_model->_cauterizeBones) { diff --git a/libraries/render/src/render/Shape.cpp b/libraries/render/src/render/Shape.cpp index 2177a71138..ed988adb5a 100644 --- a/libraries/render/src/render/Shape.cpp +++ b/libraries/render/src/render/Shape.cpp @@ -41,14 +41,14 @@ const Shape::PipelinePointer Shape::_pickPipeline(RenderArgs* args, const Key& k void Shape::PipelineLib::addPipeline(Key key, gpu::ShaderPointer& vertexShader, gpu::ShaderPointer& pixelShader) { gpu::Shader::BindingSet slotBindings; - slotBindings.insert(gpu::Shader::Binding(std::string("skinClusterBuffer"), Slots::SKINNING_GPU)); - slotBindings.insert(gpu::Shader::Binding(std::string("materialBuffer"), Slots::MATERIAL_GPU)); - slotBindings.insert(gpu::Shader::Binding(std::string("diffuseMap"), Slots::DIFFUSE_MAP)); - slotBindings.insert(gpu::Shader::Binding(std::string("normalMap"), Slots::NORMAL_MAP)); - slotBindings.insert(gpu::Shader::Binding(std::string("specularMap"), Slots::SPECULAR_MAP)); - slotBindings.insert(gpu::Shader::Binding(std::string("emissiveMap"), Slots::LIGHTMAP_MAP)); - slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), Slots::LIGHT_BUFFER)); - slotBindings.insert(gpu::Shader::Binding(std::string("normalFittingMap"), Slots::NORMAL_FITTING_MAP)); + slotBindings.insert(gpu::Shader::Binding(std::string("skinClusterBuffer"), Slot::SKINNING_GPU)); + slotBindings.insert(gpu::Shader::Binding(std::string("materialBuffer"), Slot::MATERIAL_GPU)); + slotBindings.insert(gpu::Shader::Binding(std::string("diffuseMap"), Slot::DIFFUSE_MAP)); + slotBindings.insert(gpu::Shader::Binding(std::string("normalMap"), Slot::NORMAL_MAP)); + slotBindings.insert(gpu::Shader::Binding(std::string("specularMap"), Slot::SPECULAR_MAP)); + slotBindings.insert(gpu::Shader::Binding(std::string("emissiveMap"), Slot::LIGHTMAP_MAP)); + slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), Slot::LIGHT_BUFFER)); + slotBindings.insert(gpu::Shader::Binding(std::string("normalFittingMap"), Slot::NORMAL_FITTING_MAP)); gpu::ShaderPointer program = gpu::Shader::createProgram(vertexShader, pixelShader); gpu::Shader::makeProgram(*program, slotBindings); diff --git a/libraries/render/src/render/Shape.h b/libraries/render/src/render/Shape.h index 394b54858c..917b27f2dc 100644 --- a/libraries/render/src/render/Shape.h +++ b/libraries/render/src/render/Shape.h @@ -122,7 +122,7 @@ inline QDebug operator<<(QDebug debug, const ShapeKey& renderKey) { // Rendering abstraction over gpu::Pipeline and map locations class ShapePipeline { public: - class Slots { + class Slot { public: static const int SKINNING_GPU = 2; static const int MATERIAL_GPU = 3; @@ -163,7 +163,7 @@ public: using Key = ShapeKey; using Pipeline = ShapePipeline; using PipelinePointer = std::shared_ptr; - using Slots = ShapePipeline::Slots; + using Slot = ShapePipeline::Slot; using Locations = ShapePipeline::Locations; using PipelineMap = std::unordered_map; From 444a014252c1148850a85cf4903dc20fcbc1f6d5 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 5 Jan 2016 17:10:47 -0800 Subject: [PATCH 16/39] Delay renderEngine init for GLBackend init --- interface/src/Application.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e8673e7eac..69fef254c5 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -452,8 +452,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : _bookmarks = new Bookmarks(); // Before setting up the menu _runningScriptsWidget = new RunningScriptsWidget(_window); - _renderEngine->addTask(make_shared()); - _renderEngine->registerScene(_main3DScene); // start the nodeThread so its event loop is running QThread* nodeThread = new QThread(this); @@ -660,6 +658,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) : _offscreenContext->makeCurrent(); initializeGL(); + // Start rendering + _renderEngine->addTask(make_shared()); + _renderEngine->registerScene(_main3DScene); _toolWindow = new ToolWindow(); _toolWindow->setWindowFlags((_toolWindow->windowFlags() | Qt::WindowStaysOnTopHint) & ~Qt::WindowMinimizeButtonHint); From 948dc26d24d26c358874e2050eba39e292dc2619 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 5 Jan 2016 17:19:23 -0800 Subject: [PATCH 17/39] Add debug statement for invalid ShapeKey --- libraries/render/src/render/DrawTask.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index 2fa96efdd4..f66b6461b9 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -230,6 +230,8 @@ void renderShape(RenderArgs* args, const Shape& shapeContext, Item& item) { } } else if (!key.hasPipeline()) { item.render(args); + } else { + qDebug() << "Item could not be rendered: invalid key ?" << key; } } From da50eacaad3fd0040118089304f2b8263de4102e Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 5 Jan 2016 18:08:16 -0800 Subject: [PATCH 18/39] Resolve Hash const function and include per Jenkins --- libraries/render-utils/src/DeferredLightingEffect.h | 4 ++-- libraries/render/src/render/Shape.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index 40800258de..e0926fb5b8 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -21,7 +21,7 @@ #include "model/Stage.h" #include "model/Geometry.h" -#include "render/Shape.h" +#include "ShapeRender.h" class RenderArgs; class SimpleProgramKey; @@ -32,7 +32,7 @@ class DeferredLightingEffect : public Dependency { SINGLETON_DEPENDENCY public: - static const int NORMAL_FITTING_MAP_SLOT = render::Shape::Slot::NORMAL_FITTING_MAP; + static const int NORMAL_FITTING_MAP_SLOT = ShapeRender::Slot::NORMAL_FITTING_MAP; static const int DEFERRED_TRANSFORM_BUFFER_SLOT = 2; void init(); diff --git a/libraries/render/src/render/Shape.h b/libraries/render/src/render/Shape.h index 917b27f2dc..8fc93d76af 100644 --- a/libraries/render/src/render/Shape.h +++ b/libraries/render/src/render/Shape.h @@ -87,7 +87,7 @@ public: // Hasher for use in unordered_maps class Hash { public: - size_t operator() (const ShapeKey& key) { + size_t operator() (const ShapeKey& key) const { return std::hash()(key._flags); } }; From d8ff133cc681df28b6bb471c257c12c14e726d46 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 5 Jan 2016 18:11:24 -0800 Subject: [PATCH 19/39] Fix include in gpu-test --- libraries/render-utils/src/DeferredLightingEffect.h | 4 ++-- tests/gpu-test/CMakeLists.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index e0926fb5b8..40800258de 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -21,7 +21,7 @@ #include "model/Stage.h" #include "model/Geometry.h" -#include "ShapeRender.h" +#include "render/Shape.h" class RenderArgs; class SimpleProgramKey; @@ -32,7 +32,7 @@ class DeferredLightingEffect : public Dependency { SINGLETON_DEPENDENCY public: - static const int NORMAL_FITTING_MAP_SLOT = ShapeRender::Slot::NORMAL_FITTING_MAP; + static const int NORMAL_FITTING_MAP_SLOT = render::Shape::Slot::NORMAL_FITTING_MAP; static const int DEFERRED_TRANSFORM_BUFFER_SLOT = 2; void init(); diff --git a/tests/gpu-test/CMakeLists.txt b/tests/gpu-test/CMakeLists.txt index 3d83c310cf..6b985da4c9 100644 --- a/tests/gpu-test/CMakeLists.txt +++ b/tests/gpu-test/CMakeLists.txt @@ -3,5 +3,5 @@ AUTOSCRIBE_SHADER_LIB(gpu model render-utils) # This is not a testcase -- just set it up as a regular hifi project setup_hifi_project(Quick Gui OpenGL Script Widgets) set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Tests/manual-tests/") -link_hifi_libraries(networking gl gpu procedural shared fbx model model-networking animation script-engine render-utils ) +link_hifi_libraries(networking gl gpu procedural shared fbx model model-networking animation script-engine render render-utils ) package_libraries_for_deployment() \ No newline at end of file From 9bc661adc8e98f13d818ae0e22c43a78b39acdd8 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Wed, 6 Jan 2016 11:42:58 -0800 Subject: [PATCH 20/39] Cleanup for style/dead code --- .../render-utils/src/MeshPartPayload.cpp | 38 +++++++++---------- libraries/render-utils/src/MeshPartPayload.h | 6 +-- .../render-utils/src/RenderDeferredTask.h | 18 ++++++--- libraries/render-utils/src/ShapeRender.cpp | 3 +- libraries/render-utils/src/ShapeRender.h | 5 ++- libraries/render/src/render/DrawTask.cpp | 4 +- libraries/render/src/render/DrawTask.h | 8 +--- libraries/render/src/render/Scene.h | 5 ++- libraries/render/src/render/Shape.h | 36 ++++++++++-------- 9 files changed, 67 insertions(+), 56 deletions(-) diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 53feaa5a44..7b1f6887f1 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -129,14 +129,14 @@ void MeshPartPayload::bindMesh(gpu::Batch& batch) const { } } -void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::LocationsPointer locations) const { +void MeshPartPayload::bindMaterial(gpu::Batch& batch, const Shape::Pipeline::LocationsPointer locations) const { if (!_drawMaterial) { return; } auto textureCache = DependencyManager::get(); - batch.setUniformBuffer(ShapePipeline::Slot::MATERIAL_GPU, _drawMaterial->getSchemaBuffer()); + batch.setUniformBuffer(Shape::Pipeline::Slot::MATERIAL_GPU, _drawMaterial->getSchemaBuffer()); auto materialKey = _drawMaterial->getKey(); auto textureMaps = _drawMaterial->getTextureMaps(); @@ -146,44 +146,44 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat if (materialKey.isDiffuseMap()) { auto diffuseMap = textureMaps[model::MaterialKey::DIFFUSE_MAP]; if (diffuseMap && diffuseMap->isDefined()) { - batch.setResourceTexture(ShapePipeline::Slot::DIFFUSE_MAP, diffuseMap->getTextureView()); + batch.setResourceTexture(Shape::Pipeline::Slot::DIFFUSE_MAP, diffuseMap->getTextureView()); if (!diffuseMap->getTextureTransform().isIdentity()) { diffuseMap->getTextureTransform().getMatrix(texcoordTransform[0]); } } else { - batch.setResourceTexture(ShapePipeline::Slot::DIFFUSE_MAP, textureCache->getGrayTexture()); + batch.setResourceTexture(Shape::Pipeline::Slot::DIFFUSE_MAP, textureCache->getGrayTexture()); } } else { - batch.setResourceTexture(ShapePipeline::Slot::DIFFUSE_MAP, textureCache->getWhiteTexture()); + batch.setResourceTexture(Shape::Pipeline::Slot::DIFFUSE_MAP, textureCache->getWhiteTexture()); } // Normal map if (materialKey.isNormalMap()) { auto normalMap = textureMaps[model::MaterialKey::NORMAL_MAP]; if (normalMap && normalMap->isDefined()) { - batch.setResourceTexture(ShapePipeline::Slot::NORMAL_MAP, normalMap->getTextureView()); + batch.setResourceTexture(Shape::Pipeline::Slot::NORMAL_MAP, normalMap->getTextureView()); // texcoord are assumed to be the same has diffuse } else { - batch.setResourceTexture(ShapePipeline::Slot::NORMAL_MAP, textureCache->getBlueTexture()); + batch.setResourceTexture(Shape::Pipeline::Slot::NORMAL_MAP, textureCache->getBlueTexture()); } } else { - batch.setResourceTexture(ShapePipeline::Slot::NORMAL_MAP, nullptr); + batch.setResourceTexture(Shape::Pipeline::Slot::NORMAL_MAP, nullptr); } // TODO: For now gloss map is used as the "specular map in the shading, we ll need to fix that if (materialKey.isGlossMap()) { auto specularMap = textureMaps[model::MaterialKey::GLOSS_MAP]; if (specularMap && specularMap->isDefined()) { - batch.setResourceTexture(ShapePipeline::Slot::SPECULAR_MAP, specularMap->getTextureView()); + batch.setResourceTexture(Shape::Pipeline::Slot::SPECULAR_MAP, specularMap->getTextureView()); // texcoord are assumed to be the same has diffuse } else { - batch.setResourceTexture(ShapePipeline::Slot::SPECULAR_MAP, textureCache->getBlackTexture()); + batch.setResourceTexture(Shape::Pipeline::Slot::SPECULAR_MAP, textureCache->getBlackTexture()); } } else { - batch.setResourceTexture(ShapePipeline::Slot::SPECULAR_MAP, nullptr); + batch.setResourceTexture(Shape::Pipeline::Slot::SPECULAR_MAP, nullptr); } // TODO: For now lightmaop is piped into the emissive map unit, we need to fix that and support for real emissive too @@ -191,7 +191,7 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat auto lightmapMap = textureMaps[model::MaterialKey::LIGHTMAP_MAP]; if (lightmapMap && lightmapMap->isDefined()) { - batch.setResourceTexture(ShapePipeline::Slot::LIGHTMAP_MAP, lightmapMap->getTextureView()); + batch.setResourceTexture(Shape::Pipeline::Slot::LIGHTMAP_MAP, lightmapMap->getTextureView()); auto lightmapOffsetScale = lightmapMap->getLightmapOffsetScale(); batch._glUniform2f(locations->emissiveParams, lightmapOffsetScale.x, lightmapOffsetScale.y); @@ -200,10 +200,10 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat lightmapMap->getTextureTransform().getMatrix(texcoordTransform[1]); } } else { - batch.setResourceTexture(ShapePipeline::Slot::LIGHTMAP_MAP, textureCache->getGrayTexture()); + batch.setResourceTexture(Shape::Pipeline::Slot::LIGHTMAP_MAP, textureCache->getGrayTexture()); } } else { - batch.setResourceTexture(ShapePipeline::Slot::LIGHTMAP_MAP, nullptr); + batch.setResourceTexture(Shape::Pipeline::Slot::LIGHTMAP_MAP, nullptr); } // Texcoord transforms ? @@ -212,7 +212,7 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat } } -void MeshPartPayload::bindTransform(gpu::Batch& batch, const ShapePipeline::LocationsPointer locations) const { +void MeshPartPayload::bindTransform(gpu::Batch& batch, const Shape::Pipeline::LocationsPointer locations) const { batch.setModelTransform(_drawTransform); } @@ -377,7 +377,7 @@ ShapeKey ModelMeshPartPayload::getShapeKey() const { int vertexCount = mesh.vertices.size(); if (vertexCount == 0) { // sanity check - return ShapeKey::Builder::invalid(); + return ShapeKey::Builder::invalid(); // FIXME } @@ -431,16 +431,16 @@ void ModelMeshPartPayload::bindMesh(gpu::Batch& batch) const { } } -void ModelMeshPartPayload::bindTransform(gpu::Batch& batch, const ShapePipeline::LocationsPointer locations) const { +void ModelMeshPartPayload::bindTransform(gpu::Batch& batch, const Shape::Pipeline::LocationsPointer locations) const { // Still relying on the raw data from the model const Model::MeshState& state = _model->_meshStates.at(_meshIndex); Transform transform; if (state.clusterBuffer) { if (_model->_cauterizeBones) { - batch.setUniformBuffer(ShapePipeline::Slot::SKINNING_GPU, state.cauterizedClusterBuffer); + batch.setUniformBuffer(Shape::Pipeline::Slot::SKINNING_GPU, state.cauterizedClusterBuffer); } else { - batch.setUniformBuffer(ShapePipeline::Slot::SKINNING_GPU, state.clusterBuffer); + batch.setUniformBuffer(Shape::Pipeline::Slot::SKINNING_GPU, state.clusterBuffer); } } else { if (_model->_cauterizeBones) { diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index 7d693dcbe9..1e6e6214ae 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -46,8 +46,8 @@ public: // ModelMeshPartPayload functions to perform render void drawCall(gpu::Batch& batch) const; virtual void bindMesh(gpu::Batch& batch) const; - virtual void bindMaterial(gpu::Batch& batch, const render::ShapePipeline::LocationsPointer locations) const; - virtual void bindTransform(gpu::Batch& batch, const render::ShapePipeline::LocationsPointer locations) const; + virtual void bindMaterial(gpu::Batch& batch, const render::Shape::Pipeline::LocationsPointer locations) const; + virtual void bindTransform(gpu::Batch& batch, const render::Shape::Pipeline::LocationsPointer locations) const; // Payload resource cached values model::MeshPointer _drawMesh; @@ -89,7 +89,7 @@ public: // ModelMeshPartPayload functions to perform render void bindMesh(gpu::Batch& batch) const override; - void bindTransform(gpu::Batch& batch, const render::ShapePipeline::LocationsPointer locations) const override; + void bindTransform(gpu::Batch& batch, const render::Shape::Pipeline::LocationsPointer locations) const override; void initCache(); diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index 051f19c133..01e9ab2a16 100755 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -51,29 +51,35 @@ public: }; class DrawOpaqueDeferred { - ShapeRender _renderer; public: void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const render::ItemIDsBounds& inItems); typedef render::Job::ModelI JobModel; + +protected: + ShapeRender _renderer; }; class DrawTransparentDeferred { - ShapeRender _renderer; public: void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const render::ItemIDsBounds& inItems); typedef render::Job::ModelI JobModel; + +protected: + ShapeRender _renderer; }; class DrawStencilDeferred { - static gpu::PipelinePointer _opaquePipeline; //lazy evaluation hence mutable public: static const gpu::PipelinePointer& getOpaquePipeline(); void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); typedef render::Job::Model JobModel; + +protected: + static gpu::PipelinePointer _opaquePipeline; //lazy evaluation hence mutable }; class DrawBackgroundDeferred { @@ -84,14 +90,16 @@ public: }; class DrawOverlay3D { - static gpu::PipelinePointer _opaquePipeline; //lazy evaluation hence mutable - ShapeRender _renderer; public: static const gpu::PipelinePointer& getOpaquePipeline(); void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); typedef render::Job::Model JobModel; + +protected: + static gpu::PipelinePointer _opaquePipeline; //lazy evaluation hence mutable + ShapeRender _renderer; }; class Blit { diff --git a/libraries/render-utils/src/ShapeRender.cpp b/libraries/render-utils/src/ShapeRender.cpp index c68664b69a..c4ac9f3c2b 100644 --- a/libraries/render-utils/src/ShapeRender.cpp +++ b/libraries/render-utils/src/ShapeRender.cpp @@ -38,7 +38,8 @@ #include "model_translucent_frag.h" ShapeRender::ShapeRender() { - // TODO: There is probably a cleaner way to init the pipeline that in a derived class + // TODO: Move pipeline initialization to those Jobs using ShapeRender + // such that they own their own pipelines and it is done only once if (_pipelineLib.empty()) { initPipeline(); } diff --git a/libraries/render-utils/src/ShapeRender.h b/libraries/render-utils/src/ShapeRender.h index a3f131f21d..fc174896bb 100644 --- a/libraries/render-utils/src/ShapeRender.h +++ b/libraries/render-utils/src/ShapeRender.h @@ -16,14 +16,15 @@ #include class ShapeRender : public render::Shape { - static model::MaterialPointer _collisionHullMaterial; - public: ShapeRender(); static void initPipeline(); const PipelinePointer pickPipeline(RenderArgs* args, const Key& key) const override; static model::MaterialPointer getCollisionHullMaterial(); + +protected: + static model::MaterialPointer _collisionHullMaterial; }; #endif // hifi_render_utils_Shape_h diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index f66b6461b9..83caaa72b7 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -223,12 +223,12 @@ void render::renderLights(const SceneContextPointer& sceneContext, const RenderC void renderShape(RenderArgs* args, const Shape& shapeContext, Item& item) { assert(item.getKey().isShape()); const auto& key = item.getShapeKey(); - if (key.isValid() && key.hasPipeline()) { + if (key.isValid() && !key.hasOwnPipeline()) { args->_pipeline = shapeContext.pickPipeline(args, key); if (args->_pipeline) { item.render(args); } - } else if (!key.hasPipeline()) { + } else if (key.hasOwnPipeline()) { item.render(args); } else { qDebug() << "Item could not be rendered: invalid key ?" << key; diff --git a/libraries/render/src/render/DrawTask.h b/libraries/render/src/render/DrawTask.h index d3741a07a7..eef4247b17 100755 --- a/libraries/render/src/render/DrawTask.h +++ b/libraries/render/src/render/DrawTask.h @@ -103,12 +103,6 @@ public: } public: - class Context { - public: - virtual const ShapePipeline pickPipeline(RenderArgs* args, const ShapeKey& key) = 0; - }; - using ContextPointer = std::shared_ptr; - class Concept { std::string _name; bool _isEnabled = true; @@ -274,7 +268,7 @@ public: typedef Job::ModelIO JobModel; }; -class DrawLight : public Shape { +class DrawLight { public: void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext); diff --git a/libraries/render/src/render/Scene.h b/libraries/render/src/render/Scene.h index 90625dfd14..bff75ebcd8 100644 --- a/libraries/render/src/render/Scene.h +++ b/libraries/render/src/render/Scene.h @@ -350,7 +350,10 @@ template int payloadGetLayer(const std::shared_ptr& payloadData) { template void payloadRender(const std::shared_ptr& payloadData, RenderArgs* args) { } // Shape type interface -template const ShapeKey shapeGetShapeKey(const std::shared_ptr& payloadData) { return ShapeKey::Builder::noPipeline(); } +// This allows shapes to characterize their pipeline via a ShapeKey, to be picked with a subclass of Shape. +// When creating a new shape payload you need to create a specialized version, or the ShapeKey will be ownPipeline, +// implying that the shape will setup its own pipeline without the use of the ShapeKey. +template const ShapeKey shapeGetShapeKey(const std::shared_ptr& payloadData) { return ShapeKey::Builder::ownPipeline(); } template class Payload : public Item::PayloadInterface { public: diff --git a/libraries/render/src/render/Shape.h b/libraries/render/src/render/Shape.h index 8fc93d76af..4950af1da4 100644 --- a/libraries/render/src/render/Shape.h +++ b/libraries/render/src/render/Shape.h @@ -31,7 +31,7 @@ public: SHADOW, WIREFRAME, - NO_PIPELINE, + OWN_PIPELINE, INVALID, NUM_FLAGS, // Not a valid flag @@ -62,10 +62,10 @@ public: Builder& withDepthOnly() { _flags.set(DEPTH_ONLY); return (*this); } Builder& withShadow() { _flags.set(SHADOW); return (*this); } Builder& withWireframe() { _flags.set(WIREFRAME); return (*this); } - Builder& withoutPipeline() { _flags.set(NO_PIPELINE); return (*this); } + Builder& withOwnPipeline() { _flags.set(OWN_PIPELINE); return (*this); } Builder& invalidate() { _flags.set(INVALID); return (*this); } - static const ShapeKey noPipeline() { return Builder().withoutPipeline(); } + static const ShapeKey ownPipeline() { return Builder().withOwnPipeline(); } static const ShapeKey invalid() { return Builder().invalidate(); } }; ShapeKey(const Builder& builder) : ShapeKey(builder._flags) {} @@ -81,7 +81,7 @@ public: bool isShadow() const { return _flags[SHADOW]; } bool isWireFrame() const { return _flags[WIREFRAME]; } - bool hasPipeline() const { return !_flags[NO_PIPELINE]; } + bool hasOwnPipeline() const { return _flags[OWN_PIPELINE]; } bool isValid() const { return !_flags[INVALID]; } // Hasher for use in unordered_maps @@ -101,18 +101,22 @@ public: inline QDebug operator<<(QDebug debug, const ShapeKey& renderKey) { if (renderKey.isValid()) { - debug << "[ShapeKey:" - << "hasLightmap:" << renderKey.hasLightmap() - << "hasTangents:" << renderKey.hasTangents() - << "hasSpecular:" << renderKey.hasSpecular() - << "hasEmissive:" << renderKey.hasEmissive() - << "isTranslucent:" << renderKey.isTranslucent() - << "isSkinned:" << renderKey.isSkinned() - << "isStereo:" << renderKey.isStereo() - << "isDepthOnly:" << renderKey.isDepthOnly() - << "isShadow:" << renderKey.isShadow() - << "isWireFrame:" << renderKey.isWireFrame() - << "]"; + if (renderKey.hasOwnPipeline()) { + debug << "[ShapeKey: OWN_PIPELINE]"; + } else { + debug << "[ShapeKey:" + << "hasLightmap:" << renderKey.hasLightmap() + << "hasTangents:" << renderKey.hasTangents() + << "hasSpecular:" << renderKey.hasSpecular() + << "hasEmissive:" << renderKey.hasEmissive() + << "isTranslucent:" << renderKey.isTranslucent() + << "isSkinned:" << renderKey.isSkinned() + << "isStereo:" << renderKey.isStereo() + << "isDepthOnly:" << renderKey.isDepthOnly() + << "isShadow:" << renderKey.isShadow() + << "isWireFrame:" << renderKey.isWireFrame() + << "]"; + } } else { debug << "[ShapeKey: INVALID]"; } From b68572fdd09929ee0860c66cf5a9c746a43163c8 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 6 Jan 2016 11:43:17 -0800 Subject: [PATCH 21/39] Cleanup renderShapes render loop --- libraries/render/src/render/DrawTask.cpp | 26 ++++++++---------------- 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index f66b6461b9..f5fe5899c2 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -235,26 +235,16 @@ void renderShape(RenderArgs* args, const Shape& shapeContext, Item& item) { } } -void render::renderShapes(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const Shape& shapeContext, const ItemIDsBounds& inItems, int maxDrawnItems) { +void render::renderShapes(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, + const Shape& shapeContext, const ItemIDsBounds& inItems, int maxDrawnItems) { auto& scene = sceneContext->_scene; RenderArgs* args = renderContext->getArgs(); - - if ((maxDrawnItems < 0) || (maxDrawnItems > (int)inItems.size())) { - for (const auto& itemDetails : inItems) { - // FIXME: Every item is copied because item.render cannot mutate a const - auto item = scene->getItem(itemDetails.id); - renderShape(args, shapeContext, item); - } - } else { - int numItems = 0; - for (const auto& itemDetails : inItems) { - numItems++; - auto item = scene->getItem(itemDetails.id); - renderShape(args, shapeContext, item); - if (numItems >= maxDrawnItems) { - break; - } - } + + auto numItemsToDraw = glm::max((int)inItems.size(), maxDrawnItems); + for (auto i = 0; i < numItemsToDraw; ++i) { + // FIXME: Every item is copied because item.render cannot mutate a const + auto item = scene->getItem(inItems[i].id); + renderShape(args, shapeContext, item); } } From 7f0781f6e893374df50f817dba097bccdd5af405 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Thu, 7 Jan 2016 11:49:02 -0800 Subject: [PATCH 22/39] Move model update next to bindTransform --- libraries/render-utils/src/MeshPartPayload.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 7b1f6887f1..fd2a025d1d 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -221,7 +221,6 @@ void MeshPartPayload::render(RenderArgs* args) const { PerformanceTimer perfTimer("MeshPartPayload::render"); gpu::Batch& batch = *(args->_batch); - auto mode = args->_renderMode; ShapeKey key = getShapeKey(); @@ -359,9 +358,6 @@ ShapeKey ModelMeshPartPayload::getShapeKey() const { return ShapeKey::Builder::invalid(); } - // Back to model to update the cluster matrices right now - _model->updateClusterMatrices(_transform.getTranslation(), _transform.getRotation()); - const FBXMesh& mesh = geometry.meshes.at(_meshIndex); // if our index is ever out of range for either meshes or networkMeshes, then skip it, and set our _meshGroupsKnown @@ -463,7 +459,6 @@ void ModelMeshPartPayload::render(RenderArgs* args) const { } gpu::Batch& batch = *(args->_batch); - auto mode = args->_renderMode; ShapeKey key = getShapeKey(); if (!key.isValid()) { @@ -497,6 +492,7 @@ void ModelMeshPartPayload::render(RenderArgs* args) const { assert(locations); // Bind the model transform and the skinCLusterMatrices if needed + _model->updateClusterMatrices(_transform.getTranslation(), _transform.getRotation()); bindTransform(batch, locations); //Bind the index buffer and vertex buffer and Blend shapes if needed From 1b3e14439595319fc641680270e1f77c48c3c8aa Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Thu, 7 Jan 2016 13:27:22 -0800 Subject: [PATCH 23/39] Rename Shape to ShapePipelineLib, Shape.h to ShapePipeline.h --- .../render-utils/src/DeferredLightingEffect.h | 4 +-- .../render-utils/src/MeshPartPayload.cpp | 36 +++++++++---------- libraries/render-utils/src/MeshPartPayload.h | 6 ++-- libraries/render-utils/src/ShapeRender.h | 4 +-- libraries/render/src/render/DrawTask.cpp | 4 +-- libraries/render/src/render/DrawTask.h | 4 +-- libraries/render/src/render/Scene.h | 2 +- .../render/{Shape.cpp => ShapePipeline.cpp} | 16 +++++---- .../src/render/{Shape.h => ShapePipeline.h} | 33 +++++++++-------- 9 files changed, 56 insertions(+), 53 deletions(-) rename libraries/render/src/render/{Shape.cpp => ShapePipeline.cpp} (87%) rename libraries/render/src/render/{Shape.h => ShapePipeline.h} (93%) diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index 40800258de..f00f558122 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -21,7 +21,7 @@ #include "model/Stage.h" #include "model/Geometry.h" -#include "render/Shape.h" +#include "render/ShapePipeline.h" class RenderArgs; class SimpleProgramKey; @@ -32,7 +32,7 @@ class DeferredLightingEffect : public Dependency { SINGLETON_DEPENDENCY public: - static const int NORMAL_FITTING_MAP_SLOT = render::Shape::Slot::NORMAL_FITTING_MAP; + static const int NORMAL_FITTING_MAP_SLOT = render::ShapePipeline::Slot::NORMAL_FITTING_MAP; static const int DEFERRED_TRANSFORM_BUFFER_SLOT = 2; void init(); diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index fd2a025d1d..b1c40ac5b5 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -129,14 +129,14 @@ void MeshPartPayload::bindMesh(gpu::Batch& batch) const { } } -void MeshPartPayload::bindMaterial(gpu::Batch& batch, const Shape::Pipeline::LocationsPointer locations) const { +void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::LocationsPointer locations) const { if (!_drawMaterial) { return; } auto textureCache = DependencyManager::get(); - batch.setUniformBuffer(Shape::Pipeline::Slot::MATERIAL_GPU, _drawMaterial->getSchemaBuffer()); + batch.setUniformBuffer(ShapePipeline::Slot::MATERIAL_GPU, _drawMaterial->getSchemaBuffer()); auto materialKey = _drawMaterial->getKey(); auto textureMaps = _drawMaterial->getTextureMaps(); @@ -146,44 +146,44 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const Shape::Pipeline::Loc if (materialKey.isDiffuseMap()) { auto diffuseMap = textureMaps[model::MaterialKey::DIFFUSE_MAP]; if (diffuseMap && diffuseMap->isDefined()) { - batch.setResourceTexture(Shape::Pipeline::Slot::DIFFUSE_MAP, diffuseMap->getTextureView()); + batch.setResourceTexture(ShapePipeline::Slot::DIFFUSE_MAP, diffuseMap->getTextureView()); if (!diffuseMap->getTextureTransform().isIdentity()) { diffuseMap->getTextureTransform().getMatrix(texcoordTransform[0]); } } else { - batch.setResourceTexture(Shape::Pipeline::Slot::DIFFUSE_MAP, textureCache->getGrayTexture()); + batch.setResourceTexture(ShapePipeline::Slot::DIFFUSE_MAP, textureCache->getGrayTexture()); } } else { - batch.setResourceTexture(Shape::Pipeline::Slot::DIFFUSE_MAP, textureCache->getWhiteTexture()); + batch.setResourceTexture(ShapePipeline::Slot::DIFFUSE_MAP, textureCache->getWhiteTexture()); } // Normal map if (materialKey.isNormalMap()) { auto normalMap = textureMaps[model::MaterialKey::NORMAL_MAP]; if (normalMap && normalMap->isDefined()) { - batch.setResourceTexture(Shape::Pipeline::Slot::NORMAL_MAP, normalMap->getTextureView()); + batch.setResourceTexture(ShapePipeline::Slot::NORMAL_MAP, normalMap->getTextureView()); // texcoord are assumed to be the same has diffuse } else { - batch.setResourceTexture(Shape::Pipeline::Slot::NORMAL_MAP, textureCache->getBlueTexture()); + batch.setResourceTexture(ShapePipeline::Slot::NORMAL_MAP, textureCache->getBlueTexture()); } } else { - batch.setResourceTexture(Shape::Pipeline::Slot::NORMAL_MAP, nullptr); + batch.setResourceTexture(ShapePipeline::Slot::NORMAL_MAP, nullptr); } // TODO: For now gloss map is used as the "specular map in the shading, we ll need to fix that if (materialKey.isGlossMap()) { auto specularMap = textureMaps[model::MaterialKey::GLOSS_MAP]; if (specularMap && specularMap->isDefined()) { - batch.setResourceTexture(Shape::Pipeline::Slot::SPECULAR_MAP, specularMap->getTextureView()); + batch.setResourceTexture(ShapePipeline::Slot::SPECULAR_MAP, specularMap->getTextureView()); // texcoord are assumed to be the same has diffuse } else { - batch.setResourceTexture(Shape::Pipeline::Slot::SPECULAR_MAP, textureCache->getBlackTexture()); + batch.setResourceTexture(ShapePipeline::Slot::SPECULAR_MAP, textureCache->getBlackTexture()); } } else { - batch.setResourceTexture(Shape::Pipeline::Slot::SPECULAR_MAP, nullptr); + batch.setResourceTexture(ShapePipeline::Slot::SPECULAR_MAP, nullptr); } // TODO: For now lightmaop is piped into the emissive map unit, we need to fix that and support for real emissive too @@ -191,7 +191,7 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const Shape::Pipeline::Loc auto lightmapMap = textureMaps[model::MaterialKey::LIGHTMAP_MAP]; if (lightmapMap && lightmapMap->isDefined()) { - batch.setResourceTexture(Shape::Pipeline::Slot::LIGHTMAP_MAP, lightmapMap->getTextureView()); + batch.setResourceTexture(ShapePipeline::Slot::LIGHTMAP_MAP, lightmapMap->getTextureView()); auto lightmapOffsetScale = lightmapMap->getLightmapOffsetScale(); batch._glUniform2f(locations->emissiveParams, lightmapOffsetScale.x, lightmapOffsetScale.y); @@ -200,10 +200,10 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const Shape::Pipeline::Loc lightmapMap->getTextureTransform().getMatrix(texcoordTransform[1]); } } else { - batch.setResourceTexture(Shape::Pipeline::Slot::LIGHTMAP_MAP, textureCache->getGrayTexture()); + batch.setResourceTexture(ShapePipeline::Slot::LIGHTMAP_MAP, textureCache->getGrayTexture()); } } else { - batch.setResourceTexture(Shape::Pipeline::Slot::LIGHTMAP_MAP, nullptr); + batch.setResourceTexture(ShapePipeline::Slot::LIGHTMAP_MAP, nullptr); } // Texcoord transforms ? @@ -212,7 +212,7 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const Shape::Pipeline::Loc } } -void MeshPartPayload::bindTransform(gpu::Batch& batch, const Shape::Pipeline::LocationsPointer locations) const { +void MeshPartPayload::bindTransform(gpu::Batch& batch, const ShapePipeline::LocationsPointer locations) const { batch.setModelTransform(_drawTransform); } @@ -427,16 +427,16 @@ void ModelMeshPartPayload::bindMesh(gpu::Batch& batch) const { } } -void ModelMeshPartPayload::bindTransform(gpu::Batch& batch, const Shape::Pipeline::LocationsPointer locations) const { +void ModelMeshPartPayload::bindTransform(gpu::Batch& batch, const ShapePipeline::LocationsPointer locations) const { // Still relying on the raw data from the model const Model::MeshState& state = _model->_meshStates.at(_meshIndex); Transform transform; if (state.clusterBuffer) { if (_model->_cauterizeBones) { - batch.setUniformBuffer(Shape::Pipeline::Slot::SKINNING_GPU, state.cauterizedClusterBuffer); + batch.setUniformBuffer(ShapePipeline::Slot::SKINNING_GPU, state.cauterizedClusterBuffer); } else { - batch.setUniformBuffer(Shape::Pipeline::Slot::SKINNING_GPU, state.clusterBuffer); + batch.setUniformBuffer(ShapePipeline::Slot::SKINNING_GPU, state.clusterBuffer); } } else { if (_model->_cauterizeBones) { diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index 1e6e6214ae..7d693dcbe9 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -46,8 +46,8 @@ public: // ModelMeshPartPayload functions to perform render void drawCall(gpu::Batch& batch) const; virtual void bindMesh(gpu::Batch& batch) const; - virtual void bindMaterial(gpu::Batch& batch, const render::Shape::Pipeline::LocationsPointer locations) const; - virtual void bindTransform(gpu::Batch& batch, const render::Shape::Pipeline::LocationsPointer locations) const; + virtual void bindMaterial(gpu::Batch& batch, const render::ShapePipeline::LocationsPointer locations) const; + virtual void bindTransform(gpu::Batch& batch, const render::ShapePipeline::LocationsPointer locations) const; // Payload resource cached values model::MeshPointer _drawMesh; @@ -89,7 +89,7 @@ public: // ModelMeshPartPayload functions to perform render void bindMesh(gpu::Batch& batch) const override; - void bindTransform(gpu::Batch& batch, const render::Shape::Pipeline::LocationsPointer locations) const override; + void bindTransform(gpu::Batch& batch, const render::ShapePipeline::LocationsPointer locations) const override; void initCache(); diff --git a/libraries/render-utils/src/ShapeRender.h b/libraries/render-utils/src/ShapeRender.h index fc174896bb..590eca5511 100644 --- a/libraries/render-utils/src/ShapeRender.h +++ b/libraries/render-utils/src/ShapeRender.h @@ -12,10 +12,10 @@ #ifndef hifi_render_utils_Shape_h #define hifi_render_utils_Shape_h -#include +#include #include -class ShapeRender : public render::Shape { +class ShapeRender : public render::ShapePipelineLib { public: ShapeRender(); static void initPipeline(); diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index 756e0847fc..df2c14662f 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -220,7 +220,7 @@ void render::renderLights(const SceneContextPointer& sceneContext, const RenderC } } -void renderShape(RenderArgs* args, const Shape& shapeContext, Item& item) { +void renderShape(RenderArgs* args, const ShapePipelineLib& shapeContext, Item& item) { assert(item.getKey().isShape()); const auto& key = item.getShapeKey(); if (key.isValid() && !key.hasOwnPipeline()) { @@ -236,7 +236,7 @@ void renderShape(RenderArgs* args, const Shape& shapeContext, Item& item) { } void render::renderShapes(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, - const Shape& shapeContext, const ItemIDsBounds& inItems, int maxDrawnItems) { + const ShapePipelineLib& 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 eef4247b17..81dc7d358a 100755 --- a/libraries/render/src/render/DrawTask.h +++ b/libraries/render/src/render/DrawTask.h @@ -13,7 +13,7 @@ #define hifi_render_Task_h #include "Engine.h" -#include "Shape.h" +#include "ShapePipeline.h" #include "gpu/Batch.h" #include @@ -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 Shape& shapeContext, const ItemIDsBounds& inItems, int maxDrawnItems = -1); +void renderShapes(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ShapePipelineLib& shapeContext, const ItemIDsBounds& inItems, int maxDrawnItems = -1); class FetchItems { diff --git a/libraries/render/src/render/Scene.h b/libraries/render/src/render/Scene.h index bff75ebcd8..3a6463b538 100644 --- a/libraries/render/src/render/Scene.h +++ b/libraries/render/src/render/Scene.h @@ -25,7 +25,7 @@ #include #include "model/Material.h" -#include "Shape.h" +#include "ShapePipeline.h" namespace render { diff --git a/libraries/render/src/render/Shape.cpp b/libraries/render/src/render/ShapePipeline.cpp similarity index 87% rename from libraries/render/src/render/Shape.cpp rename to libraries/render/src/render/ShapePipeline.cpp index ed988adb5a..b766fb8695 100644 --- a/libraries/render/src/render/Shape.cpp +++ b/libraries/render/src/render/ShapePipeline.cpp @@ -1,5 +1,5 @@ // -// Shape.cpp +// ShapePipeline.cpp // render/src/render // // Created by Zach Pomerantz on 12/31/15. @@ -9,20 +9,24 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "Shape.h" +#include "ShapePipeline.h" #include using namespace render; -Shape::PipelineLib Shape::_pipelineLib; +ShapePipelineLib::PipelineLib ShapePipelineLib::_pipelineLib; -const Shape::PipelinePointer Shape::_pickPipeline(RenderArgs* args, const Key& key) { +void ShapePipelineLib::addPipeline(Key key, gpu::ShaderPointer& vertexShader, gpu::ShaderPointer& pixelShader) { + _pipelineLib.addPipeline(key, vertexShader, pixelShader); +} + +const ShapePipelineLib::PipelinePointer ShapePipelineLib::_pickPipeline(RenderArgs* args, const Key& key) { assert(!_pipelineLib.empty()); assert(args); assert(args->_batch); - PerformanceTimer perfTimer("Shape::getPipeline"); + PerformanceTimer perfTimer("ShapePipelineLib::getPipeline"); const auto& pipelineIterator = _pipelineLib.find(key); if (pipelineIterator == _pipelineLib.end()) { @@ -39,7 +43,7 @@ const Shape::PipelinePointer Shape::_pickPipeline(RenderArgs* args, const Key& k return shapePipeline; } -void Shape::PipelineLib::addPipeline(Key key, gpu::ShaderPointer& vertexShader, gpu::ShaderPointer& pixelShader) { +void ShapePipelineLib::PipelineLib::addPipeline(Key key, 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)); diff --git a/libraries/render/src/render/Shape.h b/libraries/render/src/render/ShapePipeline.h similarity index 93% rename from libraries/render/src/render/Shape.h rename to libraries/render/src/render/ShapePipeline.h index 4950af1da4..1f293cfb93 100644 --- a/libraries/render/src/render/Shape.h +++ b/libraries/render/src/render/ShapePipeline.h @@ -1,5 +1,5 @@ // -// Shape.h +// ShapePipeline.h // render/src/render // // Created by Zach Pomerantz on 12/31/15. @@ -9,8 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#ifndef hifi_render_Shape_h -#define hifi_render_Shape_h +#ifndef hifi_render_ShapePipeline_h +#define hifi_render_ShapePipeline_h #include #include @@ -160,36 +160,35 @@ public: ShapePipeline(gpu::PipelinePointer pipeline, std::shared_ptr locations) : pipeline(pipeline), locations(locations) {} }; +using ShapePipelinePointer = std::shared_ptr; // Meta-information (pipeline and locations) to render a shape -class Shape { +class ShapePipelineLib { public: using Key = ShapeKey; using Pipeline = ShapePipeline; - using PipelinePointer = std::shared_ptr; + using PipelinePointer = ShapePipelinePointer; using Slot = ShapePipeline::Slot; using Locations = ShapePipeline::Locations; + virtual ~ShapePipelineLib() = default; + + 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); + } + +protected: using PipelineMap = std::unordered_map; class PipelineLib : public PipelineMap { public: void addPipeline(Key key, gpu::ShaderPointer& vertexShader, gpu::ShaderPointer& pixelShader); }; - static void addPipeline(Key key, gpu::ShaderPointer& vertexShader, gpu::ShaderPointer& pixelShader) { - _pipelineLib.addPipeline(key, vertexShader, pixelShader); - } - virtual const PipelinePointer pickPipeline(RenderArgs* args, const Key& key) const { - return Shape::_pickPipeline(args, key); - } - - virtual ~Shape() {}; - -protected: - static const PipelinePointer _pickPipeline(RenderArgs* args, const Key& key); static PipelineLib _pipelineLib; + static const PipelinePointer _pickPipeline(RenderArgs* args, const Key& key); }; } -#endif // hifi_render_Shape_h +#endif // hifi_render_ShapePipeline_h From e809c4f89d2460cd86ecc429863beb849ee1a08d Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Thu, 7 Jan 2016 13:42:56 -0800 Subject: [PATCH 24/39] Avoid copying Item before rendering --- libraries/render/src/render/DrawTask.cpp | 8 +++----- libraries/render/src/render/Scene.h | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index df2c14662f..1b6bae54c8 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -214,13 +214,12 @@ void render::renderLights(const SceneContextPointer& sceneContext, const RenderC RenderArgs* args = renderContext->getArgs(); for (const auto& itemDetails : inItems) { - // FIXME: Every item is copied because item.render cannot mutate a const - auto item = scene->getItem(itemDetails.id); + auto& item = scene->getItem(itemDetails.id); item.render(args); } } -void renderShape(RenderArgs* args, const ShapePipelineLib& shapeContext, Item& item) { +void renderShape(RenderArgs* args, const ShapePipelineLib& shapeContext, const Item& item) { assert(item.getKey().isShape()); const auto& key = item.getShapeKey(); if (key.isValid() && !key.hasOwnPipeline()) { @@ -242,8 +241,7 @@ void render::renderShapes(const SceneContextPointer& sceneContext, const RenderC auto numItemsToDraw = glm::max((int)inItems.size(), maxDrawnItems); for (auto i = 0; i < numItemsToDraw; ++i) { - // FIXME: Every item is copied because item.render cannot mutate a const - auto item = scene->getItem(inItems[i].id); + auto& item = scene->getItem(inItems[i].id); renderShape(args, shapeContext, item); } } diff --git a/libraries/render/src/render/Scene.h b/libraries/render/src/render/Scene.h index 3a6463b538..567e054a8a 100644 --- a/libraries/render/src/render/Scene.h +++ b/libraries/render/src/render/Scene.h @@ -305,7 +305,7 @@ public: int getLayer() const { return _payload->getLayer(); } // Render call for the item - void render(RenderArgs* args) { _payload->render(args); } + void render(RenderArgs* args) const { _payload->render(args); } // Shape Type Interface const ShapeKey getShapeKey() const { return _payload->getShapeKey(); } From d8a3ae70a7c1ff418e5403376af7de927b72bdc6 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Thu, 7 Jan 2016 17:02:15 -0800 Subject: [PATCH 25/39] Conform to coding standard --- .../render-utils/src/MeshPartPayload.cpp | 45 ++++++++++++------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index b1c40ac5b5..492021c1a9 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -99,16 +99,19 @@ ShapeKey MeshPartPayload::getShapeKey() const { drawMaterialKey = _drawMaterial->getKey(); } - bool isTranslucent = drawMaterialKey.isTransparent() || drawMaterialKey.isTransparentMap(); - bool hasTangents = drawMaterialKey.isNormalMap(); - bool hasSpecular = drawMaterialKey.isGlossMap(); - bool hasLightmap = drawMaterialKey.isLightmapMap(); - ShapeKey::Builder builder; - if (isTranslucent) { builder.withTranslucent(); } - if (hasTangents) { builder.withTangents(); } - if (hasSpecular) { builder.withSpecular(); } - if (hasLightmap) { builder.withLightmap(); } + if (drawMaterialKey.isTransparent() || drawMaterialKey.isTransparentMap()) { + builder.withTranslucent(); + } + if (drawMaterialKey.isNormalMap()) { + builder.withTangents(); + } + if (drawMaterialKey.isGlossMap()) { + builder.withSpecular(); + } + if (drawMaterialKey.isLightmapMap()) { + builder.withLightmap(); + } return builder.build(); } @@ -395,12 +398,24 @@ ShapeKey ModelMeshPartPayload::getShapeKey() const { } ShapeKey::Builder builder; - if (isTranslucent) { builder.withTranslucent(); } - if (hasTangents) { builder.withTangents(); } - if (hasSpecular) { builder.withSpecular(); } - if (hasLightmap) { builder.withLightmap(); } - if (isSkinned) { builder.withSkinned(); } - if (wireframe) { builder.withWireframe(); } + if (isTranslucent) { + builder.withTranslucent(); + } + if (hasTangents) { + builder.withTangents(); + } + if (hasSpecular) { + builder.withSpecular(); + } + if (hasLightmap) { + builder.withLightmap(); + } + if (isSkinned) { + builder.withSkinned(); + } + if (wireframe) { + builder.withWireframe(); + } return builder.build(); } From 56aba412993e2db8250afc4b7921266b2eacf98b Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 8 Jan 2016 12:57:47 -0800 Subject: [PATCH 26/39] Rename ShapeRender to DeferredPipelineLib --- ...ShapeRender.cpp => DeferredPipelineLib.cpp} | 18 +++++++++--------- .../{ShapeRender.h => DeferredPipelineLib.h} | 12 ++++++------ libraries/render-utils/src/MeshPartPayload.h | 3 +-- libraries/render-utils/src/Model.cpp | 5 +++-- .../render-utils/src/RenderDeferredTask.cpp | 6 +++--- .../render-utils/src/RenderDeferredTask.h | 8 ++++---- 6 files changed, 26 insertions(+), 26 deletions(-) rename libraries/render-utils/src/{ShapeRender.cpp => DeferredPipelineLib.cpp} (92%) rename libraries/render-utils/src/{ShapeRender.h => DeferredPipelineLib.h} (69%) diff --git a/libraries/render-utils/src/ShapeRender.cpp b/libraries/render-utils/src/DeferredPipelineLib.cpp similarity index 92% rename from libraries/render-utils/src/ShapeRender.cpp rename to libraries/render-utils/src/DeferredPipelineLib.cpp index c4ac9f3c2b..0526700633 100644 --- a/libraries/render-utils/src/ShapeRender.cpp +++ b/libraries/render-utils/src/DeferredPipelineLib.cpp @@ -1,5 +1,5 @@ // -// ShapeRender.cpp +// DeferredPipelineLib.cpp // render-utils/src // // Created by Zach Pomerantz on 1/4/2015. @@ -9,7 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "ShapeRender.h" +#include "DeferredPipelineLib.h" #include @@ -37,15 +37,15 @@ #include "model_lightmap_specular_map_frag.h" #include "model_translucent_frag.h" -ShapeRender::ShapeRender() { - // TODO: Move pipeline initialization to those Jobs using ShapeRender +DeferredPipelineLib::DeferredPipelineLib() { + // TODO: Move pipeline initialization to those Jobs using DeferredPipelineLib // such that they own their own pipelines and it is done only once if (_pipelineLib.empty()) { initPipeline(); } } -void ShapeRender::initPipeline() { +void DeferredPipelineLib::initPipeline() { assert(_pipelineLib.empty()); // Vertex shaders @@ -171,8 +171,8 @@ void ShapeRender::initPipeline() { skinModelShadowVertex, modelShadowPixel); } -const ShapeRender::PipelinePointer ShapeRender::pickPipeline(RenderArgs* args, const Key& key) const { - PerformanceTimer perfTimer("ShapeRender::pickPipeline"); +const DeferredPipelineLib::PipelinePointer DeferredPipelineLib::pickPipeline(RenderArgs* args, const Key& key) const { + PerformanceTimer perfTimer("DeferredPipelineLib::pickPipeline"); auto pipeline = _pickPipeline(args, key); if (!pipeline) { @@ -187,9 +187,9 @@ const ShapeRender::PipelinePointer ShapeRender::pickPipeline(RenderArgs* args, c return pipeline; } -model::MaterialPointer ShapeRender::_collisionHullMaterial; +model::MaterialPointer DeferredPipelineLib::_collisionHullMaterial; -model::MaterialPointer ShapeRender::getCollisionHullMaterial() { +model::MaterialPointer DeferredPipelineLib::getCollisionHullMaterial() { if (!_collisionHullMaterial) { _collisionHullMaterial = std::make_shared(); _collisionHullMaterial->setDiffuse(glm::vec3(1.0f, 0.5f, 0.0f)); diff --git a/libraries/render-utils/src/ShapeRender.h b/libraries/render-utils/src/DeferredPipelineLib.h similarity index 69% rename from libraries/render-utils/src/ShapeRender.h rename to libraries/render-utils/src/DeferredPipelineLib.h index 590eca5511..98408d7754 100644 --- a/libraries/render-utils/src/ShapeRender.h +++ b/libraries/render-utils/src/DeferredPipelineLib.h @@ -1,5 +1,5 @@ // -// ShapeRender.h +// DeferredPipelineLib.h // render-utils/src // // Created by Zach Pomerantz on 1/4/2015. @@ -9,15 +9,15 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#ifndef hifi_render_utils_Shape_h -#define hifi_render_utils_Shape_h +#ifndef hifi_render_utils_DeferredPipelineLib_h +#define hifi_render_utils_DeferredPipelineLib_h #include #include -class ShapeRender : public render::ShapePipelineLib { +class DeferredPipelineLib : public render::ShapePipelineLib { public: - ShapeRender(); + DeferredPipelineLib(); static void initPipeline(); const PipelinePointer pickPipeline(RenderArgs* args, const Key& key) const override; @@ -27,4 +27,4 @@ protected: static model::MaterialPointer _collisionHullMaterial; }; -#endif // hifi_render_utils_Shape_h +#endif // hifi_render_utils_DeferredPipelineLib_h diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index 7d693dcbe9..d771a57203 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -15,11 +15,10 @@ #include #include +#include #include -#include "ShapeRender.h" - class Model; class MeshPartPayload { diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index b40d2565c3..40352a1bc3 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -22,8 +22,9 @@ #include #include "AbstractViewStateInterface.h" -#include "Model.h" +#include "DeferredPipelineLib.h" #include "MeshPartPayload.h" +#include "Model.h" #include "RenderUtilsLogging.h" @@ -1193,7 +1194,7 @@ void Model::segregateMeshGroups() { int totalParts = mesh.parts.size(); for (int partIndex = 0; partIndex < totalParts; partIndex++) { if (showingCollisionHull) { - _renderItemsSet << std::make_shared(networkMesh._mesh, partIndex, ShapeRender::getCollisionHullMaterial(), transform, offset); + _renderItemsSet << std::make_shared(networkMesh._mesh, partIndex, DeferredPipelineLib::getCollisionHullMaterial(), transform, offset); } else { _renderItemsSet << std::make_shared(this, i, partIndex, shapeID, transform, offset); diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index a35447cd05..e3bf699fc8 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -193,7 +193,7 @@ void DrawOpaqueDeferred::run(const SceneContextPointer& sceneContext, const Rend batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); - renderShapes(sceneContext, renderContext, _renderer, inItems, opaque.maxDrawn); + renderShapes(sceneContext, renderContext, _deferredPipelineLib, inItems, opaque.maxDrawn); args->_batch = nullptr; }); } @@ -219,7 +219,7 @@ void DrawTransparentDeferred::run(const SceneContextPointer& sceneContext, const batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); - renderShapes(sceneContext, renderContext, _renderer, inItems, transparent.maxDrawn); + renderShapes(sceneContext, renderContext, _deferredPipelineLib, inItems, transparent.maxDrawn); args->_batch = nullptr; }); } @@ -292,7 +292,7 @@ void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderCon batch.setPipeline(getOpaquePipeline()); batch.setResourceTexture(0, args->_whiteTexture); - renderShapes(sceneContext, renderContext, _renderer, inItems, renderContext->getItemsConfig().overlay3D.maxDrawn); + renderShapes(sceneContext, renderContext, _deferredPipelineLib, inItems, renderContext->getItemsConfig().overlay3D.maxDrawn); }); args->_batch = nullptr; args->_whiteTexture.reset(); diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index 01e9ab2a16..171fe843da 100755 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -16,7 +16,7 @@ #include "gpu/Pipeline.h" -#include "ShapeRender.h" +#include "DeferredPipelineLib.h" #include "ToneMappingEffect.h" class SetupDeferred { @@ -57,7 +57,7 @@ public: typedef render::Job::ModelI JobModel; protected: - ShapeRender _renderer; + DeferredPipelineLib _deferredPipelineLib; }; class DrawTransparentDeferred { @@ -67,7 +67,7 @@ public: typedef render::Job::ModelI JobModel; protected: - ShapeRender _renderer; + DeferredPipelineLib _deferredPipelineLib; }; class DrawStencilDeferred { @@ -99,7 +99,7 @@ public: protected: static gpu::PipelinePointer _opaquePipeline; //lazy evaluation hence mutable - ShapeRender _renderer; + DeferredPipelineLib _deferredPipelineLib; }; class Blit { From bf68f2f2fa5d554f05d09211daf36c388c59c38e Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 8 Jan 2016 11:56:19 -0800 Subject: [PATCH 27/39] Templatize item culling --- .../render-utils/src/RenderDeferredTask.cpp | 4 +-- libraries/render/src/render/DrawTask.cpp | 31 ++----------------- libraries/render/src/render/DrawTask.h | 20 +++++------- 3 files changed, 11 insertions(+), 44 deletions(-) diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index e3bf699fc8..b68108d6f1 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -56,7 +56,7 @@ RenderDeferredTask::RenderDeferredTask() : Task() { context->getItemsConfig().opaque.numFeed = count; }) ))); - _jobs.push_back(Job(new CullItemsOpaque::JobModel("CullOpaque", _jobs.back().getOutput()))); + _jobs.push_back(Job(new CullItems::JobModel("CullOpaque", _jobs.back().getOutput()))); _jobs.push_back(Job(new DepthSortItems::JobModel("DepthSortOpaque", _jobs.back().getOutput()))); auto& renderedOpaques = _jobs.back().getOutput(); @@ -67,7 +67,7 @@ RenderDeferredTask::RenderDeferredTask() : Task() { context->getItemsConfig().transparent.numFeed = count; }) ))); - _jobs.push_back(Job(new CullItemsTransparent::JobModel("CullTransparent", _jobs.back().getOutput()))); + _jobs.push_back(Job(new CullItems::JobModel("CullTransparent", _jobs.back().getOutput()))); _jobs.push_back(Job(new DepthSortItems::JobModel("DepthSortTransparent", _jobs.back().getOutput(), DepthSortItems(false)))); auto& renderedTransparents = _jobs.back().getOutput(); diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index 1b6bae54c8..ec82da3d09 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -111,34 +111,6 @@ void FetchItems::run(const SceneContextPointer& sceneContext, const RenderContex } } -void CullItems::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outItems) { - - outItems.clear(); - outItems.reserve(inItems.size()); - RenderArgs* args = renderContext->getArgs(); - args->_details.pointTo(RenderDetails::OTHER_ITEM); - cullItems(sceneContext, renderContext, inItems, outItems); -} - -void CullItemsOpaque::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outItems) { - - outItems.clear(); - outItems.reserve(inItems.size()); - RenderArgs* args = renderContext->getArgs(); - args->_details.pointTo(RenderDetails::OPAQUE_ITEM); - cullItems(sceneContext, renderContext, inItems, outItems); -} - -void CullItemsTransparent::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outItems) { - - outItems.clear(); - outItems.reserve(inItems.size()); - RenderArgs* args = renderContext->getArgs(); - args->_details.pointTo(RenderDetails::TRANSLUCENT_ITEM); - cullItems(sceneContext, renderContext, inItems, outItems); -} - - struct ItemBound { float _centerDepth = 0.0f; float _nearDepth = 0.0f; @@ -261,9 +233,10 @@ void DrawLight::run(const SceneContextPointer& sceneContext, const RenderContext inItems.emplace_back(ItemIDAndBounds(id, item.getBound())); } + RenderArgs* args = renderContext->getArgs(); + ItemIDsBounds culledItems; culledItems.reserve(inItems.size()); - RenderArgs* args = renderContext->getArgs(); args->_details.pointTo(RenderDetails::OTHER_ITEM); cullItems(sceneContext, renderContext, inItems, culledItems); diff --git a/libraries/render/src/render/DrawTask.h b/libraries/render/src/render/DrawTask.h index 81dc7d358a..ef9508365c 100755 --- a/libraries/render/src/render/DrawTask.h +++ b/libraries/render/src/render/DrawTask.h @@ -239,24 +239,18 @@ public: typedef Job::ModelO JobModel; }; +template class CullItems { public: - void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outItems); + void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outItems) { + outItems.clear(); + outItems.reserve(inItems.size()); + renderContext->getArgs()->_details.pointTo(T); + render::cullItems(sceneContext, renderContext, inItems, outItems); + } typedef Job::ModelIO JobModel; }; -class CullItemsOpaque { -public: - void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outItems); - typedef Job::ModelIO JobModel; -}; - -class CullItemsTransparent { -public: - void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outItems); - typedef Job::ModelIO JobModel; -}; - class DepthSortItems { public: bool _frontToBack = true; From ea8bdd57280d5c4ebac760daaf796b72153c3d77 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 8 Jan 2016 14:58:29 -0800 Subject: [PATCH 28/39] Change pipeline initialization to depend on class, not global pipelineLib state --- .../render-utils/src/DeferredPipelineLib.cpp | 38 ++++++++++--------- .../render-utils/src/DeferredPipelineLib.h | 4 +- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/libraries/render-utils/src/DeferredPipelineLib.cpp b/libraries/render-utils/src/DeferredPipelineLib.cpp index 0526700633..70f8d13a07 100644 --- a/libraries/render-utils/src/DeferredPipelineLib.cpp +++ b/libraries/render-utils/src/DeferredPipelineLib.cpp @@ -38,13 +38,29 @@ #include "model_translucent_frag.h" DeferredPipelineLib::DeferredPipelineLib() { - // TODO: Move pipeline initialization to those Jobs using DeferredPipelineLib - // such that they own their own pipelines and it is done only once - if (_pipelineLib.empty()) { + 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()); @@ -169,22 +185,8 @@ void DeferredPipelineLib::initPipeline() { _pipelineLib.addPipeline( Key::Builder().withSkinned().withDepthOnly().withShadow(), skinModelShadowVertex, modelShadowPixel); -} -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; + _isInitPipeline = true; } model::MaterialPointer DeferredPipelineLib::_collisionHullMaterial; diff --git a/libraries/render-utils/src/DeferredPipelineLib.h b/libraries/render-utils/src/DeferredPipelineLib.h index 98408d7754..4ea891c58c 100644 --- a/libraries/render-utils/src/DeferredPipelineLib.h +++ b/libraries/render-utils/src/DeferredPipelineLib.h @@ -18,12 +18,14 @@ class DeferredPipelineLib : public render::ShapePipelineLib { public: DeferredPipelineLib(); - static void initPipeline(); 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; }; From c1e8fe88e4506dcddeb4a45c086fd4a4802a674f Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 8 Jan 2016 16:12:32 -0800 Subject: [PATCH 29/39] Fix shader typo (ambien->ambient) --- libraries/render-utils/src/DeferredGlobalLight.slh | 4 ++-- libraries/render-utils/src/directional_ambient_light.slf | 2 +- libraries/render-utils/src/directional_light.slf | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/render-utils/src/DeferredGlobalLight.slh b/libraries/render-utils/src/DeferredGlobalLight.slh index 11e157a50c..ca46ad0ebf 100755 --- a/libraries/render-utils/src/DeferredGlobalLight.slh +++ b/libraries/render-utils/src/DeferredGlobalLight.slh @@ -70,7 +70,7 @@ uniform SphericalHarmonics ambientSphere; <@include model/Light.slh@> <@func declareEvalAmbientGlobalColor()@> -vec3 evalAmbienGlobalColor(mat4 invViewMat, float shadowAttenuation, vec3 position, vec3 normal, vec3 diffuse, vec3 specular, float gloss) { +vec3 evalAmbientGlobalColor(mat4 invViewMat, float shadowAttenuation, vec3 position, vec3 normal, vec3 diffuse, vec3 specular, float gloss) { // Need the light now Light light = getLight(); @@ -93,7 +93,7 @@ vec3 evalAmbienGlobalColor(mat4 invViewMat, float shadowAttenuation, vec3 positi <$declareSphericalHarmonics()$> -vec3 evalAmbienSphereGlobalColor(mat4 invViewMat, float shadowAttenuation, vec3 position, vec3 normal, vec3 diffuse, vec3 specular, float gloss) { +vec3 evalAmbientSphereGlobalColor(mat4 invViewMat, float shadowAttenuation, vec3 position, vec3 normal, vec3 diffuse, vec3 specular, float gloss) { // Need the light now Light light = getLight(); diff --git a/libraries/render-utils/src/directional_ambient_light.slf b/libraries/render-utils/src/directional_ambient_light.slf index ae3b05862e..a905dbdfd5 100755 --- a/libraries/render-utils/src/directional_ambient_light.slf +++ b/libraries/render-utils/src/directional_ambient_light.slf @@ -36,7 +36,7 @@ void main(void) { frag.specularVal.xyz); _fragColor = vec4(color, 1.0); } else { - vec3 color = evalAmbienSphereGlobalColor( + vec3 color = evalAmbientSphereGlobalColor( deferredTransform.viewInverse, 1.0, frag.position.xyz, diff --git a/libraries/render-utils/src/directional_light.slf b/libraries/render-utils/src/directional_light.slf index 22b0157762..eff40df255 100644 --- a/libraries/render-utils/src/directional_light.slf +++ b/libraries/render-utils/src/directional_light.slf @@ -37,7 +37,7 @@ void main(void) { frag.specularVal.xyz); _fragColor = vec4(color, 1.0); } else { - vec3 color = evalAmbienGlobalColor( + vec3 color = evalAmbientGlobalColor( deferredTransform.viewInverse, 1.0, frag.position.xyz, From 293e432fe9a031edb18b84abce256c0a7a031f3d Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 8 Jan 2016 18:05:09 -0800 Subject: [PATCH 30/39] Fix setter named getFocalLength --- libraries/octree/src/ViewFrustum.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/octree/src/ViewFrustum.h b/libraries/octree/src/ViewFrustum.h index 596d042506..795a259a3c 100644 --- a/libraries/octree/src/ViewFrustum.h +++ b/libraries/octree/src/ViewFrustum.h @@ -48,7 +48,7 @@ public: // setters for lens attributes void setProjection(const glm::mat4 & projection); - void getFocalLength(float focalLength) { _focalLength = focalLength; } + void setFocalLength(float focalLength) { _focalLength = focalLength; } // getters for lens attributes const glm::mat4& getProjection() const { return _projection; } From 407c1bc62682cf331450b7531c7d1c9bccc3866d Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 8 Jan 2016 18:47:03 -0800 Subject: [PATCH 31/39] Handle out-of-range in render::FetchItems --- libraries/render/src/render/DrawTask.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index ec82da3d09..27cd2011d8 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -97,13 +97,17 @@ void render::cullItems(const SceneContextPointer& sceneContext, const RenderCont void FetchItems::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, ItemIDsBounds& outItems) { auto& scene = sceneContext->_scene; - auto& items = scene->getMasterBucket().at(_filter); outItems.clear(); - outItems.reserve(items.size()); - for (auto id : items) { - auto& item = scene->getItem(id); - outItems.emplace_back(ItemIDAndBounds(id, item.getBound())); + + const auto& bucket = scene->getMasterBucket(); + const auto& items = bucket.find(_filter); + if (items != bucket.end()) { + outItems.reserve(items->second.size()); + for (auto& id : items->second) { + auto& item = scene->getItem(id); + outItems.emplace_back(ItemIDAndBounds(id, item.getBound())); + } } if (_probeNumItems) { From e4855b7595e954793eba406ce0fb6621047456f0 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Sun, 10 Jan 2016 15:34:46 -0800 Subject: [PATCH 32/39] Script that drops different kinds of entities near you --- examples/dropStuffNearMe.js | 88 +++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 examples/dropStuffNearMe.js diff --git a/examples/dropStuffNearMe.js b/examples/dropStuffNearMe.js new file mode 100644 index 0000000000..0b84490b4c --- /dev/null +++ b/examples/dropStuffNearMe.js @@ -0,0 +1,88 @@ +// +// Created by Philip Rosedale on January 9, 2016 +// 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 +// +// Puts a bunch of entities in front of you, with various adjustable properties for testing. +// +// Note that when creating things quickly, the entity server will ignore data if we send updates too quickly. +// like Internet MTU, these rates are set by th domain operator, so in this script there is a RATE_PER_SECOND +// variable letting you set this speed. If entities are missing from the grid after a relog, this number +// being too high may be the reason. + +var SIZE = 0.5; +var TYPE = "Box"; // Right now this can be "Box" or "Model" or "Sphere" +var MODEL_URL = "http://s3.amazonaws.com/hifi-public/models/content/basketball2.fbx"; +var MODEL_DIMENSION = { x: 0.3, y: 0.3, z: 0.3 }; + +var RATE_PER_SECOND = 1000; // The entity server will drop data if we create things too fast. +var SCRIPT_INTERVAL = 100; +var LIFETIME = 90; + +var NUMBER_TO_CREATE = 300; + +var GRAVITY = { x: 0, y: -9.8, z: 0 }; +var VELOCITY = { x: 0.0, y: 0, z: 0 }; +var ANGULAR_VELOCITY = { x: 1, y: 1, z: 1 }; + +var DAMPING = 0.5; +var ANGULAR_DAMPING = 0.5; + +var collidable = true; +var gravity = true; + + +var x = 0; +var z = 0; +var totalCreated = 0; + +var RANGE = 10; +var HOW_FAR_IN_FRONT_OF_ME = 3 * RANGE; + + +var center = Vec3.sum(MyAvatar.position, Vec3.multiply(HOW_FAR_IN_FRONT_OF_ME, Quat.getFront(Camera.orientation))); + + +function randomVector(range) { + return { + x: (Math.random() - 0.5) * range.x, + y: (Math.random() - 0.5) * range.y, + z: (Math.random() - 0.5) * range.z + } +} + +Vec3.print("Center: ", center); + +Script.setInterval(function () { + if (!Entities.serversExist() || !Entities.canRez() || (totalCreated > NUMBER_TO_CREATE)) { + return; + } + + var numToCreate = RATE_PER_SECOND * (SCRIPT_INTERVAL / 1000.0); + for (var i = 0; i < numToCreate; i++) { + var position = Vec3.sum(center, randomVector({ x: RANGE, y: RANGE, z: RANGE })); + if (totalCreated < NUMBER_TO_CREATE) { + Vec3.print("Position: ", position); + Entities.addEntity({ + type: TYPE, + modelURL: MODEL_URL, + name: "gridTest", + position: position, + dimensions: (TYPE == "Model") ? MODEL_DIMENSION : { x: SIZE, y: SIZE, z: SIZE }, + color: { red: Math.random() * 255, green: Math.random() * 255, blue: Math.random() * 255 }, + velocity: VELOCITY, + angularVelocity: Vec3.multiply(Math.random(), ANGULAR_VELOCITY), + damping: DAMPING, + angularDamping: ANGULAR_DAMPING, + gravity: (gravity ? GRAVITY : { x: 0, y: 0, z: 0}), + collisionsWillMove: collidable, + lifetime: LIFETIME + }); + } + + totalCreated++; + } +}, SCRIPT_INTERVAL); + From b8565358ffc30cdf2f9e9f8ace48ce965682d942 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Mon, 11 Jan 2016 09:16:33 -0800 Subject: [PATCH 33/39] Added basic energy bar example --- examples/example/ui/energyBar.js | 105 +++++++++++++++++++++++++++++++ examples/libraries/utils.js | 5 ++ 2 files changed, 110 insertions(+) create mode 100644 examples/example/ui/energyBar.js diff --git a/examples/example/ui/energyBar.js b/examples/example/ui/energyBar.js new file mode 100644 index 0000000000..b0abf6778b --- /dev/null +++ b/examples/example/ui/energyBar.js @@ -0,0 +1,105 @@ +// energyBar.js +// examples/ui +// +// Created by Eric Levin on 1/4/15 +// Copyright 2015 High Fidelity, Inc. +// +// This script adds an energy bar overlay which displays the amount of energy a user has left for grabbing and moving objects +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +Script.include("../../libraries/utils.js"); +var energyColor = {red: 0, green: 200, blue: 0}; +var lowEnergyColor = {red: 255, green: 0, blue: 0}; +var totalWidth = 200; +var paddingRight = 50; +var xPosition = Window.innerWidth - totalWidth - paddingRight; +var lowEnergyThreshold = 0.3; +var currentEnergy = 1.0; +var energyLossRate = 0.003; +var energyChargeRate = 0.003; +var isGrabbing = false; +var refractoryPeriod = 2000; + +var lastAvatarVelocity = MyAvatar.getVelocity(); +var lastAvatarPosition = MyAvatar.position; + +var background = Overlays.addOverlay("text", { + x: xPosition, + y: 20, + width: totalWidth, + height: 10, + backgroundColor: {red: 184, green: 181, blue: 178} +}) + +var bar = Overlays.addOverlay("text", { + x: xPosition, + y: 20, + width: totalWidth, + height: 10, + backgroundColor: energyColor +}); + + +// Takes an energy value between 0 and 1 and sets energy bar width appropriately +function setEnergy(energy) { + energy = clamp(energy, 0, 1); + var barWidth = totalWidth * energy; + var color = energy <= lowEnergyThreshold ? lowEnergyColor: energyColor; + Overlays.editOverlay(bar, { width: barWidth, backgroundColor: color}); +} + +function avatarAccelerationEnergy() { + var AVATAR_MOVEMENT_ENERGY_CONSTANT = 0.001; + var velocity = MyAvatar.getVelocity(); + var dV = Vec3.subtract(velocity, lastAvatarVelocity); + var dE = Vec3.length(lastAvatarVelocity) * Vec3.length(dV) * AVATAR_MOVEMENT_ENERGY_CONSTANT; + lastAvatarVelocity = velocity; + if (dE > 0.01) { + print("de " + dE); + } + return dE; +} + +function teleported() { + var MAX_AVATAR_MOVEMENT_PER_FRAME = 30.0; + var position = MyAvatar.position; + var dP = Vec3.length(Vec3.subtract(position, lastAvatarPosition)); + lastAvatarPosition = position; + return (dP > MAX_AVATAR_MOVEMENT_PER_FRAME); +} + +function audioEnergy() { + var AUDIO_ENERGY_CONSTANT = 0.000001; + return MyAvatar.audioLoudness * AUDIO_ENERGY_CONSTANT; +} + +function update() { + // refill energy + currentEnergy += energyChargeRate; + + // Avatar acceleration + currentEnergy -= avatarAccelerationEnergy(); + + // Teleport cost + if (teleported()) { + currentEnergy = 0; + } + + // Making sounds + currentEnergy -= audioEnergy(); + + + currentEnergy = clamp(currentEnergy, 0, 1); + setEnergy(currentEnergy); +} + +function cleanup() { + Overlays.deleteOverlay(background); + Overlays.deleteOverlay(bar); +} + +Script.update.connect(update); +Script.scriptEnding.connect(cleanup); diff --git a/examples/libraries/utils.js b/examples/libraries/utils.js index 115c1bcb65..b2b2902cb0 100644 --- a/examples/libraries/utils.js +++ b/examples/libraries/utils.js @@ -297,3 +297,8 @@ calculateHandSizeRatio = function() { var handSizeRatio = centerHandPoint/standardCenterHandPoint; return handSizeRatio; } + +clamp = function(val, min, max){ + return Math.max(min, Math.min(max, val)) + } + From 4ff2b85e1a87f14fb4cce2f80396c182aaec5722 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Mon, 11 Jan 2016 16:00:08 -0800 Subject: [PATCH 34/39] 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; } From db91b12203ab0fc0d342219b799e58f5d82b418f Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Mon, 11 Jan 2016 17:31:19 -0800 Subject: [PATCH 35/39] Refine addPipeline signature to be more explicit --- .../render-utils/src/RenderDeferredTask.cpp | 91 +++++++++++++------ libraries/render/src/render/ShapePipeline.cpp | 58 ++++-------- libraries/render/src/render/ShapePipeline.h | 27 +++--- 3 files changed, 94 insertions(+), 82 deletions(-) diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index e533e2cb49..ddb8e928c5 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -74,12 +74,7 @@ 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()); - } - }); + ShapePlumberPointer shapePlumber; initDeferredPipelines(*shapePlumber); // CPU only, create the list of renderedOpaques items @@ -513,8 +508,45 @@ int RenderDeferredTask::getToneMappingToneCurve() const { } } +void pipelineBatchSetter(const ShapePipeline& pipeline, gpu::Batch& batch) { + if (pipeline.locations->normalFittingMapUnit > -1) { + batch.setResourceTexture(pipeline.locations->normalFittingMapUnit, + DependencyManager::get()->getNormalFittingTexture()); + } +} + void initDeferredPipelines(render::ShapePlumber& plumber) { using Key = render::ShapeKey; + using ShaderPointer = gpu::ShaderPointer; + + auto addPipeline = [&plumber](const Key& key, const ShaderPointer& vertexShader, const ShaderPointer& pixelShader) { + auto state = std::make_shared(); + + // Cull backface + 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(), + // 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); + + ShaderPointer program = gpu::Shader::createProgram(vertexShader, pixelShader); + plumber.addPipeline(key, program, state, &pipelineBatchSetter); + + // Add a wireframe version + if (!key.isWireFrame()) { + auto wireFrameKey = Key::Builder(key).withWireframe(); + auto wireFrameState = std::make_shared(state->getValues()); + + wireFrameState->setFillMode(gpu::State::FILL_LINE); + + plumber.addPipeline(wireFrameKey, program, wireFrameState, &pipelineBatchSetter); + } + }; // Vertex shaders auto modelVertex = gpu::Shader::createVertex(std::string(model_vert)); @@ -539,102 +571,101 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { auto modelLightmapNormalSpecularMapPixel = gpu::Shader::createPixel(std::string(model_lightmap_normal_specular_map_frag)); // Fill the pipelineLib - - plumber.addPipeline( + addPipeline( Key::Builder(), modelVertex, modelPixel); - plumber.addPipeline( + addPipeline( Key::Builder().withTangents(), modelNormalMapVertex, modelNormalMapPixel); - plumber.addPipeline( + addPipeline( Key::Builder().withSpecular(), modelVertex, modelSpecularMapPixel); - plumber.addPipeline( + addPipeline( Key::Builder().withTangents().withSpecular(), modelNormalMapVertex, modelNormalSpecularMapPixel); - plumber.addPipeline( + addPipeline( Key::Builder().withTranslucent(), modelVertex, modelTranslucentPixel); // FIXME Ignore lightmap for translucents meshpart - plumber.addPipeline( + addPipeline( Key::Builder().withTranslucent().withLightmap(), modelVertex, modelTranslucentPixel); - plumber.addPipeline( + addPipeline( Key::Builder().withTangents().withTranslucent(), modelNormalMapVertex, modelTranslucentPixel); - plumber.addPipeline( + addPipeline( Key::Builder().withSpecular().withTranslucent(), modelVertex, modelTranslucentPixel); - plumber.addPipeline( + addPipeline( Key::Builder().withTangents().withSpecular().withTranslucent(), modelNormalMapVertex, modelTranslucentPixel); - plumber.addPipeline( + addPipeline( Key::Builder().withLightmap(), modelLightmapVertex, modelLightmapPixel); - plumber.addPipeline( + addPipeline( Key::Builder().withLightmap().withTangents(), modelLightmapNormalMapVertex, modelLightmapNormalMapPixel); - plumber.addPipeline( + addPipeline( Key::Builder().withLightmap().withSpecular(), modelLightmapVertex, modelLightmapSpecularMapPixel); - plumber.addPipeline( + addPipeline( Key::Builder().withLightmap().withTangents().withSpecular(), modelLightmapNormalMapVertex, modelLightmapNormalSpecularMapPixel); - plumber.addPipeline( + addPipeline( Key::Builder().withSkinned(), skinModelVertex, modelPixel); - plumber.addPipeline( + addPipeline( Key::Builder().withSkinned().withTangents(), skinModelNormalMapVertex, modelNormalMapPixel); - plumber.addPipeline( + addPipeline( Key::Builder().withSkinned().withSpecular(), skinModelVertex, modelSpecularMapPixel); - plumber.addPipeline( + addPipeline( Key::Builder().withSkinned().withTangents().withSpecular(), skinModelNormalMapVertex, modelNormalSpecularMapPixel); - plumber.addPipeline( + addPipeline( Key::Builder().withSkinned().withTranslucent(), skinModelVertex, modelTranslucentPixel); - plumber.addPipeline( + addPipeline( Key::Builder().withSkinned().withTangents().withTranslucent(), skinModelNormalMapVertex, modelTranslucentPixel); - plumber.addPipeline( + addPipeline( Key::Builder().withSkinned().withSpecular().withTranslucent(), skinModelVertex, modelTranslucentPixel); - plumber.addPipeline( + addPipeline( Key::Builder().withSkinned().withTangents().withSpecular().withTranslucent(), skinModelNormalMapVertex, modelTranslucentPixel); - plumber.addPipeline( + addPipeline( Key::Builder().withDepthOnly(), modelShadowVertex, modelShadowPixel); - plumber.addPipeline( + addPipeline( Key::Builder().withSkinned().withDepthOnly(), skinModelShadowVertex, modelShadowPixel); } diff --git a/libraries/render/src/render/ShapePipeline.cpp b/libraries/render/src/render/ShapePipeline.cpp index 4044750673..5b89b6c6b7 100644 --- a/libraries/render/src/render/ShapePipeline.cpp +++ b/libraries/render/src/render/ShapePipeline.cpp @@ -22,54 +22,29 @@ ShapeKey::Filter::Builder::Builder() { _mask.set(INVALID); } -void defaultStateSetter(ShapeKey key, gpu::State& state) { - // Cull backface - 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(), - // 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); - } -} - -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 +void ShapePlumber::addPipelineHelper(const Filter& filter, ShapeKey key, int bit, const PipelinePointer& pipeline) { + // Iterate over all keys if (bit < (int)ShapeKey::FlagBit::NUM_FLAGS) { - addPipelineHelper(filter, key, ++bit, program, locations); + ++bit; + addPipelineHelper(filter, key, bit, pipeline); if (filter._mask[bit]) { + // Toggle bits set as significant in filter._mask key._flags.flip(bit); - addPipelineHelper(filter, key, ++bit, program, locations); + addPipelineHelper(filter, key, bit, pipeline); } } 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))); + _pipelineMap.insert(PipelineMap::value_type(key, pipeline)); } } -void ShapePlumber::addPipeline(const Key& key, gpu::ShaderPointer& vertexShader, gpu::ShaderPointer& pixelShader) { - addPipeline(Filter{key}, vertexShader, pixelShader); +void ShapePlumber::addPipeline(const Key& key, const gpu::ShaderPointer& program, const gpu::StatePointer& state, + BatchSetter batchSetter) { + addPipeline(Filter{key}, program, state, batchSetter); } -void ShapePlumber::addPipeline(const Filter& filter, gpu::ShaderPointer& vertexShader, gpu::ShaderPointer& pixelShader) { +void ShapePlumber::addPipeline(const Filter& filter, const gpu::ShaderPointer& program, const gpu::StatePointer& state, + BatchSetter batchSetter) { 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)); @@ -80,7 +55,6 @@ void ShapePlumber::addPipeline(const Filter& filter, gpu::ShaderPointer& vertexS slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), Slot::LIGHT_BUFFER)); slotBindings.insert(gpu::Shader::Binding(std::string("normalFittingMap"), Slot::NORMAL_FITTING_MAP)); - gpu::ShaderPointer program = gpu::Shader::createProgram(vertexShader, pixelShader); gpu::Shader::makeProgram(*program, slotBindings); auto locations = std::make_shared(); @@ -96,7 +70,9 @@ void ShapePlumber::addPipeline(const Filter& filter, gpu::ShaderPointer& vertexS locations->lightBufferUnit = program->getBuffers().findLocation("lightBuffer"); ShapeKey key{filter._flags}; - addPipelineHelper(filter, key, 0, program, locations); + auto gpuPipeline = gpu::Pipeline::create(program, state); + auto shapePipeline = std::make_shared(gpuPipeline, locations, batchSetter); + addPipelineHelper(filter, key, 0, shapePipeline); } const ShapePipelinePointer ShapePlumber::pickPipeline(RenderArgs* args, const Key& key) const { @@ -114,7 +90,9 @@ const ShapePipelinePointer ShapePlumber::pickPipeline(RenderArgs* args, const Ke PipelinePointer shapePipeline(pipelineIterator->second); auto& batch = args->_batch; - _batchSetter(*batch, shapePipeline); + + // Run the pipeline's BatchSetter on the passed in batch + shapePipeline->batchSetter(*shapePipeline, *batch); // Setup the one pipeline (to rule them all) batch->setPipeline(shapePipeline->pipeline); diff --git a/libraries/render/src/render/ShapePipeline.h b/libraries/render/src/render/ShapePipeline.h index 04f9e0daa7..3d189f15fa 100644 --- a/libraries/render/src/render/ShapePipeline.h +++ b/libraries/render/src/render/ShapePipeline.h @@ -204,12 +204,18 @@ public: }; using LocationsPointer = std::shared_ptr; + using BatchSetter = std::function; + + ShapePipeline(gpu::PipelinePointer pipeline, LocationsPointer locations, BatchSetter batchSetter) : + pipeline(pipeline), locations(locations), batchSetter(batchSetter) {} + gpu::PipelinePointer pipeline; std::shared_ptr locations; - ShapePipeline() : ShapePipeline(nullptr, nullptr) {} - ShapePipeline(gpu::PipelinePointer pipeline, std::shared_ptr locations) : - pipeline(pipeline), locations(locations) {} +protected: + friend class ShapePlumber; + + BatchSetter batchSetter; }; using ShapePipelinePointer = std::shared_ptr; @@ -223,21 +229,18 @@ public: using Slot = Pipeline::Slot; using Locations = Pipeline::Locations; using LocationsPointer = Pipeline::LocationsPointer; - using StateSetter = std::function; - using BatchSetter = std::function; + using BatchSetter = Pipeline::BatchSetter; - ShapePlumber(); - explicit ShapePlumber(BatchSetter batchSetter); + void addPipeline(const Key& key, const gpu::ShaderPointer& program, const gpu::StatePointer& state, + BatchSetter batchSetter = nullptr); + void addPipeline(const Filter& filter, const gpu::ShaderPointer& program, const gpu::StatePointer& state, + BatchSetter batchSetter = nullptr); - 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: - void addPipelineHelper(const Filter& filter, Key key, int bit, gpu::ShaderPointer pipeline, LocationsPointer locations); + void addPipelineHelper(const Filter& filter, Key key, int bit, const PipelinePointer& pipeline); PipelineMap _pipelineMap; - StateSetter _stateSetter; - BatchSetter _batchSetter; }; using ShapePlumberPointer = std::shared_ptr; From 40aecf3bf423c45ea17a229f310a302054b228ce Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Mon, 11 Jan 2016 17:36:12 -0800 Subject: [PATCH 36/39] I was told there would be no math --- examples/example/ui/energyBar.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/examples/example/ui/energyBar.js b/examples/example/ui/energyBar.js index b0abf6778b..a45b09f6d4 100644 --- a/examples/example/ui/energyBar.js +++ b/examples/example/ui/energyBar.js @@ -54,12 +54,9 @@ function setEnergy(energy) { function avatarAccelerationEnergy() { var AVATAR_MOVEMENT_ENERGY_CONSTANT = 0.001; var velocity = MyAvatar.getVelocity(); - var dV = Vec3.subtract(velocity, lastAvatarVelocity); - var dE = Vec3.length(lastAvatarVelocity) * Vec3.length(dV) * AVATAR_MOVEMENT_ENERGY_CONSTANT; + var dV = Math.abs(Vec3.length(velocity) - Vec3.length(lastAvatarVelocity)); + var dE = Vec3.length(lastAvatarVelocity) * dV * AVATAR_MOVEMENT_ENERGY_CONSTANT; lastAvatarVelocity = velocity; - if (dE > 0.01) { - print("de " + dE); - } return dE; } From 3fdfa1b624580f9a9601558a1c6079cda0a424bf Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Mon, 11 Jan 2016 17:49:46 -0800 Subject: [PATCH 37/39] simpler loop --- examples/dropStuffNearMe.js | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/examples/dropStuffNearMe.js b/examples/dropStuffNearMe.js index 0b84490b4c..1c7c1f4f48 100644 --- a/examples/dropStuffNearMe.js +++ b/examples/dropStuffNearMe.js @@ -61,26 +61,25 @@ Script.setInterval(function () { } var numToCreate = RATE_PER_SECOND * (SCRIPT_INTERVAL / 1000.0); - for (var i = 0; i < numToCreate; i++) { + for (var i = 0; (i < numToCreate) && (totalCreated < NUMBER_TO_CREATE); i++) { var position = Vec3.sum(center, randomVector({ x: RANGE, y: RANGE, z: RANGE })); - if (totalCreated < NUMBER_TO_CREATE) { - Vec3.print("Position: ", position); - Entities.addEntity({ - type: TYPE, - modelURL: MODEL_URL, - name: "gridTest", - position: position, - dimensions: (TYPE == "Model") ? MODEL_DIMENSION : { x: SIZE, y: SIZE, z: SIZE }, - color: { red: Math.random() * 255, green: Math.random() * 255, blue: Math.random() * 255 }, - velocity: VELOCITY, - angularVelocity: Vec3.multiply(Math.random(), ANGULAR_VELOCITY), - damping: DAMPING, - angularDamping: ANGULAR_DAMPING, - gravity: (gravity ? GRAVITY : { x: 0, y: 0, z: 0}), - collisionsWillMove: collidable, - lifetime: LIFETIME - }); - } + + Vec3.print("Position: ", position); + Entities.addEntity({ + type: TYPE, + modelURL: MODEL_URL, + name: "gridTest", + position: position, + dimensions: (TYPE == "Model") ? MODEL_DIMENSION : { x: SIZE, y: SIZE, z: SIZE }, + color: { red: Math.random() * 255, green: Math.random() * 255, blue: Math.random() * 255 }, + velocity: VELOCITY, + angularVelocity: Vec3.multiply(Math.random(), ANGULAR_VELOCITY), + damping: DAMPING, + angularDamping: ANGULAR_DAMPING, + gravity: (gravity ? GRAVITY : { x: 0, y: 0, z: 0}), + collisionsWillMove: collidable, + lifetime: LIFETIME + }); totalCreated++; } From c9e1d8f5f4a2100b081edb127cc45c274b249ac6 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Mon, 11 Jan 2016 19:10:29 -0800 Subject: [PATCH 38/39] Set up pipelinelib correctly (use filters insig bits) --- libraries/render/src/render/ShapePipeline.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/libraries/render/src/render/ShapePipeline.cpp b/libraries/render/src/render/ShapePipeline.cpp index 5b89b6c6b7..99424cbf4b 100644 --- a/libraries/render/src/render/ShapePipeline.cpp +++ b/libraries/render/src/render/ShapePipeline.cpp @@ -25,12 +25,11 @@ ShapeKey::Filter::Builder::Builder() { void ShapePlumber::addPipelineHelper(const Filter& filter, ShapeKey key, int bit, const PipelinePointer& pipeline) { // Iterate over all keys if (bit < (int)ShapeKey::FlagBit::NUM_FLAGS) { - ++bit; - addPipelineHelper(filter, key, bit, pipeline); - if (filter._mask[bit]) { - // Toggle bits set as significant in filter._mask + addPipelineHelper(filter, key, bit + 1, pipeline); + if (!filter._mask[bit]) { + // Toggle bits set as insignificant in filter._mask key._flags.flip(bit); - addPipelineHelper(filter, key, bit, pipeline); + addPipelineHelper(filter, key, bit + 1, pipeline); } } else { // Add the brand new pipeline and cache its location in the lib From 016a14d3d507b2cb3a358dfd01ee0e90068babfc Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Mon, 11 Jan 2016 20:19:54 -0800 Subject: [PATCH 39/39] Init the shapePlumber --- libraries/render-utils/src/RenderDeferredTask.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index ddb8e928c5..ca25383a8d 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -74,7 +74,7 @@ void ToneMappingDeferred::run(const SceneContextPointer& sceneContext, const Ren RenderDeferredTask::RenderDeferredTask() : Task() { // Prepare the ShapePipelines - ShapePlumberPointer shapePlumber; + ShapePlumberPointer shapePlumber = std::make_shared(); initDeferredPipelines(*shapePlumber); // CPU only, create the list of renderedOpaques items