diff --git a/Common/Context.h b/Common/Context.h
index 0854705ba6a2363c207b77fc8bb6b08cef0ea57f..da75f02e39ea11ff7630564ae59876c97411c681 100644
--- a/Common/Context.h
+++ b/Common/Context.h
@@ -117,6 +117,7 @@ public :
   int threads, threads_lock;  // threads?, lock (should be a mutex...) 
   int alpha;                  // enable alpha blending 
   double zoom_factor;         // mouse2 zoom coefficient
+  int bg_gradient;            // draw background gradient?
 
   int fontsize;               // font size for fltk UI
   char *gl_font;              // font for opengl graphics
@@ -233,7 +234,7 @@ public :
 
   // color options
   struct{
-    unsigned int bg, fg, text, axes, small_axes;
+    unsigned int bg, bg_grad, fg, text, axes, small_axes;
     unsigned int ambient_light[6], diffuse_light[6], specular_light[6];
     struct{
       unsigned int point, line, surface, volume;
diff --git a/Common/DefaultOptions.h b/Common/DefaultOptions.h
index cea0ec45a4d9ada62822cbaabbfcf0a61ae1550d..895b09b2b14a850140789546dee3fb45cff0b341 100644
--- a/Common/DefaultOptions.h
+++ b/Common/DefaultOptions.h
@@ -468,6 +468,8 @@ StringXNumber GeneralOptions_Number[] = {
     "Number of tics on the Y-axis" },
   { F|O, "AxesTicsZ" , opt_general_axes_tics2 , 5. ,
     "Number of tics on the Z-axis" },
+  { F|O, "BackgroundGradient" , opt_general_background_gradient , 0. ,
+    "Draw background gradient (0=none, 1=vertical, 2=horizontal)" },
   { F,   "Clip0" , opt_general_clip0 , 0. ,
     "Enable clipping plane 0 (Geometry=2^0, Mesh=2^1, View[i]=2^(2+i))" },
   { F,   "Clip0A" , opt_general_clip0a , 1.0 ,
@@ -1360,6 +1362,11 @@ StringXColor GeneralOptions_Color[] = {
     PACK_COLOR(255, 255, 255, 255), 
     PACK_COLOR(255, 255, 255, 255), 
     "Background color" },
+  { F|O, "BackgroundGradient" , opt_general_color_background_gradient ,
+    PACK_COLOR(0,   0, 125, 255), 
+    PACK_COLOR(0,   0, 125, 255), 
+    PACK_COLOR(125, 125, 125, 255), 
+    "Background gradient color" },
   { F|O, "Foreground" , opt_general_color_foreground ,
     PACK_COLOR(255, 255, 255, 255),
     PACK_COLOR(0,   0,   0,   255),
diff --git a/Common/Options.cpp b/Common/Options.cpp
index 9ee439c2064b703eebfeddf2142fdd8c47a82448..b9a708d6713f8aa15cf167ed112c88b3101e5184 100644
--- a/Common/Options.cpp
+++ b/Common/Options.cpp
@@ -1,4 +1,4 @@
-// $Id: Options.cpp,v 1.263 2005-11-20 03:58:27 geuzaine Exp $
+// $Id: Options.cpp,v 1.264 2005-12-16 17:35:32 geuzaine Exp $
 //
 // Copyright (C) 1997-2005 C. Geuzaine, J.-F. Remacle
 //
@@ -3098,6 +3098,20 @@ double opt_general_color_scheme(OPT_ARGS_NUM)
   return CTX.color_scheme;
 }
 
+double opt_general_background_gradient(OPT_ARGS_NUM)
+{
+  if(action & GMSH_SET){
+    CTX.bg_gradient = (int)val;
+    if(CTX.bg_gradient < 0 || CTX.bg_gradient > 2)
+      CTX.bg_gradient = 0;
+  }
+#if defined(HAVE_FLTK)
+  if(WID && (action & GMSH_GUI))
+    WID->gen_choice[5]->value(CTX.bg_gradient);
+#endif
+  return CTX.bg_gradient;
+}
+
 double opt_general_trackball(OPT_ARGS_NUM)
 {
   if(action & GMSH_SET)
@@ -6715,12 +6729,22 @@ unsigned int opt_general_color_background(OPT_ARGS_COL)
   return CTX.color.bg;
 }
 
+unsigned int opt_general_color_background_gradient(OPT_ARGS_COL)
+{
+  if(action & GMSH_SET)
+    CTX.color.bg_grad = val;
+#if defined(HAVE_FLTK)
+  CCC(CTX.color.bg_grad, WID->gen_col[1]);
+#endif
+  return CTX.color.bg_grad;
+}
+
 unsigned int opt_general_color_foreground(OPT_ARGS_COL)
 {
   if(action & GMSH_SET)
     CTX.color.fg = val;
 #if defined(HAVE_FLTK)
-  CCC(CTX.color.fg, WID->gen_col[1]);
+  CCC(CTX.color.fg, WID->gen_col[2]);
 #endif
   return CTX.color.fg;
 }
@@ -6730,7 +6754,7 @@ unsigned int opt_general_color_text(OPT_ARGS_COL)
   if(action & GMSH_SET)
     CTX.color.text = val;
 #if defined(HAVE_FLTK)
-  CCC(CTX.color.text, WID->gen_col[2]);
+  CCC(CTX.color.text, WID->gen_col[3]);
 #endif
   return CTX.color.text;
 }
@@ -6740,7 +6764,7 @@ unsigned int opt_general_color_axes(OPT_ARGS_COL)
   if(action & GMSH_SET)
     CTX.color.axes = val;
 #if defined(HAVE_FLTK)
-  CCC(CTX.color.axes, WID->gen_col[3]);
+  CCC(CTX.color.axes, WID->gen_col[4]);
 #endif
   return CTX.color.axes;
 }
@@ -6750,7 +6774,7 @@ unsigned int opt_general_color_small_axes(OPT_ARGS_COL)
   if(action & GMSH_SET)
     CTX.color.small_axes = val;
 #if defined(HAVE_FLTK)
-  CCC(CTX.color.small_axes, WID->gen_col[4]);
+  CCC(CTX.color.small_axes, WID->gen_col[5]);
 #endif
   return CTX.color.small_axes;
 }
