RingOpenGL と RingFreeGLUT の用法 (3D グラフィックス) — プログラミング言語 Ring 1.14 取扱説明書

Skip to content

# RingOpenGL と RingFreeGLUT の用法 (3D グラフィックス)

RingOpenGL と RingFreeGLUT の用法です。

## サンプルソース (作者)

この C チュートリアルを参考に本章のサンプルを記述しました。

出典元:

1. http://www.lighthouse3d.com/tutorials/glut-tutorial/

2. http://www.wikihow.com/Make-a-Cube-in-OpenGL

## RingOpenGL とは？

RingOpenGL は Ring 付属の OpenGL ライブラリのバインディングです。

こちらから OpenGL について学べます : https://www.opengl.org/

RingOpenGL は下記のバージョンに対応しています。

- OpenGL 1.1

- OpenGL 1.2

- OpenGL 1.3

- OpenGL 1.4

- OpenGL 1.5

- OpenGL 2.0

- OpenGL 2.1

- OpenGL 3.0

- OpenGL 3.2

- OpenGL 3.3

- OpenGL 4.0

- OpenGL 4.1

- OpenGL 4.2

- OpenGL 4.3

- OpenGL 4.4

- OpenGL 4.5

- OpenGL 4.6

OpenGL 2.1 の場合は RingOpenGL 2.1 ライブラリを読み込みます。

    load "opengl21lib.ring"

## RingFreeGLUT とは？

RingFreeGLUT は Ring 付属の FreeGLUT ライブラリのバインディングです。

このサイトで FreeGLUT について学べます : http://freeglut.sourceforge.net/

RingFreeGLUT の使用前に freeglut.ring ライブラリを読み込みます。

    load "freeglut.ring"

## RingFreeGLUT によるはじめてのウィンドウ

用例:

    load "freeglut.ring"

    func main
            glutInit()
            glutInitDisplayMode(GLUT_SINGLE)
            glutInitWindowSize(800, 600)
            glutInitWindowPosition(100, 10)
            glutCreateWindow("RingFreeGLUT - Test 1")
            glutDisplayFunc(:displayCode)
            glutMainLoop()

    func displaycode

スクリーンショット:

## RingOpenGL での描画

用例:

    load "freeglut.ring"
    load "opengl21lib.ring"

    func main
            glutInit()
            glutInitDisplayMode(GLUT_SINGLE)
            glutInitWindowSize(800, 600)
            glutInitWindowPosition(100, 10)
            glutCreateWindow("RingFreeGLUT - Test 2")
            glutDisplayFunc(:displayCode)
            glutMainLoop()

    func displaycode
            glClear(GL_COLOR_BUFFER_BIT)
            glColor3f(0,255,0)
            glBegin(GL_POLYGON)
                    glVertex3f(0.0, 0.0, 0.0)
                    glVertex3f(0.5, 0.0, 0.0)
                    glVertex3f(0.5, 0.5, 0.0)
                    glVertex3f(0.0, 0.5, 0.0)
            glEnd()
            glColor3f(255,0,0)
            glBegin(GL_POLYGON)
                    glVertex3f(0.0, 0.0, 0.0)
                    glVertex3f(0.5, 0.0, 0.0)
                    glVertex3f(-0.5,- 1, 0.0)
                    glVertex3f(0.0, -1, 0.0)
            glEnd()
            glColor3f(0,0,255)
            glBegin(GL_POLYGON)
                   glVertex3f(0.0, 0.0, 0.0)
                    glVertex3f(-0.5, 0.0, 0.0)
                    glVertex3f(-0.5,- 0.5, 0.0)
                    glVertex3f(0.0, -0.5, 0.0)
            glEnd()

            glFlush()

スクリーンショット:

## はじめての三角形

用例:

    load "freeglut.ring"
    load "opengl21lib.ring"

    func main
            glutInit()
            glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA)
            glutInitWindowSize(320,320)
            glutInitWindowPosition(100, 10)
            glutCreateWindow("RingFreeGLUT - Test 3")
            glutDisplayFunc(:renderScene)
            glutMainLoop()

    func renderScene

            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

            glBegin(GL_TRIANGLES)
                    glVertex3f(-0.5,-0.5,0.0)
                    glVertex3f(0.5,0.0,0.0)
                    glVertex3f(0.0,0.5,0.0)
            glEnd()

            glutSwapBuffers()

スクリーンショット:

## ウィンドウの大きさ変更イベント

用例:

    load "freeglut.ring"
    load "opengl21lib.ring"

    func main

            // GLUT の初期化とウィンドウの作成
            glutInit()
            glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA)
            glutInitWindowPosition(100,100)
            glutInitWindowSize(320,320)
            glutCreateWindow("RingFreeGLUT - Test 4")

            glutDisplayFunc(:renderScene)
            glutReshapeFunc(:changeSize)

            glutMainLoop()

    func renderScene

            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

            glBegin(GL_TRIANGLES)
                    glVertex3f(-2,-2,-5.0)
                    glVertex3f(2,0.0,-5.0)
                    glVertex3f(0.0,2,-5.0)
            glEnd()

            glutSwapBuffers()

    func changesize

            h = glutEventHeight()
            w = glutEventWidth()

                    // ウィンドウの大きさが小さすぎる場合に、ゼロ除算エラーになるのを防ぎます。
            // (幅 0 のウィンドウは作成できません)
            if (h = 0)
                    h = 1
            ok

            ratio =  w * 1.0 / h

            // 投射行列の使用
            glMatrixMode(GL_PROJECTION)

            // 行列のリセット
            glLoadIdentity()

            // ウィンドウ全体のビューポートを設定します。
            glViewport(0, 0, w, h)

             // 正しい遠近法の設定
            gluPerspective(45,ratio,1,100)

            // Modelview の復帰
            glMatrixMode(GL_MODELVIEW)

## 三角形の回転

用例:

    load "freeglut.ring"
    load "opengl21lib.ring"

    angle = 0

    func main

            // GLUT の初期化とウィンドウの作成
            glutInit()
            glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA)
            glutInitWindowPosition(100,100)
            glutInitWindowSize(320,320)
            glutCreateWindow("RingFreeGLUT - Test 5")

            glutDisplayFunc(:renderScene)
            glutReshapeFunc(:changeSize)
            glutIdleFunc(:renderScene)

            glutMainLoop()

    func renderScene

            // 配色と深度バッファの消去
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

            // 変換のリセット
            glLoadIdentity()
            // カメラの設定
            gluLookAt(      0.0, 0.0, 10.0,
                                    0.0, 0.0,  0.0,
                                    0.0, 1.0,  0.0)

            glRotatef(angle, 0.0, 1.0, 0.0)

            glBegin(GL_TRIANGLES)
                    glVertex3f(-2.0,-2.0, 0.0)
                    glVertex3f( 2.0, 0.0, 0.0)
                    glVertex3f( 0.0, 2.0, 0.0)
            glEnd()

            angle+=0.1

            glutSwapBuffers();

    func changesize

            h = glutEventHeight()
            w = glutEventWidth()

                    // ウィンドウの大きさが小さすぎる場合に、ゼロ除算エラーになるのを防ぎます。
            // (幅 0 のウィンドウは作成できません)
            if (h = 0)
                    h = 1
            ok

            ratio =  w * 1.0 / h

            // 投射行列の使用
            glMatrixMode(GL_PROJECTION)

            // 行列のリセット
            glLoadIdentity()

            // ウィンドウ全体のビューポートを設定します。
            glViewport(0, 0, w, h)

             // 正しい遠近法の設定
            gluPerspective(45,ratio,1,100)

            // Modelview の復帰
            glMatrixMode(GL_MODELVIEW)

スクリーンショット:

## キーボードイベントと配色

