diff --git a/libraries/render-utils/src/RenderForwardTask.cpp b/libraries/render-utils/src/RenderForwardTask.cpp
index 63370109e0..b49735a53f 100755
--- a/libraries/render-utils/src/RenderForwardTask.cpp
+++ b/libraries/render-utils/src/RenderForwardTask.cpp
@@ -21,6 +21,8 @@
 
 #include <render/ShapePipeline.h>
 
+#include <render/FilterTask.h>
+
 #include "StencilMaskPass.h"
 #include "ZoneRenderer.h"
 #include "FadeEffect.h"
@@ -53,8 +55,9 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend
     const auto& transparents = items.get0()[RenderFetchCullSortTask::TRANSPARENT_SHAPE];
     //    const auto& lights = items.get0()[RenderFetchCullSortTask::LIGHT];
     const auto& metas = items.get0()[RenderFetchCullSortTask::META];
-    //    const auto& overlayOpaques = items.get0()[RenderFetchCullSortTask::OVERLAY_OPAQUE_SHAPE];
-    //    const auto& overlayTransparents = items.get0()[RenderFetchCullSortTask::OVERLAY_TRANSPARENT_SHAPE];
+    const auto& overlayOpaques = items.get0()[RenderFetchCullSortTask::OVERLAY_OPAQUE_SHAPE];
+    const auto& overlayTransparents = items.get0()[RenderFetchCullSortTask::OVERLAY_TRANSPARENT_SHAPE];
+
     //const auto& background = items.get0()[RenderFetchCullSortTask::BACKGROUND];
     //    const auto& spatialSelection = items[1];
 
@@ -75,6 +78,17 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend
     // draw a stencil mask in hidden regions of the framebuffer.
     task.addJob<PrepareStencil>("PrepareStencil", framebuffer);
 
+    // Layered Overlays
+    const auto filteredOverlaysOpaque = task.addJob<FilterLayeredItems>("FilterOverlaysLayeredOpaque", overlayOpaques, Item::LAYER_3D_FRONT);
+    const auto filteredOverlaysTransparent = task.addJob<FilterLayeredItems>("FilterOverlaysLayeredTransparent", overlayTransparents, Item::LAYER_3D_FRONT);
+    const auto overlaysInFrontOpaque = filteredOverlaysOpaque.getN<FilterLayeredItems::Outputs>(0);
+    const auto overlaysInFrontTransparent = filteredOverlaysTransparent.getN<FilterLayeredItems::Outputs>(0);
+
+    const auto overlayInFrontOpaquesInputs = DrawOverlay3D::Inputs(overlaysInFrontOpaque, lightingModel, nullptr).asVarying();
+    const auto overlayInFrontTransparentsInputs = DrawOverlay3D::Inputs(overlaysInFrontTransparent, lightingModel, nullptr).asVarying();
+    task.addJob<DrawOverlay3D>("DrawOverlayInFrontOpaque", overlayInFrontOpaquesInputs, true);
+    task.addJob<DrawOverlay3D>("DrawOverlayInFrontTransparent", overlayInFrontTransparentsInputs, false);
+
     // Draw opaques forward
     const auto opaqueInputs = DrawForward::Inputs(opaques, lightingModel).asVarying();
     task.addJob<DrawForward>("DrawOpaques", opaqueInputs, shapePlumber);
