OpenGLむずかしい…

(本日のオチは最後に書いてあります)
透視投影と平行投影を混在させた描画がかなりややこしかったです。細かい動作仕様は良く調べきっていないのですが、PROJECTIONとMODELVIEWそれぞれにmatrixstackが存在するのですか?そしてそのそれぞれを保存しなくてはいけない?どうもそのような挙動をしめしています。つまり、matrixmodeがMODELVIEWの状態の時に、

…
(この辺で思う存分透視投影描画処理を書く)
…
GL.PushMatrix()    # MODELVIEW退避用?
GL.LoadIdentity()  # 平行投影用にMODELVIEWをきれいにする?
GL.MatrixMode(GL::PROJECTION)
GL.PushMatrix()    # PROJECTION退避用?
GL.LoadIdentity()
GL.Ortho(0.0, 640.0, 480.0, 0.0, -1.0, 1.0);

とかやって、透視投影をしている状態でのMODELVIEW行列と現在のPROJECTION行列を保存したうえで、平行投影用のMODELVIEW行列とPROJECTION行列を設定し、

#[平行投影描画処理]
GL.Begin(GL::POLYGON)
  GL.Vertex(0.0,  0.0,  0.0)
  GL.Vertex(80.0, 0.0,  0.0)
  GL.Vertex(80.0, 60.0, 0.0)
  GL.Vertex(0.0,  60.0, 0.0)
GL.End()

とか言う風に平行投影描画して、最後に

GL.PopMatrix() # PROJECTION復帰用?
GL::MatrixMode(GL::MODELVIEW);
GL.PopMatrix() # MODELVIEW復帰用?

とかやったら、元の投影行列の内容を復帰できるみたいです。
というわけで、透視投影描画に平行投影描画を混ぜられ、さらに透視投影描画の側から明示的に復帰処理を書く必要(スクリーンの幅とかのパラメータを使って再設定する必要)がなくなりました。
ただ、もっと簡単な方法がありそうな気がします…rubyでいじる前に、CでもうちょっとまじめにOpenGLの勉強をしておいた方が良かったかな?
と思ってリファレンスを読んでみると、
http://www.parallab.uib.no/SGI_bookshelves/SGI_Developer/books/OpenGL_RM/sgi_html/bk02.html
曰く、

glPushMatrix
DESCRIPTION
There is a stack of matrices for each of the matrix modes. In GL_MODELVIEW mode, the stack depth is at least 32. In the other two modes, GL_PROJECTION and GL_TEXTURE, the depth is at least 2. The current matrix in any mode is the matrix on the top of the stack for that mode.
(各マトリックスモードにはマトリックススタックが存在する。MODELVIEWモードには最低32個、PEOJECTIONとTEXTUREモードには最低2個存在する。(略))

ということで、推測は当たっていたみたいです。てか最初から読みなさいという話ですかそうですか orz