diff --git a/modules/gfx/src/impl/cpk_renderer.cc b/modules/gfx/src/impl/cpk_renderer.cc
index 3c1cf9f051459493c86d6cb23b5c950c60201268..f7b0df84cd711564e052a7733258276e4acf6146 100644
--- a/modules/gfx/src/impl/cpk_renderer.cc
+++ b/modules/gfx/src/impl/cpk_renderer.cc
@@ -150,10 +150,12 @@ void CPKRenderer::Render3DSprites()
     geom::Vec3 cz=irot*geom::Vec3(0.0,0.0,1.0);
 
     uint write_normals = Shader::Instance().GetCurrentName()=="dumpnorm" ? 1 : 0;
+    uint use_hemimodel = Shader::Instance().GetCurrentName()=="hemilight" ? 1 : 0;
     Shader::Instance().PushProgram();
     Shader::Instance().Activate("fast_sphere");
     Shader::Instance().UpdateState();
     glUniform1i(glGetUniformLocation(Shader::Instance().GetCurrentProgram(),"write_normals"),write_normals);
+    glUniform1i(glGetUniformLocation(Shader::Instance().GetCurrentProgram(),"use_hemimodel"),use_hemimodel);
 
     glPushAttrib(GL_ALL_ATTRIB_BITS);
     glDisable(GL_LIGHTING);
diff --git a/modules/gfx/src/shader/fast_sphere_fs.glsl b/modules/gfx/src/shader/fast_sphere_fs.glsl
index 8832b5e28f850064d68a1082b050ed4ccb88ac04..66a8ca1605dca735386085e8b54908ebf10bb81f 100644
--- a/modules/gfx/src/shader/fast_sphere_fs.glsl
+++ b/modules/gfx/src/shader/fast_sphere_fs.glsl
@@ -2,6 +2,7 @@ uniform bool lighting_flag;
 uniform bool two_sided_flag;
 uniform bool fog_flag;
 uniform bool write_normals;
+uniform bool use_hemimodel;
 
 // gl_TexCoord[0] is from gl_MultiTexCoord0, which in turn
 // is custom crafted in the fast sphere prep routine
@@ -43,16 +44,20 @@ void main()
     return;
   }
 
-  vec4 amb = vec4(0.0);
-  vec4 diff = vec4(0.0);
-  vec4 spec = vec4(0.0);
   vec4 color = vec4(0.0);
+  if(use_hemimodel) {
+    color = gl_Color;
+  } else {
+    vec4 amb = vec4(0.0);
+    vec4 diff = vec4(0.0);
+    vec4 spec = vec4(0.0);
 
-  DirectionalLight(normal, gl_FrontMaterial.shininess, amb, diff, spec);
-  color  = gl_FrontLightModelProduct.sceneColor  +
-           (amb  * gl_FrontMaterial.ambient * gl_Color) +
-           (diff * gl_FrontMaterial.diffuse * gl_Color) +
-           (spec * gl_FrontMaterial.specular);
+    DirectionalLight(normal, gl_FrontMaterial.shininess, amb, diff, spec);
+    color  = gl_FrontLightModelProduct.sceneColor  +
+             (amb  * gl_FrontMaterial.ambient * gl_Color) +
+             (diff * gl_FrontMaterial.diffuse * gl_Color) +
+             (spec * gl_FrontMaterial.specular);
+  }
 
   if(fog_flag) {
     float fog = clamp((gl_Fog.end-(gl_FogFragCoord+z1)) * gl_Fog.scale, 0.0, 1.0);
diff --git a/modules/gfx/src/shader/fast_sphere_vs.glsl b/modules/gfx/src/shader/fast_sphere_vs.glsl
index 67bb0be4da85e77c2f195a2185c875fbcfcdbefd..5acd60562a4a59d500855e6a572f1ffe259ee439 100644
--- a/modules/gfx/src/shader/fast_sphere_vs.glsl
+++ b/modules/gfx/src/shader/fast_sphere_vs.glsl
@@ -1,3 +1,5 @@
+bool use_hemimodel;
+
 void main()
 {
   // transformed position
@@ -9,6 +11,23 @@ void main()
 
   gl_TexCoord[0]=gl_MultiTexCoord0;
 
-  gl_FrontColor=gl_Color;
-  gl_BackColor=gl_Color;
+  if(use_hemimodel) {
+    vec4 ground_color=0.2*gl_Color;
+    vec4 sky_color=1.0*gl_Color;
+
+    // hemisphere lighting contribution
+    vec3 ec_pos = vec3(gl_ModelViewMatrix* gl_Vertex);
+    vec3 normal = vec3(0,0,1);
+    if(dot(gl_Normal,gl_Normal)>0.001) {
+      normal = normalize(gl_NormalMatrix * gl_Normal);
+    }
+    vec3 l_dir  = normalize(gl_LightSource[0].position.xyz); // assume directional vector
+    float a  = 0.5+0.5*dot(normal,l_dir);
+    gl_FrontColor.rgb = mix(ground_color, sky_color, a).rgb;
+    gl_FrontColor.a = gl_Color.a;
+    gl_BackColor = gl_FrontColor;
+  } else {
+    gl_FrontColor=gl_Color;
+    gl_BackColor=gl_Color;
+  }
 }