用例:

    load "freeglut.ring"
    load "opengl21lib.ring"

    angle = 0

    red=1.0
    blue=1.0
    green=1.0

    func main

            // GLUT の初期化とウィンドウの作成
            glutInit()
            glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA)
            glutInitWindowPosition(100,100)
            glutInitWindowSize(320,320)
            glutCreateWindow("RingFreeGLUT - Test 6")

            glutDisplayFunc(:renderScene)
            glutReshapeFunc(:changeSize)
            glutIdleFunc(:renderScene)

            // これは新しいエントリーです。
            glutKeyboardFunc(:processNormalKeys)
            glutSpecialFunc(:processSpecialKeys)

            glutMainLoop()

    func renderScene

            // 配色と深度バッファの消去
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

            // 変換のリセット
            glLoadIdentity()
            // カメラの設定
            gluLookAt(      0.0, 0.0, 10.0,
                                    0.0, 0.0,  0.0,
                                    0.0, 1.0,  0.0)

            glRotatef(angle, 0.0, 1.0, 0.0)

            glColor3f(red,green,blue);

            glBegin(GL_TRIANGLES)
                    glVertex3f(-2.0,-2.0, 0.0)
                    glVertex3f( 2.0, 0.0, 0.0)
                    glVertex3f( 0.0, 2.0, 0.0)
            glEnd()

            angle+=0.1

            glutSwapBuffers();

    func changesize

            h = glutEventHeight()
            w = glutEventWidth()

                    // ウィンドウの大きさが小さすぎる場合に、ゼロ除算エラーになるのを防ぎます。
            // (幅 0 のウィンドウは作成できません)
            if (h = 0)
                    h = 1
            ok

            ratio =  w * 1.0 / h

            // 投射行列の使用
            glMatrixMode(GL_PROJECTION)

            // 行列のリセット
            glLoadIdentity()

            // ウィンドウ全体のビューポートを設定します。
            glViewport(0, 0, w, h)

             // 正しい遠近法の設定
            gluPerspective(45,ratio,1,100)

            // Modelview の復帰
            glMatrixMode(GL_MODELVIEW)

    func processNormalKeys
            key = GLUTEventKey()
            if key = 27
                    shutdown()
            ok

    func processSpecialKeys

            key = GLUTEventKey()

            switch key
                    on GLUT_KEY_F1
                                    red = 1.0
                                    green = 0.0
                                    blue = 0.0
                    on GLUT_KEY_F2
                                    red = 0.0
                                    green = 1.0
                                    blue = 0.0
                    on GLUT_KEY_F3
                                    red = 0.0
                                    green = 0.0
                                    blue = 1.0
            off

スクリーンショット:

## カメラ

用例:

    load "freeglut.ring"
    load "opengl21lib.ring"

    // カメラ方向の回転角度
    angle=0.0
    // 実際のベクトルはカメラ方向を表しています。
    lx=0.0
    lz=-1.0
    // カメラの XZ 位置
    x=0.0
    z=5.0

    func drawSnowMan

            glColor3f(1.0, 1.0, 1.0)

    // 体の描画
            glTranslatef(0.0 ,0.75, 0.0)
            glutSolidSphere(0.75,20,20)

    // 頭の描画
            glTranslatef(0.0, 1.0, 0.0)
            glutSolidSphere(0.25,20,20)

    // 目の描画
            glPushMatrix()
            glColor3f(0.0,0.0,0.0)
            glTranslatef(0.05, 0.10, 0.18)
            glutSolidSphere(0.05,10,10)
            glTranslatef(-0.1, 0.0, 0.0)
            glutSolidSphere(0.05,10,10)

            glPopMatrix()

    // 鼻の描画
            glColor3f(1.0, 0.5 , 0.5)
            glutSolidCone(0.08,0.5,10,2)

    func changeSize
            w = glutEventWidth()
            h = glutEventHeight()

            // ウィンドウの大きさが小さすぎる場合に、ゼロ除算エラーになるのを防ぎます。
            // (幅 0 のウィンドウは作成できません)
            if h = 0
                    h = 1
            ok

            ratio =  w * 1.0  / h

                    // 投射行列の使用
            glMatrixMode(GL_PROJECTION)

                    // 行列のリセット
            glLoadIdentity()

            // ウィンドウ全体のビューポートを設定します。
            glViewport(0, 0, w, h)

             // 正しい遠近法の設定
            gluPerspective(45.0, ratio, 0.1, 100.0);

            // Modelview の復帰
            glMatrixMode(GL_MODELVIEW)

    func processNormalKeys
            key = glutEventKey()

            if key = 27
                    shutdown()
            ok

    func renderScene

            // 配色と深度バッファの消去

            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

            // 変換のリセット
            glLoadIdentity()
            // カメラの設定
            gluLookAt(      x, 1.0, z,
                            x+lx, 1.0,  z+lz,
                            0.0, 1.0,  0.0)

                    // 地面の描画

            glColor3f(0.9, 0.9, 0.9)
            glBegin(GL_QUADS)
                    glVertex3f(-100.0, 0.0, -100.0)
                    glVertex3f(-100.0, 0.0,  100.0)
                    glVertex3f( 100.0, 0.0,  100.0)
                    glVertex3f( 100.0, 0.0, -100.0)
            glEnd()

                    // 36 体の雪だるまを描画
            for i = -3 to 2
                    for  j=-3 to 2
                            glPushMatrix()
                            glTranslatef(i*10.0,0,j * 10.0)
                            drawSnowMan()
                            glPopMatrix()
                    next
            next
            glutSwapBuffers()

    func processSpecialKeys

            key = glutEventKey()

            fraction = 0.1

            switch key
                    on GLUT_KEY_LEFT
                            angle -= 0.01
                            lx = sin(angle)
                            lz = -cos(angle)
                    on GLUT_KEY_RIGHT
                            angle += 0.01
                            lx = sin(angle)
                            lz = -cos(angle)
                    on GLUT_KEY_UP
                            x += lx * fraction
                            z += lz * fraction
                    on GLUT_KEY_DOWN
                            x -= lx * fraction
                            z -= lz * fraction
            off

    func main

            // GLUT の初期化とウィンドウの作成

            glutInit()
            glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA)

            glutInitWindowPosition(100,100)
            glutInitWindowSize(320,320)
            glutCreateWindow("RingFreeGLUT - Test 7")

            // コールバックの登録
            glutDisplayFunc(:renderScene)
            glutReshapeFunc(:changeSize)
            glutIdleFunc(:renderScene)
            glutKeyboardFunc(:processNormalKeys)
            glutSpecialFunc(:processSpecialKeys)

            // OpenGL の初期化
            glEnable(GL_DEPTH_TEST)

            // GLUT のイベント処理サイクルへ入ります。
            glutMainLoop()

スクリーンショット:

