補助ライブラリでサクッとOpenGL(GLFW,GLEW)
OpenGLはプラットフォーム独立のライブラリだが、ウィンドウ管理などの面倒は見てくれない。
また、シェーダーを使うのには拡張機能を有効化する必要がある。
ウィンドウ管理や拡張機能の取得はプラットフォームごとに違うので、生のGLを扱うとそれなりに労力がかかる。
そこで、補助ライブラリを使ってサクッとこの問題を解決する。
1.入力・ウィンドウ管理:GLFW
GLFWはOpenGLの補助ライブラリで、
- ウィンドウ管理や入力デバイスの制御を担当
- 出来る限りシンプルな機能構成(Teapotや文字出力なし)
- 2017年8月現在もメンテナンスが続いている
といった特徴がある。
導入
linuxならaptで入れる。
sudo apt -y install libglfw3-dev
Windowsならバイナリを直接入手できるらしい。 VSならNuGetもアリ。
2.拡張機能管理:GLEW
GLEWはGLFWと名前が似ていて紛らわしいが、
という感じである。
ちなみにOpenGLの拡張機能取得はそれ自体が結構面倒なので、それを簡略化してくれるGLEWはマルチプラットフォームを視野に入れていなくても十分有用である。
導入
こいつもaptで可。
sudo apt -y install libglew-dev
Windowsの場合はGLFWと同様バイナリを取ってくる。 やはりこいつもNuGetパッケージがある。
とりあえず初期化だけやってみる
C++で書くとこんな感じか。
#include <iostream> #include <string> #include <GL/glew.h> #include <GLFW/glfw3.h> class LogManager { public: LogManager(){}; //Info out void LOGI(std::string msg) { std::cout << msg << std::endl; } //Error out void LOGE(std::string msg) { std::cerr << msg << std::endl; } }; class App { public: App(LogManager *log) : m_log(log) {}; bool run() { if(!init()) return false; while(glfwWindowShouldClose(m_win) == GL_FALSE) { glClear(GL_COLOR_BUFFER_BIT); glfwSwapBuffers(m_win); glfwWaitEvents(); } terminate(); return true; }; private: LogManager *m_log; GLFWwindow *m_win; bool init() { if(!init_glfw()) { m_log->LOGE("Failed to initialize GLFW."); terminate(); return false; } m_log->LOGI("GLFW Initialized."); if(!init_window(640, 480, "SAMPLE")) { m_log->LOGE("Failed to initialize window."); terminate(); return false; } m_log->LOGI("Window Initialized."); //必ずGLEW初期化より前 glfwMakeContextCurrent(m_win); if(!init_glew()) { m_log->LOGE("Failed to initialize GLEW."); terminate(); return false; } m_log->LOGI("GLEW Initialized."); glClearColor(1.0f, 1.0f, 1.0f, 0.0f); return true; } void terminate() { glfwTerminate(); } bool init_glfw(void) { if(glfwInit() == GL_FALSE) return false; return true; } bool init_window(int width, int height, std::string title) { glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); m_win = glfwCreateWindow(width, height, title.c_str(), NULL, NULL); if(m_win == nullptr) return false; return true; } bool init_glew(void) { GLenum err; err = glewInit(); if(err != GLEW_OK) { m_log->LOGE( "GLEW Error :" + std::string((char*)glewGetErrorString(err)) ); return false; } return true; } }; static LogManager s_logman; int main(void) { App app(&s_logman); return app.run() ? 0 : -1; }
初期化の順としては
- GLFW初期化
- GLFWでウィンドウ初期化
- GLFWでコンテキスト有効化(glfwMakeContextCurrent)
- GLEW初期化
となる。
特に、GLEWの初期化にはコンテキストが有効である必要があるので注意する。
以降は、App.run()のようにループを組み、自由にOpenGLを利用する。
追記:コンパイルオプション
ライブラリ名の指定が迷いそうになるが、
$(LDFLAGS) = -lglfw -lGLEW -lGL
でOK。