VisualStudio2010 を用いた OpenGL(Glut) コンソール アプリケーションの作成方法 初版 : 2007.01.06 藤尾 改訂 : 2010.08.24 秋山 - 1 -
- 目次 - Ⅰ. プログラミングの準備 3 Ⅰ.1 はじめに 3 Ⅰ.2 OpenGL の環境設定 3 Ⅱ. プログラミングの第 1 歩 ( 簡単なプログラムの作成 ) 3 Ⅱ.1 プロジェクトの作成と保存 ( 空きの Win32 アプリケーションの作成 ) 3 Ⅱ.2 プロジェクトのオープンとプログラムのコンパイル ( ビルド ) と実行 4 Ⅱ.3 OpenGL 環境の設定の追加 5 Ⅲ.OpenGL の必要最低限の関数を設定する 6 Ⅳ. OpenGL プログラムの解説 7 Ⅳ.1 OpenGL プログラムの解説 7-2 -
Ⅰ. プログラミングの準備 Ⅰ.1 はじめに皆さんが使っているパソコンには Windows やペイント, ワード, エクセルなど数多くのソフトウェアが入っています. パソコンはこれらのソフトウェアが無いとただの箱になってしまい, 全く使うことができません. これらのソフトウェアはプログラム言語というパソコンなどコンピュータを動かすために作られた専用の言語で作られています. つまりソフトウェアというのはプログラムの寄せ集めであるといえます. コンピュータに仕事をさせるには, このプログラムによって仕事を指示してやる必要があるのです. プログラムを作成する ( プログラミングという ) には, 用いるプログラム言語の文法やデータ構造を理解しておく必要があります. ここでは,C 言語の基礎をある程度習得したプログラミング初心者を対象に,Windows 上で動作する OpenGL のコンソールアプルケーションソフトウェアのプロジェクトの作り方を解説します. ユーザはこのガイドで作成されたプロジェクトを基に, 自らのプログラムを追加記述してください. なお, コンソールアプルケーションソフトウェアとは, 一般的な Windows アプリケーションのようにメニューバーやダイアログによって操作するプログラムではなく, キーボードとマウスからのみデータの入力が可能で, 出力は画面内のみのアプリケーションです. Ⅰ.2 OpenGL の環境設定必要なファイルのコピーと設定 OpneGL の glut を使うためには glut32.dll,glut32.lib, glut.h が必要です. これらは, 本来は VisualStudio の決まったフォルダに入れるべきです. 一般に glut32.dll は C:\WINDOWS\system32 glut32.lib は C:\Program Files\Microsoft SDKs\Windows\v7.0A\Lib glut.h は C:\Program Files\Microsoft SDKs\Windows\v7.0A\Include\gl に格納します. 実際には使うパソコンにより異なる可能性があります. しかし, 演習のため今回は作成したプロジェクトを保存するフォルダに保存します. また, これらのファイルは http://www.opengl.org/resources/libraries/glut.html から取得できます. Ⅱ. 簡単な OpenGL プログラムの作成では最初に, まずはプログラムを書いてみましょう. 使用するソフトウェアはマイクロソフトの VisualStudio 2010 です. 作成するプロジェクトは OpenGlut2DBase です. Ⅱ.1 プロジェクトの作成と保存 ( 空きの Win32 アプリケーションの作成 ) (1)Visual Studio 2010 の起動図 Ⅰ-1 のように スタート すべてのプログラム Microsoft Visual Studio 2010 を選択して起動します. 実際の画面はこの図 Ⅰ-1 とは違いますので注意してください. 図 Ⅱ-1 VisualStudio 2010 の起動 (2) プロジェクトを作成図 Ⅱ-2 のように ファイル 新規作成 プロジェクト を選択し, プロジェクトのダイアログを表示します. 図 Ⅱ-2 プロジェクトの新規作成 図 Ⅱ-3 に示すように, ダイアログで Win32 コンソールアプリケーション を選択し, プロジェクト名を OpenGlut2DBase とします. 保存場所は, 各自で決めて設定してください. 保存場所は忘れないように注意してください. 設定が終了したら OK をクリック - 3 -
します. その後 完了 をクリックします. 図 Ⅱ-3 プロジェクトの設定 (3) ビルド図 Ⅱ-4(a) のように ビルド OpenGlut2DBase のリビルド を選択しビルドします. 正常にビルドが終了すると出力ウインドウ ( 画面下 ) に図 Ⅱ-4(b) のようなメッセージが出ます. (a) ビルドメニュー (b) ビルド結果図 Ⅱ-4 プロジェクトのビルド (4) 実行図 Ⅱ-5 のように デバック デバッグ開始 でプログラムを実行します. ツールバーのでも実行可能です. 図 Ⅱ-5 プロジェクトの実行 一瞬黒い画面が出て元の画面に戻れば正常終了です. (5) プロジェクトの終了プログラミングが終わった際には, プロジェクトを閉じます. 図 Ⅱ-6 のように ファイル ソリューションを閉じる で,VisualStudio を終了せず, プロジェクトのみ終了します. プログラムを終了したい場合は ファイル 終了 を選択します. ここでは一度, プロジェクトを終了しましょう. 図 Ⅱ-6 プロジェクトの終了 Ⅱ.2 プロジェクトのオープンとプログラムのコンパイル ( ビルド ) と実行 (1)Visual Studio2010 の起動 スタート すべてのプログラム Microsoft Visual Studio 2010 を選択して起動します. (2) プロジェクトを開く図 Ⅱ-7 のように ファイル 開く プロジェクト / ソリューション を選択します. ファイルダイアログで以前に作成した OpenGlut2DBase.sln を選択し 開く をクリックします. - 4 -
(a) ソリューションを開くメニュー (b) ファイルダイアログ図 Ⅱ-7 プロジェクト ( ソリューション ) の読み込み (3) ソリューションの破棄他のフォルダからコピーした後にプロジェクトを開く際には, フォルダ情報等が更新されていませんので, ソリューション情報を破棄し, 再度ビルドする必要があります. 以前使用したプロジェクトのフォルダと同じ場合にあるプロジェクトを開く際は, この手続きは省略できます. 図 Ⅱ-8 のように ビルド ソリューションのクリーン を選択し, 続けて ビルド OpenGlut2DBase のクリーン を選択します. 図 Ⅱ-8 プロジェクト ( ソリューション ) の削除 図 Ⅱ-9 プロジェクト ( ソリューション ) のビルド (4) ソリューションのリビルドその後, 図 Ⅱ-9 の様に ビルド ソリューションのリビルド を選択します. エラーが発生していないことを確認します. (5) 実行 デバッグ デバッグの開始 でプログラムを実行します. ツールバーのでも実行可能です. (6) プロジェクトの終了 ファイル ソリューションを閉じる を選択します. Ⅱ.3 OpenGL 環境の設定の追加次に OpenGL がプログラムで使えるように設定を変更します. (1) プロジェクトを開く ファイル 開く プロジェクト / ソリューション を選択します. ファイルダイアログで以前に作成した OpenGlut2DBase.sln を選択し 開く をクリックします. (2) ライブラリの追加 OpenGL の glut を使えるようにするには glut に必要なファイルをプロジェクトに登録しなければなりません. 図 Ⅱ-10 のように プロジェクト OpenGlut2DBase のプロパティ を選択します. 図 Ⅱ-11 に示すダイアログでリンカの入力を選択し,opengl32.lib glu32.lib glut32.lib を入力します. その後 OK をクリックします. この時, 構成を アクティブ (Debug) から Release にすると配布用のプログラムを作ることができます. 図 Ⅱ-10 プロジェクトのプロパティ 図 Ⅱ-11 プロジェクト ( ソリューション ) への追加登録 また, ここで glut を利用するに必要なファイルをプロジェクトのフォルダにコピーします. 必要なファイルは glut32.dll glut32.lib glut.h の 3 ファイルです. - 5 -
(3)OpenGL ライブラリ用のインクルードを追加ソースコードに #include glut.h 旧スタイル #include <GL/gl.h> #include <GL/glaux.h> の 1 行を追加 (4) リビルド図 Ⅱ-12 のように ビルド OpenGlut2DBase のリビルド を選択し, 再構築します. 図 Ⅱ-12 プロジェクトのビルド (5) 実行ビルドエラーもなくビルドできたら, 実行してみてください. プログラムは相変わらず画面が一瞬出て終了するだけです. (6) プロジェクトの終了 ファイル ソリューションを閉じる を選択します. Ⅲ. OpenGL の必要最低限の関数を設定する (1) ソースコードの追加 (2) コンパイルと実行 ビルド OpenGlut2DBase のビルド を選択しビルドする出力ウインドウに [ ビルド :1 正常終了,0 失敗,0 スキップ ] がでれば完了 (3) 実行 デバッグ デバッグの開始 を選択し実行する. - 6 -
画面が二つ現れ次のような画面がでると正常に作成できたことになる. (4) 終了 <ESC> キーで終了 Ⅳ. OpenGL プログラムの解説 Ⅳ.1 OpenGL プログラムの解説正常にビルドできた後, 実行するとまだ処理内容は良くわかりませんが, 画面には白い色をした四角形が描画されているはずです. では, 次にどのようにして四角形を書いているのか見ていきましょう. ソースコードは List Ⅳ-1 に示してあります. - 7 -
#include "stdafx.h" #include <GL/gl.h> #include <GL/glaux.h> // ユーザの初期化 void Initialize(void) glutinitdisplaymode(glut_single GLUT_RGB); // 表示モードの指定 glutinitwindowsize(500, 500); // 画面サイズの指定 glutinitwindowposition(100, 100); // ウインドウ位置の指定 glutcreatewindow("opengl Win32 2D Base Program"); // ウインドウの作成とタイトル設定 glclearcolor(0.0, 0.0, 0.0, 1.0); // ウインドウの背景色の設定 glortho(-500/2, 500/2, -500/2, 500/2, -1, 1); // 平行投影 // 描画関数 void draw(void) // 原点から長さ200の四角形を描画する glclear(color_buffer_bit); // 画面のクリア glbegin(lines); // 直線を書く glcolor3d(1.0,1.0,1.0); // 線の色を白色にする glvertex2d( 0.0, 0.0); glvertex2d(200.0, 0.0); // 直線の描画 glvertex2d(200.0, 0.0); glvertex2d(200.0, 200.0); // 直線の描画 glvertex2d(200.0, 200.0); glvertex2d( 0.0, 200.0); // 直線の描画 glvertex2d( 0.0, 200.0); glvertex2d( 0.0, 0.0); // 直線の描画 glend(); // 直線データの終了 glflush(); // 描画処理実行 int _tmain(int argc, _TCHAR* argv[]) glutinit(&argc,argv); // GLUTの初期化 Initialize(); // ユーザの初期化関数 glutdisplayfunc(draw); // 描画関数の指定 glutmainloop(); // GLUTのメインループ return 0; List Ⅳ-1 (1) インクルードファイル初めて見るプログラムなので何がどうなっているかわからないと思いますので, 順に説明していきます. #include "stdafx.h" #include <GL/glut.h> List Ⅳ-2 これはインクルードファイル ( ヘッダーファイル ) と呼ばれ, プログラムの中で使う必要な処理を使えるように設定する記述です. 単純にプログラムを書くためにはデフォルトでは stdafx.h だけで良いのですが, 今回は描画に OpenGL を使っているため, OpenGL が使えるように <GL/glut.h> を書き加えます. (2) 関数とプログラムの流れ C 言語のプログラムは関数 ( ある処理の固まり ) の集まりで表現されます. このプログラムでは Initialize と draw, _tmain の 3 つが関数です.C 言語のプログラムは関数の中でも main( この場合 _tmain) から始まると決まっています. ですからプログラムは tmain から実行され始めます. 実行が始まると _tmain 関数の 1 行目にある glutinit(&argc,argv); にプログラムは進みます. この形も実は関数で, 関数の形は関数名 ( 引数 ) という形式になります. 関数名が glutinit となっていますが, このように関数名の最初に gl,glut が付く関数は OpenGL を使う際に決められている関数名です. 他にも glutdisplayfunc,glutmainloop なども OpenGL を使う際に決められている関数で, 決められた使い方の値を与える ( これを引数という ) ことで指定した動きをさせることができます. この関数は OpenGL の初期化を行う関数で, この様に書くと覚えてください. glutinit が終了すれば次の行の Initialize() にプログラムは進みます. この関数はプログラムの上に書いてあるので, プログラムは Initialize() に移ります.Initialize では表示モードの設定や画面の設定を行います.Initialize の最後の行 glortho が終わるとまた _tmain に戻り Initialize の次の行の glutdisplayfunc(draw) に進み, さらに glutmainloop に進みます. この glutmailoop では描画に必要が生じた際 ( プログラムが実行された場合や, 画面が再度表示されるようになった場合 ) に引数として与えられた draw にプログラムを進めます.draw は描画する関数です, 絵を描いた後再度 glutmainloop に戻り, 再描画を待ちます. プログラムを終了させた時,glutMainLoop を終えて次の return に進みプログラムは終了します. - 8 -
プログラムの流れ START int _tmain(int argc, _TCHAR* argv[]) glutinit(&argc,argv); Initialize(); glutdisplayfunc(draw); glutmainloop(); return 0; END // ユーザの初期化 void Initialize( void) glutinitdisplaymode(glut_single GLUT_RGB); glutinitwindowsize(500, 500); glutinitwindowposition(100, 100); glutcreatewindow("opengl Win32 2D Base Program"); glclearcolor(0.0, 0.0, 0.0, 1.0); glviewport(0,0,500,500); glmatrixmode(projection); glloadidentity(); glortho(-500/2, 500/2, -500/2, 500/2, -1, 1); 画面が隠れたりする毎にこの関数だけ繰 // 描画関数り返し実行される void draw( void) // 原点から長さ200の四角形を描画する glclear(color_buffer_bit); glbegin(lines); glcolor3d(1.0,1.0,1.0) ; glvertex2d( 0.0, 0.0); glvertex2d(200.0, 0.0); glvertex2d(200.0, 0.0); glvertex2d(200.0, 200.0); glvertex2d(200.0, 200.0); glvertex2d( 0.0, 200.0); glvertex2d( 0.0, 200.0); glvertex2d( 0.0, 0.0); glend(); glflush(); (3) メイン関数メイン関数はプログラム全体を統括するプログラムです. 処理はメインプログラムに始まりメインプログラムで終わります. 手順は上の行から下の行へ実行していきます. 各関数の処理内容は次のようになっています. glutinit(&argc,argv); Initialize(); glutdisplayfunc(draw); glutmainloop(); return 0; 図 Ⅳ-1 プログラムの流れ glutinit(&argc, argv) この関数は, 今回グラフを書くために利用する OpenGL が利用できるようにするための処理 ( 関数 ) です. これを呼ぶ ( 実行する ) ことにより, 以降で線や点を書くことが可能になります. Initialize(); この関数はプログラムの上の方に記述されている関数でプログラマ ( プログラムを書く人, つまりあなた ) が記述する関数です. この中では, 画面サイズの設定やウインドウ ( 処理を行うための画面 ) の作成と表示を行います. glutdisplayfunc(draw) この関数は, 他のウインドウの裏に隠れていた画面が表に現れる時や, 描画するデータに変更があって描画する際 ( 再描画といいます ) に, 描画を行う関数を定義します. この例では, 再描画時に draw という関数を使うということを指示しています. glutmainloop(); この関数は,OpenGL のウインドウが閉じられるまで繰り返す関数です. 処理の内容はキーボードやマウスなどユーザ ( プログラムを使っている人 ) が何か操作を行っていないか監視しています. そして, 押されたキーボードやマウス操作 ( イベント ) に応じた処理, つまり関数 ( ハンドラ ) を呼び出します. return 0; ウインドウが閉じられて glutmainloop を終えた後実行される処理で, 処理を終了して Windows に 0 を返し, 処理を完全に終了します. (4)Initialize 関数 // ユーザの初期化 void Initialize(void) glutinitdisplaymode(glut_single GLUT_RGB); glutinitwindowsize(500, 500); glutinitwindowposition(100, 100); glutcreatewindow("opengl Win32 2D Base Program"); glclearcolor(0.0, 0.0, 0.0, 1.0); glortho(-500/2, 500/2, -500/2, 500/2, -1, 1); // GLUTの初期化 // ユーザの初期化関数 // 描画関数の指定 // GLUTのメインループ // 表示モードの指定 // 画面サイズの指定 // ウインドウ位置の指定 // ウインドウの作成とタイトル設定 // ウインドウの背景色の設定 // 平行投影 List Ⅳ-3 List Ⅳ-4 この関数はユーザが描画を行うために必要な処理を実行します. 内部では 6 個の関数を呼び出しています. 全ての関数に gl または glut が付いていますので, 全て OpenGL に対する設定をしていることがわかります. では各処理内容を見ていきましょう. 表示される画面の位置や名前は図 Ⅳ-2 に示すようになっています. glutinitdisplaymode(glut_single GLUT_RGB) - 9 -
これは表示の状態を設定しています. ここで使われる引数の意味は, 単一画面で RGB( 赤緑青で光の三原色といわれます ) を使うことを定義しています. glutinitwindowsize(500,500); この関数はユーザが使うための描画画面サイズを設定します. この例では横 500( ひとつめの引数 ), 縦 500( 二つめの引数 ) を表しています. glutinitwindowposition(100,100); この関数は描画ウインドウの位置を指定します. この例では画面の左上 ( ディスプレイ原点 ) から右横方向に 100( ひとつめの引数 ), 下方向に 100( 二つめの引数 ) の位置に描画ウインドウの左上を配置します. glutcreatewindow( OpenGL Win32 2DBase Program ); この関数は実際に画面を作成し ( 描画ウインドウとコンソールウインドウ ), 描画画面のタイトルバーに引数である文字列 OpenGL Win32 2DBase Program ( アプリケーションタイトル ) を書き込みます. glclearcolor(0.0, 0.0, 0.0, 1.0); この関数は画面を消去 ( 描画されていた画像をクリア ) した時の色を指定します. 最初の 3 個の引数が色を表します. それぞれ順に R,G,B を意味しています. 全て ZERO の場合は黒, 全て 1.0 の場合は白を意味します. また,R を 1.0 にして, それ以外を ZERO にした場合は赤色となります. glortho( -500/2, 500/2, -500, 500/2, -1, 1); ユーザが設定している座標 ( ワールド座標 ) からカメラを用いて描画したい部分を設定します. この例では原点 (0,0) から長さ 200 の正方形を書いていますので, ワールド座標では図 Ⅳ-3(a) に示すような形と座標を持ちます. それら全体を描画できるように図 Ⅳ-3(b) に示すようにワールド座標上の (-250,-250) から (250,250) の四角を描画ウインドウに書き出します. 画面の長さは上で設定した描画画面サイズの 500 を用いたので, その半分の 250 を使っています. この結果, 描画ウインドウはワールド座標原点を中心とした座標形を持ち四角形は図 Ⅳ-3(c) に示すように描画されます. この関数を省略するとデフォルトでワールド座標上の (-1,-1) から (1,1) の四角を描画ウインドウ ( 正規デバイス座標系 ) に書き出します.3 次元で考える場合は, 奥行き (Z 座標 ) も考えなければならず, 視点 ( カメラの位置と方向 ) を決めてスクリーンに投影します. この時, デフォルトでは視点はワールド座標の原点で Z 軸の反対を向いています. 視点の先がプラスで, 視点の後ろがマイナスとなります. この例では,2 次元の立体は Z 軸が ZERO の位置にありますので,-1 と 1 を設定します. 投影には 2 種類あり, 今回のように視点から平行に投影する手法を平行投影といいます. この投影法では遠近感を出す事ができませんので一般的には CAD など 2 次元を表現する際に用いられます. このように設定されてできる四角柱の空間を視体積 ( ビューボリューム ) と呼び, この中にない図形は描画されません. (0, 0) ディスプレイ原点 タイトルバー 図 Ⅳ-2 画面名称 (100,100) 描画ウインドウ位置 アプリケーションタイトル 描画ウインドウ コンソールウインドウ - 10 -
Y Y ( 250, 250) OpenGL Win32 2D Base Program ( 0, 200) ( 200, 200) ( 0, 200) ( 200, 200) ( 0, 0 ) ( 200, 0) X ( 0, 0 ) ( 200, 0) X (- 250, - 250) (a) ワールド座標 (b) ビュー座標 (c) 実際の画面図 Ⅳ-3 画面の座標系の設定 glortho( -500/2, 500/2, -500, 500/2, -1, 1) ( 0, 200) まで線はある Y ( 0, 1 ) ( 1, 1 ) OpenGL Win32 2D Base Program ( 0, 0) ( 1, 0 ) X ( 200, 0) まで線はある (- 1, - 1) (a) ワールド座標 (b) 実際の画面図 Ⅳ-4 デフォルトの座標系 スクリーン 視体積 near top Z Y left カメラ right X bottom far ( right, top, far) カメラの向き ( left, bottom, near) ワールド座標 図 Ⅳ-5 平行投影 glortho( -500/2, 500/2, -500, 500/2, -1, 1) (5)draw 関数 // 描画関数 void draw(void) // 原点から長さ200の四角形を描画する glclear(color_buffer_bit); // 画面のクリア glbegin(lines); // 直線を書く glcolor3d(1.0,1.0,1.0); // 線の色を白色にする glvertex2d( 0.0, 0.0); glvertex2d(200.0, 0.0); // 直線の描画 glvertex2d(200.0, 0.0); glvertex2d(200.0, 200.0); // 直線の描画 glvertex2d(200.0, 200.0); glvertex2d( 0.0, 200.0); // 直線の描画 glvertex2d( 0.0, 200.0); glvertex2d( 0.0, 0.0); // 直線の描画 glend(); // 直線データの終了 glflush(); // 描画処理実行 List Ⅳ-5 この関数は実際に図形を描く処理です. この関数内で呼ばれる関数も全て頭に gl が付いていますので,OpenGL の処理関数であることがわかります. 処理の流れは画面をクリアした後, 線分を描き, 描画命令を実行しています. では具体的に追っていきましょう. glclear(color_buffer_bit); 画面を指定された色でクリアします. 色の設定は glclearcolor で設定された色を利用します. glbegin(lines); - 11 -
引数で指定された図形を描くことを宣言します. この宣言は glend が来るまで有効です. 言い換えれば glbegin から glend でひとつの図形のかたまりを描画することを示しています. glcolor3d(1.0, 1.0, 1.0); 描画する線の色を指定しています. 引数は順に R,G,B を表しており, 各値の最大値は 1.0 です. ここでは RGB 全てに 1.0 が設定されているので白色を使うと宣言していることになります. glvertex2d(0.0, 0.0); glvertex(200.0, 0.0); この二つの関数で (0.0, 0.0) から (200.0, 0.0) まで線を描くことを意味しています. つまり2 点を指定するとそれがひとつの線分となります.4 本の線を描く場合はこの関数を 4 組 8 個使うことになります. glend(); glbegin で指定された描画対象形状の指定終了を意味します. 描画できる対象形状は LINES の他にも様々な物があります. POINTS LINES LINE_ STRIP LINE_ LOOP POLYGON TRIANGLE_ FAN V 5 TRIANGLE_ STRIP V 5 TRIANGLES V 7 V 6 V V 6 5 QUADS 図 Ⅳ-6 OpenGL の基本図形 V 5 V 7 QUAD_ STRIP (6) コメントプログラムの中で // を用いると, その後から行の最後までがコメントとなりプログラムとして認識されません. また任意の位置で /* から */ の間もコメント見なされます. これを使うと複数行まとめてコメントとすることができます. ただし, /* から */ の間に /* と */ は入れることができません. コンパイル ( ビルド ) 時にエラーとなります. - 12 -