その他の用例:

    load "freeglut.ring"
    load "opengl21lib.ring"

    // カメラ方向の回転角度
    angle = 0.0

    // 実際のベクトルはカメラ方向を表しています。
    lx=0.0 lz=-1.0

    // カメラの XZ 位置
    x=0.0 z=5.0
    // キーの状態
    // キーを押していない時は変数は 0 です。
    deltaAngle = 0.0
    deltaMove = 0

    func changeSize
            w = glutEventWidth()
            h = glutEventHeight()

            // ウィンドウの大きさが小さすぎる場合に、ゼロ除算エラーになるのを防ぎます。
            // (幅 0 のウィンドウは作成できません)
            if h = 0
                    h = 1
            ok

            ratio =  w * 1.0 / h

            // 投射行列の使用
            glMatrixMode(GL_PROJECTION)

            // 行列のリセット
            glLoadIdentity()

            // ウィンドウ全体のビューポートを設定します。
            glViewport(0, 0, w, h)

             // 正しい遠近法の設定
            gluPerspective(45.0, ratio, 0.1, 100.0)

            // Modelview の復帰
            glMatrixMode(GL_MODELVIEW)

    func drawSnowMan

            glColor3f(1.0, 1.0, 1.0)

    // 体の描画

            glTranslatef(0.0 ,0.75, 0.0)
            glutSolidSphere(0.75,20,20)

    // 頭の描画
            glTranslatef(0.0, 1.0, 0.0)
            glutSolidSphere(0.25,20,20)

    // 目の描画
            glPushMatrix()
            glColor3f(0.0,0.0,0.0)
            glTranslatef(0.05, 0.10, 0.18)
            glutSolidSphere(0.05,10,10)
            glTranslatef(-0.1, 0.0, 0.0)
            glutSolidSphere(0.05,10,10)
            glPopMatrix()

    // 鼻の描画
            glColor3f(1.0, 0.5 , 0.5)
            glRotatef(0.0,1.0, 0.0, 0.0)
            glutSolidCone(0.08,0.5,10,2)

    func computePos deltaMove

            x += deltaMove * lx * 0.1
            z += deltaMove * lz * 0.1

    func computeDir deltaAngle

            angle += deltaAngle
            lx = sin(angle)
            lz = -cos(angle)

    func renderScene

            if deltaMove
                    computePos(deltaMove)
            ok

            if deltaAngle
                    computeDir(deltaAngle)
            ok

            // 配色と深度バッファの消去
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

            // 変換のリセット
            glLoadIdentity()
            // カメラの設定
            gluLookAt(      x, 1.0, z,
                                    x+lx, 1.0,  z+lz,
                                    0.0, 1.0,  0.0)

    // 地面の描画

            glColor3f(0.9, 0.9, 0.9)
            glBegin(GL_QUADS)
                    glVertex3f(-100.0, 0.0, -100.0)
                    glVertex3f(-100.0, 0.0,  100.0)
                    glVertex3f( 100.0, 0.0,  100.0)
                    glVertex3f( 100.0, 0.0, -100.0)
            glEnd()

    // 36 体の雪だるまを描画

            for i = -3 to 2
                    for j=-3 to 2
                            glPushMatrix()
                            glTranslatef(i*10.0,0,j * 10.0)
                            drawSnowMan()
                            glPopMatrix()
                    next
            next
            glutSwapBuffers()

    func pressKey
            key = glutEventKey()
            xx = glutEventX()
            yy = glutEventY()

            switch key
                    on GLUT_KEY_LEFT
                             deltaAngle = -0.01
                    on GLUT_KEY_RIGHT
                             deltaAngle = 0.01
                    on GLUT_KEY_UP
                             deltaMove = 0.5
                    on GLUT_KEY_DOWN
                            deltaMove = -0.5
            off

    func releaseKey

            key = glutEventKey()

            switch key
                    on GLUT_KEY_LEFT
                            deltaAngle = 0.0
                    on GLUT_KEY_RIGHT
                            deltaAngle = 0.0
                    on GLUT_KEY_UP
                            deltaMove = 0
                    on GLUT_KEY_DOWN
                            deltaMove = 0
            off

    func main

            // GLUT の初期化とウィンドウの作成
            glutInit()
            glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA)
            glutInitWindowPosition(100,100)
            glutInitWindowSize(320,320)
            glutCreateWindow("RingFreeGLUT - Test 8")

            // コールバックの登録
            glutDisplayFunc(:renderScene)
            glutReshapeFunc(:changeSize)
            glutIdleFunc(:renderScene)

            glutSpecialFunc(:pressKey)

            // これは新しいエントリーです。
            glutIgnoreKeyRepeat(1)
            glutSpecialUpFunc(:releaseKey)

            // OpenGL の初期化
            glEnable(GL_DEPTH_TEST)

            // GLUT のイベント処理サイクルへ入ります。
            glutMainLoop()

## マウスイベント

用例:

    load "freeglut.ring"
    load "opengl21lib.ring"

    // カメラ方向の回転角度
    angle = 0.0

    // 実際のベクトルはカメラ方向を表しています。
    lx=0.0 lz=-1.0

    // カメラの XZ 位置
    x=0.0  z=5.0

    // キーの状態
    // キーを押していない時は変数は 0 です。
    deltaAngle = 0.0
    deltaMove = 0.0
    xOrigin = -1

    func changeSize
            w = glutEventWidth()
            h = glutEventHeight()

            // ウィンドウの大きさが小さすぎる場合に、ゼロ除算エラーになるのを防ぎます。
            // (幅 0 のウィンドウは作成できません)
            if h = 0
                    h = 1
            ok

            ratio =  w * 1.0 / h

            // 投射行列の使用
            glMatrixMode(GL_PROJECTION)

            // 行列のリセット
            glLoadIdentity()

            // ウィンドウ全体のビューポートを設定します。
            glViewport(0, 0, w, h)

             // 正しい遠近法の設定
            gluPerspective(45.0, ratio, 0.1, 100.0)

            // Modelview の復帰
            glMatrixMode(GL_MODELVIEW)

    func drawSnowMan

            glColor3f(1.0, 1.0, 1.0)

            // 体の描画
            glTranslatef(0.0 ,0.75, 0.0)
            glutSolidSphere(0.75,20,20)

            // 頭の描画
            glTranslatef(0.0, 1.0, 0.0)
            glutSolidSphere(0.25,20,20)

            // 目の描画
            glPushMatrix()
            glColor3f(0.0,0.0,0.0)
            glTranslatef(0.05, 0.10, 0.18)
            glutSolidSphere(0.05,10,10)
            glTranslatef(-0.1, 0.0, 0.0)
            glutSolidSphere(0.05,10,10)
            glPopMatrix()

            // 鼻の描画
            glColor3f(1.0, 0.5 , 0.5)
            glRotatef(0.0,1.0, 0.0, 0.0)
            glutSolidCone(0.08,0.5,10,2)

    func computePos deltaMove

            x += deltaMove * lx * 0.1
            z += deltaMove * lz * 0.1

    func renderScene

            if deltaMove
                    computePos(deltaMove)
            ok

            // 配色と深度バッファの消去
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

            // 変換のリセット
            glLoadIdentity()
            // カメラの設定
            gluLookAt(      x, 1.0, z,
                            x+lx, 1.0,  z+lz,
                            0.0, 1.0,  0.0)

            // 地面の描画

            glColor3f(0.9, 0.9, 0.9)
            glBegin(GL_QUADS)
                    glVertex3f(-100.0, 0.0, -100.0)
                    glVertex3f(-100.0, 0.0,  100.0)
                    glVertex3f( 100.0, 0.0,  100.0)
                    glVertex3f( 100.0, 0.0, -100.0)
            glEnd()

            // 36 体の雪だるまを描画

            for i = -3 to 2
                    for  j=-3 to 2
                                             glPushMatrix()
                                             glTranslatef(i*10.0,0,j * 10.0)
                                             drawSnowMan()
                                             glPopMatrix()
                     next
            next
            glutSwapBuffers()

    func processNormalKeys

            key  = glutEventKey()

                    if key = 27
                             shutdown()
                    ok

    func pressKey
            key  = glutEventKey()

               switch key
                             on GLUT_KEY_UP
                                    deltaMove = 0.5
                             on GLUT_KEY_DOWN
                                     deltaMove = -0.5
               off

    func releaseKey
            key  = glutEventKey()
                    switch key
                             on GLUT_KEY_UP
                                    deltaMove = 0
                             on GLUT_KEY_DOWN
                                    deltaMove = 0
                    off

    func mouseMove
            xx = glutEventX()
            yy = glutEventY()
                    // これは左ボタンを押したときのみ true になります。
                    if xOrigin >= 0

                    // deltaAngle の更新
                    deltaAngle = (xx - xOrigin) * 0.001

                    // カメラ方向の更新
                    lx = sin(angle + deltaAngle)
                    lz = -cos(angle + deltaAngle)
            ok

    func mouseButton

            button  = glutEventButton()
            state = glutEventState()
            xx = glutEventX()
            yy = glutEventY()

            // これは左ボタンを押したときのみ動作開始になります。
            if button = GLUT_LEFT_BUTTON
                    // ボタンを離したとき
                    if state = GLUT_UP
                            angle += deltaAngle
                            xOrigin = -1
                    else
                            // state = GLUT_DOWN
                            xOrigin = xx
                    ok
                    fflush(stdout)
            ok

    func main

            // GLUT の初期化とウィンドウの作成
            glutInit()
            glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA)
            glutInitWindowPosition(100,100)
            glutInitWindowSize(320,320)
            glutCreateWindow("RingFreeGLUT - Test 9")

            // コールバックの登録
            glutDisplayFunc(:renderScene)
            glutReshapeFunc(:changeSize)
            glutIdleFunc(:renderScene)

            glutIgnoreKeyRepeat(1)
            glutKeyboardFunc(:processNormalKeys)
            glutSpecialFunc(:pressKey)
            glutSpecialUpFunc(:releaseKey)

             // ここには二つの新しい関数があります。
            glutMouseFunc(:mouseButton)
            glutMotionFunc(:mouseMove)

            // OpenGL の初期化
            glEnable(GL_DEPTH_TEST)

            // GLUT のイベント処理サイクルへ入ります。
            glutMainLoop()

