CDR6275

Michio SHIRAISHI Official Site


OpenGL 4.1とOpenGL ES SL 1.0で学ぶ3次元コンピュータグラフィックス

東邦大学理学部情報科学科 白石路雄
最終更新:

2. 最初のプログラム

 この章では三角形をウィンドウに表示するプログラムを通して、基本的な部分について説明します。

2.1 最初のプログラムを見てみる

 何か絵を描くためにはウィンドウが必要です。ウィンドウを開くだけのプログラムをFirstStartMain.cppにすべて書きました。ウィンドウを開くためのライブラリとして、GLFWを使用しています。ここで使用しているGLFWのメジャーバージョンは3です。2で紹介しているウェブページも多数ありますので注意してください。

 それでは、実行結果とソースコードです。

#include <iostream>

#if defined _WIN32
#include <GL/glew.h>
#pragma comment(lib, "glew32.lib")
#pragma comment(lib, "glfw3dll.lib")
#pragma comment(lib, "opengl32.lib")
#endif

#if defined __APPLE__
#define GLFW_INCLUDE_GLCOREARB
#define GL3_PROTOTYPES
#endif
#include <GLFW/glfw3.h>

// GLFWでエラーとなったときに呼び出される関数
void glfw_error_callback_func(int error, const char* description){
  std::cerr << "GLFW Error: " << description << std::endl;
}

int main(int argc, const char * argv[]){
  // GLFWでエラーとなったときに呼び出される関数の設定
	glfwSetErrorCallback(glfw_error_callback_func);
  
  // GLFWの初期化
  if(!glfwInit()){
    std::cerr << "glfwInit failed." << std::endl;
    return EXIT_FAILURE;
  }
  
  // 使用するOpenGLのバージョン(4.1 Core Profile)の指定
  glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
  glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
  glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
  glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
  
  // ウィンドウとOpenGLコンテキストの作成
  GLFWwindow* window = glfwCreateWindow(640, 640, "FirstStart", NULL, NULL);
  if(!window){
    std::cerr << "glfwCreateWindow failed." << std::endl;
    glfwTerminate();
    return NULL;
  }
  
  // 現在のウィンドウに描くようにカレントコンテキストを設定
  glfwMakeContextCurrent(window);
  
  // GLEWの初期化
#if defined _WIN32
  glewExperimental=GL_TRUE;
  if(glewInit()!=GLEW_OK){
    std::cerr << "glewInit failed." << std::endl;
    return EXIT_FAILURE;
  }
#endif

  // OpenGLのバージョンチェック
  std::cerr << "GL_VERSION: "  <<  glGetString(GL_VERSION) << std::endl;
  std::cerr << "GL_SHADING_LANGUAGE_VERSION: " <<  glGetString(GL_SHADING_LANGUAGE_VERSION) << std::endl;
  std::cerr << "GL_VENDOR: "   <<  glGetString(GL_VENDOR) << std::endl;
  std::cerr << "GL_RENDERER: " <<  glGetString(GL_RENDERER) << std::endl;

  // 背景色の設定
  glClearColor(0.75f, 0.75f, 0.75f, 1.0f);

  // ユーザがウィンドウを閉じるまでループする
  while (!glfwWindowShouldClose(window)){
    // 背景色でウィンドウを塗りつぶす
    glClear(GL_COLOR_BUFFER_BIT);
    // 描画する
    // ...描画する命令
    // バッファの入れ替え
    glfwSwapBuffers(window);
    // イベントの取得
    glfwPollEvents();
  }
  
  // GLFWの終了
  glfwTerminate();
  return EXIT_SUCCESS;
}

 さて、このプログラムを実行すると、次のような結果が得られるはずです。

first-start

 まずは#で始まるプリプロセッサの部分がありますが、「そういうものだ」と思っておきましょう。

 次に、GLFWでエラーが起きたときに呼び出される関数glfw_error_callback_funcを作成しています。

 で、main関数でウィンドウを作ります。

GLFWでのウィンドウの作成

 GLFWでウィンドウを作成するには次の4ステップで行います。

  1. GLFWでエラーが起きたときに呼び出される関数の登録
  2. GLFWの初期化
  3. 使用するOpenGLのバージョンの設定
  4. ウィンドウの作成

 このうち、ウィンドウの作成のステップでは、

  GLFWwindow* window = glfwCreateWindow(640, 640, "FirstStart", NULL, NULL);

というように行います。この引数は、順に

  • ウィンドウの幅
  • ウィンドウの高さ
  • ウィンドウのタイトル
  • フルスクリーンモードにするかどうか (ここではしないのでNULL)
  • リソースを共有するかどうか (ここではしないのでNULL)

 このようにしてウィンドウを作成したら、いま作成したウィンドウに描画するように、glfwMakeContextCurrent(window)としておきます。

GLEWの初期化

 Windowsでのプログラムでは、GLEWというライブラリが必要なので、ここで初期化しておきます。

OpenGLのバージョンのチェック

 この部分は必須ではありませんが、使用する環境を確認するために入れておきました。次のような文字列が出力されればOKです。

背景色の設定

 OpenGLでの描画ですが、次の項目で説明するメインループでフレームごとに毎回描き直します。その際には背景を消去してから描くのが一般的ですが、そのための描画色を設定します。

 そのための関数がglClearColorという関数です。それぞれ、0から1までの値で、赤、緑、青、アルファ(不透明度)の成分を指定します。

メインループ

 メインループでは、ウィンドウがユーザによって閉じられない限り(glfwWindowShouldClose関数で調べています)、以下の動作を繰り返します。

  1. 背景を消去する
  2. 描画する
  3. バッファを入れ替える
  4. イベントを取得する

 まず、描画するために背景を消去します。この際には、先ほどglClearColorで指定した色が使用されます。

 次に、描画します。ここでは何も描画していません。

 アニメーションをちらつきなく描くための仕組みとしてダブルバッファというものがあります。絵を保存する領域として、画面に表示しているバッファ(フロントバッファ)と描画するためのバッファ(バックバッファ)の2つを用意します。絵を描くためには一定の時間がかかるので、直接フロントバッファに描いてしまうと描画の過程が表示されてしまうので、バックバッファに描いておき、描画が終わった段階で、2つのバッファを入れ替える、ということを行います。

 次に、イベントを取得します。ここでのイベントはバレンタインデーなどのイベントという意味ではなく、ユーザがマウスボタンをクリックしたり、キーボードをタイプしたり、という動作のことを指しています。インタラクティブなアプリケーションでは、これらをもとに次に描画するための準備をします。

やってみよう

  1. 背景の色のグレーをもっと明るくするにはどのようにしたらいいですか?
  2. ウィンドウの大きさを変えてみましょう。