diff --git a/modules/gfx/pymod/export_scene.cc b/modules/gfx/pymod/export_scene.cc
index 89a5738cee543684eaf5d0d51cafd2913a7eaa26..06e81223e147400c3d803e379cbef5667684d867 100644
--- a/modules/gfx/pymod/export_scene.cc
+++ b/modules/gfx/pymod/export_scene.cc
@@ -69,6 +69,22 @@ void (Scene::*scene_set_bg1)(const Color&) = &Scene::SetBackground;
 void (Scene::*scene_set_bg2)(const Gradient&) = &Scene::SetBackground;
 void (Scene::*scene_set_bg3)(const Bitmap&) = &Scene::SetBackground;
 
+tuple scene_get_hemi_p(Scene* s)
+{
+  geom::Vec4 hfp=s->GetHemiParams();
+  return make_tuple(hfp[0],hfp[1],hfp[2],hfp[3]);
+}
+
+void scene_set_hemi_p(Scene* s, tuple p)
+{
+  geom::Vec4 hfp;
+  hfp[0]=extract<float>(p[0]);
+  hfp[1]=extract<float>(p[1]);
+  hfp[2]=extract<float>(p[2]);
+  hfp[3]=extract<float>(p[3]);
+  s->SetHemiParams(hfp);
+}
+
 } // anon ns
 
 
@@ -246,5 +262,6 @@ void export_Scene()
     .add_property("bounding_box",scene_get_bb1)
     .add_property("export_aspect",&Scene::GetExportAspect,&Scene::SetExportAspect)
     .add_property("show_export_aspect",&Scene::GetShowExportAspect,&Scene::SetShowExportAspect)
+    .add_property("hemi_params",scene_get_hemi_p,scene_set_hemi_p)
   ;
 }
diff --git a/modules/gfx/src/impl/fast_spheres.cc b/modules/gfx/src/impl/fast_spheres.cc
index e10ac2d03d62fdc90a8eedc955d169b6ce1f8e55..325742d75ce41b465bbebe2391da46f8e346fefe 100644
--- a/modules/gfx/src/impl/fast_spheres.cc
+++ b/modules/gfx/src/impl/fast_spheres.cc
@@ -77,6 +77,12 @@ namespace ost { namespace gfx { namespace impl {
     if(Shader::Instance().GetCurrentName()=="hemilight" ||
        Shader::Instance().GetCurrentName()=="hf") {
       Shader::Instance().Activate("fast_sphere_hf");
+      GLuint cpr=Shader::Instance().GetCurrentProgram();
+      GLuint loc=glGetUniformLocation(cpr,"hemi_param");
+      if(loc>0) {
+        geom::Vec4 hp=Scene::Instance().GetHemiParams();
+        glUniform4f(loc,hp[0],hp[1],hp[2],hp[3]);
+      }
     } else if(Shader::Instance().GetCurrentName()=="toon1") {
       Shader::Instance().Activate("fast_sphere_toon1");
     } else if(Shader::Instance().GetCurrentName()=="toon2") {
diff --git a/modules/gfx/src/scene.cc b/modules/gfx/src/scene.cc
index ad80008a5b631d769381f24a3f3e329947824666..dc2183f27b1cd066266a81893c6af05aaee284ec 100644
--- a/modules/gfx/src/scene.cc
+++ b/modules/gfx/src/scene.cc
@@ -109,6 +109,7 @@ Scene::Scene():
   light_amb_(0.1,0.1,0.1),
   light_diff_(0.9,0.9,0.9),
   light_spec_(0.5,0.5,0.5),
+  hemi_param_(0.4,1.0,0.0,1.0),
   cor_flag_(false),
   fix_cor_flag_(true),
   fog_flag_(true),
@@ -341,6 +342,12 @@ float Scene::GetAmbientOcclusionSize() const
 #endif
 }
 
+void Scene::SetHemiParams(const geom::Vec4& p)
+{
+  hemi_param_=p;
+  RequestRedraw();
+}
+
 void Scene::SetShadingMode(const std::string& smode)
 {
 #if OST_SHADER_SUPPORT_ENABLED
@@ -836,6 +843,17 @@ void Scene::RenderGL()
 
   prep_blur();
 
+#if OST_SHADER_SUPPORT_ENABLED
+  {
+    GLuint cpr=Shader::Instance().GetCurrentProgram();
+    GLuint loc=glGetUniformLocation(cpr,"hemi_param");
+    if(loc>0) {
+      glUniform4f(loc,hemi_param_[0],hemi_param_[1],hemi_param_[2],hemi_param_[3]);
+    }
+  }
+#endif
+
+
   if(stereo_mode_==1 || stereo_mode_==2 || stereo_mode_==3) {
     render_stereo();
   } else {
diff --git a/modules/gfx/src/scene.hh b/modules/gfx/src/scene.hh
index 0980ce561c69b1d31097458d6cb40ff6c2a91868..89717de74999e157aeae36443d60333a9e479018 100644
--- a/modules/gfx/src/scene.hh
+++ b/modules/gfx/src/scene.hh
@@ -143,7 +143,10 @@ class DLLEXPORT_OST_GFX Scene {
   void SetAmbientOcclusionSize(float f);
   /// experimental feature
   float GetAmbientOcclusionSize() const;
-  
+ 
+  void SetHemiParams(const geom::Vec4&);
+  geom::Vec4 GetHemiParams() const {return hemi_param_;}
+
   /// \brief select shading mode
   /// one of fallback, basic, default, hf, toon1, toon2
   void SetShadingMode(const std::string& smode);
@@ -574,6 +577,7 @@ private:
   Color light_amb_;
   Color light_diff_;
   Color light_spec_;
+  geom::Vec4 hemi_param_;
 
   bool cor_flag_;
   bool fix_cor_flag_;
diff --git a/modules/gfx/src/shader/material_hemi.glsl b/modules/gfx/src/shader/material_hemi.glsl
index e9d223deaad03c709d20a8b42f5f0aaf9d3e1754..23f17c03613b8b59ff827717d9866f52f4d1a9ed 100644
--- a/modules/gfx/src/shader/material_hemi.glsl
+++ b/modules/gfx/src/shader/material_hemi.glsl
@@ -1,12 +1,16 @@
+uniform vec4 hemi_param;
+
 vec4 light(in vec3 normal,
            in vec4 color,
            in bool two_sided)
 {
-  vec4 ground_color=0.2*color;
-  vec4 sky_color=1.0*color;
+  vec4 ground_color=hemi_param[0]*color;
+  vec4 sky_color=hemi_param[1]*color;
   
   vec3 l_dir  = normalize(gl_LightSource[0].position.xyz); // assume directional vector
-  float a  = 0.5+0.5*dot(normal,l_dir);
+  // min(1.0,max(0.0,x-u)/(v-u))
+  float a=min(1.0,max(0.0,dot(normal,l_dir)-hemi_param[2])/(hemi_param[3]-hemi_param[2]));
+  //float a  = 0.5+0.5*dot(normal,l_dir);
   color.rgb = mix(ground_color, sky_color, a).rgb;
   bool backside = false;
   if(two_sided && backside) {