## メニューイベント

用例:

    load "freeglut.ring"
    load "opengl21lib.ring"

    // カメラ方向の回転角度
    angle = 0.0

    // 実際のベクトルはカメラ方向を表しています。
    lx=0.0 lz=-1.0

    // カメラの XZ 位置
    x=0.0  z=5.0

    // キーの状態
    // キーを押していない時は変数は 0 です。
    deltaAngle = 0.0
    deltaMove = 0
    xOrigin = -1

    // メニューを定義するための定数

    // RingFreeGLUT では - メニューの項目ごとに異なる ID を指定してください。
    C_RED = 1
    C_GREEN = 2
    C_BLUE  = 3
    C_ORANGE = 4

    C_FILL = 5
    C_LINE = 6

    C_SHRINK = 7
    C_NORMAL = 8

    // ポップアップメニューの定義
    fillMenu= 0
    shrinkMenu= 0
    mainMenu=0
    colorMenu=0

    // 鼻の配色
    red = 1.0  blue=0.5  green=0.5

    // 雪だるまの大きさ
    scale = 1.0

    // メニューの状態
    menuFlag = 0

    func changeSize
            w = glutEventWidth()
            h = glutEventHeight()

            // ウィンドウの大きさが小さすぎる場合に、ゼロ除算エラーになるのを防ぎます。
            // (幅 0 のウィンドウは作成できません)
            if h = 0
                    h = 1
            ok

            ratio =  w * 1.0 / h

            // 投射行列の使用
            glMatrixMode(GL_PROJECTION)

            // 行列のリセット
            glLoadIdentity()

            // ウィンドウ全体のビューポートを設定します。
            glViewport(0, 0, w, h)

             // 正しい遠近法の設定
            gluPerspective(45.0, ratio, 0.1, 100.0)

            // Modelview の復帰
            glMatrixMode(GL_MODELVIEW)

    func drawSnowMan

            glScalef(scale, scale, scale)
            glColor3f(1.0, 1.0, 1.0)

    // 体の描画
            glTranslatef(0.0 ,0.75, 0.0)
            glutSolidSphere(0.75,20,20)

    // 頭の描画
            glTranslatef(0.0, 1.0, 0.0)
            glutSolidSphere(0.25,20,20)

    // 目の描画
            glPushMatrix()
            glColor3f(0.0,0.0,0.0)
            glTranslatef(0.05, 0.10, 0.18)
            glutSolidSphere(0.05,10,10)
            glTranslatef(-0.1, 0.0, 0.0)
            glutSolidSphere(0.05,10,10)
            glPopMatrix()

    // 鼻の描画
            glColor3f(red, green, blue)
            glRotatef(0.0,1.0, 0.0, 0.0)
            glutSolidCone(0.08,0.5,10,2)

            glColor3f(1.0, 1.0, 1.0)

    func computePos deltaMove

            x += deltaMove * lx * 0.1
            z += deltaMove * lz * 0.1

    func renderScene

            if deltaMove
                    computePos(deltaMove)
            ok

            // 配色と深度バッファの消去
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

            // 変換のリセット
            glLoadIdentity()
            // カメラの設定
            gluLookAt(      x, 1.0, z,
                            x+lx, 1.0,  z+lz,
                            0.0, 1.0,  0.0)

    // 地面の描画

            glColor3f(0.9, 0.9, 0.9)
            glBegin(GL_QUADS)
                    glVertex3f(-100.0, 0.0, -100.0)
                    glVertex3f(-100.0, 0.0,  100.0)
                    glVertex3f( 100.0, 0.0,  100.0)
                    glVertex3f( 100.0, 0.0, -100.0)
            glEnd()

    // 36 体の雪だるまを描画

            for  i = -3 to 2
                    for  j = -3 to 2
                            glPushMatrix()
                            glTranslatef(i*10.0, 0.0, j * 10.0)
                            drawSnowMan()
                            glPopMatrix()
                    next
            next
            glutSwapBuffers()

    // -----------------------------------
    //             キーボード
    // -----------------------------------

    func processNormalKeys
            key = glutEventKey()
            xx = glutEventX()
            yy = glutEventY()

            glutSetMenu(mainMenu)
            switch key
                    on 27
                            glutDestroyMenu(mainMenu)
                            glutDestroyMenu(fillMenu)
                            glutDestroyMenu(colorMenu)
                            glutDestroyMenu(shrinkMenu)
                            shutdown()

                    on 's'
                            if not menuFlag
                              glutChangeToSubMenu(2,"Shrink",shrinkMenu)
                            ok
                    on 'c'
                            if not menuFlag
                                    glutChangeToSubMenu(2,"Color",colorMenu)
                            ok
            off
            if key = 27
                    shutdown()
            ok

    func pressKey

            key = glutEventKey()
            xx = glutEventX()
            yy = glutEventY()

            switch key
                    on GLUT_KEY_UP
                             deltaMove = 0.5
                    on GLUT_KEY_DOWN
                            deltaMove = -0.5
            off

    func releaseKey

            key = glutEventKey()

            switch key
                    on GLUT_KEY_UP
                            deltaMove = 0
                    on GLUT_KEY_DOWN
                            deltaMove = 0
            off

    // -----------------------------------
    //             マウス
    // -----------------------------------

    func mouseMove
            xx = glutEventX()
            yy = glutEventY()

            // これは左ボタンを押したときのみ true になります。
            if xOrigin >= 0

                    // deltaAngle の更新
                    deltaAngle = (xx - xOrigin) * 0.001

                    // カメラ方向の更新
                    lx = sin(angle + deltaAngle)
                    lz = -cos(angle + deltaAngle)
            ok

    func mouseButton

            button = glutEventButton()
            state = glutEventState()
            xx = glutEventX()
            yy = glutEventY()

            // これは左ボタンを押したときのみ動作開始になります。
            if button = GLUT_LEFT_BUTTON
                    // ボタンを離したとき
                    if state = GLUT_UP
                            angle += deltaAngle
                            xOrigin = -1
                    else
                            // state = GLUT_DOWN
                            xOrigin = xx
                    ok
            ok

    // -----------------------------------
    //             メニュー
    // -----------------------------------

    func processMenuStatus

            status = glutEventStatus()
            xx = glutEventX()
            yy = glutEventY()

            if  status = GLUT_MENU_IN_USE
                    menuFlag = 1
            else
                    menuFlag = 0
            ok

    func processMainMenu

            // ここにはなにもありません。
            // 動作は全てサブメニューから行います。

    func processFillMenu

            option = glutEventValue()

            switch option

                    on C_FILL
                             glPolygonMode(GL_FRONT, GL_FILL)
                    on C_LINE
                             glPolygonMode(GL_FRONT, GL_LINE)
            off

    func processShrinkMenu

            option = glutEventValue()

            switch option

                    on C_SHRINK
                            scale = 0.5
                    on C_NORMAL
                             scale = 1.0
            off

    func processColorMenu

            option = glutEventValue()

            switch option
                    on C_RED
                            red = 1.0
                            green = 0.0
                            blue = 0.0
                    on C_GREEN
                            red = 0.0
                            green = 1.0
                            blue = 0.0
                    on C_BLUE
                            red = 0.0
                            green = 0.0
                            blue = 1.0
                    on C_ORANGE
                            red = 1.0
                            green = 0.5
                            blue = 0.5
            off

    func createPopupMenus

            shrinkMenu = glutCreateMenu(:processShrinkMenu)

            glutAddMenuEntry("Shrink",C_SHRINK)
            glutAddMenuEntry("NORMAL",C_NORMAL)

            fillMenu = glutCreateMenu(:processFillMenu)

            glutAddMenuEntry("Fill",C_FILL)
            glutAddMenuEntry("Line",C_LINE)

            colorMenu = glutCreateMenu(:processColorMenu)
            glutAddMenuEntry("Red",C_RED)
            glutAddMenuEntry("Blue",C_BLUE)
            glutAddMenuEntry("Green",C_GREEN)
            glutAddMenuEntry("Orange",C_ORANGE)

            mainMenu = glutCreateMenu(:processMainMenu)

            glutAddSubMenu("Polygon Mode", fillMenu)
            glutAddSubMenu("Color", colorMenu)
             // 右ボタンでメニューへ接続
            glutAttachMenu(GLUT_RIGHT_BUTTON)

            // これでアクティブなメニューか検知できるようにします。
            glutMenuStatusFunc(:processMenuStatus)

    // -----------------------------------
    //             メイン
    // -----------------------------------

    func main

            // GLUT の初期化とウィンドウの作成
            glutInit()
            glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA)
            glutInitWindowPosition(100,100)
            glutInitWindowSize(320,320)
            glutCreateWindow("RingFreeGLUT - Test 10")

            // コールバックの登録
            glutDisplayFunc(:renderScene)
            glutReshapeFunc(:changeSize)
            glutIdleFunc(:renderScene)

            glutIgnoreKeyRepeat(1)
            glutKeyboardFunc(:processNormalKeys)
            glutSpecialFunc(:pressKey)
            glutSpecialUpFunc(:releaseKey)

             // ここには二つの新しい関数があります。
            glutMouseFunc(:mouseButton)
            glutMotionFunc(:mouseMove)

            // OpenGL の初期化
            glEnable(GL_DEPTH_TEST)
            glEnable(GL_CULL_FACE)

            // メニューの初期化
            createPopupMenus()

            // GLUT のイベント処理サイクルへ入ります。
            glutMainLoop()

