diff --git a/Common/Context.cpp b/Common/Context.cpp
index 2374eeb9d9daf745fe9c9f6338b6b963d1c2463b..b5c3cadb15bad93b60cad78bf5ec8d39b7d2fce8 100644
--- a/Common/Context.cpp
+++ b/Common/Context.cpp
@@ -107,6 +107,7 @@ CTX::CTX() : gamepad(0)
   mesh.minCircPoints = mesh.order = 0;
   mesh.secondOrderLinear = mesh.secondOrderIncomplete = 0;
   mesh.preserveNumberingMsh2 = 1;
+  mesh.lightLines = 1;
 }
 
 CTX::~CTX()
diff --git a/Common/Context.h b/Common/Context.h
index 1d0dfe9642d9c7520620699a05673e485ccafdcc..973fb709eded9d0a2134394b06aaa47a145ba488 100644
--- a/Common/Context.h
+++ b/Common/Context.h
@@ -20,7 +20,8 @@ class GamePad;
 
 struct contextMeshOptions {
   int draw, changed, light, lightTwoSide, lightLines, pointType;
-  int points, lines, triangles, quadrangles, tetrahedra, hexahedra, prisms, pyramids, trihedra;
+  int points, lines, triangles, quadrangles, tetrahedra, hexahedra, prisms;
+  int pyramids, trihedra;
   int surfacesEdges, surfacesFaces, volumesEdges, volumesFaces, numSubEdges;
   int pointsNum, linesNum, surfacesNum, volumesNum, qualityType, labelType;
   int optimize, optimizeNetgen, optimizeLloyd, smoothCrossField, refineSteps;
@@ -33,13 +34,14 @@ struct contextMeshOptions {
   int lcFromPoints, lcFromCurvature, lcExtendFromBoundary;
   int dual, voronoi, drawSkinOnly, colorCarousel, labelSampling;
   int fileFormat, nbSmoothing, algo2d, algo3d, algoSubdivide, oldRefinement;
-  int algoRecombine, recombineAll, recombine3DAll, recombine3DLevel, recombine3DConformity;
+  int algoRecombine, recombineAll, recombine3DAll, recombine3DLevel;
+  int recombine3DConformity;
   int flexibleTransfinite;
   //-- for recombination test (amaury) --
-    int doRecombinationTest, recombinationTestStart;
-    int recombinationTestNoGreedyStrat, recombinationTestNewStrat;
-    int nProc, nbProc;
-    std::string recTestName;
+  int doRecombinationTest, recombinationTestStart;
+  int recombinationTestNoGreedyStrat, recombinationTestNewStrat;
+  int nProc, nbProc;
+  std::string recTestName;
   //-------------------------------------
   int remeshParam, remeshAlgo;
   int order, secondOrderLinear, secondOrderIncomplete;
diff --git a/Common/DefaultOptions.h b/Common/DefaultOptions.h
index 2c8fee3ba85cdb969f0dab35de5c55092b3aea79..47063de79c33575985926225db029ea467b25c54 100644
--- a/Common/DefaultOptions.h
+++ b/Common/DefaultOptions.h
@@ -1082,7 +1082,7 @@ StringXNumber MeshOptions_Number[] = {
   { F|O, "Light" , opt_mesh_light , 1. ,
     "Enable lighting for the mesh" },
   { F|O, "LightLines" , opt_mesh_light_lines , 1. ,
-    "Enable lighting for mesh lines (element edges)" },
+    "Enable lighting for mesh edges (0=no, 1=surfaces, 2=surfaces+volumes" },
   { F|O, "LightTwoSide" , opt_mesh_light_two_side , 1. ,
     "Light both sides of surfaces (leads to slower rendering)" },
   { F|O, "Lines" , opt_mesh_lines , 0. ,
diff --git a/Common/Options.cpp b/Common/Options.cpp
index 8596be5eec33cdb44afae7ba0e3bbf7c78095140..0da0f579a80463b93a3cf25942e58ff6c831473f 100644
--- a/Common/Options.cpp
+++ b/Common/Options.cpp
@@ -5605,11 +5605,17 @@ double opt_mesh_light(OPT_ARGS_NUM)
 
 double opt_mesh_light_lines(OPT_ARGS_NUM)
 {
-  if(action & GMSH_SET)
+  if(action & GMSH_SET){
+    if(CTX::instance()->mesh.lightLines != (int)val)
+      CTX::instance()->mesh.changed |= ENT_SURFACE|ENT_VOLUME;
     CTX::instance()->mesh.lightLines = (int)val;
+    if(CTX::instance()->mesh.lightLines < 0 ||
+       CTX::instance()->mesh.lightLines > 2)
+      CTX::instance()->mesh.lightLines = 1;
+  }
 #if defined(HAVE_FLTK)
   if(FlGui::available() && (action & GMSH_GUI))
-    FlGui::instance()->options->mesh.butt[20]->value
+    FlGui::instance()->options->mesh.choice[10]->value
       (CTX::instance()->mesh.lightLines);
 #endif
   return CTX::instance()->mesh.lightLines;
diff --git a/Common/VertexArray.cpp b/Common/VertexArray.cpp
index 987f5263fb950726556abb3faa922b17646db7f7..03039ab9368f055ea21b343d8f793c88ab934d20 100644
--- a/Common/VertexArray.cpp
+++ b/Common/VertexArray.cpp
@@ -90,7 +90,9 @@ void VertexArray::add(double *x, double *y, double *z, SVector3 *n, unsigned cha
     return;
   }
 
-#if 0 // removed this for now
+  // enabling this will reduce memory and rendering time; but will increase the
+  // time it takes to create the vertex array
+#if 0
   if(unique){
     Barycenter pc(0.0F, 0.0F, 0.0F);
     for(int i = 0; i < npe; i++)
diff --git a/Fltk/optionWindow.cpp b/Fltk/optionWindow.cpp
index 094659acbee94e16cf886113e1a241281eeccd83..9e5808ccfd65610146fac4184029a363c5a86a22 100644
--- a/Fltk/optionWindow.cpp
+++ b/Fltk/optionWindow.cpp
@@ -504,7 +504,9 @@ static void mesh_options_ok_cb(Fl_Widget *w, void *data)
   opt_mesh_light(0, GMSH_SET, o->mesh.butt[17]->value());
   opt_mesh_light_two_side(0, GMSH_SET, o->mesh.butt[18]->value());
   opt_mesh_smooth_normals(0, GMSH_SET, o->mesh.butt[19]->value());
-  opt_mesh_light_lines(0, GMSH_SET, o->mesh.butt[20]->value());
+  opt_mesh_recombine_all(0, GMSH_SET, o->mesh.butt[21]->value());
+  opt_mesh_recombine3d_all(0, GMSH_SET, o->mesh.butt[22]->value());
+
   opt_mesh_nb_smoothing(0, GMSH_SET, o->mesh.value[0]->value());
   opt_mesh_lloyd(0, GMSH_SET, o->mesh.value[27]->value());
   opt_mesh_lc_factor(0, GMSH_SET, o->mesh.value[2]->value());
@@ -523,7 +525,6 @@ static void mesh_options_ok_cb(Fl_Widget *w, void *data)
   opt_mesh_label_sampling(0, GMSH_SET, o->mesh.value[12]->value());
   opt_mesh_angle_smooth_normals(0, GMSH_SET, o->mesh.value[18]->value());
 
-  opt_mesh_recombine3d_all(0, GMSH_SET, o->mesh.butt[22]->value());
   opt_mesh_point_type(0, GMSH_SET, o->mesh.choice[0]->value());
   opt_mesh_algo2d(0, GMSH_SET,
                   (o->mesh.choice[2]->value() == 1) ? ALGO_2D_MESHADAPT :
@@ -541,14 +542,13 @@ static void mesh_options_ok_cb(Fl_Widget *w, void *data)
                   (o->mesh.choice[3]->value() == 6) ? ALGO_3D_RTREE :
                   ALGO_3D_DELAUNAY);
   opt_mesh_algo_recombine(0, GMSH_SET, o->mesh.choice[1]->value());
-  opt_mesh_recombine_all(0, GMSH_SET, o->mesh.butt[21]->value());
-
   opt_mesh_algo_subdivide(0, GMSH_SET, o->mesh.choice[5]->value());
   opt_mesh_remesh_algo(0, GMSH_SET, o->mesh.choice[8]->value());
   opt_mesh_remesh_param(0, GMSH_SET, o->mesh.choice[9]->value());
   opt_mesh_color_carousel(0, GMSH_SET, o->mesh.choice[4]->value());
   opt_mesh_quality_type(0, GMSH_SET, o->mesh.choice[6]->value());
   opt_mesh_label_type(0, GMSH_SET, o->mesh.choice[7]->value());
+  opt_mesh_light_lines(0, GMSH_SET, o->mesh.choice[10]->value());
 
   if(CTX::instance()->fastRedraw)
     CTX::instance()->post.draw = CTX::instance()->mesh.draw = 0;
@@ -2627,10 +2627,17 @@ optionWindow::optionWindow(int deltaFontSize)
       mesh.butt[17]->type(FL_TOGGLE_BUTTON);
       mesh.butt[17]->callback(mesh_options_ok_cb, (void*)"mesh_light");
 
-      mesh.butt[20] = new Fl_Check_Button
-        (L + 2 * WB, 2 * WB + 2 * BH, BW, BH, "Enable lighting of lines");
-      mesh.butt[20]->type(FL_TOGGLE_BUTTON);
-      mesh.butt[20]->callback(mesh_options_ok_cb);
+      static Fl_Menu_Item menu_mesh_light_lines[] = {
+        {"No", 0, 0, 0},
+        {"Surface", 0, 0, 0},
+        {"Volume and surface", 0, 0, 0},
+        {0}
+      };
+      mesh.choice[10] = new Fl_Choice
+        (L + 2 * WB, 2 * WB + 2 * BH, IW, BH, "Edge lighting");
+      mesh.choice[10]->menu(menu_mesh_light_lines);
+      mesh.choice[10]->align(FL_ALIGN_RIGHT);
+      mesh.choice[10]->callback(mesh_options_ok_cb);
 
       mesh.butt[18] = new Fl_Check_Button
         (L + 2 * WB, 2 * WB + 3 * BH, BW, BH, "Use two-side lighting");
@@ -3978,14 +3985,14 @@ void optionWindow::activate(const char *what)
     if(mesh.butt[17]->value()){
       mesh.butt[18]->activate();
       mesh.butt[19]->activate();
-      mesh.butt[20]->activate();
+      mesh.choice[10]->activate();
       mesh.butt[0]->activate();
       mesh.value[18]->activate();
     }
     else{
       mesh.butt[18]->deactivate();
       mesh.butt[19]->deactivate();
-      mesh.butt[20]->deactivate();
+      mesh.choice[10]->deactivate();
       mesh.butt[0]->deactivate();
       mesh.value[18]->deactivate();
     }
diff --git a/Geo/MTetrahedron.cpp b/Geo/MTetrahedron.cpp
index aadfe0eee8c57d51dede13e4f6784228e9b12cee..f75c507b67b84b615ea0667ee1e4ed8a4473055e 100644
--- a/Geo/MTetrahedron.cpp
+++ b/Geo/MTetrahedron.cpp
@@ -25,26 +25,35 @@ void MTetrahedron::getEdgeRep(bool curved, int num, double *x, double *y, double
   MVertex *v1 = getVertex(edges_tetra(num, 1));
   x[0] = v0->x(); y[0] = v0->y(); z[0] = v0->z();
   x[1] = v1->x(); y[1] = v1->y(); z[1] = v1->z();
-#if 0 // compute normals so that we can light the edges
-  static const int vv[6] = {2, 0, 1, 1, 0, 2};
-  MVertex *v2 = getVertex(vv[num]);
-  double nn[3];
-  normal3points(v0->x(), v0->y(), v0->z(),
-                v1->x(), v1->y(), v1->z(),
-                v2->x(), v2->y(), v2->z(), nn);
-  n[0] = n[1] = SVector3(nn[0], nn[1], nn[2]);
-#else
-  n[0] = n[1] = SVector3();
-#endif
+  if(CTX::instance()->mesh.lightLines > 1){
+    static const int vv[6] = {2, 0, 1, 1, 0, 2};
+    MVertex *v2 = getVertex(vv[num]);
+    SVector3 t1(x[1] - x[0], y[1] - y[0], z[1] - z[0]);
+    SVector3 t2(v2->x() - x[0], v2->y() - y[0], v2->z() - z[0]);
+    SVector3 normal = crossprod(t1, t2);
+    normal.normalize();
+    n[0] = n[1] = normal;
+  }
+  else{
+    n[0] = n[1] = SVector3(0., 0., 1.);
+  }
 }
 
 void MTetrahedron::getFaceRep(bool curved, int num, double *x, double *y, double *z,
                               SVector3 *n)
 {
-  // don't use general MElement::_getFaceRep: it's slow due to the creation of
-  // MFaces
-  MFace f(getFace(num));
-  _getFaceRep(f.getVertex(0), f.getVertex(1), f.getVertex(2), x, y, z, n);
+  // don't use MElement::_getFaceRep: it's slow due to the creation of MFaces
+  MVertex *v0 = getVertex(faces_tetra(num, 0));
+  MVertex *v1 = getVertex(faces_tetra(num, 1));
+  MVertex *v2 = getVertex(faces_tetra(num, 2));
+  x[0] = v0->x(); x[1] = v1->x(); x[2] = v2->x();
+  y[0] = v0->y(); y[1] = v1->y(); y[2] = v2->y();
+  z[0] = v0->z(); z[1] = v1->z(); z[2] = v2->z();
+  SVector3 t1(x[1] - x[0], y[1] - y[0], z[1] - z[0]);
+  SVector3 t2(x[2] - x[0], y[2] - y[0], z[2] - z[0]);
+  SVector3 normal = crossprod(t1, t2);
+  normal.normalize();
+  for(int i = 0; i < 3; i++) n[i] = normal;
 }
 
 SPoint3 MTetrahedron::circumcenter()
diff --git a/Graphics/drawMesh.cpp b/Graphics/drawMesh.cpp
index 76a9ea56e39619a00e5118579c234d4cd19fa3e8..4e03ad80425bfcb569891fd6c5239f9ab9e2f221 100644
--- a/Graphics/drawMesh.cpp
+++ b/Graphics/drawMesh.cpp
@@ -570,7 +570,7 @@ class drawMeshGRegion {
     }
 
     drawArrays(_ctx, r, r->va_lines, GL_LINES, CTX::instance()->mesh.light &&
-               CTX::instance()->mesh.lightLines, CTX::instance()->mesh.volumesFaces,
+               (CTX::instance()->mesh.lightLines > 1), CTX::instance()->mesh.volumesFaces,
                CTX::instance()->color.mesh.line);
     drawArrays(_ctx, r, r->va_triangles, GL_TRIANGLES, CTX::instance()->mesh.light);