2019/10/16 参考 : http://marina.sys.wakayama-u.ac.jp/~tokoi/GLFWdraft.pdf ## OpenGLとは OpenGL APIは様々なグラフィックスハードウェアを抽象化し、制御するための基本的な機能のみをもつ。3DCGを描画するにはCGの理論の知識も必要である。 OpenGLはIRIX(UNIX系OS)を搭載したEWSのグラフィックス表示に用いられていたIRIS GLを様々なプラットフォームで動作するよう再実装され、オープンソース化されたものである。 最初シリコングラフィックス社により開発され、現在はクロノス(Khronos Groups)によって規格が策定されている。 他のグラフィックスライブラリ APIには、 * Microsoft社が開発しているXbox・Windows向けのDirect X * Apple社が開発しているiPhone・iPad・macOSむけのMetal が存在する。 これらは各社が各社のデバイス向けに開発しているものであり、Windows・Linuxの両方で動作するものとしてはOpenGL、その後継のVulkanしか存在しない。 なおApple社の製品は、以前はOpenGLに対応していたが、今年のアップデートで非対応とし、Metalへの移行を強制化した。 そして、組み込み機器向けのOpenGLとして OpenGL ESが存在し、Xilinx Zynq UltraScaleが搭載するARM GPUが対応しているものはOpenGL ESのみである。 そのため、今回はOpenGL ESを用いたプログラム開発を行う。 ## GLFWとは OpenGLそのものはマルチプラットフォームにだが、ウインドウ生成などプラットフォーム依存の部分はそれぞれに応じてコードが必要になる。 このプラットフォームごとの差異を吸収するツールキットとして、GLFWがある。 ツールキットは他にもGLUT、Qtなどが存在するが、GLUTはメンテナンスが滞っており、Qtは高機能すぎるため、今回研究で行いたいことが十分達成できそうな小さなツールキットとしてGLFWを採用する。 なお、ライセンスはzlib/libpng licenseである。 ## GLEWとは GLEW (the OpenGL Extension Wrangler Library) を用いることで、OpenGLのVersionを指定できるようになる。 Windows環境ではデフォルトのOpenGL Versionが1.1となっており、ハードウェアがそれ以上のバージョンに対応していたとしても、1.1で動作してしまう。 OpenGL環境でOpenGL ESを動かすにはOpenGL 4.1が必要である。 GLEWを用いて、PC上でもOpenGL ES環境を有効化し、開発を行う。 ## プログラミング ### データ型 | OpenGLのデータ型 | 最小ビット数 | 説明 | | -------- | -------- | -------- | | GLboolean | 1 | bool型 | | GLbyte | 8 | 1byteの符号付き二進整数(二の補数表現)| | GLubyte | 8 | 1byteの符号なし二進整数 | | GLchar | 8 | char型 | | GLshort | 16 | short int型 | | GLushort | 16 | unsigned short int型 | | GLint | 32 | int型 | | GLuint | 32 | unsigned int型 | | GLint64 | 64 | long int型 | | GLuint64 | 64 | unsigned long int型 | | GLsizei | 32 | 非負の二進整数で表したサイズ | | GLenum | 32 | 二進整数で表した列挙子 | | GLintptr | | int * (ポインタ) | | GLsizeiptr| | GLsizeiのポインタ | | GLsync | | 同期オブジェクトのハンドル | | GLbitfield| 32 | ビットフィールド | | GLhalf | 16 | 符号なしの値に符号化された半精度浮動小数点数(CPU側には存在しない) | | GLfloat | 32 | float型 | | GLdouble | 64 | double型 | ### ウインドウの生成 GLFWを使ってウインドウを生成する際には、 1. glfwInit() : GLFWの初期化 2. glfwCreateWindow() : ウインドウの生成 3. glfwMakeContextCurrent(window) : OpenGLの処理対象のウインドウを指定 4. glClearColor(Red,Green,Blue,Alpha) : ウインドウの塗りつぶし 5. glfwWindowShouldClose() : ウインドウが開いている間の繰り返し描画 6. glfwSwapBuffers() : ダブルバッファリングのバッファ入れ替え 7. glfwTerminate() : ウインドウを閉じた際の終了処理 の順で処理を行う。 #### 1. GLFWの初期化 main関数内に ``` if (glfwInit() == GL_FALSE) { std::cerr << "Can't initilize GLFW" << std::endl; return 1; } ``` と記述することでGLFWの初期化が行える。 #### 2. ウインドウの生成 , 3. OpenGLの処理対象のウインドウを指定 , 4. ウインドウの塗りつぶし ``` // ウィンドウを作成する GLFWwindow* const window = glfwCreateWindow(640, 480, "SAMPLE", NULL, NULL); if (window == NULL) { std::cerr << "Can't create GLFW window." << std::endl; glfwTerminate(); return 1; } // 作成したウィンドウを OpenGL の処理対象にする glfwMakeContextCurrent(window); // 背景色を指定する glClearColor(1.0f, 1.0f, 1.0f, 0.0f); ``` とすることで、640x480のSAMPLEというタイトルのウインドウが生成され、OpenGLの処理対象となり白(R:1,G:1,B:1,Alpha:0)で塗りつぶされる。 ### シェーダープログラム GLSLのシェーダープログラムの流れは、 1. glCreateProgram() : プログラムオブジェクト作成 2. glCreateShader() : バーテックス(頂点)シェーダーとフラグメントシェーダーのシェーダーオブジェクトを作成 3. glShaderSource() : シェーダーオブジェクトにソースプログラムを読み込む 4. glCompileShader() : ソースプログラムをコンパイル 5. glAttachShader() : プログラムオブジェクトにシェーダーオブジェクトを組み込み 6. glLinkProgram() : プログラムオブジェクトをリンク #### バーテックスシェーダー バーテックスシェーダーの`in` 変数にはCPUから送られた図形データの一つの頂点データが格納される。この頂点データを **頂点属性(attribute)** といい、このin変数を特に **attribute 変数** という。 シェーダープログラムは引数、返り値をもたない `void main()` 関数から実行される。 頂点属性(attribute)はCPUからGPUの **頂点バッファオブジェクト** メモリに格納される。その後CPUから描画命令(ドローコール)を送ると、GPUは頂点バッファオブジェクトから頂点属性(attribute)を取り出しattribute変数に格納し、バーテックスシェーダー処理を行う。 `gl_Position` はGLSLの組み込み変数で、この値がレンダリングパイプラインの次のステージに送られる。 #### フラグメントシェーダー out 変数に代入したデータはレンダリングパイプラインの次のステージに送られる。 フラグメントシェーダーのout変数はフレームバッファのカラーバッファに格納される。 もしフレームバッファに値を格納しない (画素を描かない) なら、フラグメントシェーダで discard 命令を実行します。 ####