スクリーンショット:

## フォントの用法

用例:

    load "freeglut.ring"
    load "opengl21lib.ring"

    // カメラ方向の回転角度
    angle = 0.0

    // 実際のベクトルはカメラ方向を表しています。
    lx=0.0 lz=-1.0

    // カメラの XZ 位置
    x=0.0  z=5.0

    // キーの状態
    // キーを押していない時は変数は 0 です。
    deltaAngle = 0.0
    deltaMove = 0
    xOrigin = -1

    // メニューを定義するための定数
    C_RED  = 1
    C_GREEN = 2
    C_BLUE = 3
    C_ORANGE = 4

    C_FILL = 5
    C_LINE = 6

    // ポップアップメニューの定義
    fillMenu=NULL
    fontMenu=NULL
    mainMenu=NULL
    colorMenu=NULL

    // 鼻の配色
    red = 1.0
    blue=0.5
    green=0.5

    // 雪だるまの大きさ
    scale = 1.0

    // メニューの状態
    menuFlag = 0

    // デフォルトのフォント
    font = GLUT_BITMAP_TIMES_ROMAN_24

    C_INT_GLUT_BITMAP_8_BY_13 = 7
    C_INT_GLUT_BITMAP_9_BY_15 = 8
    C_INT_GLUT_BITMAP_TIMES_ROMAN_10  = 9
    C_INT_GLUT_BITMAP_TIMES_ROMAN_24  = 10
    C_INT_GLUT_BITMAP_HELVETICA_10  = 11
    C_INT_GLUT_BITMAP_HELVETICA_12  = 12
    C_INT_GLUT_BITMAP_HELVETICA_18  = 13

    func changeSize
            w = glutEventWidth()
            h = glutEventHeight()

            // ウィンドウの大きさが小さすぎる場合に、ゼロ除算エラーになるのを防ぎます。
            // (幅 0 のウィンドウは作成できません)
            if h = 0
                    h = 1
            ok

            ratio =  w * 1.0 / h

            // 投射行列の使用
            glMatrixMode(GL_PROJECTION)

            // 行列のリセット
            glLoadIdentity()

            // ウィンドウ全体のビューポートを設定します。
            glViewport(0, 0, w, h)

             // 正しい遠近法の設定
            gluPerspective(45.0, ratio, 0.1, 100.0)

            // Modelview の復帰
            glMatrixMode(GL_MODELVIEW)

    func drawSnowMan

            glScalef(scale, scale, scale)
            glColor3f(1.0, 1.0, 1.0)

    // 体の描画
            glTranslatef(0.0 ,0.75, 0.0)
            glutSolidSphere(0.75,20,20)

    // 頭の描画
            glTranslatef(0.0, 1.0, 0.0)
            glutSolidSphere(0.25,20,20)

    // 目の描画
            glPushMatrix()
            glColor3f(0.0,0.0,0.0)
            glTranslatef(0.05, 0.10, 0.18)
            glutSolidSphere(0.05,10,10)
            glTranslatef(-0.1, 0.0, 0.0)
            glutSolidSphere(0.05,10,10)
            glPopMatrix()

    // 鼻の描画
            glColor3f(red, green, blue)
            glRotatef(0.0,1.0, 0.0, 0.0)
            glutSolidCone(0.08,0.5,10,2)

            glColor3f(1.0, 1.0, 1.0)

    func renderBitmapString x,y,z,font,string
            glRasterPos3f(x, y,z)
            for c in string
                    glutBitmapCharacter(font,ascii(c))
            next

    func computePos deltaMove

            x += deltaMove * lx * 0.1
            z += deltaMove * lz * 0.1

    func renderScene

            if  deltaMove
                    computePos(deltaMove)
            ok

            // 配色と深度バッファの消去
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

            // 変換のリセット
            glLoadIdentity()

            // カメラの設定
            gluLookAt(      x, 1.0, z,
                            x+lx, 1.0,  z+lz,
                            0.0, 1.0,  0.0)

            // 地面の描画

            glColor3f(0.9, 0.9, 0.9)
            glBegin(GL_QUADS)
                    glVertex3f(-100.0, 0.0, -100.0)
                    glVertex3f(-100.0, 0.0,  100.0)
                    glVertex3f( 100.0, 0.0,  100.0)
                    glVertex3f( 100.0, 0.0, -100.0)
            glEnd()

    // 36 体の雪だるまを描画
            for i = -3 to 2
                    for j = -3 to 2
                            glPushMatrix()
                            glTranslatef(i*10.0, 0.0, j * 10.0)
                            drawSnowMan()
                            number = (i+3)*6+(j+3)
                            renderBitmapString(0.0, 0.5, 0.0,font ,""+number)
                            glPopMatrix()
                    next
            next

            glutSwapBuffers()

    // -----------------------------------
    //             キーボード
    // -----------------------------------

    func processNormalKeys
            key = glutEventKey()
            xx = glutEventX()
            yy = glutEventY()

            switch key
                    on 27
                            glutDestroyMenu(mainMenu)
                            glutDestroyMenu(fillMenu)
                            glutDestroyMenu(colorMenu)
                            glutDestroyMenu(fontMenu)
                            Shutdown()
            off

    func pressKey

            key = glutEventKey()
            xx = glutEventX()
            yy = glutEventY()

            switch key
                    on GLUT_KEY_UP
                             deltaMove = 0.5
                    on GLUT_KEY_DOWN
                            deltaMove = -0.5
            off

    func releaseKey

            key = glutEventKey()

            switch key
                    on GLUT_KEY_UP
                            deltaMove = 0
                    on GLUT_KEY_DOWN
                            deltaMove = 0
            off

    // -----------------------------------
    //             マウス
    // -----------------------------------

    func mouseMove
            xx = glutEventX()
            yy = glutEventY()

            // これは左ボタンを押したときのみ true になります。
            if xOrigin >= 0

                    // deltaAngle の更新
                    deltaAngle = (xx - xOrigin) * 0.001

                    // カメラ方向の更新
                    lx = sin(angle + deltaAngle)
                    lz = -cos(angle + deltaAngle)
            ok

    func mouseButton

            button = glutEventButton()
            state = glutEventState()
            xx = glutEventX()
            yy = glutEventY()

            // これは左ボタンを押したときのみ動作開始になります。
            if button = GLUT_LEFT_BUTTON
                    // ボタンを離したとき
                    if state = GLUT_UP
                            angle += deltaAngle
                            xOrigin = -1
                    else
                            // state = GLUT_DOWN
                            xOrigin = xx
                    ok
            ok

    // -----------------------------------
    //             メニュー
    // -----------------------------------

    func processMenuStatus

            status = glutEventStatus()

            if status = GLUT_MENU_IN_USE
                    menuFlag = 1
            else
                    menuFlag = 0
            ok

    func processMainMenu

            // ここにはなにもありません。
            // 動作は全てサブメニューから行います。

    func processFillMenu

            option = glutEventValue()

            switch option

                    on C_FILL
                            glPolygonMode(GL_FRONT, GL_FILL)
                    on C_LINE
                             glPolygonMode(GL_FRONT, GL_LINE)
            off

    func processFontMenu

            option = glutEventValue()

            switch (option) {
                    on C_INT_GLUT_BITMAP_8_BY_13
                            font = GLUT_BITMAP_8_BY_13
                    on C_INT_GLUT_BITMAP_9_BY_15
                            font = GLUT_BITMAP_9_BY_15
                    on C_INT_GLUT_BITMAP_TIMES_ROMAN_10
                            font = GLUT_BITMAP_TIMES_ROMAN_10
                    on C_INT_GLUT_BITMAP_TIMES_ROMAN_24
                            font = GLUT_BITMAP_TIMES_ROMAN_24
                    on C_INT_GLUT_BITMAP_HELVETICA_10
                            font = GLUT_BITMAP_HELVETICA_10
                    on C_INT_GLUT_BITMAP_HELVETICA_12
                            font = GLUT_BITMAP_HELVETICA_12
                    on C_INT_GLUT_BITMAP_HELVETICA_18
                            font = GLUT_BITMAP_HELVETICA_18
            off

    func processColorMenu

            option = glutEventValue()

            switch option
                    on C_RED
                            red = 1.0
                            green = 0.0
                            blue = 0.0
                    on C_GREEN
                            red = 0.0
                            green = 1.0
                            blue = 0.0
                    on C_BLUE
                            red = 0.0
                            green = 0.0
                            blue = 1.0
                    on C_ORANGE
                            red = 1.0
                            green = 0.5
                            blue = 0.5
            off

    func createPopupMenus

            fontMenu = glutCreateMenu(:processFontMenu)

            glutAddMenuEntry("BITMAP_8_BY_13 ",C_INT_GLUT_BITMAP_8_BY_13 )
            glutAddMenuEntry("BITMAP_9_BY_15",C_INT_GLUT_BITMAP_9_BY_15 )
            glutAddMenuEntry("BITMAP_TIMES_ROMAN_10 ",C_INT_GLUT_BITMAP_TIMES_ROMAN_10  )
            glutAddMenuEntry("BITMAP_TIMES_ROMAN_24",C_INT_GLUT_BITMAP_TIMES_ROMAN_24  )
            glutAddMenuEntry("BITMAP_HELVETICA_10 ",C_INT_GLUT_BITMAP_HELVETICA_10  )
            glutAddMenuEntry("BITMAP_HELVETICA_12",C_INT_GLUT_BITMAP_HELVETICA_12  )
            glutAddMenuEntry("BITMAP_HELVETICA_18",C_INT_GLUT_BITMAP_HELVETICA_18  )

            fillMenu = glutCreateMenu(:processFillMenu)

            glutAddMenuEntry("Fill",C_FILL)
            glutAddMenuEntry("Line",C_LINE)

            colorMenu = glutCreateMenu(:processColorMenu)
            glutAddMenuEntry("Red",C_RED);
            glutAddMenuEntry("Blue",C_BLUE);
            glutAddMenuEntry("Green",C_GREEN);
            glutAddMenuEntry("Orange",C_ORANGE);

            mainMenu = glutCreateMenu(:processMainMenu)

            glutAddSubMenu("Polygon Mode", fillMenu)
            glutAddSubMenu("Color", colorMenu)
            glutAddSubMenu("Font",fontMenu)
             // 右ボタンでメニューへ接続
            glutAttachMenu(GLUT_RIGHT_BUTTON)

            // これでアクティブなメニューか検知できるようにします。
            glutMenuStatusFunc(:processMenuStatus)

    // -----------------------------------
    //             メイン
    // -----------------------------------

    func main

            // GLUT の初期化とウィンドウの作成
            glutInit()
            glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA)
            glutInitWindowPosition(100,100)
            glutInitWindowSize(320,320)
            glutCreateWindow("RingFreeGLUT - Test 11")

            // コールバックの登録
            glutDisplayFunc(:renderScene)
            glutReshapeFunc(:changeSize)
            glutIdleFunc(:renderScene)

            glutIgnoreKeyRepeat(1)
            glutKeyboardFunc(:processNormalKeys)
            glutSpecialFunc(:pressKey)
            glutSpecialUpFunc(:releaseKey)

             // ここには二つの新しい関数があります。
            glutMouseFunc(:mouseButton)
            glutMotionFunc(:mouseMove)

            // OpenGL の初期化
            glEnable(GL_DEPTH_TEST)
            glEnable(GL_CULL_FACE)

            // メニューの初期化
            createPopupMenus()

            // GLUT のイベント処理サイクルへ入ります。
            glutMainLoop()

