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

スクリーンショット:

RingFreeGLUT

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()

スクリーンショット:

RingFreeGLUT

はじめての三角形

用例:

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()

スクリーンショット:

RingFreeGLUT

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

用例:

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)

スクリーンショット:

RingFreeGLUT

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

用例:

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

スクリーンショット:

RingFreeGLUT

カメラ

用例:

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()

スクリーンショット:

RingFreeGLUT

その他の用例:

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()

スクリーンショット:

RingFreeGLUT

フォントの用法

用例:

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()

スクリーンショット:

RingFreeGLUT

一秒あたりのフレーム数

用例:

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()

スクリーンショット:

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

RingFreeGLUT

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

RingFreeGLUT

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 へ戻ります。

スクリーンショット:

RingOpenGL