diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp
index ae4654a21a..e75f8593d6 100644
--- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp
+++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp
@@ -97,8 +97,11 @@ void PolyLineEntityRenderer::buildPipelines() {
 }
 
 ItemKey PolyLineEntityRenderer::getKey() {
-    // FIXME: implement isTransparent() for polylines and an opaque pipeline
-    auto builder = ItemKey::Builder::transparentShape().withTypeMeta().withTagBits(getTagMask()).withLayer(getHifiRenderLayer());
+    auto builder = ItemKey::Builder::opaqueShape().withTypeMeta().withTagBits(getTagMask()).withLayer(getHifiRenderLayer());
+
+    if (isTransparent()) {
+        builder.withTransparent();
+    }
 
     if (_cullWithParent) {
         builder.withSubMetaCulled();
diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp
index 60e11f5301..fe005df2d4 100755
--- a/libraries/render-utils/src/RenderShadowTask.cpp
+++ b/libraries/render-utils/src/RenderShadowTask.cpp
@@ -61,12 +61,12 @@ void RenderShadowTask::build(JobModel& task, const render::Varying& input, rende
     const auto currentKeyLight = setupOutput.getN<RenderShadowSetup::Output>(4);
     // Fetch and cull the items from the scene
 
-    static const auto shadowCasterReceiverFilter = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered().withTagBits(tagBits, tagMask);
+    static const auto shadowCasterReceiverFilter = ItemFilter::Builder::visibleWorldItems().withOpaque().withoutLayered().withTagBits(tagBits, tagMask);
 
     const auto fetchInput = FetchSpatialTree::Inputs(shadowCasterReceiverFilter, queryResolution).asVarying();
     const auto shadowSelection = task.addJob<FetchSpatialTree>("FetchShadowTree", fetchInput);
-    const auto selectionInputs = FilterSpatialSelection::Inputs(shadowSelection, shadowCasterReceiverFilter).asVarying();
-    const auto shadowItems = task.addJob<FilterSpatialSelection>("FilterShadowSelection", selectionInputs);
+    const auto selectionInputs = CullSpatialSelection::Inputs(shadowSelection, shadowCasterReceiverFilter).asVarying();
+    const auto shadowItems = task.addJob<CullSpatialSelection>("FilterShadowSelection", selectionInputs, nullptr, true, RenderDetails::SHADOW);
 
     // Cull objects that are not visible in camera view. Hopefully the cull functor only performs LOD culling, not
     // frustum culling or this will make shadow casters out of the camera frustum disappear.
diff --git a/libraries/render/src/render/CullTask.cpp b/libraries/render/src/render/CullTask.cpp
index 5e5c6b4c6e..068d6f9851 100644
--- a/libraries/render/src/render/CullTask.cpp
+++ b/libraries/render/src/render/CullTask.cpp
@@ -172,7 +172,7 @@ void FetchSpatialTree::run(const RenderContextPointer& renderContext, const Inpu
 void CullSpatialSelection::configure(const Config& config) {
     _justFrozeFrustum = _justFrozeFrustum || (config.freezeFrustum && !_freezeFrustum);
     _freezeFrustum = config.freezeFrustum;
-    _skipCulling = config.skipCulling;
+    _overrideSkipCulling = config.skipCulling;
 }
 
 void CullSpatialSelection::run(const RenderContextPointer& renderContext,
@@ -209,7 +209,7 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext,
         // filter individually against the _filter
         // visibility cull if partially selected ( octree cell contianing it was partial)
         // distance cull if was a subcell item ( octree cell is way bigger than the item bound itself, so now need to test per item)
-        if (_skipCulling) {
+        if (_skipCulling || _overrideSkipCulling) {
             // inside & fit items: filter only, culling is disabled
             {
                 PerformanceTimer perfTimer("insideFitItems");
@@ -444,69 +444,3 @@ void ApplyCullFunctorOnItemBounds::run(const RenderContextPointer& renderContext
         args->popViewFrustum();
     }
 }
-
-void FilterSpatialSelection::run(const RenderContextPointer& renderContext,
-                               const Inputs& inputs, ItemBounds& outItems) {
-    assert(renderContext->args);
-    auto& scene = renderContext->_scene;
-    auto& inSelection = inputs.get0();
-
-    // Now we have a selection of items to render
-    outItems.clear();
-    outItems.reserve(inSelection.numItems());
-
-    const auto filter = inputs.get1();
-    if (!filter.selectsNothing()) {
-        // Now get the bound, and
-        // filter individually against the _filter
-
-        // inside & fit items: filter only
-        {
-            PerformanceTimer perfTimer("insideFitItems");
-            for (auto id : inSelection.insideItems) {
-                auto& item = scene->getItem(id);
-                if (filter.test(item.getKey())) {
-                    ItemBound itemBound(id, item.getBound());
-                    outItems.emplace_back(itemBound);
-                }
-            }
-        }
-
-        // inside & subcell items: filter only
-        {
-            PerformanceTimer perfTimer("insideSmallItems");
-            for (auto id : inSelection.insideSubcellItems) {
-                auto& item = scene->getItem(id);
-                if (filter.test(item.getKey())) {
-                    ItemBound itemBound(id, item.getBound());
-                    outItems.emplace_back(itemBound);
-
-                }
-            }
-        }
-
-        // partial & fit items: filter only
-        {
-            PerformanceTimer perfTimer("partialFitItems");
-            for (auto id : inSelection.partialItems) {
-                auto& item = scene->getItem(id);
-                if (filter.test(item.getKey())) {
-                    ItemBound itemBound(id, item.getBound());
-                    outItems.emplace_back(itemBound);
-                }
-            }
-        }
-
-        // partial & subcell items: filter only
-        {
-            PerformanceTimer perfTimer("partialSmallItems");
-            for (auto id : inSelection.partialSubcellItems) {
-                auto& item = scene->getItem(id);
-                if (filter.test(item.getKey())) {
-                    ItemBound itemBound(id, item.getBound());
-                    outItems.emplace_back(itemBound);
-                }
-            }
-        }
-    }
-}
diff --git a/libraries/render/src/render/CullTask.h b/libraries/render/src/render/CullTask.h
index 99ca7abe6c..e67edd6666 100644
--- a/libraries/render/src/render/CullTask.h
+++ b/libraries/render/src/render/CullTask.h
@@ -100,26 +100,25 @@ namespace render {
     };
 
     class CullSpatialSelection {
-        bool _freezeFrustum{ false }; // initialized by Config
-        bool _justFrozeFrustum{ false };
-        bool _skipCulling{ false };
-        ViewFrustum _frozenFrustum;
     public:
         using Config = CullSpatialSelectionConfig;
         using Inputs = render::VaryingSet2<ItemSpatialTree::ItemSelection, ItemFilter>;
         using JobModel = Job::ModelIO<CullSpatialSelection, Inputs, ItemBounds, Config>;
 
-        CullSpatialSelection(CullFunctor cullFunctor, RenderDetails::Type type) :
-            _cullFunctor{ cullFunctor },
+        CullSpatialSelection(CullFunctor cullFunctor, bool skipCulling, RenderDetails::Type type) :
+            _cullFunctor(cullFunctor),
+            _skipCulling(skipCulling),
             _detailType(type) {}
 
-        CullSpatialSelection(CullFunctor cullFunctor) :
-            _cullFunctor{ cullFunctor } {
-        }
-
         CullFunctor _cullFunctor;
+        bool _skipCulling { false };
         RenderDetails::Type _detailType{ RenderDetails::OTHER };
 
+        bool _freezeFrustum { false }; // initialized by Config
+        bool _justFrozeFrustum { false };
+        bool _overrideSkipCulling { false };
+        ViewFrustum _frozenFrustum;
+
         void configure(const Config& config);
         void run(const RenderContextPointer& renderContext, const Inputs& inputs, ItemBounds& outItems);
     };
@@ -147,15 +146,6 @@ namespace render {
 
     };
 
-    class FilterSpatialSelection {
-    public:
-        using Inputs = render::VaryingSet2<ItemSpatialTree::ItemSelection, ItemFilter>;
-        using JobModel = Job::ModelIO<FilterSpatialSelection, Inputs, ItemBounds>;
-
-        FilterSpatialSelection() {}
-        void run(const RenderContextPointer& renderContext, const Inputs& inputs, ItemBounds& outItems);
-    };
-
     class ApplyCullFunctorOnItemBounds {
     public:
         using Inputs = render::VaryingSet2<ItemBounds, ViewFrustumPointer>;
diff --git a/libraries/render/src/render/RenderFetchCullSortTask.cpp b/libraries/render/src/render/RenderFetchCullSortTask.cpp
index 6b1a57ed88..ebcf5a432b 100644
--- a/libraries/render/src/render/RenderFetchCullSortTask.cpp
+++ b/libraries/render/src/render/RenderFetchCullSortTask.cpp
@@ -27,7 +27,7 @@ void RenderFetchCullSortTask::build(JobModel& task, const Varying& input, Varyin
     const auto fetchInput = FetchSpatialTree::Inputs(filter, glm::ivec2(0,0)).asVarying();
     const auto spatialSelection = task.addJob<FetchSpatialTree>("FetchSceneSelection", fetchInput);
     const auto cullInputs = CullSpatialSelection::Inputs(spatialSelection, spatialFilter).asVarying();
-    const auto culledSpatialSelection = task.addJob<CullSpatialSelection>("CullSceneSelection", cullInputs, cullFunctor, RenderDetails::ITEM);
+    const auto culledSpatialSelection = task.addJob<CullSpatialSelection>("CullSceneSelection", cullInputs, cullFunctor, false, RenderDetails::ITEM);
 
     // Layered objects are not culled
     const ItemFilter layeredFilter = ItemFilter::Builder::visibleWorldItems().withTagBits(tagBits, tagMask);