From 25e4f59d55800abb16db2c87f7e0fc484cc80b4c Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Tue, 23 Feb 2021 20:54:57 -0800 Subject: [PATCH] gizmos have materials, working on images --- .../src/RenderableEntityItem.cpp | 172 +++++++++++++++++- .../src/RenderableEntityItem.h | 19 +- .../src/RenderableGizmoEntityItem.cpp | 55 +++++- .../src/RenderableGizmoEntityItem.h | 4 + .../src/RenderableImageEntityItem.cpp | 16 +- .../src/RenderableImageEntityItem.h | 2 + .../src/RenderableShapeEntityItem.cpp | 163 ++++------------- .../src/RenderableShapeEntityItem.h | 3 - 8 files changed, 286 insertions(+), 148 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index b2670e3bce..6fb4be7025 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -29,6 +29,8 @@ #include "RenderableZoneEntityItem.h" #include "RenderableMaterialEntityItem.h" +#include "RenderPipelines.h" + using namespace render; using namespace render::entities; @@ -149,10 +151,11 @@ Item::Bound EntityRenderer::getBound(RenderArgs* args) { } ShapeKey EntityRenderer::getShapeKey() { + ShapeKey::Builder builder = ShapeKey::Builder().withOwnPipeline(); if (_primitiveMode == PrimitiveMode::LINES) { - return ShapeKey::Builder().withOwnPipeline().withWireframe(); + builder.withWireframe(); } - return ShapeKey::Builder().withOwnPipeline(); + return builder.build(); } render::hifi::Tag EntityRenderer::getTagMask() const { @@ -365,6 +368,7 @@ bool EntityRenderer::needsRenderUpdate() const { if (_prevIsTransparent != isTransparent()) { return true; } + return needsRenderUpdateFromEntity(_entity); } @@ -486,6 +490,170 @@ void EntityRenderer::removeMaterial(graphics::MaterialPointer material, const st emit requestRenderUpdate(); } +EntityRenderer::Pipeline EntityRenderer::getPipelineType(const graphics::MultiMaterial& materials) { + if (materials.top().material && materials.top().material->isProcedural() && materials.top().material->isReady()) { + return Pipeline::PROCEDURAL; + } + + graphics::MaterialKey drawMaterialKey = materials.getMaterialKey(); + if (drawMaterialKey.isEmissive() || drawMaterialKey.isUnlit() || drawMaterialKey.isMetallic() || drawMaterialKey.isScattering()) { + return Pipeline::MATERIAL; + } + + // If the material is using any map, we need to use a material ShapeKey + for (int i = 0; i < graphics::Material::MapChannel::NUM_MAP_CHANNELS; i++) { + if (drawMaterialKey.isMapChannel(graphics::Material::MapChannel(i))) { + return Pipeline::MATERIAL; + } + } + return Pipeline::SIMPLE; +} + +bool EntityRenderer::needsRenderUpdateFromMaterials() const { + MaterialMap::const_iterator materials; + { + std::lock_guard lock(_materialsLock); + materials = _materials.find("0"); + + if (materials == _materials.cend()) { + return false; + } + } + + if (materials->second.shouldUpdate()) { + return true; + } + + if (materials->second.top().material && materials->second.top().material->isProcedural() && materials->second.top().material->isReady()) { + auto procedural = std::static_pointer_cast(materials->second.top().material); + if (procedural->isFading()) { + return true; + } + } + + return false; +} + +void EntityRenderer::updateMaterials(bool baseMaterialChanged) { + MaterialMap::iterator materials; + { + std::lock_guard lock(_materialsLock); + materials = _materials.find("0"); + + if (materials == _materials.end()) { + return; + } + } + + if (baseMaterialChanged) { + materials->second.setNeedsUpdate(true); + } + + bool requestUpdate = false; + if (materials->second.top().material && materials->second.top().material->isProcedural() && materials->second.top().material->isReady()) { + auto procedural = std::static_pointer_cast(materials->second.top().material); + if (procedural->isFading()) { + procedural->setIsFading(Interpolate::calculateFadeRatio(procedural->getFadeStartTime()) < 1.0f); + requestUpdate = true; + } + } + + if (materials->second.shouldUpdate()) { + RenderPipelines::updateMultiMaterial(materials->second); + requestUpdate = true; + } + + if (requestUpdate) { + emit requestRenderUpdate(); + } +} + +bool EntityRenderer::materialsTransparent() const { + MaterialMap::const_iterator materials; + { + std::lock_guard lock(_materialsLock); + materials = _materials.find("0"); + + if (materials == _materials.cend()) { + return false; + } + } + + if (materials->second.top().material) { + if (materials->second.top().material->isProcedural() && materials->second.top().material->isReady()) { + auto procedural = std::static_pointer_cast(materials->second.top().material); + if (procedural->isFading()) { + return true; + } + } + + if (materials->second.getMaterialKey().isTranslucent()) { + return true; + } + } + + return false; +} + +Item::Bound EntityRenderer::getMaterialBound(RenderArgs* args) { + MaterialMap::iterator materials; + { + std::lock_guard lock(_materialsLock); + materials = _materials.find("0"); + + if (materials == _materials.end()) { + return EntityRenderer::getBound(args); + } + } + + if (materials->second.top().material && materials->second.top().material->isProcedural() && materials->second.top().material->isReady()) { + auto procedural = std::static_pointer_cast(materials->second.top().material); + if (procedural->hasVertexShader() && procedural->hasBoundOperator()) { + return procedural->getBound(args); + } + } + + return EntityRenderer::getBound(args); +} + +EntityRenderer::MaterialMap::iterator EntityRenderer::getAndUpdateMaterials() { + std::lock_guard lock(_materialsLock); + auto materials = _materials.find("0"); + if (materials != _materials.end() && materials->second.shouldUpdate()) { + RenderPipelines::updateMultiMaterial(materials->second); + } + + return materials; +} + +void EntityRenderer::updateShapeKeyBuilderFromMaterials(ShapeKey::Builder& builder, MaterialMap::iterator materials) const { + { + std::lock_guard lock(_materialsLock); + if (materials == _materials.end()) { + return; + } + } + + builder.withCullFaceMode(materials->second.getCullFaceMode()); + auto pipelineType = getPipelineType(materials->second); + if (pipelineType == Pipeline::MATERIAL) { + builder.withMaterial(); + + graphics::MaterialKey drawMaterialKey = materials->second.getMaterialKey(); + if (drawMaterialKey.isNormalMap()) { + builder.withTangents(); + } + if (drawMaterialKey.isLightMap()) { + builder.withLightMap(); + } + if (drawMaterialKey.isUnlit()) { + builder.withUnlit(); + } + } else if (pipelineType == Pipeline::PROCEDURAL) { + builder.withOwnPipeline(); + } +} + glm::vec4 EntityRenderer::calculatePulseColor(const glm::vec4& color, const PulsePropertyGroup& pulseProperties, quint64 start) { if (pulseProperties.getPeriod() == 0.0f || (pulseProperties.getColorMode() == PulseMode::NONE && pulseProperties.getAlphaMode() == PulseMode::NONE)) { return color; diff --git a/libraries/entities-renderer/src/RenderableEntityItem.h b/libraries/entities-renderer/src/RenderableEntityItem.h index 7f0e1e16ee..6bf145c4e7 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.h +++ b/libraries/entities-renderer/src/RenderableEntityItem.h @@ -55,8 +55,14 @@ public: const uint64_t& getUpdateTime() const { return _updateTime; } + enum class Pipeline { + SIMPLE, + MATERIAL, + PROCEDURAL + }; virtual void addMaterial(graphics::MaterialLayer material, const std::string& parentMaterialName); virtual void removeMaterial(graphics::MaterialPointer material, const std::string& parentMaterialName); + static Pipeline getPipelineType(const graphics::MultiMaterial& materials); virtual scriptable::ScriptableModelBase getScriptableModel() override { return scriptable::ScriptableModelBase(); } @@ -119,6 +125,15 @@ protected: static void makeStatusGetters(const EntityItemPointer& entity, Item::Status::Getters& statusGetters); const Transform& getModelTransform() const; + // Shared methods for entities that support materials + using MaterialMap = std::unordered_map; + bool needsRenderUpdateFromMaterials() const; + void updateMaterials(bool baseMaterialChanged = false); + bool materialsTransparent() const; + Item::Bound getMaterialBound(RenderArgs* args); + MaterialMap::iterator getAndUpdateMaterials(); + void updateShapeKeyBuilderFromMaterials(ShapeKey::Builder& builder, MaterialMap::iterator materials) const; + Item::Bound _bound; SharedSoundPointer _collisionSound; QUuid _changeHandlerId; @@ -139,8 +154,8 @@ protected: bool _moving { false }; Transform _renderTransform; - std::unordered_map _materials; - std::mutex _materialsLock; + MaterialMap _materials; + mutable std::mutex _materialsLock; quint64 _created; diff --git a/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp b/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp index bf005ae2e5..1d4c238148 100644 --- a/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableGizmoEntityItem.cpp @@ -11,10 +11,15 @@ #include #include +#include "RenderPipelines.h" + using namespace render; using namespace render::entities; -GizmoEntityRenderer::GizmoEntityRenderer(const EntityItemPointer& entity) : Parent(entity) {} +GizmoEntityRenderer::GizmoEntityRenderer(const EntityItemPointer& entity) : Parent(entity) { + _material->setCullFaceMode(graphics::MaterialKey::CullFaceMode::CULL_NONE); + addMaterial(graphics::MaterialLayer(_material, 0), "0"); +} GizmoEntityRenderer::~GizmoEntityRenderer() { auto geometryCache = DependencyManager::get(); @@ -31,12 +36,8 @@ GizmoEntityRenderer::~GizmoEntityRenderer() { } } -bool GizmoEntityRenderer::isTransparent() const { - bool ringTransparent = _gizmoType == GizmoType::RING && (_ringProperties.getInnerStartAlpha() < 1.0f || - _ringProperties.getInnerEndAlpha() < 1.0f || _ringProperties.getOuterStartAlpha() < 1.0f || - _ringProperties.getOuterEndAlpha() < 1.0f); - - return Parent::isTransparent() || ringTransparent; +bool GizmoEntityRenderer::needsRenderUpdate() const { + return needsRenderUpdateFromMaterials() || Parent::needsRenderUpdate(); } void GizmoEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) { @@ -193,10 +194,20 @@ void GizmoEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPoint } } } + + updateMaterials(); +} + +bool GizmoEntityRenderer::isTransparent() const { + bool ringTransparent = _gizmoType == GizmoType::RING && (_ringProperties.getInnerStartAlpha() < 1.0f || + _ringProperties.getInnerEndAlpha() < 1.0f || _ringProperties.getOuterStartAlpha() < 1.0f || + _ringProperties.getOuterEndAlpha() < 1.0f); + + return ringTransparent || Parent::isTransparent() || materialsTransparent(); } Item::Bound GizmoEntityRenderer::getBound(RenderArgs* args) { - auto bound = Parent::getBound(args); + auto bound = Parent::getMaterialBound(args); if (_ringProperties.getHasTickMarks()) { glm::vec3 scale = bound.getScale(); for (int i = 0; i < 3; i += 2) { @@ -221,12 +232,19 @@ Item::Bound GizmoEntityRenderer::getBound(RenderArgs* args) { ShapeKey GizmoEntityRenderer::getShapeKey() { auto builder = render::ShapeKey::Builder().withoutCullFace(); + + auto mat = getAndUpdateMaterials(); + if (isTransparent()) { builder.withTranslucent(); } + if (_primitiveMode == PrimitiveMode::LINES) { - builder.withUnlit().withDepthBias(); + builder.withUnlit().withDepthBias().withWireframe(); } + + updateShapeKeyBuilderFromMaterials(builder, mat); + return builder.build(); } @@ -249,15 +267,32 @@ void GizmoEntityRenderer::doRender(RenderArgs* args) { transparent = isTransparent(); }); + graphics::MultiMaterial materials; + { + std::lock_guard lock(_materialsLock); + materials = _materials["0"]; + } + bool wireframe = render::ShapeKey(args->_globalShapeKey).isWireframe() || _primitiveMode == PrimitiveMode::LINES; bool forward = _renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD; - geometryCache->bindSimpleProgram(batch, false, transparent, wireframe, true, true, forward, graphics::MaterialKey::CULL_NONE); + //geometryCache->bindSimpleProgram(batch, false, transparent, wireframe, true, true, forward, materials.getCullFaceMode()); transform.setRotation(BillboardModeHelpers::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? BillboardModeHelpers::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition(), true)); batch.setModelTransform(transform); + Pipeline pipelineType = getPipelineType(materials); + if (pipelineType == Pipeline::PROCEDURAL) { + auto procedural = std::static_pointer_cast(materials.top().material); + transparent |= procedural->isFading(); + procedural->prepare(batch, transform.getTranslation(), transform.getScale(), transform.getRotation(), _created, ProceduralProgramKey(transparent)); + } else { + if (RenderPipelines::bindMaterials(materials, batch, args->_renderMode, args->_enableTexturing)) { + args->_details._materialSwitches++; + } + } + // Background circle geometryCache->renderVertices(batch, wireframe ? gpu::LINE_STRIP : _solidPrimitive, _ringGeometryID); diff --git a/libraries/entities-renderer/src/RenderableGizmoEntityItem.h b/libraries/entities-renderer/src/RenderableGizmoEntityItem.h index 6a09d1a047..b6c22b19de 100644 --- a/libraries/entities-renderer/src/RenderableGizmoEntityItem.h +++ b/libraries/entities-renderer/src/RenderableGizmoEntityItem.h @@ -13,6 +13,8 @@ #include +#include + namespace render { namespace entities { class GizmoEntityRenderer : public TypedEntityRenderer { @@ -29,10 +31,12 @@ protected: bool isTransparent() const override; private: + virtual bool needsRenderUpdate() const override; virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override; virtual void doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) override; virtual void doRender(RenderArgs* args) override; + std::shared_ptr _material { std::make_shared() }; GizmoType _gizmoType { UNSET_GIZMO_TYPE }; RingGizmoPropertyGroup _ringProperties; PrimitiveMode _prevPrimitiveMode; diff --git a/libraries/entities-renderer/src/RenderableImageEntityItem.cpp b/libraries/entities-renderer/src/RenderableImageEntityItem.cpp index e03655f09c..d96c948d7d 100644 --- a/libraries/entities-renderer/src/RenderableImageEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableImageEntityItem.cpp @@ -25,8 +25,8 @@ ImageEntityRenderer::~ImageEntityRenderer() { } } -bool ImageEntityRenderer::isTransparent() const { - return Parent::isTransparent() || (_textureIsLoaded && _texture->getGPUTexture() && _texture->getGPUTexture()->getUsage().isAlpha()) || _alpha < 1.0f || _pulseProperties.getAlphaMode() != PulseMode::NONE; +bool ImageEntityRenderer::needsRenderUpdate() const { + return needsRenderUpdateFromMaterials() || Parent::needsRenderUpdate(); } void ImageEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) { @@ -63,6 +63,18 @@ void ImageEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPoint emit requestRenderUpdate(); } _textureIsLoaded = _texture && (_texture->isLoaded() || _texture->isFailed()); + + updateMaterials(); +} + +bool ImageEntityRenderer::isTransparent() const { + bool imageTransparent = _alpha < 1.0f || _pulseProperties.getAlphaMode() != PulseMode::NONE || + (_textureIsLoaded && _texture->getGPUTexture() && _texture->getGPUTexture()->getUsage().isAlpha()); + return imageTransparent || Parent::isTransparent() || materialsTransparent(); +} + +Item::Bound ImageEntityRenderer::getBound(RenderArgs* args) { + return Parent::getMaterialBound(args); } ShapeKey ImageEntityRenderer::getShapeKey() { diff --git a/libraries/entities-renderer/src/RenderableImageEntityItem.h b/libraries/entities-renderer/src/RenderableImageEntityItem.h index 2359dcc6d1..ca4173d938 100644 --- a/libraries/entities-renderer/src/RenderableImageEntityItem.h +++ b/libraries/entities-renderer/src/RenderableImageEntityItem.h @@ -23,11 +23,13 @@ public: ~ImageEntityRenderer(); protected: + Item::Bound getBound(RenderArgs* args) override; ShapeKey getShapeKey() override; bool isTransparent() const override; private: + virtual bool needsRenderUpdate() const override; virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override; virtual void doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) override; virtual void doRender(RenderArgs* args) override; diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index 674d7c297d..496d933889 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -29,26 +29,7 @@ ShapeEntityRenderer::ShapeEntityRenderer(const EntityItemPointer& entity) : Pare } bool ShapeEntityRenderer::needsRenderUpdate() const { - if (resultWithReadLock([&] { - auto mat = _materials.find("0"); - if (mat != _materials.end() && mat->second.top().material && mat->second.top().material->isProcedural() && - mat->second.top().material->isReady()) { - auto procedural = std::static_pointer_cast(mat->second.top().material); - if (procedural->isFading()) { - return true; - } - } - - if (mat != _materials.end() && mat->second.shouldUpdate()) { - return true; - } - - return false; - })) { - return true; - } - - return Parent::needsRenderUpdate(); + return needsRenderUpdateFromMaterials() || Parent::needsRenderUpdate(); } void ShapeEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) { @@ -94,81 +75,21 @@ void ShapeEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPoint materialChanged = true; } - withReadLock([&] { - auto materials = _materials.find("0"); - if (materials != _materials.end()) { - if (materialChanged) { - materials->second.setNeedsUpdate(true); - } - - bool requestUpdate = false; - if (materials->second.top().material && materials->second.top().material->isProcedural() && materials->second.top().material->isReady()) { - auto procedural = std::static_pointer_cast(materials->second.top().material); - if (procedural->isFading()) { - procedural->setIsFading(Interpolate::calculateFadeRatio(procedural->getFadeStartTime()) < 1.0f); - requestUpdate = true; - } - } - - if (materials->second.shouldUpdate()) { - RenderPipelines::updateMultiMaterial(materials->second); - requestUpdate = true; - } - - if (requestUpdate) { - emit requestRenderUpdate(); - } - } - }); + updateMaterials(materialChanged); } bool ShapeEntityRenderer::isTransparent() const { - if (_pulseProperties.getAlphaMode() != PulseMode::NONE) { - return true; - } - - auto mat = _materials.find("0"); - if (mat != _materials.end() && mat->second.top().material) { - if (mat->second.top().material->isProcedural() && mat->second.top().material->isReady()) { - auto procedural = std::static_pointer_cast(mat->second.top().material); - if (procedural->isFading()) { - return true; - } - } - - if (mat->second.getMaterialKey().isTranslucent()) { - return true; - } - } - - return Parent::isTransparent(); + return _pulseProperties.getAlphaMode() != PulseMode::NONE || Parent::isTransparent() || materialsTransparent(); } -ShapeEntityRenderer::Pipeline ShapeEntityRenderer::getPipelineType(const graphics::MultiMaterial& materials) const { - if (materials.top().material && materials.top().material->isProcedural() && materials.top().material->isReady()) { - return Pipeline::PROCEDURAL; - } - - graphics::MaterialKey drawMaterialKey = materials.getMaterialKey(); - if (drawMaterialKey.isEmissive() || drawMaterialKey.isUnlit() || drawMaterialKey.isMetallic() || drawMaterialKey.isScattering()) { - return Pipeline::MATERIAL; - } - - // If the material is using any map, we need to use a material ShapeKey - for (int i = 0; i < graphics::Material::MapChannel::NUM_MAP_CHANNELS; i++) { - if (drawMaterialKey.isMapChannel(graphics::Material::MapChannel(i))) { - return Pipeline::MATERIAL; - } - } - return Pipeline::SIMPLE; +Item::Bound ShapeEntityRenderer::getBound(RenderArgs* args) { + return Parent::getMaterialBound(args); } ShapeKey ShapeEntityRenderer::getShapeKey() { ShapeKey::Builder builder; - auto mat = _materials.find("0"); - if (mat != _materials.end() && mat->second.shouldUpdate()) { - RenderPipelines::updateMultiMaterial(mat->second); - } + + auto mat = getAndUpdateMaterials(); if (isTransparent()) { builder.withTranslucent(); @@ -178,71 +99,46 @@ ShapeKey ShapeEntityRenderer::getShapeKey() { builder.withWireframe(); } - auto pipelineType = getPipelineType(mat->second); - if (pipelineType == Pipeline::MATERIAL) { - builder.withMaterial(); - - graphics::MaterialKey drawMaterialKey = mat->second.getMaterialKey(); - if (drawMaterialKey.isNormalMap()) { - builder.withTangents(); - } - if (drawMaterialKey.isLightMap()) { - builder.withLightMap(); - } - if (drawMaterialKey.isUnlit()) { - builder.withUnlit(); - } - builder.withCullFaceMode(mat->second.getCullFaceMode()); - } else if (pipelineType == Pipeline::PROCEDURAL) { - builder.withOwnPipeline(); - } + updateShapeKeyBuilderFromMaterials(builder, mat); return builder.build(); } -Item::Bound ShapeEntityRenderer::getBound(RenderArgs* args) { - auto mat = _materials.find("0"); - if (mat != _materials.end() && mat->second.top().material && mat->second.top().material->isProcedural() && - mat->second.top().material->isReady()) { - auto procedural = std::static_pointer_cast(mat->second.top().material); - if (procedural->hasVertexShader() && procedural->hasBoundOperator()) { - return procedural->getBound(args); - } - } - return Parent::getBound(args); -} - void ShapeEntityRenderer::doRender(RenderArgs* args) { PerformanceTimer perfTimer("RenderableShapeEntityItem::render"); Q_ASSERT(args->_batch); gpu::Batch& batch = *args->_batch; - graphics::MultiMaterial materials; auto geometryCache = DependencyManager::get(); GeometryCache::Shape geometryShape = geometryCache->getShapeForEntityShape(_shape); - glm::vec4 outColor; - Pipeline pipelineType; Transform transform; withReadLock([&] { transform = _renderTransform; - materials = _materials["0"]; - pipelineType = getPipelineType(materials); - auto& schema = materials.getSchemaBuffer().get(); - outColor = glm::vec4(ColorUtils::tosRGBVec3(schema._albedo), schema._opacity); }); + graphics::MultiMaterial materials; + { + std::lock_guard lock(_materialsLock); + materials = _materials["0"]; + } + + auto& schema = materials.getSchemaBuffer().get(); + glm::vec4 outColor = glm::vec4(ColorUtils::tosRGBVec3(schema._albedo), schema._opacity); outColor = EntityRenderer::calculatePulseColor(outColor, _pulseProperties, _created); if (outColor.a == 0.0f) { return; } + bool wireframe = render::ShapeKey(args->_globalShapeKey).isWireframe() || _primitiveMode == PrimitiveMode::LINES; + transform.setRotation(BillboardModeHelpers::getBillboardRotation(transform.getTranslation(), transform.getRotation(), _billboardMode, args->_renderMode == RenderArgs::RenderMode::SHADOW_RENDER_MODE ? BillboardModeHelpers::getPrimaryViewFrustumPosition() : args->getViewFrustum().getPosition(), _shape < entity::Shape::Cube || _shape > entity::Shape::Icosahedron)); batch.setModelTransform(transform); + Pipeline pipelineType = getPipelineType(materials); if (pipelineType == Pipeline::PROCEDURAL) { auto procedural = std::static_pointer_cast(materials.top().material); outColor = procedural->getColor(outColor); @@ -251,7 +147,7 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) { procedural->prepare(batch, _position, _dimensions, _orientation, _created, ProceduralProgramKey(outColor.a < 1.0f)); }); - if (render::ShapeKey(args->_globalShapeKey).isWireframe() || _primitiveMode == PrimitiveMode::LINES) { + if (wireframe) { geometryCache->renderWireShape(batch, geometryShape, outColor); } else { geometryCache->renderShape(batch, geometryShape, outColor); @@ -259,12 +155,21 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) { } else if (pipelineType == Pipeline::SIMPLE) { // FIXME, support instanced multi-shape rendering using multidraw indirect outColor.a *= _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f; - render::ShapePipelinePointer pipeline = geometryCache->getShapePipelinePointer(outColor.a < 1.0f, false, - _renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD, materials.top().material->getCullFaceMode()); - if (render::ShapeKey(args->_globalShapeKey).isWireframe() || _primitiveMode == PrimitiveMode::LINES) { - geometryCache->renderWireShapeInstance(args, batch, geometryShape, outColor, pipeline); + bool forward = _renderLayer != RenderLayer::WORLD || args->_renderMethod == Args::RenderMethod::FORWARD; + if (outColor.a >= 1.0f) { + render::ShapePipelinePointer pipeline = geometryCache->getShapePipelinePointer(false, wireframe, + forward, materials.top().material->getCullFaceMode()); + if (wireframe) { + geometryCache->renderWireShapeInstance(args, batch, geometryShape, outColor, pipeline); + } else { + geometryCache->renderSolidShapeInstance(args, batch, geometryShape, outColor, pipeline); + } } else { - geometryCache->renderSolidShapeInstance(args, batch, geometryShape, outColor, pipeline); + if (wireframe) { + geometryCache->renderWireShape(batch, geometryShape, outColor); + } else { + geometryCache->renderShape(batch, geometryShape, outColor); + } } } else { if (RenderPipelines::bindMaterials(materials, batch, args->_renderMode, args->_enableTexturing)) { diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.h b/libraries/entities-renderer/src/RenderableShapeEntityItem.h index fe62ad48b9..b77822aa19 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.h +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.h @@ -35,9 +35,6 @@ private: virtual void doRender(RenderArgs* args) override; virtual bool isTransparent() const override; - enum Pipeline { SIMPLE, MATERIAL, PROCEDURAL }; - Pipeline getPipelineType(const graphics::MultiMaterial& materials) const; - QString _proceduralData; entity::Shape _shape { entity::Sphere };