diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt
index 1ca5f16dc..79a64c2db 100644
--- a/builtin/settingtypes.txt
+++ b/builtin/settingtypes.txt
@@ -279,6 +279,9 @@ enable_clouds (Clouds) bool true
 #    Use 3D cloud look instead of flat.
 enable_3d_clouds (3D clouds) bool true
 
+#    Method used to highlight selected object.
+node_highlighting (Node highlighting) enum box box,halo
+
 [***Filtering]
 
 #    Use mip mapping to scale textures. May slightly increase performance.
@@ -482,9 +485,6 @@ desynchronize_mapblock_texture_animation (Desynchronize block animation) bool tr
 #    Useful if there's something to be displayed right or left of hotbar.
 hud_hotbar_max_width (Maximum hotbar width) float 1.0
 
-#    Enable selection highlighting for nodes (disables selectionbox).
-enable_node_highlighting (Node highlighting) bool false
-
 #    Enables caching of facedir rotated meshes.
 enable_mesh_cache (Mesh cache) bool false
 
diff --git a/client/shaders/default_shader/opengl_fragment.glsl b/client/shaders/default_shader/opengl_fragment.glsl
new file mode 100644
index 000000000..925ab6e1d
--- /dev/null
+++ b/client/shaders/default_shader/opengl_fragment.glsl
@@ -0,0 +1,4 @@
+void main(void)
+{
+	gl_FragColor = gl_Color;
+}
diff --git a/client/shaders/default_shader/opengl_vertex.glsl b/client/shaders/default_shader/opengl_vertex.glsl
new file mode 100644
index 000000000..0f4609177
--- /dev/null
+++ b/client/shaders/default_shader/opengl_vertex.glsl
@@ -0,0 +1,9 @@
+uniform mat4 mWorldViewProj;
+
+void main(void)
+{
+	gl_TexCoord[0] = gl_MultiTexCoord0;
+	gl_Position = mWorldViewProj * gl_Vertex;
+
+	gl_FrontColor = gl_BackColor = gl_Color;
+}
diff --git a/client/shaders/selection_shader/opengl_fragment.glsl b/client/shaders/selection_shader/opengl_fragment.glsl
new file mode 100644
index 000000000..c679d0e12
--- /dev/null
+++ b/client/shaders/selection_shader/opengl_fragment.glsl
@@ -0,0 +1,9 @@
+uniform sampler2D baseTexture;
+
+void main(void)
+{
+	vec2 uv = gl_TexCoord[0].st;
+	vec4 color = texture2D(baseTexture, uv);
+	color.rgb *= gl_Color.rgb;
+	gl_FragColor = color;
+}
diff --git a/client/shaders/selection_shader/opengl_vertex.glsl b/client/shaders/selection_shader/opengl_vertex.glsl
new file mode 100644
index 000000000..0f4609177
--- /dev/null
+++ b/client/shaders/selection_shader/opengl_vertex.glsl
@@ -0,0 +1,9 @@
+uniform mat4 mWorldViewProj;
+
+void main(void)
+{
+	gl_TexCoord[0] = gl_MultiTexCoord0;
+	gl_Position = mWorldViewProj * gl_Vertex;
+
+	gl_FrontColor = gl_BackColor = gl_Color;
+}
diff --git a/minetest.conf.example b/minetest.conf.example
index 198b93238..1bf56720e 100644
--- a/minetest.conf.example
+++ b/minetest.conf.example
@@ -555,9 +555,9 @@
 #    type: float
 # hud_hotbar_max_width = 1.0
 
-#    Enable selection highlighting for nodes (disables selectionbox).
-#    type: bool
-# enable_node_highlighting = false
+#    Selection highlighting method (box or halo)
+#    type: string
+# node_highlighting = box
 
 #    Enables caching of facedir rotated meshes.
 #    type: bool
diff --git a/src/client.cpp b/src/client.cpp
index 8e49ee3ba..a845277bd 100644
--- a/src/client.cpp
+++ b/src/client.cpp
@@ -235,11 +235,9 @@ Client::Client(
 	m_inventory_updated(false),
 	m_inventory_from_server(NULL),
 	m_inventory_from_server_age(0.0),
-	m_show_highlighted(false),
 	m_animation_time(0),
 	m_crack_level(-1),
 	m_crack_pos(0,0,0),
-	m_highlighted_pos(0,0,0),
 	m_map_seed(0),
 	m_password(password),
 	m_chosen_auth_mech(AUTH_MECHANISM_NONE),
@@ -1508,15 +1506,6 @@ int Client::getCrackLevel()
 	return m_crack_level;
 }
 
-void Client::setHighlighted(v3s16 pos, bool show_highlighted)
-{
-	m_show_highlighted = show_highlighted;
-	v3s16 old_highlighted_pos = m_highlighted_pos;
-	m_highlighted_pos = pos;
-	addUpdateMeshTaskForNode(old_highlighted_pos, false, true);
-	addUpdateMeshTaskForNode(m_highlighted_pos, false, true);
-}
-
 void Client::setCrack(int level, v3s16 pos)
 {
 	int old_crack_level = m_crack_level;
@@ -1601,7 +1590,6 @@ void Client::addUpdateMeshTask(v3s16 p, bool ack_to_server, bool urgent)
 		// Debug: 1-6ms, avg=2ms
 		data->fill(b);
 		data->setCrack(m_crack_level, m_crack_pos);
-		data->setHighlighted(m_highlighted_pos, m_show_highlighted);
 		data->setSmoothLighting(m_cache_smooth_lighting);
 	}
 
diff --git a/src/client.h b/src/client.h
index 07fb79dca..98a8bc129 100644
--- a/src/client.h
+++ b/src/client.h
@@ -456,9 +456,6 @@ public:
 	int getCrackLevel();
 	void setCrack(int level, v3s16 pos);
 
-	void setHighlighted(v3s16 pos, bool show_higlighted);
-	v3s16 getHighlighted(){ return m_highlighted_pos; }
-
 	u16 getHP();
 	u16 getBreath();
 
@@ -609,12 +606,10 @@ private:
 	Inventory *m_inventory_from_server;
 	float m_inventory_from_server_age;
 	PacketCounter m_packetcounter;
-	bool m_show_highlighted;
 	// Block mesh animation parameters
 	float m_animation_time;
 	int m_crack_level;
 	v3s16 m_crack_pos;
-	v3s16 m_highlighted_pos;
 	// 0 <= m_daynight_i < DAYNIGHT_CACHE_COUNT
 	//s32 m_daynight_i;
 	//u32 m_daynight_ratio;
diff --git a/src/content_mapblock.cpp b/src/content_mapblock.cpp
index 01a06b6cd..ab8091dee 100644
--- a/src/content_mapblock.cpp
+++ b/src/content_mapblock.cpp
@@ -171,7 +171,6 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
 		MeshCollector &collector)
 {
 	INodeDefManager *nodedef = data->m_gamedef->ndef();
-	ITextureSource *tsrc = data->m_gamedef->tsrc();
 	scene::ISceneManager* smgr = data->m_gamedef->getSceneManager();
 	scene::IMeshManipulator* meshmanip = smgr->getMeshManipulator();
 
@@ -1615,55 +1614,5 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
 		break;}
 		}
 	}
