«Screen Space Motion Blur 最新 (2) エラー処理, 初期設定の追加»

床井研究室

※このブログは遅くとも 2027 年 3 月に管理者の定年退職により閉鎖します (移転先は管理者本人共々模索中)

■ 2012年09月06日 [OpenGL][GLFW] (1) GLFW で OpenGL を使う

2013年11月10日 00:55更新

GLUT の現状

OpenGL は「プラットフォームに依存しないグラフィックス API」ですが, これと稼働するプラットフォームとのインタフェースの部分はやはりプラットフォームごとに異なっていて, そのあたりの実装はそれなりにめんどくさいものです. そのために, そこをうまくラップするツールキットがいくつも提案されています. 中でも GLUT は, OpenGL を作ったところの人が作った, 使いやすいツールキットです. また GLUT はマルチプラットフォームに対応しているため, これを使ったソースプログラムは Unix / Linux, Windows, Mac OS X の間で共通にすることができます. GLUT は OpenGL の初期に作られたものですが, OpenGL の学習や OpenGL を使った簡単なプログラムの作成を手軽に始めることができるため, 今でも有用なツールキットです.

しかし, オリジナルの GLUT は (バグがあるにもかかわらず) もう長い間メンテナンスされていません. また Mac OS X に標準で搭載されている GLUT は OpenGL 2.1 しか使えず, Lion 以降で使用可能になった OpenGL 3.2 Core Profile を (公式には) 使用することができません.

gl3w というツールを使えば, GLUT でも OpenGL 3/4 の Core Profile を使うことができます.

また, オリジナルの GLUT 互換のツールキットとして freeglutOpenGLUT が使われいてますが, これらは Mac OS X には対応していません.

GLFW

OpenGL に対応していて GLUT のようにマルチプラットフォームで使用できるツールキットには, FLTKQt, SDL などがあります. 中でも Qt は非常に高機能なツールキットであり, CG 関連のいくつかの主要なアプリケーションがこれを使って開発されていたりします. しかし, OpenGL の学習のためにあれこれ試したり, ちょっとしたプログラムを書いたりするには, Qt などはちょっと大きすぎる気がします. そこで GLUT の代わりになる簡単で小さなツールキットとして, 試しに GLFW を使ってみようと思いました.

