GLFWを用いてウィンドウを作る

今回はOpenGLを便利に使えるフレームワーク(ライブラリ?)のGLFWを使用してウィンドウを生成するプログラムを書いていきます。

そもそも何故外部ライブラリを使う必要があるのかという疑問については以下で解説しています。

開発環境は以下

  • OS: windows10
  • GLFW: version3.3
  • Visual Studio 2019

GLFWのダウンロード

インストール方法はOSによって異なります

Windows
→ CMakeやNuGetを用いて自分でコンパイルする方法もあるが私はあまり詳しくない&VisualStudioを使うのでWindows用にプリコンパイルされてるバイナリファイルをダウンロードします。
公式のダウンロードページ
のWindows pre-compiled binariesの横のダウンロードボタンからダウンロードします。今回は32-bitをダウンロードしました。

MacOS,Linuxの場合
以下の記事&pdfが参考になると思います。
https://grainrigi.hatenablog.com/entry/2017/08/27/144218
https://tokoik.github.io/GLFWdraft.pdf

VisualStudioの設定

  1. まずプロジェクトを作成する。今回は空のコンソールアプリケーションを使用する。
  2. プロジェクトを右クリック→プロパティを開く
  3. プロパティページのC/C++ → 全般から追加のインクルードディレクトリの右端の矢印ボタンをクリック→編集をクリック
  4. GLFWのディレクトリの中にあるincludeディレクトリのパスを追加します。($(SolutionDir)を使うことで相対パスを指定することも出来ます。)
  5. プロジェクトのプロパティの中のリンカータブをクリック
  6. 追加のライブラリディレクトリにGLFWのライブラリディレクトリを追加します。今回はVS2019を使っているのでlib-vc2019を指定。
  7. リンカー→入力タブから追加の依存ファイルにopengl32.libとglfw3dll.libを追加します。
  8. 今回は動的リンクを行うためライブラリファイルと同階層に配置されているdllファイル(glfw3.dll)を出力ディレクトリにコピーして配置してください。

GLFWの処理手順

コードの開設の前にGLFWの処理手順について説明する。

  1. GLFWを初期化する (glfwInit())
  2. ウィンドウを作成する (glfwCreateWindow())
  3. ウィンドウが開いている間繰り返し描画する (glfwWindowShouldClose())
  4. ダブルバッファリングのバッファの入れ替えを行う (glfwSwapBuffers())
  5. ウィンドウが閉じたら終了処理を行う (glfwTerminate())

コードを書いていく

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

#include <iostream>
#include <GLFW/glfw3.h>

using namespace std;

int main(){
  // GLFWを初期化する
  if (glfwInit() == GL_FALSE) {
	// 初期化に失敗
    cerr << "Can't initialize GLFW" << endl;
    glfwTerminate();
    return 1;
  }
  // Setup GLFW window properties
  // OpenGLのバージョン指定 今回は4.6を使ってみる
  glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
  glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
  // 古い機能を削除したプロファイルを使用するか
  glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
  // OpenGLのプロファイルを指定する
  glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
  
  GLFWwindow* mainWindow = glfwCreateWindow(640,480,"Sample Window", NULL, NULL);
  if(mnainWindow == NULL){
    // ウィンドウの作成に失敗
    cerr << "Can't create GLFW window" << endl;
    glfwTerminate();
    return 1;
  }
  // ウィンドウをOpenGLの処理対象にする
  glfwMakeContextCurrent(mainWindow);
  // 背景色を指定
  // 引数は 0~1のfloat型で r g b a を指定する。今回は不透明の赤100%
  glClearColor(1.0f,0.0f,0.0f,1.0f);
  // ウィンドウが閉じるまでループする
  while(glfwWindowShouldClose(mainWindow) == GL_FALSE){
    // ウィンドウを消去する
    glClear(GL_COLOR_BUFFER_BIT);
    // 
    //  ここで描画処理
    //
    // カラーバッファを入れ替える
    glfwSwapBuffers(mainWindow);
    
    // イベントを取り出す (ユーザーのインプットイベントなどなどを取り扱います。)
    glfwPollEvents();
  } 
}

コードの解説

まず最初の数行について

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

これはライブラリの使用を宣言する。VisualStudioのリンカーの入力タブでライブラリの設定をしたと思うが、ここで宣言をすればそれをする必要がない。
また今回は動的リンク(DLL)を使用するためglfw3.libではなくglfw3dll.libを使用している。

#include <iostream>
#include <GLFW/glfw3.h>

ヘッダファイルをインクルードする。GLFWを使うにはglfw3.hをインクルードする。

if (glfwInit() == GL_FALSE) {
	// 初期化に失敗
    cerr << "Can't initialize GLFW" << endl;
    glfwTerminate();
    return 1;
  }

まず最初にglfwInit()でglfwを初期化する。
int glfwInit(void)
成功すればGL_TRUEが失敗すればGL_FALSEが返ってくる

GLFWwindow* mainWindow = glfwCreateWindow(640,480,"Sample Window", NULL, NULL);
if(mainWindow == NULL){
    // ウィンドウの作成に失敗
    cerr << "Can't create GLFW window" << endl;
    glfwTerminate();
    return 1;
}

glfwCreateWindow(int width,int height,const char *title,GLFWmonitor *monitor, GLFWwindow *share)を用いてGLFWのウィンドウを作成する。戻り値はウィンドウのハンドル。ウィンドウが開けなかったらNULLを返す。NULLチェックを忘れずに。

width,height: 幅と高さ。0より大きい必要がある。
title: ウィンドウのタイトルバーに表示する文字列。文字コードはUTF-8
monitor: ウィンドウを全画面に表示するとき、表示するモニタを指定する。フルスクリーンモードでなければNULLを指定する
share: 他のウィンドウハンドルを指定すると、そのウィンドウとテクスチャなどのリソースを共有。

 // ウィンドウが閉じるまでループする
  while(glfwWindowShouldClose(mainWindow) == GL_FALSE){
    // ウィンドウを消去する
    glClear(GL_COLOR_BUFFER_BIT);
    // 
    //  ここで描画処理
    //
    // カラーバッファを入れ替える
    glfwSwapBuffers(mainWindow);
    
    // イベントを取り出す (ユーザーのインプットイベントなどなどを取り扱います。)
    glfwPollEvents();
  } 

glfwWindowShouldClose(GLFWwindow* window)関数で閉じるかどうかを確認出来る。

glClear(GL_COLOR_BUFFER_BIT)でウィンドウを塗りつぶす。今回はGL_COLOR_BUFFER_BITを指定したので、カラーバッファだけをglClearColor()関数で指定した色で塗りつぶす

glfwSwapBuffers(mainWindow) windowに指定したウィンドウのカラーバッファを入れ替える。これで画面を更新することが出来る。

glfwPollEvents(void) マウスの操作などのイベントを取りだし、それを記録する。特徴はglfwWaitEvents(void)と違いプログラムを停止させないこと

glfwWaitEvents(void) マウス操作などのイベントの発生を待つ。イベントが来るまでプログラムが停止する。待ち時間の最大値を引数に指定できるglfwWaitEventsTimeout(double sec)もある。

終わり

これでひとまず赤いウィンドウを作成することが出来る。GLFWを用いることでプラットフォームに依存したコード(Win32 APIとか)を書く必要がなくなるので非常に楽になる。

他にもOpenGLに関する記事を書いていこうと思っています。役に立てれば嬉しいです。それでは。

コメント

タイトルとURLをコピーしました