I. OpenGLとは
まず、OpenGLとは何なのかを理解しましょう。Application Programming Interface一般的には、グラフィックスやイメージを操作するための一連の関数を含むAPI(アプリケーション・プログラミング・インターフェース)と考えられています。しかし、OpenGL自体はAPIではなく、組織によって開発され、維持されている単なる仕様です。
OpenGLの仕様では、各関数がどのように実行され、どのような出力値を持つべきかを厳密に定義しています。各関数を内部でどのように実装するかは、OpenGLライブラリの開発者が決定します。OpenGL仕様は実装の詳細を規定していないため、特定のOpenGLライブラリは、その機能と結果が仕様に一致する限り、異なる実装を使用することが許されています。
実際のOpenGLライブラリの開発者は、通常グラフィックカードのメーカーです。あなたが購入したグラフィックカードでサポートされているOpenGLのバージョンは、そのシリーズのカード専用に開発されています。Appleのシステムを使う場合、OpenGLライブラリはApple自身が保守しています。Linuxでは、グラフィックカードメーカーが提供するOpenGLライブラリがあり、また、一部のマニアが適合させたバージョンもあります。これはまた、OpenGLライブラリが仕様と矛盾した動作をするときはいつでも、基本的にライブラリの開発者が残したバグであることを意味します。
OpenGLのほとんどの実装はグラフィックカードメーカーによって書かれているため、バグが発生した場合、通常はグラフィックカードのドライバを更新することで解決できます。これらのドライバには、グラフィックスカードがサポートするOpenGLの最新バージョンが含まれています。そのため、グラフィックスカードのドライバを時々更新することを常にお勧めします。
OpenGL関連用語分析
OpenGL
- OpenGLの状態は、しばしばOpenGLコンテキストと呼ばれます。OpenGLの状態は通常、次の経路で変更されます:オプションの設定、バッファの操作、そして最後に、現在のOpenGLコンテキストをレンダリングに使用します。最後に、現在のOpenGLコンテキストがレンダリングに使用されます。
- OpenGL命令がアプリケーションによって呼び出される前に、OpenGLコンテキストファイルが作成されなければなりません。このコンテキストは、OpenGLの様々な状態を保持し、OpenGL命令の実行の基礎となる非常に大きなステートマシンです。
- OpenGLライブラリはCで書かれており、複数の言語派生もサポートしていますが、そのカーネルは依然としてCライブラリです。C言語の言語構造のいくつかは、他の高級言語には簡単に翻訳できないため、OpenGLはいくつかの抽象化レイヤーを使って開発されました。そのひとつが「オブジェクト」です。
- OpenGLのオブジェクトは、OpenGLの状態のサブセットを表すオプションの集まりです。例えば、オブジェクトは描画ウィンドウの設定を表すのに使われ、サイズやサポートする色のビット数などを設定することができます。オブジェクトはCスタイルの構造体と考えることができます:
struct object_name {
 float option1;
 int option2;
 char[] name;
};
- コンテキストの切り替えはオーバーヘッドになる可能性がありますが、異なる描画モジュールは完全に独立した状態管理を使用する必要があるかもしれません。したがって、アプリケーション内に複数の異なるコンテキストを作成し、異なるスレッドで異なるコンテキストを使用し、コンテキスト間でテクスチャ、バッファ、およびその他のリソースを共有することが可能です。これは、コンテキストの切り替えを繰り返したり、レンダリングステートを大きく変更したりするよりも、はるかに論理的で効率的なソリューションです。
OpenGL
- ステートマシンとは、定義上、状態を含むマシンのことです。ステートマシンには、オブジェクトがライフサイクル中に経験する状態、状態間の遷移、遷移の原因と条件、遷移中に実行されるアクティビティが記述されます。言い換えると、ステートマシンは、オブジェクトがライフサイクル中のイベントに応答して経験する状態のシーケンスと、それらの状態イベントに対する応答を記述する振る舞いです。そのため、次のような特徴があります。 - 現在の状態を記憶するメモリー機能があります。
- 入力を受け取り、入力と自分の元の状態に基づいて自分の現在の状態を修正し、それに対応する出力を持つことが可能です。
- 特別な状態になると、チェンジは入力を受け付けなくなり、動作しなくなります。
 
- OpenGLのステートマシンは、OpenGLでは次のように理解されます。 - OpenGLは自身の状態を記録することができます。
- OpenGLは入力を受け取ることができます。例えば、glColor3fが呼ばれた場合、OpenGLはこの入力を受け取った後、「現在の色」の状態を変更します。
- OpenGLは停止状態になり、入力を受け取らなくなることがあります。OpenGLは常に、プログラムが終了する前に動作を停止します。
 
レンダリング
- グラフィック/イメージデータを3D空間イメージに変換することをレンダリングと呼びます。簡単に言うと、表示するグラフィック/イメージデータを、画面に表示するコンテンツに変換することです。
頂点配列と頂点バッファ
現代の建物は、基本的に骨組みのある構造になっています。 家を建てるときには、まず大枠を作り、その中に設計図面に従って、対応する位置にさまざまな材料を詰めていきます。OPenGLの表示イメージも同様に、まず骨組みを作り、それを埋めていきます。現実とは異なり、OpenGLのイメージはタプルで構成されます。OpenGLESでは点、線、三角形の3種類のタプルがあります。この3種類のタプルの固定点の位置さえ分かれば、イメージの正確な位置が分かるわけです。では、この頂点データは最終的にどこに格納されるのでしょうか?
- 図形を描くとき、図形の必要な要素の位置を形成する点を頂点と呼びます。
- 開発者は、drawメソッドが呼ばれたときに、頂点データがメモリから直接渡されるように関数ポインタを設定することができます。つまり、データのこの部分はメモリに格納され、このデータは頂点配列と呼ばれます。
- より高性能な方法としては、ビデオメモリのブロックをあらかじめ割り当て、そこに頂点データをあらかじめ格納しておく方法があります。メモリのこの部分は頂点バッファと呼ばれます。
パイプライン
自動車の生産ラインは、合金フレームから段階的に自動車を組み立て、走行可能な自動車にするプロセスです。パイプラインはOpenGLでも同様で、イメージをレンダリングするプロセスです。パイプラインは抽象的な概念で、グラフィックカードが決まった順序でデータを処理し、その順序に厳密に従うことからそう呼ばれています。ちょうどパイプの端から端まで水が流れるように、この順序を破ることはできません。また、パイプラインは固定パイプラインとプログラマブルパイプラインに分けられます:
- 固定パイプライン、別名ストアドシェーダー:固定パイプラインを使用する場合、OpenGLは頂点レンダリングとピクセルレンダリングのための独自のロジックを定義する必要がなく、また定義することもできません。 内部で完全なレンダリングプロセスが固まっており、開発者はレンダリングに必要なパラメータを入力し、CPUコード側で特定のスイッチを指定するだけで、さまざまなレンダリングのレンダリングが完了します。 
- プログラム可能なパイプライン: OpenGLのプログラム可能なパイプラインは、開発者が実装しなければ最終的なイメージが描画されません。開発者は、レンダリングパイプラインのロジックを単純化してレンダリング効率を向上させるために、頂点とピクセルのレンダリング用に独自の特定のロジックを記述したり、固定パイプラインではレンダリングできないエフェクトをレンダリングするために、独自の特定のアルゴリズムとロジックを実装することができます。 
固定パイプラインとプログラマブルパイプラインの違いは、固定パイプラインはOpenGLによってカプセル化されており、パラメータを使って直接呼び出すことができることです。プログラム可能なパイプラインは、開発者がレンダリングを完全にカスタマイズする必要があります。OpenGLES 3.0までは、最も基本的な2つのシェーダであるバーテックスシェーダとスライスシェーダのみがサポートされています。
シェーダープログラム
**シェーダー** は GPU 上で動作するアプレットです。これらの小さなプログラ ムは、グラフィックスレンダリングパイプラインの特定の部分で実行されます。基本的な意味で、シェーダは入力を出力に変換するプログラムです。シェーダ同士は通信できないため、シェーダは非常にスタンドアロン なプログラムでもあります。これにより、グラフィックスレンダリングパイプラインの特定の部分をよりきめ細かく制御することができ、また GPU 上で実行されるため、貴重な CPU 時間を節約することができます。
- GLSL:シェーダー言語、GLSLはC言語のクラスです。GLSLはグラフィカル・コンピューティング用に調整されており、ベクトルや行列演算のための便利な機能をいくつか含んでいます。シェーダは常にバージョン宣言から始まり、入出力変数、ユニフォーム、メイン関数が続きます。すべてのシェーダのエントリーポイントはメイン関数で、ここですべての入力変数が処理され、結果が出力変数に出力されます。典型的なシェーダは次のような構造をしています:
#version version_number
in type in_variable_name;
in type in_variable_name;
out type out_variable_name;
uniform type uniform_name;
int main()
{
 // 入力を処理し、いくつかのグラフィックス操作を実行する
 ...
 // 処理結果を出力変数に出力する
 out_variable_name = weird_stuff_we_processed;
}
OpenGL Colour Separation Language(GLSL)は、OpenGLで色をプログラムするために使用される言語、つまり開発者によって書かれた短いカスタムプログラムです。GLSLはグラフィックカードのGPU上で実行され、レンダリングパイプラインの固定部分を置き換え、レンダリングパイプラインの異なるレベルをプログラム可能にします。GLSLのシェーダーコードは、VertexShader(頂点シェーダー)とFragmentShader(フラグメントシェーダー)の2つの部分に分かれています。
- 一般的なシェーダには、バーテックス・シェーダ、フラグメント・シェーダ/ピクセル・シェーダ、ジオメトリ・シェーダ、サーフェス・サブディビジョン・シェーダがあります。フラグメントシェーダとピクセルシェーダは、OpenGLとDXでは単に異なる名前で呼ばれています。
- OpenGL は他のコンパイラと同じようにシェーダを扱います。コンパイルとリンクのステップを経て、頂点シェーダとスライ スシェーダのロジックを含むシェーダプログラムが生成されます。OpenGLで描画するとき、頂点シェーダはまず、入力された頂点データに対して演算を行います。頂点はタプルアセンブリーによってタプルに変換されます。次にラスタライズが実行され、ベクトルグラフィックスであるタプルがラスタライズされたデータに変換されます。最後に、ラスタライズされたデータは、計算のためにピースワイズシェーダに渡されます。ピースワイズシェーダは、ラスタライズされたデータの各ピクセルに対して演算を実行し、ピクセルの色を決定します。
).頂点シェーダー
- 一般に、グラフの各頂点の回転/平行移動/射影などの変換を処理するために使用されます。
- 頂点シェーダとは、OpenGLで使用される、頂点のプロパティを計算するためのプログラムです。 頂点シェーダは頂点ごとの演算であり、頂点シェーダは各頂点データに対して1回だけ並列に実行され、頂点シェーダ演算中に他の頂点データにアクセスすることはできません。
- 計算される典型的な頂点プロパティには、頂点座標変換、頂点ごとのイルミネーション演算などがあります。ここで行われるのは、頂点座標を独自の座標系から正規化座標系に変換することです。
).ソースシェーダー
- 通常、ピクセル単位の色計算とグラフィックスの塗りつぶしを処理するために使用されます。
- ピースシェーダは、OpenGL のプログラムで、ピースの色を計算します。チップシェーダはピクセル単位の手続きで、つまり、チップシェーダは1ピクセルに1回、並列に実行されます。
Rasterization
- ラスタライズとは、頂点データをピース単位のデータに変換する処理で、グラフを個々のラスタで構成されるイメージに変換する効果があり、ラスタの各要素はフレームバッファ内のピクセルに対応します。
- ラスタライゼーションとは、いくつかの要素を2次元のイメージにすることです。このプロセスは2つの部分から成ります。最初の部分:ウィンドウ座標のどの整数ラスター領域が基本タプルで占められているかを決定する作業、2番目の部分:領域に色値と深度値を割り当てる作業。ラスタライズ処理により、スライス要素が生成されます。
- オブジェクトの数学的記述とオブジェクトに関連する色情報を、画面上の位置に対応するピクセルと、ピクセルを塗りつぶすために使用される色に変換するプロセスは、アナログ信号を離散信号に変換するプロセスであるラスタライズとして知られています。
テクスチャ
前のセクションですでに学んだように、各頂点に色を追加してグラフのディテールを増やし、面白いイメージを作成することができます。しかし、グラフをよりリアルに見せたいのであれば、十分な頂点を用意し、十分な色を指定する必要があります。これは、各モデルがより多くの頂点を要求し、各頂点が順番に色属性を要求するため、多くの余分なオーバーヘッドが発生します。
アーティストやプログラマーはテクスチャを好んで使います。テクスチャは、オブジェクトにディテールを追加するために使用できる2Dイメージです。テクスチャは、レンガが描かれた紙のようなもので、シームレスに折りたたまれて3Dの家にはめ込まれ、家の外壁がレンガ壁のように見えると想像してください。1つのイメージに多くのディテールを挿入できるため、頂点を追加指定しなくても、オブジェクトを非常に詳細にすることができます。下の写真のように、レンガが描かれた紙が三角形に貼り付けられています。
ハイブリッド
テストフェーズの後、ピクセルが削除されない場合、ピクセルの色はフレームバッファにアタッチされた色とブレンドされ、ブレンドアルゴリズムはOpenGL関数で指定できます。ブレンディングアルゴリズムはOpenGL関数で指定できますが、OpenGLが提供するブレンディングアルゴリズムには限界があり、より複雑なブレンディングアルゴリズムが必要な場合は、ネイティブのブレンディングアルゴリズムより性能は多少落ちますが、通常はピクセルティントを使用して実行できます。
オブジェクトの透明度には、完全な透明度と部分的な透明度の2種類があります。 完全な透明度では色を完全に透過させることができ、部分的な透明度では色を透過させると同時にそれ自身の色を表示させることができます。(glEnable(GL_BLEND))異なる透明度をレンダリングするには、ブレンドを有効にする必要があります。これは単純に、2つの異なる色のイメージが重なり合うように配置された場合、新しい色を表示するためにブレンドが適用されることを意味します。
変換行列
オブジェクトを作成し、色を塗り、テクスチャを追加し、ディテールを与える方法がわかったところで、それらはすべて静的なオブジェクトのままなので、まだ十分に面白くありません。オブジェクトの頂点を変え、フレームごとにバッファを再構成することで、オブジェクトを動かそうとすることは可能ですが、これはあまりにも面倒で、多くの処理時間を消費します。そこで、行列オブジェクトを使ってオブジェクトを変換する、よりよい解決策があります。これらの行列は順列行列と呼ばれます。##投影行列
- OpenGLでは投影が重要な役割を果たします。 テレビ、携帯電話、コンピュータなどの一般的な表示デバイスはすべて2次元ですが、表示されるコンテンツは多くの場合3次元です。投影は3次元座標を2次元のスクリーン座標に変換するために使われ、実際の線は2次元座標で描かれます。ここでも行列が使われ、投影証明とも呼ばれます。
- 投影は正射投影と透視投影に分けられ、投影方法の違いによって結果が大きく異なります。下の図。
レンダリング
- レンダーバッファは通常、ウィンドウなどのシステムリソースにマッピングされます。イメージがウィンドウの対応するレンダーバッファに直接レンダリングされると、イメージを画面に表示することができます。最も単純なケースでは、フレームバッファは1つしかなく、フレームバッファの読み込みと更新には大きな効率上の問題があります。
- この問題を解決するために、通常のOpenGLプログラムでは少なくとも2つのバッファを持つ、ダブルバッファ機構を採用しています。画面に表示される方がオンスクリーンバッファになり、表示されない方がオフスクリーンバッファになります。この場合、GPUはビデオコントローラが読み込むために1つのバッファにフレームをプリレンダリングし、次のフレームがレンダリングされるとき、GPUはビデオコントローラのポインタを直接2番目のバッファに向けます。これは大きな効率向上です。
- ダブルバッファリングは効率の問題を解決する一方で、新たな問題を引き起こします。ビデオコントローラがまだ読み取りを終了していない場合、つまり、画面のコンテンツがちょうど時間の半分を表示されている、GPUは、フレームバッファに提出されたコンテンツの新しいフレームになり、2つのバッファが交換され、ビデオコントローラは、画面の後半を表示するには、画面上のデータの新しいフレームになり、その結果、画面のティアリング現象は、次の図:
この問題を解決するために、GPUは通常、垂直同期と呼ばれるメカニズムを備えています。 垂直同期がオンになっている場合、GPUは新しいフレームのレンダリングとバッファの更新を実行する前に、ディスプレイのVSync信号が送信されるのを待ちます。これにより、画面のティアリング現象が解決され、画面の滑らかさが増しますが、より多くのコンピューティングリソースを消費する必要があり、いくらかの待ち時間も生じます。





