これはGLFWのAPIの全ての定数、型、関数プロトタイプを定義します。
また、OpenGLヘッダもインクルードされ、プラットフォームで動作させるのに必要な全ての定数と型が定義されます。
glfwTerminate();
これは、すべての残っているウィンドウを破棄して、すべての他のリソースを解放します。
これの呼出した後は、GLFW機能を利用する前に、再度
glfwInitを呼び出す必要があります。
エラーコールバックの設定
ほとんどのイベント(キーが押されたとか、GLFWウィンドウが移動したとか、エラーが発生しているとか)は、コールバックを介して報告されます。
コールバックは単なるCの関数(またはC++の静的メソッド)で、イベントに関する引数を持ってGLFWによって呼び出されます。
glfwInitまたはその他GLFW関数が失敗した場合、GLFWエラーコールバックにエラーがレポートされます。
エラーコールバックを設定することで、これらのレポートを受け取ることができます。
コールバック関数自体は
GLFWerrorfunのシグネチャと一致する必要があります。
ここに挙げるのは、単にstderrにエラーの説明を出力する単純なエラーコールバックです。
void error_callback(int error, const char* description)
{
fputs(description, stderr);
}
コールバックを設定することで、GLFWはそれを呼び出せることを知らせるには、
glfwSetErrorCallbackを使います。
これは、
glfwInitより前に呼び出すことのできるGLFW関数のひとつで、初期化中にエラーが発生を通知を受け取るために、他のGLFWを使う前に設定するべきです。
glfwSetErrorCallback(error_callback);
ウィンドウとコンテキストの作成
ウィンドウ (とそのコンテキスト)
glfwCreateWindowで作成され、作成されたウィンドウハンドルを返します。
例えば、640x480のウィンドウモードのウィンドウを作成するには次のようにします:
GLFWwindow* window = glfwCreateWindow(640, 480, "My Title", NULL, NULL);
ウィンドウ作成に失敗した場合は、NULLが返されるので、それを確認する必要があります。
if (!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
このハンドルは、すべてのウィンドウ関連関数に渡され、入力イベントと共に提供されるので、どのウィンドウがその入力を受け取ったかを知ることができます。
フルスクリーンウィンドウを作成するには、どのモニタにそのウィンドウを表示するかを指定する必要があります。
ほとんどの場合、ユーザのプライマリモニタを選ぶのが良いです。
glfwGetPrimaryMonitorを使うとプライマリモニタを取得できます。
上述のウィンドウをフルスクリーンにするには、単にモニタハンドルを渡すだけです:
GLFWwindow* window = glfwCreateWindow(640, 480, "My Title", glfwGetPrimaryMonitor(), NULL);
フルスクリーンウィンドウは、モニタの表示エリア全体をカバーし、境界や装飾を持たず、そして、モニタの解像度を要求したウィンドウサイズに最も近いものに変更します。
そのウィンドウを使い終えた時は、
glfwDestroyWindow関数でウィンドウを破棄します。
glfwDestroyWindow(window);
この関数が一度呼び出されたら、そのウィンドウにはそれ以上イベントが届けられなくなり、そのハンドルは無効になります。
OpenGLコンテキストをカレントにする
OpenGLのAPIを使う前に、OpenGLコンテキストを取得しなければなりません。
ウィンドウのコンテキストを
glfwMakeContextCurrentを用いてカレントにします。
他のコンテキストをカレントにするまで、あるいはコンテキストを所有するウィンドウが破棄されるまで、カレントコンテキストのままになります。
glfwMakeContextCurrent(window);
ウィンドウ閉じるフラグのチェック
各ウィンドウは、そのウィンドウが閉じられるべきであるかを示すフラグを持っています。
このフラグは、
glfwWindowShouldCloseでチェックすることができます。
ユーザが、タイトルバーの閉じるボタンを押す、あるいはAlt+F4のようなショートカットで、ウィンドウを閉じようとした時、このフラグは1にセットされます。
その際、実際にはウィンドウはまだ閉じられていないことに注意してください。このフラグをモニタリングすることで、ウィンドウを破棄するか、ユーザに何らかのフィードバックを与えることができます。
while (!glfwWindowShouldClose(window))
{
// Keep running
}
glfwSetWindowCloseCallbackでクローズコールバックを設定することで、ユーザがウィンドウを閉じようとした時に通知を受け取ることができます。
そのコールバックはクローズフラグがセットされた直後に呼び出されます。
glfwSetWindowShouldCloseを用いて、自分自身でそれをセットすることも可能です。
これは他の入力をウィンドウを閉じるに変換したいとき、例えば、エスケープキーの押下で閉じるようにしたいときに便利です。
入力イベントの受信
各ウィンドウは、すべての様々な種類のイベントを受け取るために設定できるコールバックを数多く持っています。
キー押下、押下解除イベントを受け取るには、
glfwSetKeyCallbackでキーコールバックを設定します。
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
}
イベント発生時に実際に呼び出されるイベントコールバックに、上述したようなイベント処理が必要です。
OpenGLによるレンダリング
カレントOpenGLコンテキストを取得したあとは、OpenGLを普通に使えます。
このチュートリアルでは、多色の回転する三角形をレンダリングしてみます。
この例では
glViewportや
glOrthoで必要とされるフレームバッファのサイズは、
glfwGetFramebufferSizeで受け取ることができます。
int width, height;
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);
しかし、コールバック
glfwSetFramebufferSizeCallbackを用いて、そこで
glViewportを呼ぶことで、フレームバッファサイズを設定することも可能です。
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}
タイマーの読み取り
三角形を適切に回転させるには、時間の情報源が必要です。
GLFWは、
glfwInitからの経過秒数をdouble型で返す
glfwGetTimeを提供しています。
時間の情報源は各プラットフォームにおける最も精確なものが利用され、一般にはマイクロ秒あるいはナノ秒の分解能を持っています。
double time = glfwGetTime();
バッファのスワップ
GLFWウィンドウは常にダブルバッファリングを使います。
2つのレンダリングバッファを持つことを意味しています; フロントバッファとバックバッファ。
フロントバッファは画面に表示されているもので、バックバッファはレンダリングの対象のものです。
フレーム全体のレンダリングが完了した時、レンダリングしたフレームを表示し、そして、新しいフレームのレンダリングを開始するために、バックとフロントを入れ替えます。
これは
glfwSwapBuffersで行えます。
glfwSwapBuffers(window);
イベント処理
GLFWは、イベントの受け取りのため、および、ロックされていないことを示すための両方の目的のために、ウィンドウシステムと定期的に通信する必要があります。
イベント処理は定期的に行う必要があり、通常、各フレームのレンダリングの前にとバッファスワップの後に行われます。
保留中のイベントを処理する方法は2つあります。
glfwPollEventsはそれらの受信済みイベントだけを処理して、すぐにリターンします。
これは、ほとんどのゲームが行うように継続的にレンダリングする場合に最良のチョイスです。
glfwPollEvents();
新しい入力を受け取ったときにだけレンダリングの更新が必要な場合は、代わりに、
glfwWaitEventsを使うのがベターです。
それは、少なくとも1つのイベントが受信されるまで待ち、その間はスレッドをスリープしておき、それから、
glfwPollEventsが行うようにすべての受信イベントを処理します。
この方法は、CPUサイクルをかなり抑えることができ、例えば、いろんなエディットツールにおいて有用です。
glfwWaitEvents();
書いてみよう: 小さなGLFWアプリケーション
いま、GLFWを初期化し、ウィンドウを作成し、キーボード入力を取得する方法がわかったので、シンプルなプログラムを作成できるようになりました。
#include <GLFW/glfw3.h>
#include <stdlib.h>
#include <stdio.h>
static void error_callback(int error, const char* description)
{
fputs(description, stderr);
}
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
}
int main(void)
{
GLFWwindow* window;
glfwSetErrorCallback(error_callback);
if (!glfwInit())
exit(EXIT_FAILURE);
window = glfwCreateWindow(640, 480, "Simple example", NULL, NULL);
if (!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
glfwSetKeyCallback(window, key_callback);
while (!glfwWindowShouldClose(window))
{
float ratio;
int width, height;
glfwGetFramebufferSize(window, &width, &height);
ratio = width / (float) height;
glViewport(0, 0, width, height);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-ratio, ratio, -1.f, 1.f, 1.f, -1.f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef((float) glfwGetTime() * 50.f, 0.f, 0.f, 1.f);
glBegin(GL_TRIANGLES);
glColor3f(1.f, 0.f, 0.f);
glVertex3f(-0.6f, -0.4f, 0.f);
glColor3f(0.f, 1.f, 0.f);
glVertex3f(0.6f, -0.4f, 0.f);
glColor3f(0.f, 0.f, 1.f);
glVertex3f(0.f, 0.6f, 0.f);
glEnd();
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}
このプログラムは、640x480のウィンドウモードの画面を作成してから、スクリーンの消去、三角形のレンダリング、イベント処理のループを、ウィンドウがユーザに閉じるまで行います。
これはソースコード配布の
examples/simple.cにあり、GLFWをビルドする時に、デフォルトで他のサンプルと一緒にコンパイルされます。
コンパイル
GLFWを使うプログラムをコンパイル・リンクする方法について知りたい場合は、
Building programs that use GLFWを参照してください。