[Work/Class/OpenGL/2_OpenGL2toX]

GLUTに代わりGLFWを使う

GLFW

GLFWとは,(多分)GL Frameworkの略で,基本的にOpenGL 1.x系を対象としているGLUTに対して,OpenGL 2系以降を対象としたマルチプラットフォームのライブラリである.

複数のウィンドウ(やGUI部品)を扱うための「コンテキスト」など現代的な要素を含みながら,ほぼGLUTと同じような感じで,Windowを作ったり,Windowイベントや,マウスイベント,キーボードイベントをアサインできるライブラリである.

/* MakeWindowUsingGlfw_1.cpp */
#ifdef __APPLE__
#include <OpenGL/opengl.h>
#else
#include <GL/gl.h>
#endif

#include <GLFW/glfw3.h>
#include <glm/glm.hpp>

int main(void){
  GLFWwindow* glfwWindow; //作るWindowを表現するポインタ変数

  //GLFWライブラリ自体の初期化
  if(!glfwInit()){
    //glfwInit()というライブラリ初期化関数を実行して,エラーが返ってきたら
    //(エラーというのはC言語的書法で,0以外を表す)

    return -1;
    //C言語の書法
    //mainを含むすべての関数が0以外をreturnするのは,正常ではない終了,
    //(Abnormal End, abendと呼称する)
    //上記のチェックif(!glfwInit())も
    //「glfwInit()関数を実行して0以外が返ってきたら」という意味
  }

  //windowを作って,OpenGLのコンテキストを生成して,ポインタ変数に登録する
  int windowWidth = 640;
  int windowHeight = 480;

  glfwWindow = 
    glfwCreateWindow(windowWidth, windowHeight,
		     "MakeWindowUsingGlfw_1",
		     NULL, NULL);

  if(!glfwWindow){
    //正常にWindowが生成されていなかったら(glfwWindowがNULLポインタだったら)
    //GLFWライブラリ自体を終了して,
    glfwTerminate();
    //異常終了
    return -1;
  }

  //WindowのCurrent Contextを作り登録する.
  glfwMakeContextCurrent(glfwWindow);

  //CelarColorを不透明の白に指定する.
  //これは今までと同じ
  glClearColor(1.0, 1.0, 1.0, 0.0);

  //このWhileループがメインループとなる.
  while(!glfwWindowShouldClose(glfwWindow)){
    //glfwWindowShouldClose()関数にWindowのポインタ変数を渡して,
    //Closeすべきかどうかを問い合わせる.
    //0以外が返ってきたらCloseすべきではないので,レンダリング(このWhileループ)を続ける
    
    glClear(GL_COLOR_BUFFER_BIT);

    //glutSwapBuffersの代わりにglfwSwapBuffersを使う
    glfwSwapBuffers(glfwWindow);

    //次の描画やWindowの操作,マウス・キーボードなどのイベントを待つ
    glfwPollEvents();
  }

  glfwTerminate();

  return 0;
  //C言語書法で0を返すのは「正常終了」
}
/* MakeWindowUsingGlfw_2.cpp */
#ifdef __APPLE__
#include <OpenGL/opengl.h>
#else
#include <GL/gl.h>
#endif

#include <GLFW/glfw3.h>
#include <glm/glm.hpp>

//関数のプロトタイプ宣言
void keyboard(GLFWwindow*, 
	      int key, int scancode, int action , int modes);
void cursorPosition(GLFWwindow* window, 
		    double xPos, double yPos);
void mouseButton(GLFWwindow* window, 
		 int button, int action, int modes);

//グローバル変数で,現在のマウスカーソルの位置を保持する変数を用意しておく
double mouseXPosition;
double mouseYPosition;

void keyboard(GLFWwindow* window, 
	      int key, int scancode, int action, int modes){
  //キーボードが押された時に呼ばれる関数とする
  //keyはGLFW_KEY_*と表現される定数タグ,
  //actionは押された時にGLFW_PRESSという定数タグを,それぞれ返す.
  if(key == GLFW_KEY_R && action == GLFW_PRESS){
    glClearColor(1.0, 0.0, 0.0, 0.0);
  }
  else if(key == GLFW_KEY_G && action == GLFW_PRESS){
    glClearColor(0.0, 1.0, 0.0, 0.0);
  }
  else if(key == GLFW_KEY_B && action == GLFW_PRESS){
    glClearColor(0.0, 0.0, 1.0, 0.0);
  }
}

void cursorPosition(GLFWwindow* window, double xPos, double yPos){
  //ウィンドウの中をマウスカーソルが動いた時に呼ばれる関数とする
  //xPosとyPosにマウスカーソルの位置が入っているので,
  //あらかじめ用意した変数に入れて保持しておく
  mouseXPosition = xPos;
  mouseYPosition = yPos;
}

void mouseButton(GLFWwindow* window, int button, int action, int modes){
  //マウスのボタンが押された時と話された時に呼ばれる関数とする
  //前のウィンドウ中のマウスのカーソル位置を検出する関数と組み合わせて使う
  if(button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS){
    //左ボタンが押された時
    double redColor = mouseXPosition / 640.0;
    double greenColor = mouseYPosition / 480.0;
    double blueColor = 1.0;
    glClearColor(redColor, greenColor, blueColor, 0.0);
  }
}

int main(void){
  GLFWwindow* glfwWindow;

  if(!glfwInit()){
    return -1;
  }

  int windowWidth = 640;
  int windowHeight = 480;
  glfwWindow = 
    glfwCreateWindow(windowWidth, windowHeight,
		     "MakeWindowUsingGlfw_2",
		     NULL, NULL);

  if(!glfwWindow){
    glfwTerminate();
    return -1;
  }

  glfwMakeContextCurrent(glfwWindow);

  //キーボードインプットの関数を登録する
  glfwSetKeyCallback(glfwWindow, keyboard);
  //マウスカーソル位置の検出関数を登録する
  glfwSetCursorPosCallback(glfwWindow, cursorPosition);
  //マウスボタン検出関数を登録する
  glfwSetMouseButtonCallback(glfwWindow, mouseButton);

  glClearColor(1.0, 1.0, 1.0, 0.0);
  
  while(!glfwWindowShouldClose(glfwWindow)){
    glClear(GL_COLOR_BUFFER_BIT);
    glfwSwapBuffers(glfwWindow);
    //次の描画やWindowの操作,マウス・キーボードなどのイベントを待つ
    glfwPollEvents();
  }

  glfwTerminate();

  return 0;
}