diff --git a/modules/gfx/src/scene.cc b/modules/gfx/src/scene.cc
index c385120ef437c62cbe84e316bca25130e797334e..f7899f7156a4969f158bff402b7f9f6d8aee3f0c 100644
--- a/modules/gfx/src/scene.cc
+++ b/modules/gfx/src/scene.cc
@@ -1968,6 +1968,37 @@ void Scene::render_glow()
 #endif  
 }
 
+namespace {
+  geom::Mat4 frustum(float left, float right, float bot, float top, float near, float far) {
+    float rl=1.0/(right-left);
+    float tb=1.0/(top-bot);
+    float fn=1.0/(far-near);
+    float tn=2.0*near;
+    return geom::Mat4(tn*rl, 0.0f, (right+left)*rl, 0.0f,
+                      0.0f, tn*tb, (top+bot)*tb, 0.0f,
+                      0.0f, 0.0f, -(far+near)*fn, -tn*far*fn,
+                      0.0f, 0.0f, -1.0f, 0.0f);
+  }
+
+  geom::Mat4 translate(float x, float y, float z) {
+    return geom::Mat4(1.0f, 0.0f, 0.0f, x,
+                      0.0f, 1.0f, 0.0f, y,
+                      0.0f, 0.0f, 1.0f, z,
+                      0.0f, 0.0f, 0.0f, 1.0f);
+  }
+
+  geom::Mat4 rotate(float a, float x, float y, float z) {
+    float c=cos(a);
+    float d=1.0-c;
+    float s=sin(a);
+    geom::Vec3 v=geom::Normalize(geom::Vec3(x,y,z));
+    return geom::Mat4(v[0]*v[0]*d+c, v[0]*v[1]*d-v[2]*s, v[0]*v[2]*d+v[1]*s, 0.0f, 
+                      v[1]*v[0]*d+v[2]*s, v[1]*v[1]*d+c, v[1]*v[2]*d-v[0]*s, 0.0f, 
+                      v[0]*v[2]*d-v[1]*s, v[1]*v[2]*d+v[0]*s, v[2]*v[2]*d+c, 0.0f,
+                      0.0f, 0.0f, 0.0f, 1.0f);
+  }
+}
+
 void Scene::stereo_projection(int view)
 {
   if(!gl_init_) return;
@@ -1981,6 +2012,8 @@ void Scene::stereo_projection(int view)
   Real left = -top*aspect_ratio_;
   Real right = -left;
 
+  pmat_=frustum(left,right,bot,top,zn,zf);
+
   if(view!=0) {
     
     Real ff=(view<0 ? -1.0 : 1.0);
@@ -1988,19 +2021,17 @@ void Scene::stereo_projection(int view)
 
     if(stereo_alg_==1) {
       // Toe-in method, easy but wrong
-      glFrustum(left,right,bot,top,zn,zf);
       Real dist = -transform_.GetTrans()[2]+stereo_distance_;
-      glTranslated(0.0,0.0,-dist);
-      glRotated(-180.0/M_PI*atan(0.1*ff/iod),0.0,1.0,0.0);
-      glTranslated(0.0,0.0,dist);
+      pmat_=pmat_*translate(0.0,0.0,-dist)*rotate(-atan(0.1*ff/iod),0.0,1.0,0.0)*translate(0.0,0.0,dist);
+
     } else {
       // correct off-axis frustims
 
       Real fo=-transform_.GetTrans()[2]+stereo_distance_;
 
+#if 0
       // correction of near clipping plane to avoid extreme drifting
       // of left and right view
-#if 0
       if(iod*zn/fo<2.0) {
         zn=2.0*fo/iod;
         zf=std::max(zn+Real(0.2),zf);
@@ -2010,21 +2041,16 @@ void Scene::stereo_projection(int view)
       Real sd = -ff*0.5*iod*zn/fo;
       left+=sd;
       right+=sd;
-
-      glFrustum(left,right,bot,top,zn,zf);
-      glTranslated(-ff*iod*0.5,0.0,0.0);
+      pmat_=frustum(left,right,bot,top,zn,zf)*translate(-ff*iod*0.5,0.0,0.0);
     }
 
   } else { // view==0
-    // standard viewing frustum
-    glFrustum(left,right,bot,top,zn,zf);
+    // standard viewing frustum, no need to modify above call
   }
 
-  // TODO: generate both directly from near/far/fov
+  glMultMatrix(geom::Transpose(pmat_).Data());
+
   try {
-    float pm[16];
-    glGetFloatv(GL_PROJECTION_MATRIX,pm);
-    pmat_=geom::Transpose(geom::Mat4(pm));
     ipmat_=geom::Invert(pmat_);
   } catch (geom::GeomException& e) {
     LOG_WARNING("caught GeomException in Scene::stereo_projection: " << e.what());