diff --git a/scripts/system/+android/displayNames.js b/scripts/system/+android/displayNames.js
new file mode 100644
index 0000000000..509d85cd2b
--- /dev/null
+++ b/scripts/system/+android/displayNames.js
@@ -0,0 +1,167 @@
+"use strict";
+//
+//  displayNames.js
+//  scripts/system/
+//
+//  Created by Cristian Duarte & Gabriel Calero on May 3, 2018
+//  Copyright 2018 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
+//
+(function() { // BEGIN LOCAL_SCOPE
+
+var MAX_DISTANCE_PX = 20; // Should we use dp instead?
+var UNKNOWN_NAME = "Unknown";
+var METERS_ABOVE_HEAD = 0.4;
+
+var TEXT_LINE_HEIGHT = .1;
+var TEXT_MARGIN = 0.025;
+
+var HIDE_MS = 10000;
+
+var currentTouchToAnalyze = null;
+
+var currentlyShownAvatar = {
+    avatarID: null,
+    avatar: null,
+    overlay: null
+};
+
+var logEnabled = false;
+
+var hideTimer = null;
+
+function printd(str) {
+    if (logEnabled) {       
+        print("[displayNames.js] " + str);
+    }
+}
+
+function clearOverlay() {
+    currentlyShownAvatar.avatar = null;
+    if (currentlyShownAvatar.overlay) {
+        Overlays.editOverlay(currentlyShownAvatar.overlay, {visible: false});
+    }
+}
+
+function touchedAvatar(avatarID, avatarData) {
+    printd("[AVATARNAME] touchEnd FOUND " + JSON.stringify(avatarData));
+
+    if (hideTimer) {
+        Script.clearTimeout(hideTimer);
+    }
+
+    // Case: touching an already selected avatar
+    if (currentlyShownAvatar.avatar && currentlyShownAvatar.avatarID == avatarID) {
+        clearOverlay();
+        return;
+    }
+
+    // Save currently selected avatar
+    currentlyShownAvatar.avatarID = avatarID;
+    currentlyShownAvatar.avatar = avatarData;
+
+    if (currentlyShownAvatar.overlay == null) {
+        var over = Overlays.addOverlay("text3d", {
+            lineHeight: TEXT_LINE_HEIGHT,
+            color: { red: 255, green: 255, blue: 255},
+            backgroundColor: {red: 0, green: 0, blue: 0},
+            leftMargin: TEXT_MARGIN,
+            topMargin: TEXT_MARGIN,
+            rightMargin: TEXT_MARGIN,
+            bottomMargin: TEXT_MARGIN,
+            alpha: 0.6,
+            solid: true,
+            isFacingAvatar: true,
+            visible: false
+        });
+        currentlyShownAvatar.overlay = over;
+    }
+
+    var nameToShow = avatarData.displayName ? avatarData.displayName : 
+        (avatarData.sessionDisplayName ? avatarData.sessionDisplayName : UNKNOWN_NAME);
+    var textSize = Overlays.textSize(currentlyShownAvatar.overlay, nameToShow);
+
+    Overlays.editOverlay(currentlyShownAvatar.overlay, {
+        dimensions: {
+            x: textSize.width + 2 * TEXT_MARGIN,
+            y: TEXT_LINE_HEIGHT + 2 * TEXT_MARGIN
+        },
+        localPosition: { x: 0, y: METERS_ABOVE_HEAD, z: 0 },
+        text: nameToShow,
+        parentID: avatarData.sessionUUID,
+        parentJointIndex: avatarData.getJointIndex("Head"),
+        visible: true
+    });
+
+    hideTimer = Script.setTimeout(function() {
+        clearOverlay();
+    }, HIDE_MS);
+}
+
+function touchBegin(event) {
+    currentTouchToAnalyze = event;
+}
+
+function touchEnd(event) {
+    if (Vec3.distance({x: event.x, y: event.y }, {x: currentTouchToAnalyze.x, y: currentTouchToAnalyze.y}) > MAX_DISTANCE_PX) {
+        printd("[AVATARNAME] touchEnd moved too much");
+        currentTouchToAnalyze = null;
+        return;
+    }
+
+    var pickRay = Camera.computePickRay(event.x, event.y);
+    var avatarRay = AvatarManager.findRayIntersection(pickRay, [], [MyAvatar.sessionUUID])
+
+    if (avatarRay.intersects) {
+        touchedAvatar(avatarRay.avatarID, AvatarManager.getAvatar(avatarRay.avatarID));
+    } else {
+        printd("[AVATARNAME] touchEnd released outside the avatar");
+    }
+
+    currentTouchToAnalyze = null;
+}
+
+var runAtLeastOnce = false;
+
+function ending() {
+    if (!runAtLeastOnce) {
+        return;
+    }
+
+    Controller.touchBeginEvent.disconnect(touchBegin);
+    Controller.touchEndEvent.disconnect(touchEnd);
+    Controller.mousePressEvent.disconnect(touchBegin);
+    Controller.mouseReleaseEvent.disconnect(touchEnd);
+
+    if (currentlyShownAvatar.overlay) {
+        Overlays.deleteOverlay(currentlyShownAvatar.overlay);
+        currentlyShownAvatar.overlay = null;
+    }
+    if (currentlyShownAvatar.avatar) {
+        currentlyShownAvatar.avatar = null;
+    }
+}
+
+function init() {
+    Controller.touchBeginEvent.connect(touchBegin);
+    Controller.touchEndEvent.connect(touchEnd);
+    Controller.mousePressEvent.connect(touchBegin);
+    Controller.mouseReleaseEvent.connect(touchEnd);
+
+    Script.scriptEnding.connect(function () {
+        ending();
+    });
+
+    runAtLeastOnce = true;
+}
+
+module.exports = {
+    init: init,
+    ending: ending
+}
+
+//init(); // Enable to use in desktop as a standalone
+
+}()); // END LOCAL_SCOPE
\ No newline at end of file
diff --git a/scripts/system/+android/modes.js b/scripts/system/+android/modes.js
index f5b3609c26..2c155ae386 100644
--- a/scripts/system/+android/modes.js
+++ b/scripts/system/+android/modes.js
@@ -28,6 +28,7 @@ modeLabel[MODE_MY_VIEW]="MY VIEW";
 var logEnabled = false;
 var radar = Script.require('./radar.js');
 var uniqueColor = Script.require('./uniqueColor.js');
+var displayNames = Script.require('./displayNames.js');
 
 function printd(str) {
     if (logEnabled) {       
@@ -87,8 +88,10 @@ function switchToMode(newMode) {
 
     if (currentMode == MODE_RADAR) {
         radar.startRadarMode();
+        displayNames.ending();
     } else  if (currentMode == MODE_MY_VIEW) {
         // nothing to do yet
+        displayNames.init();
     } else {
         printd("Unknown view mode " + currentMode);
     }