-
-	/*
-		Caused by incorrect alpha blending, selection mesh needs to be created as
-		last element to ensure it gets blended correct over nodes with alpha channel
-	*/
-	// Create selection mesh
-	v3s16 p = data->m_highlighted_pos_relative;
-	if (data->m_show_hud &&
-			(p.X >= 0) && (p.X < MAP_BLOCKSIZE) &&
-			(p.Y >= 0) && (p.Y < MAP_BLOCKSIZE) &&
-			(p.Z >= 0) && (p.Z < MAP_BLOCKSIZE)) {
-
-		MapNode n = data->m_vmanip.getNodeNoEx(blockpos_nodes + p);
-		if(n.getContent() != CONTENT_AIR) {
-			// Get selection mesh light level
-			static const v3s16 dirs[7] = {
-					v3s16( 0, 0, 0),
-					v3s16( 0, 1, 0),
-					v3s16( 0,-1, 0),
-					v3s16( 1, 0, 0),
-					v3s16(-1, 0, 0),
-					v3s16( 0, 0, 1),
-					v3s16( 0, 0,-1)
-			};
-
-			u16 l = 0;
-			u16 l1 = 0;
-			for (u8 i = 0; i < 7; i++) {
-				MapNode n1 = data->m_vmanip.getNodeNoEx(blockpos_nodes + p + dirs[i]);
-				l1 = getInteriorLight(n1, -4, nodedef);
-				if (l1 > l)
-					l = l1;
-			}
-			video::SColor c = MapBlock_LightColor(255, l, 0);
-			data->m_highlight_mesh_color = c;
-			std::vector<aabb3f> boxes = n.getSelectionBoxes(nodedef);
-			TileSpec h_tile;
-			h_tile.material_flags |= MATERIAL_FLAG_HIGHLIGHTED;
-			h_tile.texture = tsrc->getTextureForMesh("halo.png",&h_tile.texture_id);
-			v3f pos = intToFloat(p, BS);
-			f32 d = 0.05 * BS;
-			for (std::vector<aabb3f>::iterator i = boxes.begin();
-					i != boxes.end(); ++i) {
-				aabb3f box = *i;
-				box.MinEdge += v3f(-d, -d, -d) + pos;
-				box.MaxEdge += v3f(d, d, d) + pos;
-				makeCuboid(&collector, box, &h_tile, 1, c, NULL);
-			}
-		}
-	}
 }
 
diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp
index 669987d00..ddd7b5fe1 100644
--- a/src/defaultsettings.cpp
+++ b/src/defaultsettings.cpp
@@ -137,8 +137,9 @@ void set_default_settings(Settings *settings)
 	settings->setDefault("console_color", "(0,0,0)");
 	settings->setDefault("console_alpha", "200");
 	settings->setDefault("selectionbox_color", "(0,0,0)");
-	settings->setDefault("enable_node_highlighting", "false");
+	settings->setDefault("selectionbox_width", "2");
 	settings->setDefault("inventory_items_animations", "false");
+	settings->setDefault("node_highlighting", "box");
 	settings->setDefault("crosshair_color", "(255,255,255)");
 	settings->setDefault("crosshair_alpha", "255");
 	settings->setDefault("hud_scaling", "1.0");
@@ -149,8 +150,7 @@ void set_default_settings(Settings *settings)
 	settings->setDefault("enable_sound", "true");
 	settings->setDefault("sound_volume", "0.8");
 	settings->setDefault("desynchronize_mapblock_texture_animation", "true");
-	settings->setDefault("selectionbox_width","2");
-	settings->setDefault("hud_hotbar_max_width","1.0");
+	settings->setDefault("hud_hotbar_max_width", "1.0");
 	settings->setDefault("enable_local_map_saving", "false");
 
 	settings->setDefault("mip_map", "false");
diff --git a/src/drawscene.cpp b/src/drawscene.cpp
index c716ca0d4..32eafeb29 100644
--- a/src/drawscene.cpp
+++ b/src/drawscene.cpp
@@ -31,27 +31,9 @@ typedef enum {
 	EYECOUNT = 2
 } paralax_sign;
 
