diff --git a/libraries/entities-renderer/src/RenderableEntityItem.h b/libraries/entities-renderer/src/RenderableEntityItem.h
index c860b849b8..2697d30de4 100644
--- a/libraries/entities-renderer/src/RenderableEntityItem.h
+++ b/libraries/entities-renderer/src/RenderableEntityItem.h
@@ -101,7 +101,7 @@ protected:
     virtual void doRender(RenderArgs* args) = 0;
 
     virtual bool isFading() const { return _isFading; }
-    void updateModelTransformAndBound();
+    virtual void updateModelTransformAndBound();
     virtual bool isTransparent() const { return _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) < 1.0f : false; }
     inline bool isValidRenderItem() const { return _renderItemID != Item::INVALID_ITEM_ID; }
 
@@ -124,7 +124,6 @@ signals:
 protected:
     template<typename T>
     std::shared_ptr<T> asTypedEntity() { return std::static_pointer_cast<T>(_entity); }
-        
 
     static void makeStatusGetters(const EntityItemPointer& entity, Item::Status::Getters& statusGetters);
     const Transform& getModelTransform() const;
@@ -153,7 +152,6 @@ protected:
 
     quint64 _created;
 
-private:
     // The base class relies on comparing the model transform to the entity transform in order 
     // to trigger an update, so the member must not be visible to derived classes as a modifiable
     // transform
diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp
index 9d2ce6fa28..9a762b3b3a 100644
--- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp
+++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp
@@ -41,23 +41,55 @@ PolyLineEntityRenderer::PolyLineEntityRenderer(const EntityItemPointer& entity)
     }
 }
 
