すりごまの鯖缶?ブログ 2缶目

鯖管のことだったりプログラミングのことだったりマイクラのことだったり

OpenGL始めました

OpenGLの勉強始めました。
とりあえず3Dよりも2Dで描画とかできないと死ぬので今回は2Dで箱表示です。


開発環境は

  • MacBookPro(Early 2015)
  • GLFW 3.2 (gitから持ってきた)
  • GLEW 1.13.0(brewで入れた)
  • OpenGL 2.1(を呼び出してる)

Header Search PathsとLibrary Search Pathsを設定して、Link Binary With Librariesに

  • OpenGL.framework
  • Cocoa.framework
  • IOKit.framework
  • CoreVideo.framework
  • CoreFoundation.framework
  • Carbon.framework
  • libglfw3.a
  • libGLEW.a

を追加。
んで、いろんな関係でC++ Language DialectをC++14に設定。

ベースにここ( WindowsかMac OS XでOpenGL事始め | shobomalog )のコードを使わせてもらいました。

以下ソースコードです。ご査証のほどよろしくお願いします。

//静的ライブラリにする場合に使うdefine
#define GLEW_STATIC

#include <stdio.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include "hsv_color.h"
using namespace arch;

//エラー用のコールバック
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);
    }
}

//初期化
static void init()
{
    //ステンシルバッファを無効化
    glDisable(GL_STENCIL_TEST);
    //デプスバッファを有効にする
    glEnable(GL_DEPTH_TEST);
    //カリング(片面描画)を有効にする
    glEnable(GL_CULL_FACE);
    //GL_BACK(BACKなのに表面)だけを描画する
    //→カリング対象になるから裏面を消すという意味らしい
    glCullFace(GL_BACK);
}
hsv_color hsv = hsv_color(0.0, 1.0, 1.0);


//描画処理
static void paint()
{
    //glClearで消す色を黒(#000000)にする(GL_COLOR_BUFFERのみ有効)
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    
    //デプスバッファを綺麗にする値を設定する
    glClearDepth(1.0f);
    
    //ステンシルバッファの初期化値を設定するけど使わないしコメントアウト
    //glClearStencil(0);
    
    //指定した対象を塗りつぶす
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT/* | GL_STENCIL_BUFFER_BIT*/);
    
    
    
    //クエリを実行する(時間計測)
    //GLEWを更新するために行っている模様
    glBeginQuery(GL_TIME_ELAPSED, 1);
    
    //hsv_colorとvector4<>はTerryBoyが作ったやつ
    hsv.h = std::fmod(hsv.h + 10.0, 360.0f);
    vector4<float> rgb = hsv.to_vector4<float>();
    
    //描画を開始する(三角形を連続設定)
    glBegin(GL_TRIANGLE_STRIP);
        //描画する色を設定
        glColor4f(rgb.r, rgb.g, rgb.b, rgb.a);
        //ポリゴンの頂点を設定する
        //設定順序は( http://d.hatena.ne.jp/nakamura001/20081231/1230719279 )を参照
        glVertex2f(-0.5f, 0.5f);
        glVertex2f(-0.5f, -0.5f);
        glVertex2f(0.5f, 0.5f);
        glVertex2f(0.5f, -0.5f);
    glEnd();
    glEndQuery(GL_TIME_ELAPSED);
}

int main(int argc, char* argv[])
{
    //エラー用のコールバックを設定
    glfwSetErrorCallback(error_callback);
    if (!glfwInit())
    {
        return -1;
    }
    // Windowのオプションを設定してる
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
    glfwWindowHint(GLFW_RED_BITS, 8);
    glfwWindowHint(GLFW_GREEN_BITS, 8);
    glfwWindowHint(GLFW_BLUE_BITS, 8);
    glfwWindowHint(GLFW_ALPHA_BITS, 8);
    glfwWindowHint(GLFW_DEPTH_BITS, 24);
    glfwWindowHint(GLFW_STENCIL_BITS, 0);
    //glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    //glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE);
    glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE);
    
    // 第4引数にglfwGetPrimaryMonitor()を入れるとフルスクリーンになる
    GLFWwindow* window = glfwCreateWindow(1280, 720, "GL Sample", NULL, NULL);
    
    //windowが初期化できないと終わる
    if (!window)
    {
        glfwTerminate();
        return -1;
    }
    
    //描画対象をwindowに設定
    glfwMakeContextCurrent(window);
    //Key入力用コールバックを設定
    glfwSetKeyCallback(window, key_callback);
    //垂直同期させる。0にすると垂直同期しなくなる。
    glfwSwapInterval(1);
    //glewも初期化
    auto glewErr = glewInit();
    if (glewErr != GLEW_OK)
    {
        //glewがミスったら標準出力でエラーを吐く
        puts((const char*)glewGetErrorString(glewErr));
        return 1;
    }
    
    init();
    
    //ウィンドウが閉じるまでループ
    while (!glfwWindowShouldClose(window))
    {
        paint();
        //バッファをバックと入れ替える
        glfwSwapBuffers(window);
        //各種コールバックを呼び出す
        //呼ばないとWindowの更新すら止まる
        glfwPollEvents();
    }
    //Windowを破棄する
    glfwDestroyWindow(window);
    glfwTerminate();
    return 0;
}