プロジェクトのホームページ (http://www.glfw.org/) には, GLFW はウィンドウを作成し, OpenGL のコンテキストを作って, 入力 (デバイス) を管理する, 無料の, オープンソースの, マルチプラットフォームのライブラリだと書いてあります. ライセンスは unmodified zlib/libpng license を採用しています.

GLFW の特徴

まだ数日しか使っていないのですが, 次のような特徴を持っているようです.

マルチプラットフォームである
  • GLUT 同様 Windows / Mac OS X / Linux でソースを共通化することができる.
OpenGL のバージョンやプロファイルが指定できる
  • Mac OS X Lion 以降では Version 3.2 Core Profile が使える.
コールバックベースではない
  • イベントループは自分で書く.
  • コールバックベースで書くこともできる.
最初からダブルバッファリングになっている
  • シングルバッファのモードは無い.
入力デバイスの取り扱い方法が異なる
  • 文字ではなく押されているキーそのものを知ることができる.
  • マウスホイールのデータを取得できる.
その他の機能
  • テクスチャ用の画像を読み込む機能がある.
  • スレッドやミューテックスを扱う機能がある.
  • Mac OS X でも Close ボタンが有効になる.
GLFW にない機能
  • Sphere や Teapot のような図形を表示する機能はない.
  • ビットマップフォントをレンダリングする機能はない.
  • ポップアップメニューを表示する機能は無い.

最初からダブルバッファリングになっていることや, マウスやキーボード, ジョイスティックの扱い方を見ると, GLFW は GLUT に比べてゲーム向きになっているように思われます. また GLUT にあって GLFW に無い機能の多くは, もともと OpenGL の Core Profile では使えない機能だと思います. Mac OS X の GLUT が Legacy Profile すなわち OpenGL 2.1 にしか対応していないのは, このような問題があるからかも知れません. あと, GLFW の Reference や User Guide がとても良くできているので, これらを読めばこのブログに書いてあるようなことは必要ないと思います.

GLFW のインストール

Windows (Visual Studio 2008/2010), Mac OS X (Xcode 4), Linux の場合について解説します.

Windows

プロジェクトのダウンロードページ http://www.glfw.org/download.html からバイナリファイル glfw-2.7.6.bin.WIN32.zip (2012 年 9 月 6 日時点) が入手できます. これには MinGW, Visual Studio 2008, Visual Studio 2010 のバイナリが入っています.

Visual Studio 2008
  • include\GL フォルダにある glfw.h
    • C:\Program Files\Microsoft SDKs\Windows\v6.0A\Include\gl にコピーする
  • lib-msvc90 フォルダにある GLFW.lib
    • C:\Program Files\Microsoft SDKs\Windows\v6.0A\Lib にコピーする
    • GLFW.lib はスタティックリンクライブラリなので DLL のコピーは不要
  • ダイナミックリンクする場合
    • GLFWDLL.lib を C:\Program Files\Microsoft SDKs\Windows\v6.0A\Lib にコピーする
    • GLFW.dll は, 32bit版 Windows なら C:\Windows\System32 に, 64bit 版Windows なら C:\Windows\SysWOW64 にコピーする
Visual Studio 2010
  • include\GL フォルダにある glfw.h
    • 32bit 版 Windows なら C:\Program Files\Microsoft SDKs\Windows\v7.0A\Include\gl にコピーする
    • 64bit 版 Windows なら C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Include\gl にコピーする
  • lib-msvc100 フォルダにある GLFW.lib
    • 32bit 版 Windows なら C:\Program Files\Microsoft SDKs\Windows\v7.0A\Lib にコピーする
    • 64bit 版 Windows なら C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Libにコピーする
    • GLFW.lib はスタティックリンクライブラリなので DLL のコピーは不要
  • ダイナミックリンクする場合
    • 32bit 版 Windows なら GLFWDLL.lib をC:\Program Files\Microsoft SDKs\Windows\v7.0A\Lib にコピーし GLFW.dll を C:\Windows\System32 にコピーする
    • 64bit 版 Windows なら GLFWDLL.lib を C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Lib にコピーし GLFW.dll を C:\Windows\SysWOW64 にコピーする
ソースをコンパイルする場合
プロジェクトのダウンロードページ http://www.glfw.org/download.html からソースファイル glfw-2.7.6.zip (2012 年 9 月 6 日時点) が入手できます. アーカイブを展開すると, support の中に Visual Studio 2008 のソリューションファイル (msvc90\GLFW.sln) と Visual Studio 2010 のソリューションファイル (msvc100\GLFW.sln) が入っています. このほか, D 言語用のヘッダファイルやライブラリファイル作成用 makefile, および Pascal 言語用ヘッダファイルも入っています.

Mac OS X

Mac OS X では HomeBrew (http://mxcl.github.com/homebrew/) や Fink (http://www.finkproject.org/) などのパッケージを使うと楽です.

fink install glfw
brew install glfw

なお MacPorts (http://www.macports.org/) には用意されていないようです (2012 年 9 月 6 日時点).

ソースをコンパイルする場合
プロジェクトのダウンロードページ http://www.glfw.org/download.html からソースファイル glfw-2.7.6.zip (2012 年 9 月 6 日時点) が入手できます. ターミナルを開き, 展開したディレクトリに cd して make を実行すれば,インストールの仕方が表示されます. Mac OS X では次のコマンドでインストールできます.
make cocoa
sudo make cocoa-install

shared library もインストールする場合は, さらに次のコマンドを実行してください.

sudo make cocoa-dist-install
GLFW 2.7.7 の時点では,make cocoa-dist-install も実行しないと,リンクエラーになります(西やんさんありがとうございました).

Linux

Ubuntsu, Fedora, OpenSUSE にはパッケージが用意されていると思います. 使用しているディストリビューションのパッケージマネージャで検索してください. Vine Linux には用意されていないようです (2012 年 9 月 6 日時点). その場合はソースをコンパイルしてください.

ソースをコンパイルする場合
プロジェクトのダウンロードページ http://www.glfw.org/download.html からソースファイル glfw-2.7.6.zip (2012 年 9 月 6 日時点) が入手できます. ターミナルを開き, 展開したディレクトリに cd して make を実行すれば,インストールの仕方が表示されます.
make x11
sudo make x11-install

shared library もインストールする場合は, さらに次のコマンドを実行してください.

sudo make x11-dist-install

プログラムの作成

以下に GLFW を使ったプログラムの処理手順を示します.

  1. GLFW の初期処理を行う
  2. ウィンドウを開く
  3. ウィンドウが開いている間描画を行う
  4. ダブルバッファリングのバッファの入れ替えを行う
  5. ウィンドウが閉じたら終了処理を行う

このソースプログラムは次のようになります.

#include <GL/glfw.h>
 
int main(int argc, char *argv[])
{
  glfwInit();
  
  glfwOpenWindow(0, 0, 0, 0, 0, 0, 0, 0, GLFW_WINDOW);
  
  while (glfwGetWindowParam(GLFW_OPENED))
  {
    /*
    ** ここで OpenGL による描画を行う
    */
    
    glfwSwapBuffers();
  }
  
  glfwTerminate();
  
  return 0;
}
int glfwInit(void)
GLFW を初期化します. 他のすべての GLFW の関数を実行する前に実行する必要があります. 初期化に成功すれば GL_TRUE (非 0), 失敗すれば GL_FALSE (0) を返します.
int glfwOpenWindow(int width, int height, int redbits, int greenbits, int bluebits, int alphabits, int depthbits, int stencilbits, int mode)
GLFW のウィンドウを開きます. ウィンドウが開ければ GL_TRUE, 開けなければ GL_FALSE を返します.
width
ウィンドウの横幅の画素数で, 0 なら height の 4/3 になります. height も 0 のときは width は 640 になります.
height
開くウィンドウの高さの画素数で, 0 なら width の 3/4 になります. width も 0 のときは height は 480 になります.
redbits, greenbits, bluebits
ウィンドウのカラーバッファの, それぞれ赤 (R), 緑 (G), 青 (B) のチャネルに割り当てるビット数で, 0 ならデフォルトの色深度が使われます.
alphabits
アルファチャネル (不透明度, A) のビット数で, 0 ならアルファチャネルは作成されません.
depthbits
デプスバッファに割り当てるビット数で, 0 ならデプスバッファは作成されません.
stencilbits
ステンシルバッファに割り当てるビット数で, 0 ならステンシルバッファは作成されません.
mode
ウィンドウの開き方を指定します. GLFW_WINDOW を指定すれば通常のウィンドウを開きます. GLFW_FULLSCREEN を指定すれば, フルスクリーンで開きます.
int glfwGetWindowParam(int param)
開いているウィンドウの param に指定したパラメータを取得します. param に GLFW_OPENED を指定すれば, ウィンドウが開いているときには GL_TRUE, 閉じているときには GL_FALSE を返します.
void glfwSwapBuffers(void)
ダブルバッファリングのフロントバッファとバックバッファを入れ替えます. 描画が完了した時点で呼び出します. この関数は内部で glfwPollEvents() を呼び出して, マウスやキーボードなどのイベントの取得を行います.
void glfwTerminate(void)
この関数は開いている他のウィンドウを閉じたり, 走っているスレッドを停止させたりします. この関数はプログラムの終了時に呼び出します.

glfwOpenWindows() の設定に問題がある (ハードウェアが対応していない設定を行ったなど) と, ウィンドウは開かれません. またウィンドウのクローズ動作はイベントとして取得されず, 描画の前に glfwGetWindowParam(GLFW_OPENED) によってウィンドウが開いていることを確かめる必要があります. またイベントの取得は glfwSwapBuffers() あるいは glfwPollEvents(), glfwWaitEvents() で行いますので, これらが実行されなければイベントは取得されません (マウスやキーボードの操作を知ることができません).

コンパイルの仕方

Windows

プログラムの作成は「Win32 コンソールアプリケーション」のプロジェクトを作成して行ってください. その際, 作成したプロジェクトの「プロパティ」の「構成プロパティ」「リンカー」「入力」にある「追加の依存ファイル」に, opengl32.lib と GLFW.lib を追加してください. 以下に手順の説明を用意しています.

あるいは, ソースプログラム (main() 関数を含むものだけでよい) の冒頭に次の2行を置くだけでも構いません. DLL を使う場合は, GLFW.lib の代わりに GLFWDLL.lib を指定してください.

#pragma comment(lib, "GLFW.lib")
#pragma comment(lib, "opengl32.lib")

コンソールウィンドウを開きたくない場合は, 次の1行をこれに追加してください.

#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")
ソリューション構成が「Debug」のとき, ビルド時に「LINK : warning LNK4098: defaultlib 'MSVCRT' は他のライブラリの使用と競合しています。/NODEFAULTLIB:library を使用してください。」という警告が出ることがあります. これは無視しても問題ないと思います. 気になるなら, 次の1行を追加すれば表示されなくなります.
#pragma warning(disable:4098)
あるいは, 「プロジェクト」の「プロパティ」(Alt-F7) の「構成プロパティ」「C/C++」「コード生成」のところにある「ランタイムライブラリ」で, 「マルチスレッド DLL (/MD)」を選択してください.

Mac OS X

コマンドラインでコンパイルする場合は, -framework OpenGL -lglfw オプションを追加してください.

cc main.c -framework OpenGL -lglfw
c++ main.cpp -framework OpenGL -lglfw

Xcode を使ってプログラムを作成する場合は, プロジェクトの新規作成の際に Application の Command Line Tool のテンプレートを指定してください. その際,"Product Name" には作成するプログラムの名前, "Organization Name" には作成者の名前, "Company Identifier" には, Apple に開発者として登録しているなら Apple から取得した開発者 ID を指定しますが, 開発者 ID を持っていなければ適当な文字列を設定してください. あと "Type" には使用するプログラミング言語を指定してください.

プロジェクトが作成されると, 中に main.c あるいは main.cpp, main.m などといったファイルができています. これに main() 関数が定義されています. このほかに "プロジェクト名.1" というファイルも作られていますが, これは man 形式のオンラインマニュアルなので, マニュアルを書かないなら削除して構いません.

次に, 左のペインの「プロダクト名」を選んでから, その右の TARGETS のところの「プロダクト名」を選んで, 中央の Build Settings を選んでください. そして, その下にある All を選んだのち, Other Linker Flags という項目を探し (右側に検索ボックスがあります) そこに -framework OpenGL -L/usr/local/lib -lglfw を設定してください. 同様に Header Search Path という項目を探して, そこに /usr/local/include を設定してください. また Library Search Path という項目を探して, そこに /usr/local/lib を設定してください. なお, fink の場合は /usr/local のところを /sw にしてください. 以下に手順の説明を用意しています.

あるいは, Build Phases を選んで OpenGL Framework と /usr/local/lib/libglfw.a を Link Binary With Libraries に追加しても構いません. ターミナルで次のコマンドを実行すればディレクトリ /usr/local/lib の内容が Finder に表示されますので, Drag & Drop でファイルをここに入れることができます.

open /usr/local/lib
たまに "Xcode cannot run using selected destination." と表示されてビルドが失敗することがあります. その場合は Build Settings で Base SDK という項目を探して, 設定内容を一度別のものに変更してから元に戻してみてください.

Linux

cc/c++ コマンドに -lGL -lglfw オプションを追加してください.

cc main.c -lGL -lglfw
c++ main.cpp -lGL -lglfw

たとえば, 次のような Makefile を作っておくと便利です (下の例はタブが失われているのでコピペでは使えません). 「プログラム名」は作成するプログラム名に置き換えてください. C 言語を使う時は CXX と CXXFLAGS をそれぞれ CC, CFLAGS に, .cpp を .c にすべて置き換えてください.

CXXFLAGS        = -I/usr/X11R6/include -DX11 -Wall
LDLIBS  = -L/usr/X11R6/lib -lglfw -lGL -lm
OBJECTS = $(patsubst %.cpp,%.o,$(wildcard *.cpp))
TARGET  = プログラム名
 
.PHONY: clean depend
 
$(TARGET): $(OBJECTS)
        $(LINK.cc) $^ $(LOADLIBES) $(LDLIBS) -o $@
 
clean:
        -$(RM) $(TARGET) *.o *~ .*~ core
 
depend:
        $(CXX) $(CXXFLAGS) -MM *.cpp > $(TARGET).dep
 
-include $(wildcard *.dep)

空のディレクトリにプログラムのソースファイルとこの Makefile を置き, 最初に一度だけ make depend を実行してください (ヘッダファイルを追加した場合も実行してください). 以降は make だけでプログラムがコンパイル・リンクされます.

make depend
make

今後の予定

次回以降, GLFW を使って実際にプログラムを作成します. OpenGL 3.2 の Core Profile を使用する予定です.

コメント(9) [コメントを投稿する]
とこ 2012年09月08日 11:37

最初 GLEW との共存ができないと書いていましたが, Twitter で「できてる」というご指摘をいただいたので別のマシンで試したところ, 問題なくできました. ブログを訂正しました. ありがとうございました.

西やん 2013年03月13日 11:24

こんにちは。床井様のサイトは本当に、大変役立っています。<br><br>ところで、"brew install glew"は、"brew install glfw"が正しいのでしょうか?<br><br>ちなみに、"brew install glfw"を実行せずに、glfw-2.7.7をソースからコンパイルしてインストールしましたが、"sudo make cocoa-install" だけだとシンボルが見つからないエラーとなりました(詳細は忘れました...)ので、<br>http://sourceforge.net/p/glfw/discussion/247562/thread/784bc62f/を参考にして、"sudo make cocoa-dist-install"までやったら解決しました。<br>環境はMac Book Air + OS X 10.8.2 + Xcode4.6 です。

とこ 2013年03月16日 01:17

西やんさん,コメントありがとうございます.typo でした.すみません,直しておきます.<br><br>あと,cocoa-install でインストールされるライブラリファイルは static library なので cocoa-dist-install でインストールされる dll は必要ないはずなんですけが…いま出先で手元に Mac がないので,後ほど確認します.ありがとうございます.

とこ 2013年03月31日 12:58

西やんさん,<br><br>随分間が開いてしまいましたけど(すみません),確認しました.おっしゃるとおり,cocoa-dist-install しないと ranlib されないせいか,リンクに失敗しますね.本文の方にも付け加えさせて頂きます.ありがとうございます.

Hingis 2013年10月17日 14:21

GLFW3.0X以上からは、glfwReadImageとかが廃止になってしまいました。Raw画像データを読み込んで、glfwで作成したウィンドウに表示するのにお勧めの方法は有りますでしょうか?今はfreeglutと組み合わせて使って、glfwで作成したウィンドウに、glDrawPixelsで画像データを書き込んで、一応、描画できておりますが、画像データを読み込んで描画するためだけにOpenGLのライブラリを2つも使うのもなんだかなぁ・・・と感じております。GLFWはコールバックベースではないので、自分でイベントループを書くので、便利なのですが。

とこ 2013年10月18日 23:34

Hingis さま,コメントありがとうございます.<br>最近,glfwReadImage() に似た TGA ファイルの読み込み関数を自分で作って使っています.<br>TGA ファイルは RAW 画像に毛が生えた程度のフォーマットですので,割と簡単です.<br>https://github.com/tokoik/glfwsample/blob/master/gg.cpp の 4710 行目あたりにあります.<br>でも,glpng のほうがいいなあと思っています.

とこ 2013年10月18日 23:41

GLFW3 版はこっちでした.<br>https://github.com/tokoik/glfw3sample/blob/master/gg.cpp

Hingis 2013年10月29日 09:33

 床井様、アドバイスありがとうございます。画像の読み込み関数を使用するか、画像読み込みようの別ライブラリを使用するのが良さそうですね。OpenGL系のライブラリは画像読み込み系が今ひとつ充実していない感じがします。この辺が改善されるとすごく便利になるのですが、クロスプラットフォームとの両立が難しいのですかねー。

とこ 2013年11月10日 00:55

Hingis さま、そこはやはり OpenGL が「グラフィックスハードウェアを制御する API」であることに由来しているんだと思います。テクスチャやモデルの読み込みなど、その周辺の機能については、個別に独立したライブラリを組み合わせてもいいと思いますが、Open Scene Graph http://www.openscenegraph.org のようなミドルウェアを使うと言うのも一つの手ではないでしょうか。


編集 «Screen Space Motion Blur 最新 (2) エラー処理, 初期設定の追加»