-void PolyLineEntityRenderer::buildPipelines() {
-    // FIXME: opaque pipelines
+void PolyLineEntityRenderer::updateModelTransformAndBound() {
+    bool success = false;
+    auto newModelTransform = _entity->getTransformToCenter(success);
+    if (success) {
+        _modelTransform = newModelTransform;
 
+        auto lineEntity = std::static_pointer_cast<PolyLineEntityItem>(_entity);
+        AABox bound;
+        lineEntity->computeTightLocalBoundingBox(bound);
+        bound.transform(newModelTransform);
+        _bound = bound;
+    }
+}
+
+bool PolyLineEntityRenderer::isTransparent() const {
+    return _glow || (_textureLoaded && _texture->getGPUTexture() && _texture->getGPUTexture()->getUsage().isAlpha());
+}
+
+void PolyLineEntityRenderer::buildPipelines() {
     static const std::vector<std::pair<render::Args::RenderMethod, bool>> keys = {
         { render::Args::DEFERRED, false }, { render::Args::DEFERRED, true }, { render::Args::FORWARD, false }, { render::Args::FORWARD, true },
     };
 
     for (auto& key : keys) {
-        gpu::ShaderPointer program = gpu::Shader::createProgram(key.first == render::Args::DEFERRED ? shader::entities_renderer::program::paintStroke : shader::entities_renderer::program::paintStroke_forward);
+        gpu::ShaderPointer program;
+        render::Args::RenderMethod renderMethod = key.first;
+        bool transparent = key.second;
+
+        if (renderMethod == render::Args::DEFERRED) {
+            if (transparent) {
+                program = gpu::Shader::createProgram(shader::entities_renderer::program::paintStroke_translucent);
+            } else {
+                program = gpu::Shader::createProgram(shader::entities_renderer::program::paintStroke);
+            }
+        } else { // render::Args::FORWARD
+            program = gpu::Shader::createProgram(shader::entities_renderer::program::paintStroke_forward);
+        }
 
         gpu::StatePointer state = gpu::StatePointer(new gpu::State());
 
         state->setCullMode(gpu::State::CullMode::CULL_NONE);
-        state->setDepthTest(true, !key.second, gpu::LESS_EQUAL);
-        PrepareStencil::testMask(*state);
+        state->setDepthTest(true, !transparent, gpu::LESS_EQUAL);
+        if (transparent) {
+            PrepareStencil::testMask(*state);
+        } else {
+            PrepareStencil::testMaskDrawShape(*state);
+        }
 
-        state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
+        state->setBlendFunction(transparent, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
             gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
 
         _pipelines[key] = gpu::Pipeline::create(program, state);
@@ -65,11 +97,16 @@ void PolyLineEntityRenderer::buildPipelines() {
 }
 
 ItemKey PolyLineEntityRenderer::getKey() {
-    return ItemKey::Builder::transparentShape().withTypeMeta().withTagBits(getTagMask()).withLayer(getHifiRenderLayer());
+    return isTransparent() ?
+        ItemKey::Builder::transparentShape().withTypeMeta().withTagBits(getTagMask()).withLayer(getHifiRenderLayer()) :
+        ItemKey::Builder::opaqueShape().withTypeMeta().withTagBits(getTagMask()).withLayer(getHifiRenderLayer());
 }
 
 ShapeKey PolyLineEntityRenderer::getShapeKey() {
-    auto builder = ShapeKey::Builder().withOwnPipeline().withTranslucent().withoutCullFace();
+    auto builder = ShapeKey::Builder().withOwnPipeline().withoutCullFace();
+    if (isTransparent()) {
+        builder.withTranslucent();
+    }
     if (_primitiveMode == PrimitiveMode::LINES) {
         builder.withWireframe();
     }
@@ -294,7 +331,7 @@ void PolyLineEntityRenderer::doRender(RenderArgs* args) {
         buildPipelines();
     }
 
-    batch.setPipeline(_pipelines[{args->_renderMethod, _glow}]);
+    batch.setPipeline(_pipelines[{args->_renderMethod, isTransparent()}]);
     batch.setModelTransform(transform);
     batch.setResourceTexture(0, texture);
     batch.draw(gpu::TRIANGLE_STRIP, (gpu::uint32)(2 * numVertices), 0);
diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h
index 9139c260ea..41b66c0e51 100644
--- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h
+++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.h
@@ -25,8 +25,9 @@ class PolyLineEntityRenderer : public TypedEntityRenderer<PolyLineEntityItem> {
 public:
     PolyLineEntityRenderer(const EntityItemPointer& entity);
 
-    // FIXME: shouldn't always be transparent: take into account texture and glow
-    virtual bool isTransparent() const override { return true; }
+    void updateModelTransformAndBound() override;
+
+    virtual bool isTransparent() const override;
 
 protected:
     virtual bool needsRenderUpdate() const override;
diff --git a/libraries/entities-renderer/src/entities-renderer/paintStroke.slp b/libraries/entities-renderer/src/entities-renderer/paintStroke.slp
index e283f4edcb..acdda4dece 100644
--- a/libraries/entities-renderer/src/entities-renderer/paintStroke.slp
+++ b/libraries/entities-renderer/src/entities-renderer/paintStroke.slp
@@ -1 +1 @@
-DEFINES forward
\ No newline at end of file
+DEFINES translucent:f forward
diff --git a/libraries/entities-renderer/src/paintStroke.slf b/libraries/entities-renderer/src/paintStroke.slf
index 4ae242655c..3d5cc190d0 100644
--- a/libraries/entities-renderer/src/paintStroke.slf
+++ b/libraries/entities-renderer/src/paintStroke.slf
@@ -34,7 +34,11 @@ void main(void) {
     texel.a *= mix(1.0, pow(1.0 - min(1.0, abs(_distanceFromCenter)), 10.0), _polylineData.faceCameraGlow.y);
 
 <@if not HIFI_USE_FORWARD@>
-    packDeferredFragmentTranslucent((2.0 * float(gl_FrontFacing) - 1.0) * _normalWS, texel.a, texel.rgb, DEFAULT_ROUGHNESS);
+    <@if HIFI_USE_TRANSLUCENT@>
+        packDeferredFragmentTranslucent((2.0 * float(gl_FrontFacing) - 1.0) * _normalWS, texel.a, texel.rgb, DEFAULT_ROUGHNESS);
+    <@else@>
+        packDeferredFragmentUnlit((2.0 * float(gl_FrontFacing) - 1.0) * _normalWS, texel.a, texel.rgb);
+    <@endif@>
 <@else@>
     _fragColor0 = texel;
 <@endif@>
diff --git a/libraries/entities/src/PolyLineEntityItem.cpp b/libraries/entities/src/PolyLineEntityItem.cpp
index 645d2b39f8..fe14ba6925 100644
--- a/libraries/entities/src/PolyLineEntityItem.cpp
+++ b/libraries/entities/src/PolyLineEntityItem.cpp
@@ -14,6 +14,7 @@
 #include <QDebug>
 
 #include <ByteCountCoding.h>
+#include <Extents.h>
 
 #include "EntitiesLogging.h"
 #include "EntityItemProperties.h"
@@ -85,7 +86,7 @@ void PolyLineEntityItem::setLinePoints(const QVector<glm::vec3>& points) {
         _points = points;
         _pointsChanged = true;
     });
-    computeAndUpdateDimensionsAndPosition();
+    computeAndUpdateDimensions();
 }
 
 void PolyLineEntityItem::setStrokeWidths(const QVector<float>& strokeWidths) {
@@ -93,7 +94,7 @@ void PolyLineEntityItem::setStrokeWidths(const QVector<float>& strokeWidths) {
         _widths = strokeWidths;
         _widthsChanged = true;
     });
-    computeAndUpdateDimensionsAndPosition();
+    computeAndUpdateDimensions();
 }
 
 void PolyLineEntityItem::setNormals(const QVector<glm::vec3>& normals) {
@@ -110,7 +111,7 @@ void PolyLineEntityItem::setStrokeColors(const QVector<glm::vec3>& strokeColors)
     });
 }
 
-void PolyLineEntityItem::computeAndUpdateDimensionsAndPosition() {
+void PolyLineEntityItem::computeAndUpdateDimensions() {
     QVector<glm::vec3> points;
     QVector<float> widths;
 
@@ -129,6 +130,32 @@ void PolyLineEntityItem::computeAndUpdateDimensionsAndPosition() {
     setScaledDimensions(2.0f * (maxHalfDim + maxWidth));
 }
 
+void PolyLineEntityItem::computeTightLocalBoundingBox(AABox& localBox) const {
+    QVector<glm::vec3> points;
+    QVector<float> widths;
+    withReadLock([&] {
+        points = _points;
+        widths = _widths;
+    });
+
+    if (points.size() > 0) {
+        Extents extents;
+        float maxWidth = DEFAULT_LINE_WIDTH;
+        for (int i = 0; i < points.length(); i++) {
+            extents.addPoint(points[i]);
+            if (i < widths.size()) {
+                maxWidth = glm::max(maxWidth, widths[i]);
+            }
+        }
+        extents.addPoint(extents.minimum - maxWidth * Vectors::ONE);
+        extents.addPoint(extents.maximum + maxWidth * Vectors::ONE);
+
+        localBox.setBox(extents.minimum, extents.maximum - extents.minimum);
+    } else {
+        localBox.setBox(glm::vec3(-0.5f * DEFAULT_LINE_WIDTH), glm::vec3(DEFAULT_LINE_WIDTH));
+    }
+}
+
 int PolyLineEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
                                                          ReadBitstreamToTreeParams& args,
                                                          EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
@@ -267,4 +294,4 @@ void PolyLineEntityItem::setFaceCamera(bool faceCamera) {
         _needsRenderUpdate = _faceCamera != faceCamera;
         _faceCamera = faceCamera;
     });
-}
\ No newline at end of file
+}
diff --git a/libraries/entities/src/PolyLineEntityItem.h b/libraries/entities/src/PolyLineEntityItem.h
index fc3b085cf1..e68666d75e 100644
--- a/libraries/entities/src/PolyLineEntityItem.h
+++ b/libraries/entities/src/PolyLineEntityItem.h
@@ -15,7 +15,7 @@
 #include "EntityItem.h"
 
 class PolyLineEntityItem : public EntityItem {
- public:
+public:
     static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
 
     PolyLineEntityItem(const EntityItemID& entityItemID);
@@ -90,10 +90,12 @@ class PolyLineEntityItem : public EntityItem {
                                                   BoxFace& face, glm::vec3& surfaceNormal,
                                                   QVariantMap& extraInfo, bool precisionPicking) const override { return false; }
 
+    void computeTightLocalBoundingBox(AABox& box) const;
+
     virtual void debugDump() const override;
 private:
-    void computeAndUpdateDimensionsAndPosition();
-    
+    void computeAndUpdateDimensions();
+
  protected:
     glm::u8vec3 _color;
     QVector<glm::vec3> _points;
diff --git a/libraries/render-utils/src/DeferredBufferWrite.slh b/libraries/render-utils/src/DeferredBufferWrite.slh
index de4581d66e..de3d0a3087 100644
--- a/libraries/render-utils/src/DeferredBufferWrite.slh
+++ b/libraries/render-utils/src/DeferredBufferWrite.slh
@@ -52,7 +52,8 @@ void packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float r
 }
 
 void packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {
-    if (alpha < 1.0) {
+    // to reduce texel flickering for floating point error we discard when alpha is "almost one"
+    if (alpha < 0.999999) {
         discard;
     }
     _fragColor0 = vec4(color, packUnlit());