-
-void draw_selectionbox(video::IVideoDriver* driver, Hud& hud,
-		std::vector<aabb3f>& hilightboxes, bool show_hud)
-{
-	static const s16 selectionbox_width = rangelim(g_settings->getS16("selectionbox_width"), 1, 5);
-
-	if (!show_hud)
-		return;
-
-	video::SMaterial oldmaterial = driver->getMaterial2D();
-	video::SMaterial m;
-	m.Thickness = selectionbox_width;
-	m.Lighting = false;
-	driver->setMaterial(m);
-	hud.drawSelectionBoxes(hilightboxes);
-	driver->setMaterial(oldmaterial);
-}
-
 void draw_anaglyph_3d_mode(Camera& camera, bool show_hud, Hud& hud,
-		std::vector<aabb3f> hilightboxes, video::IVideoDriver* driver,
-		scene::ISceneManager* smgr, bool draw_wield_tool, Client& client,
+		video::IVideoDriver* driver, scene::ISceneManager* smgr,
+		bool draw_wield_tool, Client& client,
 		gui::IGUIEnvironment* guienv )
 {
 
@@ -85,10 +67,8 @@ void draw_anaglyph_3d_mode(Camera& camera, bool show_hud, Hud& hud,
 	camera.getCameraNode()->setTarget(focusPoint);
 	smgr->drawAll();
 	driver->setTransform(video::ETS_WORLD, core::IdentityMatrix);
-	if (show_hud)
-	{
-		draw_selectionbox(driver, hud, hilightboxes, show_hud);
-
+	if (show_hud) {
+		hud.drawSelectionMesh();
 		if (draw_wield_tool)
 			camera.drawWieldedTool(&leftMove);
 	}
@@ -115,10 +95,8 @@ void draw_anaglyph_3d_mode(Camera& camera, bool show_hud, Hud& hud,
 	camera.getCameraNode()->setTarget(focusPoint);
 	smgr->drawAll();
 	driver->setTransform(video::ETS_WORLD, core::IdentityMatrix);
-	if (show_hud)
-	{
-		draw_selectionbox(driver, hud, hilightboxes, show_hud);
-
+	if (show_hud) {
+		hud.drawSelectionMesh();
 		if (draw_wield_tool)
 			camera.drawWieldedTool(&rightMove);
 	}
@@ -144,16 +122,15 @@ void init_texture(video::IVideoDriver* driver, const v2u32& screensize,
 			irr::video::ECF_A8R8G8B8);
 }
 
-video::ITexture* draw_image(const v2u32& screensize,
-		paralax_sign psign, const irr::core::matrix4& startMatrix,
-		const irr::core::vector3df& focusPoint, bool show_hud,
-		video::IVideoDriver* driver, Camera& camera, scene::ISceneManager* smgr,
-		Hud& hud, std::vector<aabb3f>& hilightboxes,
-		bool draw_wield_tool, Client& client, gui::IGUIEnvironment* guienv,
-		video::SColor skycolor )
+video::ITexture* draw_image(const v2u32 &screensize,
+		paralax_sign psign, const irr::core::matrix4 &startMatrix,
+		const irr::core::vector3df &focusPoint, bool show_hud,
+		video::IVideoDriver *driver, Camera &camera, scene::ISceneManager *smgr,
+		Hud &hud, bool draw_wield_tool, Client &client,
+		gui::IGUIEnvironment *guienv, const video::SColor &skycolor)
 {
 	static video::ITexture* images[2] = { NULL, NULL };
-	static v2u32 last_screensize = v2u32(0,0);
+	static v2u32 last_screensize = v2u32(0, 0);
 
 	video::ITexture* image = NULL;
 
@@ -187,10 +164,8 @@ video::ITexture* draw_image(const v2u32& screensize,
 
 	driver->setTransform(video::ETS_WORLD, core::IdentityMatrix);
 
-	if (show_hud)
-	{
-		draw_selectionbox(driver, hud, hilightboxes, show_hud);
-
+	if (show_hud) {
+		hud.drawSelectionMesh();
 		if (draw_wield_tool)
 			camera.drawWieldedTool(&movement);
 	}
@@ -232,7 +207,7 @@ video::ITexture*  draw_hud(video::IVideoDriver* driver, const v2u32& screensize,
 }
 
 void draw_interlaced_3d_mode(Camera& camera, bool show_hud,
-		Hud& hud, std::vector<aabb3f> hilightboxes, video::IVideoDriver* driver,
+		Hud& hud, video::IVideoDriver* driver,
 		scene::ISceneManager* smgr, const v2u32& screensize,
 		bool draw_wield_tool, Client& client, gui::IGUIEnvironment* guienv,
 		video::SColor skycolor )
@@ -248,7 +223,7 @@ void draw_interlaced_3d_mode(Camera& camera, bool show_hud,
 
 	/* create left view */
 	video::ITexture* left_image = draw_image(screensize, LEFT, startMatrix,
-			focusPoint, show_hud, driver, camera, smgr, hud, hilightboxes,
+			focusPoint, show_hud, driver, camera, smgr, hud,
 			draw_wield_tool, client, guienv, skycolor);
 
 	//Right eye...
@@ -267,10 +242,8 @@ void draw_interlaced_3d_mode(Camera& camera, bool show_hud,
 
 	driver->setTransform(video::ETS_WORLD, core::IdentityMatrix);
 
-	if (show_hud)
-	{
-		draw_selectionbox(driver, hud, hilightboxes, show_hud);
-
+	if (show_hud) {
+		hud.drawSelectionMesh();
 		if(draw_wield_tool)
 			camera.drawWieldedTool(&rightMove);
 	}
@@ -293,7 +266,7 @@ void draw_interlaced_3d_mode(Camera& camera, bool show_hud,
 }
 
 void draw_sidebyside_3d_mode(Camera& camera, bool show_hud,
-		Hud& hud, std::vector<aabb3f> hilightboxes, video::IVideoDriver* driver,
+		Hud& hud, video::IVideoDriver* driver,
 		scene::ISceneManager* smgr, const v2u32& screensize,
 		bool draw_wield_tool, Client& client, gui::IGUIEnvironment* guienv,
 		video::SColor skycolor )
@@ -309,12 +282,12 @@ void draw_sidebyside_3d_mode(Camera& camera, bool show_hud,
 
 	/* create left view */
 	video::ITexture* left_image = draw_image(screensize, LEFT, startMatrix,
-			focusPoint, show_hud, driver, camera, smgr, hud, hilightboxes,
+			focusPoint, show_hud, driver, camera, smgr, hud,
 			draw_wield_tool, client, guienv, skycolor);
 
 	/* create right view */
 	video::ITexture* right_image = draw_image(screensize, RIGHT, startMatrix,
-			focusPoint, show_hud, driver, camera, smgr, hud, hilightboxes,
+			focusPoint, show_hud, driver, camera, smgr, hud,
 			draw_wield_tool, client, guienv, skycolor);
 
 	/* create hud overlay */
@@ -349,7 +322,7 @@ void draw_sidebyside_3d_mode(Camera& camera, bool show_hud,
 }
 
 void draw_top_bottom_3d_mode(Camera& camera, bool show_hud,
-		Hud& hud, std::vector<aabb3f> hilightboxes, video::IVideoDriver* driver,
+		Hud& hud, video::IVideoDriver* driver,
 		scene::ISceneManager* smgr, const v2u32& screensize,
 		bool draw_wield_tool, Client& client, gui::IGUIEnvironment* guienv,
 		video::SColor skycolor )
@@ -365,12 +338,12 @@ void draw_top_bottom_3d_mode(Camera& camera, bool show_hud,
 
 	/* create left view */
 	video::ITexture* left_image = draw_image(screensize, LEFT, startMatrix,
-			focusPoint, show_hud, driver, camera, smgr, hud, hilightboxes,
+			focusPoint, show_hud, driver, camera, smgr, hud,
 			draw_wield_tool, client, guienv, skycolor);
 
 	/* create right view */
 	video::ITexture* right_image = draw_image(screensize, RIGHT, startMatrix,
-			focusPoint, show_hud, driver, camera, smgr, hud, hilightboxes,
+			focusPoint, show_hud, driver, camera, smgr, hud,
 			draw_wield_tool, client, guienv, skycolor);
 
 	/* create hud overlay */
@@ -405,7 +378,7 @@ void draw_top_bottom_3d_mode(Camera& camera, bool show_hud,
 }
 
 void draw_pageflip_3d_mode(Camera& camera, bool show_hud,
-		Hud& hud, std::vector<aabb3f> hilightboxes, video::IVideoDriver* driver,
+		Hud& hud, video::IVideoDriver* driver,
 		scene::ISceneManager* smgr, const v2u32& screensize,
 		bool draw_wield_tool, Client& client, gui::IGUIEnvironment* guienv,
 		video::SColor skycolor)
@@ -438,11 +411,9 @@ void draw_pageflip_3d_mode(Camera& camera, bool show_hud,
 	driver->setTransform(video::ETS_WORLD, core::IdentityMatrix);
 
 	if (show_hud) {
-		draw_selectionbox(driver, hud, hilightboxes, show_hud);
-
+		hud.drawSelectionMesh();
 		if (draw_wield_tool)
 			camera.drawWieldedTool(&leftMove);
-
 		hud.drawHotbar(client.getPlayerItem());
 		hud.drawLuaElements(camera.getOffset());
 	}
@@ -467,11 +438,9 @@ void draw_pageflip_3d_mode(Camera& camera, bool show_hud,
 	driver->setTransform(video::ETS_WORLD, core::IdentityMatrix);
 
 	if (show_hud) {
-		draw_selectionbox(driver, hud, hilightboxes, show_hud);
-
+		hud.drawSelectionMesh();
 		if (draw_wield_tool)
 			camera.drawWieldedTool(&rightMove);
-
 		hud.drawHotbar(client.getPlayerItem());
 		hud.drawLuaElements(camera.getOffset());
 	}
@@ -482,23 +451,24 @@ void draw_pageflip_3d_mode(Camera& camera, bool show_hud,
 	camera.getCameraNode()->setTarget(oldTarget);
 }
 
-void draw_plain(Camera& camera, bool show_hud, Hud& hud,
-		std::vector<aabb3f> hilightboxes, video::IVideoDriver* driver,
-		bool draw_wield_tool, Client& client, gui::IGUIEnvironment* guienv)
+void draw_plain(Camera &camera, bool show_hud, Hud &hud,
+		video::IVideoDriver *driver, bool draw_wield_tool,
+		Client &client, gui::IGUIEnvironment *guienv)
 {
 	driver->setTransform(video::ETS_WORLD, core::IdentityMatrix);
-
-	draw_selectionbox(driver, hud, hilightboxes, show_hud);
-
-	if(draw_wield_tool)
-		camera.drawWieldedTool();
+	if (show_hud) {
+		hud.drawSelectionMesh();
+		if (draw_wield_tool) {
+			camera.drawWieldedTool();
+		}
+	}
 }
 
 void draw_scene(video::IVideoDriver *driver, scene::ISceneManager *smgr,
 		Camera &camera, Client& client, LocalPlayer *player, Hud &hud,
 		Mapper &mapper, gui::IGUIEnvironment *guienv,
-		std::vector<aabb3f> hilightboxes, const v2u32 &screensize,
-		video::SColor skycolor, bool show_hud, bool show_minimap)
+		const v2u32 &screensize, const video::SColor &skycolor,
+		bool show_hud, bool show_minimap)
 {
 	TimeTaker timer("smgr");
 
@@ -522,37 +492,37 @@ void draw_scene(video::IVideoDriver *driver, scene::ISceneManager *smgr,
 
 	if (draw_mode == "anaglyph")
 	{
-		draw_anaglyph_3d_mode(camera, show_hud, hud, hilightboxes, driver,
+		draw_anaglyph_3d_mode(camera, show_hud, hud, driver,
 				smgr, draw_wield_tool, client, guienv);
 		draw_crosshair = false;
 	}
 	else if (draw_mode == "interlaced")
 	{
-		draw_interlaced_3d_mode(camera, show_hud, hud, hilightboxes, driver,
+		draw_interlaced_3d_mode(camera, show_hud, hud, driver,
 				smgr, screensize, draw_wield_tool, client, guienv, skycolor);
 		draw_crosshair = false;
 	}
 	else if (draw_mode == "sidebyside")
 	{
-		draw_sidebyside_3d_mode(camera, show_hud, hud, hilightboxes, driver,
+		draw_sidebyside_3d_mode(camera, show_hud, hud, driver,
 				smgr, screensize, draw_wield_tool, client, guienv, skycolor);
 		show_hud = false;
 	}
 	else if (draw_mode == "topbottom")
 	{
-		draw_top_bottom_3d_mode(camera, show_hud, hud, hilightboxes, driver,
+		draw_top_bottom_3d_mode(camera, show_hud, hud, driver,
 				smgr, screensize, draw_wield_tool, client, guienv, skycolor);
 		show_hud = false;
 	}
 	else if (draw_mode == "pageflip")
 	{
-		draw_pageflip_3d_mode(camera, show_hud, hud, hilightboxes, driver,
+		draw_pageflip_3d_mode(camera, show_hud, hud, driver,
 				smgr, screensize, draw_wield_tool, client, guienv, skycolor);
 		draw_crosshair = false;
 		show_hud = false;
 	}
 	else {
-		draw_plain(camera, show_hud, hud, hilightboxes, driver,
+		draw_plain(camera, show_hud, hud, driver,
 				draw_wield_tool, client, guienv);
 	}
 
diff --git a/src/drawscene.h b/src/drawscene.h
index 0630f2970..364fcd499 100644
--- a/src/drawscene.h
+++ b/src/drawscene.h
@@ -31,9 +31,9 @@ void draw_load_screen(const std::wstring &text, IrrlichtDevice *device,
 		bool clouds = true);
 
 void draw_scene(video::IVideoDriver *driver, scene::ISceneManager *smgr,
-		Camera &camera, Client &client, LocalPlayer *player, Hud &hud,
-		Mapper &mapper, gui::IGUIEnvironment *guienv,
-		std::vector<aabb3f> hilightboxes, const v2u32 &screensize,
-		video::SColor skycolor, bool show_hud, bool show_minimap);
+		Camera &camera, Client &client, LocalPlayer *player,
+		Hud &hud, Mapper &mapper, gui::IGUIEnvironment *guienv,
+		const v2u32 &screensize, const video::SColor &skycolor,
+		bool show_hud, bool show_minimap);
 
 #endif /* DRAWSCENE_H_ */
diff --git a/src/game.cpp b/src/game.cpp
index 3902c50bb..cae468d4c 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -57,6 +57,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "util/pointedthing.h"
 #include "version.h"
 #include "minimap.h"
+#include "mapblock_mesh.h"
 
 #include "sound.h"
 
@@ -288,14 +289,16 @@ inline bool isPointableNode(const MapNode &n,
 /*
 	Find what the player is pointing at
 */
-PointedThing getPointedThing(Client *client, v3f player_position,
-		v3f camera_direction, v3f camera_position, core::line3d<f32> shootline,
-		f32 d, bool liquids_pointable, bool look_for_object, v3s16 camera_offset,
-		std::vector<aabb3f> &hilightboxes, ClientActiveObject *&selected_object)
+PointedThing getPointedThing(Client *client, Hud *hud, const v3f &player_position,
+		const v3f &camera_direction, const v3f &camera_position,
+		core::line3d<f32> shootline, f32 d, bool liquids_pointable,
+		bool look_for_object, const v3s16 &camera_offset,
+		ClientActiveObject *&selected_object)
 {
 	PointedThing result;
 
-	hilightboxes.clear();
+	std::vector<aabb3f> *selectionboxes = hud->getSelectionBoxes();
+	selectionboxes->clear();
 	selected_object = NULL;
 
 	INodeDefManager *nodedef = client->getNodeDefManager();
@@ -316,9 +319,9 @@ PointedThing getPointedThing(Client *client, v3f player_position,
 				assert(selection_box);
 
 				v3f pos = selected_object->getPosition();
-				hilightboxes.push_back(aabb3f(
-							       selection_box->MinEdge + pos - intToFloat(camera_offset, BS),
-							       selection_box->MaxEdge + pos - intToFloat(camera_offset, BS)));
+				selectionboxes->push_back(aabb3f(
+					selection_box->MinEdge, selection_box->MaxEdge));
+				hud->setSelectionPos(pos, camera_offset);
 			}
 
 			mindistance = (selected_object->getPosition() - camera_position).getLength();
@@ -414,22 +417,56 @@ PointedThing getPointedThing(Client *client, v3f player_position,
 						result.node_abovesurface = np_above;
 						mindistance = distance;
 
-						hilightboxes.clear();
-
-						if (!g_settings->getBool("enable_node_highlighting")) {
-							for (std::vector<aabb3f>::const_iterator
-									i2 = boxes.begin();
-									i2 != boxes.end(); ++i2) {
-								aabb3f box = *i2;
-								box.MinEdge += npf + v3f(-d, -d, -d) - intToFloat(camera_offset, BS);
-								box.MaxEdge += npf + v3f(d, d, d) - intToFloat(camera_offset, BS);
-								hilightboxes.push_back(box);
-							}
+						selectionboxes->clear();
+						for (std::vector<aabb3f>::const_iterator
+								i2 = boxes.begin();
+								i2 != boxes.end(); ++i2) {
+							aabb3f box = *i2;
+							box.MinEdge += v3f(-d, -d, -d);
+							box.MaxEdge += v3f(d, d, d);
+							selectionboxes->push_back(box);
 						}
+						hud->setSelectionPos(npf, camera_offset);
 					}
 				}
 			} // for coords
 
+	// Update selection mesh light level and vertex colors
+	if (selectionboxes->size() > 0) {
+		v3f pf = hud->getSelectionPos();
+		v3s16 p = floatToInt(pf, BS);  
+
+		// Get selection mesh light level
+		MapNode n = map.getNodeNoEx(p);	
+		u16 node_light = getInteriorLight(n, -1, nodedef);
+		u16 light_level = node_light;
+
+		for (u8 i = 0; i < 6; i++) {
+			n = map.getNodeNoEx(p + g_6dirs[i]);
+			node_light = getInteriorLight(n, -1, nodedef);
+			if (node_light > light_level)
+				light_level = node_light;
+		}
+
+		video::SColor c = MapBlock_LightColor(255, light_level, 0);
+		u8 day = c.getRed();
+		u8 night = c.getGreen();
+		u32 daynight_ratio = client->getEnv().getDayNightRatio();
+		finalColorBlend(c, day, night, daynight_ratio);
+
+		// Modify final color a bit with time
+		u32 timer = porting::getTimeMs() % 5000;
+		float timerf = (float)(irr::core::PI * ((timer / 2500.0) - 0.5));
+		float sin_r = 0.08 * sin(timerf);
+		float sin_g = 0.08 * sin(timerf + irr::core::PI * 0.5);
+		float sin_b = 0.08 * sin(timerf + irr::core::PI);
+		c.setRed(core::clamp(core::round32(c.getRed() * (0.8 + sin_r)), 0, 255));
+		c.setGreen(core::clamp(core::round32(c.getGreen() * (0.8 + sin_g)), 0, 255));
+		c.setBlue(core::clamp(core::round32(c.getBlue() * (0.8 + sin_b)), 0, 255));
+
+		// Set mesh final color
+		hud->setSelectionMeshColor(c);
+	}
 	return result;
 }
 
@@ -1522,8 +1559,7 @@ protected:
 	void updateCamera(VolatileRunFlags *flags, u32 busy_time, f32 dtime,
 			float time_from_last_punch);
 	void updateSound(f32 dtime);
-	void processPlayerInteraction(std::vector<aabb3f> &highlight_boxes,
-			GameRunData *runData, f32 dtime, bool show_hud,
+	void processPlayerInteraction(GameRunData *runData, f32 dtime, bool show_hud,
 			bool show_debug);
 	void handlePointingAtNothing(GameRunData *runData, const ItemStack &playerItem);
 	void handlePointingAtNode(GameRunData *runData,
@@ -1535,8 +1571,7 @@ protected:
 	void handleDigging(GameRunData *runData, const PointedThing &pointed,
 			const v3s16 &nodepos, const ToolCapabilities &playeritem_toolcap,
 			f32 dtime);
-	void updateFrame(std::vector<aabb3f> &highlight_boxes, ProfilerGraph *graph,
-			RunStats *stats, GameRunData *runData,
+	void updateFrame(ProfilerGraph *graph, RunStats *stats, GameRunData *runData,
 			f32 dtime, const VolatileRunFlags &flags, const CameraOrientation &cam);
 	void updateGui(float *statustext_time, const RunStats &stats,
 			const GameRunData& runData, f32 dtime, const VolatileRunFlags &flags,
@@ -1630,7 +1665,6 @@ private:
 	 *       a later release.
 	 */
 	bool m_cache_doubletap_jump;
-	bool m_cache_enable_node_highlighting;
 	bool m_cache_enable_clouds;
 	bool m_cache_enable_particles;
 	bool m_cache_enable_fog;
@@ -1668,8 +1702,6 @@ Game::Game() :
 {
 	g_settings->registerChangedCallback("doubletap_jump",
 		&settingChangedCallback, this);
-	g_settings->registerChangedCallback("enable_node_highlighting",
-		&settingChangedCallback, this);
 	g_settings->registerChangedCallback("enable_clouds",
 		&settingChangedCallback, this);
 	g_settings->registerChangedCallback("enable_particles",
@@ -1719,8 +1751,6 @@ Game::~Game()
 
 	g_settings->deregisterChangedCallback("doubletap_jump",
 		&settingChangedCallback, this);
-	g_settings->deregisterChangedCallback("enable_node_highlighting",
-		&settingChangedCallback, this);
 	g_settings->deregisterChangedCallback("enable_clouds",
 		&settingChangedCallback, this);
 	g_settings->deregisterChangedCallback("enable_particles",
@@ -1807,8 +1837,6 @@ void Game::run()
 			&runData.fog_range,
 			client));
 
-	std::vector<aabb3f> highlight_boxes;
-
 	set_light_table(g_settings->getFloat("display_gamma"));
 
 #ifdef __ANDROID__
@@ -1858,10 +1886,9 @@ void Game::run()
 		updateCamera(&flags, draw_times.busy_time, dtime,
 				runData.time_from_last_punch);
 		updateSound(dtime);
-		processPlayerInteraction(highlight_boxes, &runData, dtime,
-				flags.show_hud, flags.show_debug);
-		updateFrame(highlight_boxes, &graph, &stats, &runData, dtime,
-				flags, cam_view);
+		processPlayerInteraction(&runData, dtime, flags.show_hud,
+				flags.show_debug);
+		updateFrame(&graph, &stats, &runData, dtime, flags, cam_view);
 		updateProfilerGraphs(&graph);
 
 		// Update if minimap has been disabled by the server
@@ -2888,8 +2915,6 @@ void Game::toggleHud(float *statustext_time, bool *flag)
 	*flag = !*flag;
 	*statustext_time = 0;
 	statustext = msg[*flag];
-	if (g_settings->getBool("enable_node_highlighting"))
-		client->setHighlighted(client->getHighlighted(), *flag);
 }
 
 void Game::toggleMinimap(float *statustext_time, bool *flag,
@@ -3475,8 +3500,8 @@ void Game::updateSound(f32 dtime)
 }
 
 
-void Game::processPlayerInteraction(std::vector<aabb3f> &highlight_boxes,
-		GameRunData *runData, f32 dtime, bool show_hud, bool show_debug)
+void Game::processPlayerInteraction(GameRunData *runData,
+		f32 dtime, bool show_hud, bool show_debug)
 {
 	LocalPlayer *player = client->getEnv().getLocalPlayer();
 
@@ -3534,25 +3559,17 @@ void Game::processPlayerInteraction(std::vector<aabb3f> &highlight_boxes,
 
 	PointedThing pointed = getPointedThing(
 			// input
-			client, player_position, camera_direction,
+			client, hud, player_position, camera_direction,
 			camera_position, shootline, d,
 			playeritem_def.liquids_pointable,
 			!runData->ldown_for_dig,
 			camera_offset,
 			// output
-			highlight_boxes,
 			runData->selected_object);
 
 	if (pointed != runData->pointed_old) {
 		infostream << "Pointing at " << pointed.dump() << std::endl;
-
-		if (m_cache_enable_node_highlighting) {
-			if (pointed.type == POINTEDTHING_NODE) {
-				client->setHighlighted(pointed.node_undersurface, show_hud);
-			} else {
-				client->setHighlighted(pointed.node_undersurface, false);
-			}
-		}
+		hud->updateSelectionMesh(camera_offset);
 	}
 
 	/*
@@ -3576,6 +3593,7 @@ void Game::processPlayerInteraction(std::vector<aabb3f> &highlight_boxes,
 				infostream << "Pointing away from node"
 				           << " (stopped digging)" << std::endl;
 				runData->digging = false;
+				hud->updateSelectionMesh(camera_offset);
 			}
 		}
 
@@ -3900,9 +3918,9 @@ void Game::handleDigging(GameRunData *runData,
 }
 
 
-void Game::updateFrame(std::vector<aabb3f> &highlight_boxes,
-		ProfilerGraph *graph, RunStats *stats, GameRunData *runData,
-		f32 dtime, const VolatileRunFlags &flags, const CameraOrientation &cam)
+void Game::updateFrame(ProfilerGraph *graph, RunStats *stats,
+		GameRunData *runData, f32 dtime, const VolatileRunFlags &flags,
+		const CameraOrientation &cam)
 {
 	LocalPlayer *player = client->getEnv().getLocalPlayer();
 
@@ -4094,7 +4112,7 @@ void Game::updateFrame(std::vector<aabb3f> &highlight_boxes,
 	}
 
 	draw_scene(driver, smgr, *camera, *client, player, *hud, *mapper,
-			guienv,	highlight_boxes, screensize, skycolor, flags.show_hud,
+			guienv, screensize, skycolor, flags.show_hud,
 			flags.show_minimap);
 
 	/*
@@ -4374,7 +4392,6 @@ void Game::settingChangedCallback(const std::string &setting_name, void *data)
 void Game::readSettings()
 {
 	m_cache_doubletap_jump            = g_settings->getBool("doubletap_jump");
-	m_cache_enable_node_highlighting  = g_settings->getBool("enable_node_highlighting");
 	m_cache_enable_clouds             = g_settings->getBool("enable_clouds");
 	m_cache_enable_particles          = g_settings->getBool("enable_particles");
 	m_cache_enable_fog                = g_settings->getBool("enable_fog");
diff --git a/src/hud.cpp b/src/hud.cpp
index 1c144b021..0a77a1a28 100644
--- a/src/hud.cpp
+++ b/src/hud.cpp
@@ -32,6 +32,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "porting.h"
 #include "fontengine.h"
 #include "guiscalingfilter.h"
+#include "mesh.h"
 #include <IGUIStaticText.h>
 
 #ifdef HAVE_TOUCHSCREENGUI
@@ -80,6 +81,39 @@ Hud::Hud(video::IVideoDriver *driver, scene::ISceneManager* smgr,
 	use_hotbar_image = false;
 	hotbar_selected_image = "";
 	use_hotbar_selected_image = false;
+
+	m_selection_mesh = NULL;
+	m_selection_boxes.clear();
+	m_selection_pos = v3f(0.0, 0.0, 0.0);
+	std::string mode = g_settings->get("node_highlighting");
+	m_selection_material.Lighting = false;
+
+	if (g_settings->getBool("enable_shaders")) {
+		IShaderSource *shdrsrc = gamedef->getShaderSource();
+		u16 shader_id = shdrsrc->getShader(
+			mode == "halo" ? "selection_shader" : "default_shader", 1, 1);
+		m_selection_material.MaterialType = shdrsrc->getShaderInfo(shader_id).material;
+	} else {
+		m_selection_material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
+	}
+
+	if (mode == "box") {
+		m_use_selection_mesh = false;
+		m_selection_material.Thickness =
+			rangelim(g_settings->getS16("selectionbox_width"), 1, 5);	
+	} else if (mode == "halo") {
+		m_use_selection_mesh = true;
+		m_selection_material.setTexture(0, tsrc->getTextureForMesh("halo.png"));
+		m_selection_material.setFlag(video::EMF_BACK_FACE_CULLING, true);
+	} else {
+		m_selection_material.MaterialType = video::EMT_SOLID;
+	}
+}
+
+Hud::~Hud()
+{
+	if (m_selection_mesh)
+		m_selection_mesh->drop();
 }
 
 void Hud::drawItem(const ItemStack &item, const core::rect<s32>& rect,
@@ -239,7 +273,7 @@ void Hud::drawItems(v2s32 upperleftpos, s32 itemcount, s32 offset,
 }
 
 
-void Hud::drawLuaElements(v3s16 camera_offset) {
+void Hud::drawLuaElements(const v3s16 &camera_offset) {
 	u32 text_height = g_fontengine->getTextHeight();
 	irr::gui::IGUIFont* font = g_fontengine->getFont();
 	for (size_t i = 0; i != player->maxHudId(); i++) {
@@ -466,15 +500,85 @@ void Hud::drawCrosshair() {
 	}
 }
 
-
-void Hud::drawSelectionBoxes(std::vector<aabb3f> &hilightboxes) {
-	for (std::vector<aabb3f>::const_iterator
-			i = hilightboxes.begin();
-			i != hilightboxes.end(); ++i) {
-		driver->draw3DBox(*i, selectionbox_argb);
+void Hud::setSelectionPos(const v3f &pos, const v3s16 &camera_offset)
+{
+	m_camera_offset = camera_offset;
+	m_selection_pos = pos;
+	m_selection_pos_with_offset = pos - intToFloat(camera_offset, BS);
+}
+	
+void Hud::drawSelectionMesh()
+{	
+	if (!m_use_selection_mesh) {
+		// Draw 3D selection boxes
+		video::SMaterial oldmaterial = driver->getMaterial2D();
+		driver->setMaterial(m_selection_material);
+		for (std::vector<aabb3f>::const_iterator
+				i = m_selection_boxes.begin();
+				i != m_selection_boxes.end(); ++i) {
+			aabb3f box = aabb3f(
+				i->MinEdge + m_selection_pos_with_offset,
+				i->MaxEdge + m_selection_pos_with_offset);
+			
+			u32 r = (selectionbox_argb.getRed() *
+					m_selection_mesh_color.getRed() / 255);		
+			u32 g = (selectionbox_argb.getGreen() *
+					m_selection_mesh_color.getGreen() / 255);
+			u32 b = (selectionbox_argb.getBlue() *
+					m_selection_mesh_color.getBlue() / 255);
+			driver->draw3DBox(box, video::SColor(255, r, g, b));
+		}
+		driver->setMaterial(oldmaterial);
+	} else if (m_selection_mesh) {
+		// Draw selection mesh
+		video::SMaterial oldmaterial = driver->getMaterial2D();
+		driver->setMaterial(m_selection_material);
+		setMeshColor(m_selection_mesh, m_selection_mesh_color);
+		scene::IMesh* mesh = cloneMesh(m_selection_mesh);
+		translateMesh(mesh, m_selection_pos_with_offset);
+		u32 mc = m_selection_mesh->getMeshBufferCount();
+		for (u32 i = 0; i < mc; i++) {
+			scene::IMeshBuffer *buf = mesh->getMeshBuffer(i);
+			driver->drawMeshBuffer(buf);
+		}
+		mesh->drop();
+		driver->setMaterial(oldmaterial);
 	}
 }
 
+void Hud::updateSelectionMesh(const v3s16 &camera_offset)
+{
+	m_camera_offset = camera_offset;
+	if (!m_use_selection_mesh)
+		return;
+
+	if (m_selection_mesh) {
+		m_selection_mesh->drop();
+		m_selection_mesh = NULL;
+	}
+
+	if (!m_selection_boxes.size()) {
+		// No pointed object
+		return;
+	}
+
+	// New pointed object, create new mesh.
+
+	// Texture UV coordinates for selection boxes
+	static f32 texture_uv[24] = {
+		0,0,1,1,
+		0,0,1,1,
+		0,0,1,1,
+		0,0,1,1,
+		0,0,1,1,
+		0,0,1,1
+	};
+
+	m_selection_mesh = convertNodeboxesToMesh(m_selection_boxes, texture_uv);
+
+	// scale final halo mesh
+	scaleMesh(m_selection_mesh, v3f(1.08, 1.08, 1.08));
+}
 
 void Hud::resizeHotbar() {
 	if (m_screensize != porting::getWindowSize()) {
diff --git a/src/hud.h b/src/hud.h
index f373d4fe2..d0158b2f8 100644
--- a/src/hud.h
+++ b/src/hud.h
@@ -119,17 +119,31 @@ public:
 	bool use_hotbar_image;
 	std::string hotbar_selected_image;
 	bool use_hotbar_selected_image;
-	v3s16 camera_offset;
 
 	Hud(video::IVideoDriver *driver,scene::ISceneManager* smgr,
 		gui::IGUIEnvironment* guienv, IGameDef *gamedef, LocalPlayer *player,
 		Inventory *inventory);
+	~Hud();
 
 	void drawHotbar(u16 playeritem);
 	void resizeHotbar();
 	void drawCrosshair();
-	void drawSelectionBoxes(std::vector<aabb3f> &hilightboxes);
-	void drawLuaElements(v3s16 camera_offset);
+	void drawSelectionMesh();
+	void updateSelectionMesh(const v3s16 &camera_offset);
+	
+	std::vector<aabb3f> *getSelectionBoxes()
+	{ return &m_selection_boxes; }
+
+	void setSelectionPos(const v3f &pos, const v3s16 &camera_offset);
+
+	v3f getSelectionPos() const
+	{ return m_selection_pos; }
+
+	void setSelectionMeshColor(const video::SColor &c)
+	{ m_selection_mesh_color = c; }
+
+	void drawLuaElements(const v3s16 &camera_offset);
+
 private:
 	void drawStatbar(v2s32 pos, u16 corner, u16 drawdir, std::string texture,
 			s32 count, v2s32 offset, v2s32 size=v2s32());
@@ -140,11 +154,21 @@ private:
 	void drawItem(const ItemStack &item, const core::rect<s32>& rect,
 		bool selected);
 
+	v3s16 m_camera_offset;
 	v2u32 m_screensize;
 	v2s32 m_displaycenter;
 	s32 m_hotbar_imagesize;
 	s32 m_padding;
 	video::SColor hbar_colors[4];
+
+	std::vector<aabb3f> m_selection_boxes;
+	v3f m_selection_pos;
+	v3f m_selection_pos_with_offset;
+
+	scene::IMesh* m_selection_mesh;
+	video::SColor m_selection_mesh_color;
+	video::SMaterial m_selection_material;
+	bool m_use_selection_mesh;
 };
 
 enum ItemRotationKind {
diff --git a/src/mapblock_mesh.cpp b/src/mapblock_mesh.cpp
index 9bcc4fa6a..9486220e0 100644
--- a/src/mapblock_mesh.cpp
+++ b/src/mapblock_mesh.cpp
@@ -47,10 +47,8 @@ MeshMakeData::MeshMakeData(IGameDef *gamedef, bool use_shaders):
 	m_vmanip(),
 	m_blockpos(-1337,-1337,-1337),
 	m_crack_pos_relative(-1337, -1337, -1337),
-	m_highlighted_pos_relative(-1337, -1337, -1337),
 	m_smooth_lighting(false),
 	m_show_hud(false),
-	m_highlight_mesh_color(255, 255, 255, 255),
 	m_gamedef(gamedef),
 	m_use_shaders(use_shaders)
 {}
@@ -138,12 +136,6 @@ void MeshMakeData::setCrack(int crack_level, v3s16 crack_pos)
 		m_crack_pos_relative = crack_pos - m_blockpos*MAP_BLOCKSIZE;
 }
 
-void MeshMakeData::setHighlighted(v3s16 highlighted_pos, bool show_hud)
-{
-	m_show_hud = show_hud;
-	m_highlighted_pos_relative = highlighted_pos - m_blockpos*MAP_BLOCKSIZE;
-}
-
 void MeshMakeData::setSmoothLighting(bool smooth_lighting)
 {
 	m_smooth_lighting = smooth_lighting;
@@ -1036,12 +1028,10 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
 	m_animation_force_timer(0), // force initial animation
 	m_last_crack(-1),
 	m_crack_materials(),
-	m_highlighted_materials(),
 	m_last_daynight_ratio((u32) -1),
 	m_daynight_diffs()
 {
 	m_enable_shaders = data->m_use_shaders;
-	m_enable_highlighting = g_settings->getBool("enable_node_highlighting");
 
 	if (g_settings->getBool("enable_minimap")) {
 		m_minimap_mapblock = new MinimapMapblock;
@@ -1116,8 +1106,6 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
 
 	mapblock_mesh_generate_special(data, collector);
 
-	m_highlight_mesh_color = data->m_highlight_mesh_color;
-
 	/*
 		Convert MeshCollector to SMesh
 	*/
@@ -1162,9 +1150,6 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
 			p.tile.texture = animation_frame.texture;
 		}
 
-		if(m_enable_highlighting && p.tile.material_flags & MATERIAL_FLAG_HIGHLIGHTED)
-			m_highlighted_materials.push_back(i);
-
 		for(u32 j = 0; j < p.vertices.size(); j++)
 		{
 			video::S3DVertex *vertex = &p.vertices[j];
@@ -1205,19 +1190,15 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
 		material.setFlag(video::EMF_FOG_ENABLE, true);
 		material.setTexture(0, p.tile.texture);
 
-		if (p.tile.material_flags & MATERIAL_FLAG_HIGHLIGHTED) {
-			material.MaterialType = video::EMT_TRANSPARENT_ADD_COLOR;
-		} else {
-			if (m_enable_shaders) {
-				material.MaterialType = m_shdrsrc->getShaderInfo(p.tile.shader_id).material;
-				p.tile.applyMaterialOptionsWithShaders(material);
-				if (p.tile.normal_texture) {
-					material.setTexture(1, p.tile.normal_texture);
-				}
-				material.setTexture(2, p.tile.flags_texture);
-			} else {
-				p.tile.applyMaterialOptions(material);
+		if (m_enable_shaders) {
+			material.MaterialType = m_shdrsrc->getShaderInfo(p.tile.shader_id).material;
+			p.tile.applyMaterialOptionsWithShaders(material);
+			if (p.tile.normal_texture) {
+				material.setTexture(1, p.tile.normal_texture);
 			}
+			material.setTexture(2, p.tile.flags_texture);
+		} else {
+			p.tile.applyMaterialOptions(material);
 		}
 
 	// Create meshbuffer
@@ -1273,8 +1254,7 @@ MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset):
 	m_has_animation =
 		!m_crack_materials.empty() ||
 		!m_daynight_diffs.empty() ||
-		!m_animation_tiles.empty() ||
-		!m_highlighted_materials.empty();
+		!m_animation_tiles.empty();
 }
 
 MapBlockMesh::~MapBlockMesh()
@@ -1377,30 +1357,6 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack, u32 daynight_rat
 		m_last_daynight_ratio = daynight_ratio;
 	}
 
-	// Node highlighting
-	if (m_enable_highlighting) {
-		u8 day = m_highlight_mesh_color.getRed();
-		u8 night = m_highlight_mesh_color.getGreen();
-		video::SColor hc;
-		finalColorBlend(hc, day, night, daynight_ratio);
-		float sin_r = 0.07 * sin(1.5 * time);
-		float sin_g = 0.07 * sin(1.5 * time + irr::core::PI * 0.5);
-		float sin_b = 0.07 * sin(1.5 * time + irr::core::PI);
-		hc.setRed(core::clamp(core::round32(hc.getRed() * (0.8 + sin_r)), 0, 255));
-		hc.setGreen(core::clamp(core::round32(hc.getGreen() * (0.8 + sin_g)), 0, 255));
-		hc.setBlue(core::clamp(core::round32(hc.getBlue() * (0.8 + sin_b)), 0, 255));
-
-		for(std::list<u32>::iterator
-			i = m_highlighted_materials.begin();
-			i != m_highlighted_materials.end(); ++i)
-		{
-			scene::IMeshBuffer *buf = m_mesh->getMeshBuffer(*i);
-			video::S3DVertex *vertices = (video::S3DVertex *)buf->getVertices();
-			for (u32 j = 0; j < buf->getVertexCount() ;j++)
-				vertices[j].Color = hc;
-		}
-	}
-
 	return true;
 }
 
diff --git a/src/mapblock_mesh.h b/src/mapblock_mesh.h
index 9c4fb655a..421e8f2b3 100644
--- a/src/mapblock_mesh.h
+++ b/src/mapblock_mesh.h
@@ -41,10 +41,8 @@ struct MeshMakeData
 	VoxelManipulator m_vmanip;
 	v3s16 m_blockpos;
 	v3s16 m_crack_pos_relative;
-	v3s16 m_highlighted_pos_relative;
 	bool m_smooth_lighting;
 	bool m_show_hud;
-	video::SColor m_highlight_mesh_color;
 
 	IGameDef *m_gamedef;
 	bool m_use_shaders;
@@ -67,11 +65,6 @@ struct MeshMakeData
 	*/
 	void setCrack(int crack_level, v3s16 crack_pos);
 
-	/*
-		Set the highlighted node position
-	*/
-
-	void setHighlighted(v3s16 highlighted_pos, bool show_hud);
 	/*
 		Enable or disable smooth lighting
 	*/
@@ -137,10 +130,7 @@ private:
 	IShaderSource *m_shdrsrc;
 
 	bool m_enable_shaders;
-	bool m_enable_highlighting;
 
-	video::SColor m_highlight_mesh_color;
-	
 	// Must animate() be called before rendering?
 	bool m_has_animation;
 	int m_animation_force_timer;
@@ -150,7 +140,6 @@ private:
 	int m_last_crack;
 	// Maps mesh buffer (i.e. material) indices to base texture names
 	std::map<u32, std::string> m_crack_materials;
-	std::list<u32> m_highlighted_materials;
 
 	// Animation info: texture animationi
 	// Maps meshbuffers to TileSpecs
diff --git a/src/mesh.cpp b/src/mesh.cpp
index a800ddf1e..d79f545f3 100644
--- a/src/mesh.cpp
+++ b/src/mesh.cpp
@@ -405,9 +405,11 @@ scene::IMesh* cloneMesh(scene::IMesh *src_mesh)
 	return dst_mesh;
 }
 
-scene::IMesh* convertNodeboxNodeToMesh(ContentFeatures *f)
+scene::IMesh* convertNodeboxesToMesh(const std::vector<aabb3f> &boxes,
+		const f32 *uv_coords)
 {
 	scene::SMesh* dst_mesh = new scene::SMesh();
+
 	for (u16 j = 0; j < 6; j++)
 	{
 		scene::IMeshBuffer *buf = new scene::SMeshBuffer();
@@ -416,12 +418,10 @@ scene::IMesh* convertNodeboxNodeToMesh(ContentFeatures *f)
 		dst_mesh->addMeshBuffer(buf);
 		buf->drop();
 	}
-	
+
 	video::SColor c(255,255,255,255);	
 
-	std::vector<aabb3f> boxes = f->node_box.fixed;
-		
-	for(std::vector<aabb3f>::iterator
+	for(std::vector<aabb3f>::const_iterator
 			i = boxes.begin();
 			i != boxes.end(); ++i)
 	{
@@ -446,27 +446,33 @@ scene::IMesh* convertNodeboxNodeToMesh(ContentFeatures *f)
 				box.MinEdge.Z=box.MaxEdge.Z;
 				box.MaxEdge.Z=temp;
 			}
-		// Compute texture coords
-		f32 tx1 = (box.MinEdge.X/BS)+0.5;
-		f32 ty1 = (box.MinEdge.Y/BS)+0.5;
-		f32 tz1 = (box.MinEdge.Z/BS)+0.5;
-		f32 tx2 = (box.MaxEdge.X/BS)+0.5;
-		f32 ty2 = (box.MaxEdge.Y/BS)+0.5;
-		f32 tz2 = (box.MaxEdge.Z/BS)+0.5;
-		f32 txc[24] = {
+
+		// Compute texture UV coords
+		f32 tx1 = (box.MinEdge.X / BS) + 0.5;
+		f32 ty1 = (box.MinEdge.Y / BS) + 0.5;
+		f32 tz1 = (box.MinEdge.Z / BS) + 0.5;
+		f32 tx2 = (box.MaxEdge.X / BS) + 0.5;
+		f32 ty2 = (box.MaxEdge.Y / BS) + 0.5;
+		f32 tz2 = (box.MaxEdge.Z / BS) + 0.5;
+
+		f32 txc_default[24] = {
 			// up
-			tx1, 1-tz2, tx2, 1-tz1,
+			tx1, 1 - tz2, tx2, 1 - tz1,
 			// down
 			tx1, tz1, tx2, tz2,
 			// right
-			tz1, 1-ty2, tz2, 1-ty1,
+			tz1, 1 - ty2, tz2, 1 - ty1,
 			// left
-			1-tz2, 1-ty2, 1-tz1, 1-ty1,
+			1 - tz2, 1 - ty2, 1 - tz1, 1 - ty1,
 			// back
-			1-tx2, 1-ty2, 1-tx1, 1-ty1,
+			1 - tx2, 1 - ty2, 1 - tx1, 1 - ty1,
 			// front
-			tx1, 1-ty2, tx2, 1-ty1,
+			tx1, 1 - ty2, tx2, 1 - ty1,
 		};
+
+		// use default texture UV mapping if not provided
+		const f32 *txc = uv_coords ? uv_coords : txc_default;
+
 		v3f min = box.MinEdge;
 		v3f max = box.MaxEdge;
 
diff --git a/src/mesh.h b/src/mesh.h
index ec109e9e9..ad3f8db4b 100644
--- a/src/mesh.h
+++ b/src/mesh.h
@@ -83,9 +83,12 @@ void rotateMeshYZby (scene::IMesh *mesh, f64 degrees);
 scene::IMesh* cloneMesh(scene::IMesh *src_mesh);
 
 /*
-	Convert nodebox drawtype node to mesh.
+	Convert nodeboxes to mesh.
+	boxes - set of nodeboxes to be converted into cuboids
+	uv_coords[24] - table of texture uv coords for each cuboid face
 */
-scene::IMesh* convertNodeboxNodeToMesh(ContentFeatures *f);
+scene::IMesh* convertNodeboxesToMesh(const std::vector<aabb3f> &boxes,
+		const f32 *uv_coords = NULL);
 
 /*
 	Update bounding box for a mesh.
diff --git a/src/nodedef.cpp b/src/nodedef.cpp
index e30cf6f12..c60958ba5 100644
--- a/src/nodedef.cpp
+++ b/src/nodedef.cpp
@@ -972,7 +972,7 @@ void CNodeDefManager::updateTextures(IGameDef *gamedef,
 			//Convert regular nodebox nodes to meshnodes
 			//Change the drawtype and apply scale
 			f->drawtype = NDT_MESH;
-			f->mesh_ptr[0] = convertNodeboxNodeToMesh(f);
+			f->mesh_ptr[0] = convertNodeboxesToMesh(f->node_box.fixed);
 			v3f scale = v3f(1.0, 1.0, 1.0) * f->visual_scale;
 			scaleMesh(f->mesh_ptr[0], scale);
 			recalculateBoundingBox(f->mesh_ptr[0]);
diff --git a/textures/base/pack/halo.png b/textures/base/pack/halo.png
index e13b54419..eaea782da 100644
Binary files a/textures/base/pack/halo.png and b/textures/base/pack/halo.png differ