vertix shaderを試してみた。なんとか動いたけど行列が、わからない。
追々探るとして、とりあえず載せてみました。

追記
d-kamiさんの情報を元にvertex shaderを修正しました。

# -*- encoding: utf-8 -*-
require "opengl"
require "glut"

vs = <<EOF
  attribute vec3 position;
  void main(){
    gl_Position = gl_ModelViewProjectionMatrix * vec4(position, 1.0);
    // ↓もOK
    //gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * vec4(position, 1.0);
    // ↓は修正前
    //gl_Position = gl_ModelViewProjectionMatrix * gl_ModelViewMatrix * vec4(position, 1.0); 
  }
EOF

fs = <<EOF
  void main( void ) {
   gl_FragColor  =  vec4(1.0, 0.5, 1.0, 1.0);
  }
EOF

GLUT.InitWindowPosition(100, 100)
GLUT.InitWindowSize(300,300)
GLUT.Init
GLUT.InitDisplayMode(GLUT::GLUT_DOUBLE | GLUT::GLUT_RGB | GLUT::GLUT_DEPTH)
GLUT.CreateWindow("Ruby de GLSL")

program = GL.CreateProgram
for src in [{:code=>vs, :type=>GL::VERTEX_SHADER},
            {:code=>fs, :type=>GL::FRAGMENT_SHADER}]
  shader = GL.CreateShader(src[:type])
  GL.ShaderSource(shader, src[:code])
  GL.CompileShader(shader)
  GL.AttachShader(program, shader)
  GL.DeleteShader(shader)
end
GL.LinkProgram(program)
GL.UseProgram(program)

vertices = proc{|radius, tube, segV, segH|
  vec = []
  for v in 0..segV do
    vTheta = 2 * Math::PI * v / segV
    r = Math.cos(vTheta) * tube
    y = Math.sin(vTheta) * tube
    for h in  0..segH do
      hTheta = 2 * Math::PI * h / segH
      x = Math.cos(hTheta) * (radius + r)
      z = Math.sin(hTheta) * (radius + r)
      vec << [x, y, z]
    end
  end
  vec.flatten
}[1, 0.5, 50, 100]

buffers = GL.GenBuffers(1)
GL.BindBuffer(GL::ARRAY_BUFFER, buffers[0])
GL.BufferData(GL::ARRAY_BUFFER, 4 * vertices.size, vertices.pack('f*'), GL::STATIC_DRAW)
location = GL.GetAttribLocation(program, "position")
GL.EnableVertexAttribArray(location)
GL.VertexAttribPointer(location, 3, GL::FLOAT, false, 0, 0)

GLUT.ReshapeFunc proc{|w,h|
  GL.Viewport(0,0,w,h)
  GL.MatrixMode(GL::PROJECTION)
  GL.LoadIdentity
  GLU.Perspective(45, w.to_f / h.to_f, 0.1, 100)
}

GL.ClearColor(0, 0, 0, 1)
GLUT.DisplayFunc proc{
  GL.Clear(GL::COLOR_BUFFER_BIT | GL::DEPTH_BUFFER_BIT)
  GL.DrawArrays(GL::POINTS, 0, vertices.size / 3)
  GLUT.SwapBuffers
}

theta = 0
update = proc{
  GLUT.TimerFunc(1000 / 30 , update , 0)
  GL.MatrixMode(GL::MODELVIEW)
  GL.LoadIdentity
  GLU.LookAt(0, 0, 5, 0, 0, 0, 0, 1, 0)
  GL.Rotate(theta, 1, 1, 0)
  GLUT.PostRedisplay
  theta = (theta + 1) % 360
}
update[]

GLUT.MainLoop