web-dev-qa-db-ja.com

OpenGLシェーダーの明示的な属性と自動属性の場所のバインド

OpenGLシェーダープログラムの属性の場所を設定するとき、2つのオプションに直面します。

glBindAttribLocation()リンクしてから属性の場所を明示的に定義します。

または

glGetAttribLocation()リンク後、自動的に割り当てられた属性の場所を取得します。

一方を他方に対して使用するためのユーティリティは何ですか?

そして、もしあれば、実際にどれが好まれますか?

74
Jing

explicitロケーション定義を好む理由は1つあります。

ジオメトリデータを Vertex Array Objects。 に保持することを検討してください。特定のオブジェクトに対して、次のような方法でVAOを作成します。インデックスは、たとえば次のものに対応します。

  • インデックス0:位置、
  • インデックス1:法線、
  • インデックス2:texcoords

ここで、1つのオブジェクトを2つの異なるシェーダーで描画したいと考えます。 1つのシェーダーには入力として位置と通常のデータが必要で、もう1つのシェーダーには-位置とテクスチャー座標

これらのシェーダーをコンパイルすると、最初のシェーダーは属性インデックス0の位置と法線1を期待し、もう1つのシェーダーは0の位置を期待しますが、テクスチャ座標は1を期待します。

引用 https://www.opengl.org/wiki/Vertex_Shader

自動割り当て

前の2つの方法のいずれも入力を属性インデックスに割り当てない場合、インデックスはプログラムがリンクされるときにOpenGLによって自動的に割り当てられます。割り当てられたインデックスは完全に任意であり、リンクされているプログラムによっては、まったく同じ頂点シェーダーコードを使用している場合でも異なる場合があります。

これは、両方のシェーダーでVAOを使用できないことを意味します。たとえばオブジェクトごとに1つのVAOを持つのではなく、 -最悪の場合-シェーダーごとのオブジェクトごとに個別のVAO

シェーダーがglBindAttribLocationを介して独自の属性番号付け規則を使用するように強制すると、この問題を簡単に解決できます。属性とその安定化ID間の一貫した関係を維持し、シェーダーにその規則を強制的に使用させるだけですリンク。

(別個のVAOを使用しない場合、それは実際には大きな問題ではありませんが、それでもコードが明確になる可能性があります。)


ところで:

OpenGLシェーダープログラムの属性の場所を設定するとき、2つのオプションに直面します

OpenGL/GLSL 3.3には3番目のオプションがあります:shader codeで場所を直接指定します。次のようになります。

layout(location=0) in vec4 position;

しかし、これはGLSL ESシェーダー言語には存在しません。

87
Kos

ここでのもう1つの答えは、glGetAttribLocationが呼び出し元にデータを返すということです。つまり、暗黙的にパイプラインフラッシュが必要です。プログラムをコンパイルした直後に呼び出すと、本質的に同期コンパイルを強制的に非同期コンパイルすることになります。

18
Litherum

3番目のオプション、つまりシェーダーコードのlayout(location=0) in vec4 position;は、OpenGL ES 3.0/GLSL 300 esで使用できるようになりました。ただし、頂点シェーダー入力変数のみ。

8
lane