スクリーンショット:

## 一秒あたりのフレーム数

用例:

    load "freeglut.ring"
    load "opengl21lib.ring"

    // カメラ方向の回転角度
    angle = 0.0

    // 実際のベクトルはカメラ方向を表しています。
    lx=0.0 lz=-1.0

    // カメラの XZ 位置
    x=0.0  z=5.0

    // キーの状態
    // キーを押していない時は変数は 0 です。
    deltaAngle = 0.0
    deltaMove = 0
    xOrigin = -1

    // メニューを定義するための定数
    C_RED  = 1
    C_GREEN = 2
    C_BLUE = 3
    C_ORANGE = 4

    C_FILL = 5
    C_LINE = 6

    // ポップアップメニューの定義
    fillMenu=NULL
    fontMenu=NULL
    mainMenu=NULL
    colorMenu=NULL

    // 鼻の配色
    red = 1.0
    blue=0.5
    green=0.5

    // 雪だるまの大きさ
    scale = 1.0

    // メニューの状態
    menuFlag = 0

    // デフォルトのフォント
    font = GLUT_BITMAP_TIMES_ROMAN_24

    C_INT_GLUT_BITMAP_8_BY_13 = 7
    C_INT_GLUT_BITMAP_9_BY_15 = 8
    C_INT_GLUT_BITMAP_TIMES_ROMAN_10  = 9
    C_INT_GLUT_BITMAP_TIMES_ROMAN_24  = 10
    C_INT_GLUT_BITMAP_HELVETICA_10  = 11
    C_INT_GLUT_BITMAP_HELVETICA_12  = 12
    C_INT_GLUT_BITMAP_HELVETICA_18  = 13

    // ウィンドウの幅と高さ
    h = 0
    w = 0

    // 一秒あたりのフレーム数を計算するための変数
    frame=0
    time=0
    timebase=0
    s = ""

    func changeSize
            w = glutEventWidth()
            h = glutEventHeight()

            // ウィンドウの大きさが小さすぎる場合に、ゼロ除算エラーになるのを防ぎます。
            // (幅 0 のウィンドウは作成できません)
            if h = 0
                    h = 1
            ok

            ratio =  w * 1.0 / h

            // 投射行列の使用
            glMatrixMode(GL_PROJECTION)

            // 行列のリセット
            glLoadIdentity()

            // ウィンドウ全体のビューポートを設定します。
            glViewport(0, 0, w, h)

             // 正しい遠近法の設定
            gluPerspective(45.0, ratio, 0.1, 100.0)

            // Modelview の復帰
            glMatrixMode(GL_MODELVIEW)

    func drawSnowMan

            glScalef(scale, scale, scale)
            glColor3f(1.0, 1.0, 1.0)

    // 体の描画
            glTranslatef(0.0 ,0.75, 0.0)
            glutSolidSphere(0.75,20,20)

    // 頭の描画
            glTranslatef(0.0, 1.0, 0.0)
            glutSolidSphere(0.25,20,20)

    // 目の描画
            glPushMatrix()
            glColor3f(0.0,0.0,0.0)
            glTranslatef(0.05, 0.10, 0.18)
            glutSolidSphere(0.05,10,10)
            glTranslatef(-0.1, 0.0, 0.0)
            glutSolidSphere(0.05,10,10)
            glPopMatrix()

    // 鼻の描画
            glColor3f(red, green, blue)
            glRotatef(0.0,1.0, 0.0, 0.0)
            glutSolidCone(0.08,0.5,10,2)

            glColor3f(1.0, 1.0, 1.0)

    func renderBitmapString x,y,z,font,string
            glRasterPos3f(x, y,z)
            for c in string
                    glutBitmapCharacter(font,ascii(c))
            next

    func renderStrokeFontString x,y,z,font,string
            glPushMatrix()
            glTranslatef(x, y,z)
            glScalef(0.002, 0.002, 0.002)
            for c in string
                    glutStrokeCharacter(font, Ascii(c));
            next
            glPopMatrix()

    func restorePerspectiveProjection

            glMatrixMode(GL_PROJECTION)
            // 以前の投射行列へ復帰
            glPopMatrix()

            // Modelview モードの復帰
            glMatrixMode(GL_MODELVIEW)

    func setOrthographicProjection

            // 投射モードの切り替え
            glMatrixMode(GL_PROJECTION)

            // 透視図の設定を有する
            // 以前の行列を保存します。
            glPushMatrix()

            // 行列のリセット
            glLoadIdentity()

            // 2D 正投射の設定
            gluOrtho2D(0, w, h, 0)

            // modelview モードへ復帰切り替え
            glMatrixMode(GL_MODELVIEW)

    func computePos deltaMove

            x += deltaMove * lx * 0.1
            z += deltaMove * lz * 0.1

    func renderScene

            if  deltaMove
                    computePos(deltaMove)
            ok

            // 配色と深度バッファの消去
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

            // 変換のリセット
            glLoadIdentity()

            // カメラの設定
            gluLookAt(      x, 1.0, z,
                            x+lx, 1.0,  z+lz,
                            0.0, 1.0,  0.0)

            // 地面の描画

            glColor3f(0.9, 0.9, 0.9)
            glBegin(GL_QUADS)
                    glVertex3f(-100.0, 0.0, -100.0)
                    glVertex3f(-100.0, 0.0,  100.0)
                    glVertex3f( 100.0, 0.0,  100.0)
                    glVertex3f( 100.0, 0.0, -100.0)
            glEnd()

    // 9 体の雪だるまを描画
            for i = -3 to -1
                    for j = -3 to -1
                            glPushMatrix()
                            glTranslatef(i*10.0, 0.0, j * 10.0)
                            drawSnowMan()
                            number = (i+3)*3+(j+3)
                            renderBitmapString(0.0, 0.5, 0.0,font ,""+number)
                            glPopMatrix()
                    next
            next

            // 一秒あたりのフレーム数を計算するためのコード
            frame++

            time=glutGet(GLUT_ELAPSED_TIME)
            if time - timebase > 1000
                    s = "RingFreeGLUT - FPS: " + (frame*1000.0/(time-timebase))
                    timebase = time
                    frame = 0
            ok

            // ビットマップフォントで文字列 (fps) を表示するためのコード
            setOrthographicProjection()

            glPushMatrix()
            glLoadIdentity()
            renderBitmapString(5,30,0,GLUT_BITMAP_HELVETICA_18,s)
            glPopMatrix()

            restorePerspectiveProjection()

            glutSwapBuffers()

    // -----------------------------------
    //             キーボード
    // -----------------------------------

    func processNormalKeys
            key = glutEventKey()
            xx = glutEventX()
            yy = glutEventY()

            switch key
                    on 27
                            glutDestroyMenu(mainMenu)
                            glutDestroyMenu(fillMenu)
                            glutDestroyMenu(colorMenu)
                            glutDestroyMenu(fontMenu)
                            Shutdown()
            off

    func pressKey

            key = glutEventKey()
            xx = glutEventX()
            yy = glutEventY()

            switch key
                    on GLUT_KEY_UP
                             deltaMove = 0.5
                    on GLUT_KEY_DOWN
                            deltaMove = -0.5
            off

    func releaseKey

            key = glutEventKey()

            switch key
                    on GLUT_KEY_UP
                            deltaMove = 0
                    on GLUT_KEY_DOWN
                            deltaMove = 0
            off

    // -----------------------------------
    //             マウス
    // -----------------------------------

    func mouseMove
            xx = glutEventX()
            yy = glutEventY()

            // これは左ボタンを押したときのみ true になります。
            if xOrigin >= 0

                    // deltaAngle の更新
                    deltaAngle = (xx - xOrigin) * 0.001

                    // カメラ方向の更新
                    lx = sin(angle + deltaAngle)
                    lz = -cos(angle + deltaAngle)
            ok

    func mouseButton

            button = glutEventButton()
            state = glutEventState()
            xx = glutEventX()
            yy = glutEventY()

            // これは左ボタンを押したときのみ動作開始になります。
            if button = GLUT_LEFT_BUTTON
                    // ボタンを離したとき
                    if state = GLUT_UP
                            angle += deltaAngle
                            xOrigin = -1
                    else
                            // state = GLUT_DOWN
                            xOrigin = xx
                    ok
            ok

    // -----------------------------------
    //             メニュー
    // -----------------------------------

    func processMenuStatus

            status = glutEventStatus()

            if status = GLUT_MENU_IN_USE
                    menuFlag = 1
            else
                    menuFlag = 0
            ok

    func processMainMenu

            // ここにはなにもありません。
            // 動作は全てサブメニューから行います。

    func processFillMenu

            option = glutEventValue()

            switch option

                    on C_FILL
                            glPolygonMode(GL_FRONT, GL_FILL)
                    on C_LINE
                             glPolygonMode(GL_FRONT, GL_LINE)
            off

    func processFontMenu

            option = glutEventValue()

            switch (option) {
                    on C_INT_GLUT_BITMAP_8_BY_13
                            font = GLUT_BITMAP_8_BY_13
                    on C_INT_GLUT_BITMAP_9_BY_15
                            font = GLUT_BITMAP_9_BY_15
                    on C_INT_GLUT_BITMAP_TIMES_ROMAN_10
                            font = GLUT_BITMAP_TIMES_ROMAN_10
                    on C_INT_GLUT_BITMAP_TIMES_ROMAN_24
                            font = GLUT_BITMAP_TIMES_ROMAN_24
                    on C_INT_GLUT_BITMAP_HELVETICA_10
                            font = GLUT_BITMAP_HELVETICA_10
                    on C_INT_GLUT_BITMAP_HELVETICA_12
                            font = GLUT_BITMAP_HELVETICA_12
                    on C_INT_GLUT_BITMAP_HELVETICA_18
                            font = GLUT_BITMAP_HELVETICA_18
            off

    func processColorMenu

            option = glutEventValue()

            switch option
                    on C_RED
                            red = 1.0
                            green = 0.0
                            blue = 0.0
                    on C_GREEN
                            red = 0.0
                            green = 1.0
                            blue = 0.0
                    on C_BLUE
                            red = 0.0
                            green = 0.0
                            blue = 1.0
                    on C_ORANGE
                            red = 1.0
                            green = 0.5
                            blue = 0.5
            off

    func createPopupMenus

            fontMenu = glutCreateMenu(:processFontMenu)

            glutAddMenuEntry("BITMAP_8_BY_13 ",C_INT_GLUT_BITMAP_8_BY_13 )
            glutAddMenuEntry("BITMAP_9_BY_15",C_INT_GLUT_BITMAP_9_BY_15 )
            glutAddMenuEntry("BITMAP_TIMES_ROMAN_10 ",C_INT_GLUT_BITMAP_TIMES_ROMAN_10  )
            glutAddMenuEntry("BITMAP_TIMES_ROMAN_24",C_INT_GLUT_BITMAP_TIMES_ROMAN_24  )
            glutAddMenuEntry("BITMAP_HELVETICA_10 ",C_INT_GLUT_BITMAP_HELVETICA_10  )
            glutAddMenuEntry("BITMAP_HELVETICA_12",C_INT_GLUT_BITMAP_HELVETICA_12  )
            glutAddMenuEntry("BITMAP_HELVETICA_18",C_INT_GLUT_BITMAP_HELVETICA_18  )

            fillMenu = glutCreateMenu(:processFillMenu)

            glutAddMenuEntry("Fill",C_FILL)
            glutAddMenuEntry("Line",C_LINE)

            colorMenu = glutCreateMenu(:processColorMenu)
            glutAddMenuEntry("Red",C_RED);
            glutAddMenuEntry("Blue",C_BLUE);
            glutAddMenuEntry("Green",C_GREEN);
            glutAddMenuEntry("Orange",C_ORANGE);

            mainMenu = glutCreateMenu(:processMainMenu)

            glutAddSubMenu("Polygon Mode", fillMenu)
            glutAddSubMenu("Color", colorMenu)
            glutAddSubMenu("Font",fontMenu)
             // 右ボタンでメニューへ接続
            glutAttachMenu(GLUT_RIGHT_BUTTON)

            // これでアクティブなメニューか検知できるようにします。
            glutMenuStatusFunc(:processMenuStatus)

    // -----------------------------------
    //             メイン
    // -----------------------------------

    func main

            // GLUT の初期化とウィンドウの作成
            glutInit()
            glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA)
            glutInitWindowPosition(100,100)
            glutInitWindowSize(320,320)
            glutCreateWindow("RingFreeGLUT - Test - 9 SnowMan")

            // コールバックの登録
            glutDisplayFunc(:renderScene)
            glutReshapeFunc(:changeSize)
            glutIdleFunc(:renderScene)

            glutIgnoreKeyRepeat(1)
            glutKeyboardFunc(:processNormalKeys)
            glutSpecialFunc(:pressKey)
            glutSpecialUpFunc(:releaseKey)

             // ここには二つの新しい関数があります。
            glutMouseFunc(:mouseButton)
            glutMotionFunc(:mouseMove)

            // OpenGL の初期化
            glEnable(GL_DEPTH_TEST)
            glEnable(GL_CULL_FACE)

            // メニューの初期化
            createPopupMenus()

            // GLUT のイベント処理サイクルへ入ります。
            glutMainLoop()

