OpenGLプログラミング/モダンOpenGL チュートリアル 02
さて、理解のための動作例はできたので、新しい機能やさらなる堅牢性の追加にとりかかれます。
以前のシェーダーは、できるだけ簡単になるように意図的に最小限にしていましたが、実世界の例ではもっと付属コードを使用します。
シェーダのロード

最初に追加するものは、シェーダをロードするためのより便利な方法です:外部ファイルのロードがとても簡単になるはずです(Cの文字列としてコードにコピーペーストするよりも)。 それに加えて、こうすることでCコードを再コンパイルせずにGLSLコードを変更できるようになります!
シェーダのロード

まず、ファイルを文字列としてロードする関数が必要になります。 基本的なC言語のコードで、ファイルのサイズに割り当てられたバッファの中にファイルの内容を読み取ります。
シェーダのロード

現時点でシェーダにエラーがある場合、プログラムは何のエラーかを特に説明することなく、ただ停止します。 infologを使用することで、OpenGLからより多くの情報を得ることができます:
シェーダのロード

GLES2関数だけを使用する場合、アプリケーションはデスクトップとモバイルデバイスの両方にほぼ移植可能です。 対処する問題がまだひと組あります:
シェーダのロード

The #version needs to be the very first line in some GLSL compilers (for instance on the PowerVR SGX540), so we cannot use #ifdef directives to abstract it in the GLSL shader. Instead, we'll prepend the version in the C++ code:
シェーダのロード

私たちはすべてのチュートリアルで同じバージョンのGLSLを使用するため、これが最も簡単な解決策です。
シェーダのロード

#ifdef と精度のヒントは、次のセクションで説明します。
シェーダのロード

これらの新しいユーティリティ関数と知識を使って、シェーダのロードとデバッグのための別の関数を作ることができます:
シェーダのロード

これでもうシェーダーをシンプルに使用してコンパイルできます:
シェーダのロード

同様にリンクエラーも表示します:
シェーダのロード

これらの新しい関数を、 shader_utils.cppに配置します。
シェーダのロード

これらの関数の記述を可能な限り少なくしようとしている点にお気づきでしょうか: OpenGL Wikibookの目標は、OpenGLがどのように動作するかを理解することであって、開発しているツールキットの使用方法を理解することではありません。
シェーダのロード

shader_utils.hヘッダファイルを作成しましょう:
シェーダのロード

triangle.cpp内の新しいファイルを参照 :
シェーダのロード

そして Makefileの中で :
シェーダのロード

頂点バッファオブジェクト(VBO)を使用して、グラフィックカードに頂点を直接格納することは、良い習慣です。
シェーダのロード

そのうえ、 "client-side arrays"のサポートはOpenGL 3.0以降は公式に削除され、WebGLには存在せず、そして低速なので、少し単純さには欠けても、今のうちからVBOを使用してみましょう。 たまたま出くわした既存のOpenGLコードで使用されていたりするかもしれないですから、両方の方法について知っておくことが重要です。
シェーダのロード

2つのステップでこれを実装します:
シェーダのロード

グローバル変数を作成 (#includeの下) してVBOハンドルを格納する:
シェーダのロード

init_resourcesで、 triangle_verticesを定義しているところに移動して、ひとつ(1)のデータバッファを作成し、それを現在のアクティブなバッファにします:
シェーダのロード

さて、このバッファに頂点をプッシュすることができます。 データの編成方法や使用される頻度を指定します。 GL_STATIC_DRAW は、このバッファにはあまり頻繁に書き込みはせず、そしてGPUが自身のメモリ内にコピーを保持する必要があるということを示しています。 VBOに新しい値を書き込むことは常に可能です。フレームあたりに1度かそれ以上頻繁にデータを変更する場合は、GL_DYNAMIC_DRAWまたはGL_STREAM_DRAWを使用することができます。
シェーダのロード

どんな時でも、アクティブなバッファの設定解除を、このように行えます:
シェーダのロード

とりわけ、C言語の配列を常に直接渡す必要がある場合は、アクティブバッファを無効にしていることを確認してください。
シェーダのロード

onDisplayで、コードを少し適合させます。 glBindBufferを呼び出して、 glVertexAttribPointerの最後の2つのパラメータを変更します :
シェーダのロード

終了時のクリーンアップを忘れずにやっておきましょう:
シェーダのロード

今はもう、シーンを描画するたびに、OpenGLがすべての頂点をGPU側で既に持っていることになります。 数千ポリゴンもの大きなシーンの場合、これは莫大なスピードアップになりえます。
シェーダのロード

一部のユーザーが持っているグラフィックカードは、OpenGL 2をサポートしていない可能性があります。 これはおそらくプログラムをクラッシュさせたり、不完全なシーンを表示したり、といったことにつながります。 GLEWを使用してこれを確認することができます(glewInit()の呼び出しが成功した後に):
シェーダのロード

注意点として、一部のチュートリアルは2.0付近のカードでしか動作しないこともあり、たとえばIntel 945GMが公式でサポートしているOpenGL 1.4以外はシェーダのサポートが限定的です。
シェーダのロード

他のOpenGLのコードの中で、次のようなヘッダーに出会うかもしれません:
シェーダのロード

OpenGLの拡張機能をロードする必要がない場合で、 かつヘッダが十分に最近のものである場合は、GLEWの代わりにこれを使用することができます。 私たちのテストによると、Windowsユーザーは古いヘッダを持っているかもしれず、GL_VERTEX_SHADERなどのようなシンボルを見失ってしまうので、これらのチュートリアルではGLEWを使用します(プラス私たちが拡張をロードするときのための準備にもなります)。
シェーダのロード

GLEWとGLeeの比較については、 APIs, Libraries and acronyms セクションもご覧ください。
シェーダのロード

ユーザーの報告によると、Intel 945GM GPUのGLEWのかわりにこのテクニックを使用することで、シンプルなチュートリアルでは不完全なOpenGL 2.0サポートをバイパスすることができたそうです。 GLEW自体は部分的なサポートを有効にすることもでき、glutInitを呼び出す前に glewExperimental = GL_TRUE;を追加することで行えます。
シェーダのロード

今私たちのプログラムはさらにメンテナンスしやすくなっていますが、やっていることは以前とまったく同じです! そういうわけで透明度でちょっと実験しながら、 "昔のテレビ "のエフェクトをつけて三角形を表示してみましょう。
シェーダのロード

まず、GLUTをアルファといっしょに初期化します:
シェーダのロード

その後、OpenGLで透明度(デフォルトではオフです)を明示的に有効にします:
シェーダのロード

そして最後に、フラグメントシェーダを変更し、アルファの透明度を定義します:
シェーダのロード

mod と floor は一般的な数学演算子で、偶数か奇数のどちらのラインにいるかの判断に使用しています。 したがって、2つに1つラインが透明になり、他は不透明になります。