@@ -6761,7 +6785,7 @@ unsigned int opt_general_color_ambient_light(OPT_ARGS_COL)
     for(int i = 0; i < 6; i++)
       CTX.color.ambient_light[i] = val;
 #if defined(HAVE_FLTK)
-  CCC(CTX.color.ambient_light[0], WID->gen_col[5]);
+  CCC(CTX.color.ambient_light[0], WID->gen_col[6]);
 #endif
   return CTX.color.ambient_light[0];
 }
@@ -6772,7 +6796,7 @@ unsigned int opt_general_color_diffuse_light(OPT_ARGS_COL)
     for(int i = 0; i < 6; i++)
       CTX.color.diffuse_light[i] = val;
 #if defined(HAVE_FLTK)
-  CCC(CTX.color.diffuse_light[0], WID->gen_col[6]);
+  CCC(CTX.color.diffuse_light[0], WID->gen_col[7]);
 #endif
   return CTX.color.diffuse_light[0];
 }
@@ -6783,7 +6807,7 @@ unsigned int opt_general_color_specular_light(OPT_ARGS_COL)
     for(int i = 0; i < 6; i++)
       CTX.color.specular_light[i] = val;
 #if defined(HAVE_FLTK)
-  CCC(CTX.color.specular_light[0], WID->gen_col[7]);
+  CCC(CTX.color.specular_light[0], WID->gen_col[8]);
 #endif
   return CTX.color.specular_light[0];
 }
diff --git a/Common/Options.h b/Common/Options.h
index 898bbc56ce7f965df0f80f7dd30989a92ced8e1e..fb51fa38cc79a047d78179418954b578bf5ff5f5 100644
--- a/Common/Options.h
+++ b/Common/Options.h
@@ -282,6 +282,7 @@ double opt_general_line_width(OPT_ARGS_NUM);
 double opt_general_shine(OPT_ARGS_NUM);
 double opt_general_shine_exponent(OPT_ARGS_NUM);
 double opt_general_color_scheme(OPT_ARGS_NUM);
+double opt_general_background_gradient(OPT_ARGS_NUM);
 double opt_general_verbosity(OPT_ARGS_NUM);
 double opt_general_nopopup(OPT_ARGS_NUM);
 double opt_general_terminal(OPT_ARGS_NUM);
@@ -627,6 +628,7 @@ double opt_print_gif_transparent(OPT_ARGS_NUM);
 // COLORS
 
 unsigned int opt_general_color_background(OPT_ARGS_COL);
+unsigned int opt_general_color_background_gradient(OPT_ARGS_COL);
 unsigned int opt_general_color_foreground(OPT_ARGS_COL);
 unsigned int opt_general_color_text(OPT_ARGS_COL);
 unsigned int opt_general_color_axes(OPT_ARGS_COL);
diff --git a/Fltk/Callbacks.cpp b/Fltk/Callbacks.cpp
index d797deff2f95d1286750fe562dbd3d37f460c2b6..8b7633e57d72d1c4cd866460006a7a386e015bb4 100644
--- a/Fltk/Callbacks.cpp
+++ b/Fltk/Callbacks.cpp
@@ -1,4 +1,4 @@
-// $Id: Callbacks.cpp,v 1.384 2005-12-08 20:35:34 geuzaine Exp $
+// $Id: Callbacks.cpp,v 1.385 2005-12-16 17:35:32 geuzaine Exp $
 //
 // Copyright (C) 1997-2005 C. Geuzaine, J.-F. Remacle
 //
@@ -1001,6 +1001,7 @@ void general_options_ok_cb(CALLBACK_ARGS)
   opt_general_graphics_font(0, GMSH_SET, (char *)WID->gen_choice[1]->text());
   opt_general_orthographic(0, GMSH_SET | GMSH_GUI, !WID->gen_choice[2]->value());
   opt_general_axes(0, GMSH_SET, WID->gen_choice[4]->value());
+  opt_general_background_gradient(0, GMSH_SET, WID->gen_choice[5]->value());
 }
 
 void general_arrow_param_cb(CALLBACK_ARGS)
diff --git a/Fltk/GUI.cpp b/Fltk/GUI.cpp
index 66865a9ab04075cee813401b4841b4f52c78bccc..049adbbe103e772c2540b5972879dfe6d4ad233a 100644
--- a/Fltk/GUI.cpp
+++ b/Fltk/GUI.cpp
@@ -1,4 +1,4 @@
-// $Id: GUI.cpp,v 1.471 2005-12-08 20:35:34 geuzaine Exp $
+// $Id: GUI.cpp,v 1.472 2005-12-16 17:35:32 geuzaine Exp $
 //
 // Copyright (C) 1997-2005 C. Geuzaine, J.-F. Remacle
 //
@@ -1985,10 +1985,21 @@ void GUI::create_option_window()
       gen_choice[3]->align(FL_ALIGN_RIGHT);
       gen_choice[3]->tooltip("(Alt+c)");
 
-      Fl_Scroll *s = new Fl_Scroll(L + 2 * WB, 3 * WB + 2 * BH, IW + 20, height - 5 * WB - 2 * BH);
+      static Fl_Menu_Item menu_bg_grad[] = {
+	{"None", 0, 0, 0},
+	{"Vertical", 0, 0, 0},
+	{"Horizontal", 0, 0, 0},
+	{0}
+      };
+
+      gen_choice[5] = new Fl_Choice(L + 2 * WB, 2 * WB + 2 * BH, IW, BH, "Background gradient");
+      gen_choice[5]->menu(menu_bg_grad);
+      gen_choice[5]->align(FL_ALIGN_RIGHT);
+
+      Fl_Scroll *s = new Fl_Scroll(L + 2 * WB, 3 * WB + 3 * BH, IW + 20, height - 5 * WB - 3 * BH);
       int i = 0;
       while(GeneralOptions_Color[i].str) {
-        gen_col[i] = new Fl_Button(L + 2 * WB, 3 * WB + (2 + i) * BH, IW, BH, GeneralOptions_Color[i].str);
+        gen_col[i] = new Fl_Button(L + 2 * WB, 3 * WB + (3 + i) * BH, IW, BH, GeneralOptions_Color[i].str);
         gen_col[i]->callback(color_cb, (void *)GeneralOptions_Color[i].function);
         i++;
       }
diff --git a/Fltk/Opengl.cpp b/Fltk/Opengl.cpp
index 4aacc0108f876ce1f4cf9dc2f0b0c8fcf6c20f5e..4a716479444f386e30d19135f99a65274371a11b 100644
--- a/Fltk/Opengl.cpp
+++ b/Fltk/Opengl.cpp
@@ -1,4 +1,4 @@
-// $Id: Opengl.cpp,v 1.55 2005-10-09 18:00:54 geuzaine Exp $
+// $Id: Opengl.cpp,v 1.56 2005-12-16 17:35:33 geuzaine Exp $
 //
 // Copyright (C) 1997-2005 C. Geuzaine, J.-F. Remacle
 //
@@ -35,25 +35,11 @@ extern Context_T CTX;
 
 // Draw specialization
 
-void InitOpengl(void)
-{
-  WID->make_opengl_current();
-  Orthogonalize(0, 0);
-}
-
 void SetOpenglContext(void)
 {
   WID->make_opengl_current();
 }
 
-void ClearOpengl(void)
-{
-  glClearColor(UNPACK_RED(CTX.color.bg) / 255.,
-               UNPACK_GREEN(CTX.color.bg) / 255.,
-               UNPACK_BLUE(CTX.color.bg) / 255., 0.);
-  glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
-}
-
 void Draw(void)
 {
   WID->redraw_opengl();
diff --git a/Fltk/Opengl_Window.cpp b/Fltk/Opengl_Window.cpp
index 0a20247daebc29a0d48d34ce08fba4c1fdbb1286..7287e55275e3b423fbfafe72ea283f58c7751539 100644
--- a/Fltk/Opengl_Window.cpp
+++ b/Fltk/Opengl_Window.cpp
@@ -1,4 +1,4 @@
-// $Id: Opengl_Window.cpp,v 1.50 2005-10-09 18:00:54 geuzaine Exp $
+// $Id: Opengl_Window.cpp,v 1.51 2005-12-16 17:35:33 geuzaine Exp $
 //
 // Copyright (C) 1997-2005 C. Geuzaine, J.-F. Remacle
 //
@@ -63,8 +63,8 @@ void Opengl_Window::draw()
   }
 
   if(!ZoomMode) {
-    Orthogonalize(0, 0);
     ClearOpengl();
+    Orthogonalize(0, 0);
     Draw3d();
     Draw2d();
   }
diff --git a/Graphics/CreateFile.cpp b/Graphics/CreateFile.cpp
index e40b49c45a49cf228be75a8e4054c6f08f708d81..e5f9fca99b4111be8ee82ef0cee045019ff9744e 100644
--- a/Graphics/CreateFile.cpp
+++ b/Graphics/CreateFile.cpp
@@ -1,4 +1,4 @@
-// $Id: CreateFile.cpp,v 1.69 2005-06-08 19:12:04 geuzaine Exp $
+// $Id: CreateFile.cpp,v 1.70 2005-12-16 17:35:33 geuzaine Exp $
 //
 // Copyright (C) 1997-2005 C. Geuzaine, J.-F. Remacle
 //
@@ -39,8 +39,9 @@ extern Mesh M;
 
 void FillBuffer(void)
 {
-  InitOpengl();
+  SetOpenglContext();
   ClearOpengl();
+  Orthogonalize(0, 0);
   Draw3d();
   Draw2d();
 }
diff --git a/Graphics/Draw.cpp b/Graphics/Draw.cpp
index 18c464b4efbcc4181d46662b9331ecb25c39a22f..59c7d58472ad16164d3b52ef63674fe76b54075c 100644
--- a/Graphics/Draw.cpp
+++ b/Graphics/Draw.cpp
@@ -1,4 +1,4 @@
-// $Id: Draw.cpp,v 1.80 2005-11-19 14:59:41 geuzaine Exp $
+// $Id: Draw.cpp,v 1.81 2005-12-16 17:35:33 geuzaine Exp $
 //
 // Copyright (C) 1997-2005 C. Geuzaine, J.-F. Remacle
 //
@@ -121,6 +121,14 @@ void DrawPlugin(void (*draw)(void))
   CTX.mesh.draw = 1;
 }
 
+void ClearOpengl(void)
+{
+  glClearColor(UNPACK_RED(CTX.color.bg) / 255.,
+               UNPACK_GREEN(CTX.color.bg) / 255.,
+               UNPACK_BLUE(CTX.color.bg) / 255., 0.);
+  glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
+}
+
 // Ortho
 
 void Orthogonalize(int x, int y)
@@ -173,6 +181,8 @@ void Orthogonalize(int x, int y)
   // buffer might become insufficient (at least with the "software"
   // Mesa on Linux; with hardware acceleration or on Windows
   // everyhting seems to be fine).
+
+  double gradient_zdist, gradient_xyfact;
   if(CTX.ortho) {
     double maxz = MAX(fabs(CTX.min[2]), fabs(CTX.max[2]));
     if(maxz < CTX.lc) maxz = CTX.lc;
@@ -180,16 +190,61 @@ void Orthogonalize(int x, int y)
     glOrtho(CTX.vxmin, CTX.vxmax, CTX.vymin, CTX.vymax, -clip, clip);
     glMatrixMode(GL_MODELVIEW);
     glLoadIdentity();
+    gradient_zdist = 0.99 * clip;
+    gradient_xyfact = 1.;
   }
   else {
-    glFrustum(CTX.vxmin, CTX.vxmax, CTX.vymin, CTX.vymax, CTX.lc,
-              100 * CTX.lc);
+    double near = 0.75 * CTX.clip_factor * CTX.lc;
+    double far = 75. * CTX.clip_factor * CTX.lc;
+
+    // recenter the model such that the perspective is always at the
+    // center of the screen. FIXME: this screws up the zoom, so let's
+    // leave it out for now
+    /*
+    double w = (CTX.max[0] - CTX.min[0]) / 2.;
+    double h = (CTX.max[1] - CTX.min[1]) / 2.;
+    CTX.vxmin -= w;
+    CTX.vxmax -= w;
+    CTX.vymin -= h;
+    CTX.vymax -= h;
+    */
+    double w = 0.;
+    double h = 0.;
+    glFrustum(CTX.vxmin, CTX.vxmax, CTX.vymin, CTX.vymax, near, far);
     glMatrixMode(GL_MODELVIEW);
     glLoadIdentity();
-    glTranslated(0.0, 0.0, -10 * CTX.lc);
-    glScaled(10., 10., 10.);
+    glTranslated(-5 * w, -5 * h, -5 * near);
+    glScaled(5., 5., 5.);
+    gradient_zdist = 0.99 * far;
+    gradient_xyfact = far / near;
   }
 
+  // draw background gradient
+  if(CTX.bg_gradient){
+    glPushMatrix();
+    glLoadIdentity();
+    glTranslated(0., 0., -gradient_zdist);
+    glShadeModel(GL_SMOOTH);
+    glBegin(GL_QUADS);
+    if(CTX.bg_gradient == 1){
+      glColor4ubv((GLubyte *) & CTX.color.bg);
+      glVertex2d(gradient_xyfact * CTX.vxmin, gradient_xyfact * CTX.vymin);
+      glVertex2d(gradient_xyfact * CTX.vxmax, gradient_xyfact * CTX.vymin);
+      glColor4ubv((GLubyte *) & CTX.color.bg_grad);
+      glVertex2d(gradient_xyfact * CTX.vxmax, gradient_xyfact * CTX.vymax);
+      glVertex2d(gradient_xyfact * CTX.vxmin, gradient_xyfact * CTX.vymax);
+    }
+    else{
+      glColor4ubv((GLubyte *) & CTX.color.bg);
+      glVertex2d(gradient_xyfact * CTX.vxmax, gradient_xyfact * CTX.vymin);
+      glVertex2d(gradient_xyfact * CTX.vxmax, gradient_xyfact * CTX.vymax);
+      glColor4ubv((GLubyte *) & CTX.color.bg_grad);
+      glVertex2d(gradient_xyfact * CTX.vxmin, gradient_xyfact * CTX.vymax);
+      glVertex2d(gradient_xyfact * CTX.vxmin, gradient_xyfact * CTX.vymin);
+    }
+    glEnd();
+    glPopMatrix();
+  }
 }
 
 // Init
diff --git a/Graphics/Draw.h b/Graphics/Draw.h
index e0486f162ad6a7ed4e7a28eb996cfe455ab4fc61..0c8804e5e101c06984a6afa07390535711d6c403 100644
--- a/Graphics/Draw.h
+++ b/Graphics/Draw.h
@@ -30,7 +30,6 @@
 
 #define SELECTION_BUFFER_SIZE  1024
 
-void InitOpengl(void);
 void InitRenderModel(void);
 void InitPosition(void);
 
diff --git a/Graphics/Mesh.cpp b/Graphics/Mesh.cpp
index c7ba19797b5340db82863256ecc97f87ccbd8010..7359b5f97aede850ffaa2f08592956e1effba82c 100644
--- a/Graphics/Mesh.cpp
+++ b/Graphics/Mesh.cpp
@@ -1,4 +1,4 @@
-// $Id: Mesh.cpp,v 1.143 2005-12-05 20:36:55 geuzaine Exp $
+// $Id: Mesh.cpp,v 1.144 2005-12-16 17:35:33 geuzaine Exp $
 //
 // Copyright (C) 1997-2005 C. Geuzaine, J.-F. Remacle
 //
@@ -59,7 +59,8 @@ void draw_polygon_2d(double r, double g, double b, int n,
   int i;
 
   CalculateMinMax(THEM->Points, NULL);
-  InitOpengl();
+  SetOpenglContext();
+  Orthogonalize(0, 0);
   InitPosition();
 
   glDisable(GL_DEPTH_TEST);