スクリーンショット:

一枚目のスクリーンショット:

二枚目のスクリーンショット:

## RingOpenGL と RingFreeGLUT による立方体の作例

用例:

    load "freeglut.ring"
    load "opengl21lib.ring"

    // ----------------------------------------------------------
    // グローバル変数
    // ----------------------------------------------------------
    rotate_y=0
    rotate_x=0

    // ----------------------------------------------------------
    // display() コールバック関数
    // ----------------------------------------------------------
    func display

      // 画面と Z バッファの消去
      glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)

      // 変換のリセット
      glLoadIdentity()

      // rotate_x および rotate_y のユーザによる変更をリセットします。
      glRotatef( rotate_x, 1.0, 0.0, 0.0 )
      glRotatef( rotate_y, 0.0, 1.0, 0.0 )

      // 多色面 - 前
      glBegin(GL_POLYGON)

      glColor3f( 1.0, 0.0, 0.0 )     glVertex3f(  0.5, -0.5, -0.5 )      # P1 is red
      glColor3f( 0.0, 1.0, 0.0 )     glVertex3f(  0.5,  0.5, -0.5 )      # P2 is green
      glColor3f( 0.0, 0.0, 1.0 )     glVertex3f( -0.5,  0.5, -0.5 )      # P3 is blue
      glColor3f( 1.0, 0.0, 1.0 )     glVertex3f( -0.5, -0.5, -0.5 )      # P4 is purple

      glEnd()

      // 白面 - 後
      glBegin(GL_POLYGON)
      glColor3f(   1.0,  1.0, 1.0 )
      glVertex3f(  0.5, -0.5, 0.5 )
      glVertex3f(  0.5,  0.5, 0.5 )
      glVertex3f( -0.5,  0.5, 0.5 )
      glVertex3f( -0.5, -0.5, 0.5 )
      glEnd()

      // 紫面 - 右
      glBegin(GL_POLYGON)
      glColor3f(  1.0,  0.0,  1.0 )
      glVertex3f( 0.5, -0.5, -0.5 )
      glVertex3f( 0.5,  0.5, -0.5 )
      glVertex3f( 0.5,  0.5,  0.5 )
      glVertex3f( 0.5, -0.5,  0.5 )
      glEnd()

      // 緑面 - 左
      glBegin(GL_POLYGON)
      glColor3f(   0.0,  1.0,  0.0 )
      glVertex3f( -0.5, -0.5,  0.5 )
      glVertex3f( -0.5,  0.5,  0.5 )
      glVertex3f( -0.5,  0.5, -0.5 )
      glVertex3f( -0.5, -0.5, -0.5 )
      glEnd()

      // 青面 - 上
      glBegin(GL_POLYGON)
      glColor3f(   0.0,  0.0,  1.0 )
      glVertex3f(  0.5,  0.5,  0.5 )
      glVertex3f(  0.5,  0.5, -0.5 )
      glVertex3f( -0.5,  0.5, -0.5 )
      glVertex3f( -0.5,  0.5,  0.5 )
      glEnd()

      // 赤面 - 下
      glBegin(GL_POLYGON)
      glColor3f(   1.0,  0.0,  0.0 )
      glVertex3f(  0.5, -0.5, -0.5 )
      glVertex3f(  0.5, -0.5,  0.5 )
      glVertex3f( -0.5, -0.5,  0.5 )
      glVertex3f( -0.5, -0.5, -0.5 )
      glEnd()

      glFlush()
      glutSwapBuffers()

    // ----------------------------------------------------------
    // specialKeys() コールバック関数
    // ----------------------------------------------------------
    func specialKeys

            key = glutEventKey()

      // 右矢印 - 回転を五度増分します。
            switch Key

            on GLUT_KEY_RIGHT
                    rotate_y += 5

            // 左矢印 - 回転を五度減分します。
            on GLUT_KEY_LEFT
                    rotate_y -= 5

            on GLUT_KEY_UP
                    rotate_x += 5

            on GLUT_KEY_DOWN
                    rotate_x -= 5

            off

      //  更新の要求
      glutPostRedisplay()

    // ----------------------------------------------------------
    // main() 関数
    // ----------------------------------------------------------
    func main

      // GLUT の初期化とユーザ仮引数の処理
      glutInit()

      // トゥルーカラーのウィンドウのために Z-バッファによるダブルバッファを要求します。
      glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH)

      // ウィンドウの作成
      glutCreateWindow("Awesome Cube")

      // Z バッファの深度テストを有効にします。
      glEnable(GL_DEPTH_TEST)

      // コールバック関数
      glutDisplayFunc(:display)
      glutSpecialFunc(:specialKeys)

      // イベントに関する GLUT への制御を渡します。
      glutMainLoop()

      // OS へ戻ります。

スクリーンショット: