私が収集した情報によると、glActiveTexture
アクティブな「テクスチャ ユニット」を設定します。各テクスチャ ユニットには、複数のテクスチャ ターゲット (通常は GL_TEXTURE_1D、2D、3D、または CUBE_MAP) を設定できます。
glActiveTexture
私の理解が正しければ、最初に を呼び出してテクスチャ ユニットを設定し ( に初期化GL_TEXTURE0
)、次に (1 つ以上の)「テクスチャ ターゲット」をそのテクスチャ ユニットにバインドする必要があるということですね?
利用可能なテクスチャユニットの数はシステムに依存します。私のライブラリには最大32の列挙型があります。これは基本的に、GPUの制限の小さい方(おそらく
16
8) と 32 テクスチャを GPU メモリに同時に保存できますか? GPU の最大メモリ (おそらく 1 GB) を超えないようにするという追加の制限があると思います。
テクスチャ ターゲットとテクスチャ ユニットの関係を正しく理解していますか? 16 個のユニットとそれぞれ 4 個のターゲットが許可されているとすると、16*4=64 個のターゲットの余地があるということですか、それともそのようには機能しないのですか?
次に、通常はテクスチャをロードします。これは で実行できますglTexImage2D
。その最初の引数はテクスチャターゲットです。これが次のように動作しますglBufferData
次に、基本的に「ハンドル」/「テクスチャ名」をテクスチャ ターゲットにバインドし、テクスチャ データをそのターゲットにロードして、間接的にそのハンドルに関連付けます。
はどうでしょうかglTexParameter
? テクスチャ ターゲットをバインドしてから、同じターゲットを最初の引数として再度選択する必要がありますか? または、正しいアクティブ テクスチャ ユニットがある限り、テクスチャ ターゲットをバインドする必要はありませんか?
glGenerateMipmap
ターゲットにも作用します...成功するには、そのターゲットがテクスチャ名にバインドされている必要がありますか?
では、テクスチャ付きのオブジェクトを描画したい場合、両方アクティブなテクスチャ ユニットを選択してから、テクスチャ ターゲットを選択しますか? それとも、テクスチャ ユニットを選択してから、そのユニットに関連付けられている 4 つのターゲットのいずれかからデータを取得できるのでしょうか? これが、私が本当に混乱している部分です。
ベストアンサー1
OpenGL オブジェクトについて
OpenGL オブジェクトの標準モデルは次のとおりです。
オブジェクトには状態があります。 として考えてみましょうstruct
。次のように定義されたオブジェクトがあるとします。
struct Object
{
int count;
float opacity;
char *name;
};
オブジェクトには特定の値が格納されており、州OpenGL オブジェクトにも状態があります。
状態の変更
C/C++ では、 型のインスタンスがある場合Object
、その状態を次のように変更します。obj.count = 5;
オブジェクトのインスタンスを直接参照し、変更する特定の状態を取得して、そこに値を挿入します。
OpenGLでは、しないこれを行う。
レガシーな理由により、OpenGLオブジェクトの状態を変更するには、まず練るそれをコンテキストに追加します。これは、glBind*
呼び出しの何らかの形式で行われます。
これに相当する C/C++ は次のとおりです。
Object *g_objs[MAX_LOCATIONS] = {NULL};
void BindObject(int loc, Object *obj)
{
g_objs[loc] = obj;
}
テクスチャは興味深いもので、バインディングの特別なケースを表します。多くのglBind*
呼び出しには「ターゲット」パラメータがあります。これは、そのタイプのオブジェクトをバインドできる OpenGL コンテキスト内のさまざまな場所を表します。たとえば、フレームバッファ オブジェクトを読み取り用 ( GL_READ_FRAMEBUFFER
) または書き込み用 ( GL_DRAW_FRAMEBUFFER
) にバインドできます。これは、OpenGL がバッファを使用する方法に影響します。これは、loc
上記のパラメータが表すものです。
テクスチャは特別なものです。初めターゲットにバインドすると、特別な情報が得られます。テクスチャを としてバインドするとGL_TEXTURE_2D
、実際にはテクスチャに特別な状態が設定されます。このテクスチャは2Dテクスチャであると言っています。そして、いつも2Dテクスチャである。この状態は変更できない。これまで最初に としてバインドされたテクスチャがある場合はGL_TEXTURE_2D
、いつもとしてバインドしますGL_TEXTURE_2D
。 としてバインドしようとすると、GL_TEXTURE_1D
エラーが発生します (実行時)。
オブジェクトがバインドされると、その状態を変更できます。これは、そのオブジェクトに固有の汎用関数によって行われます。これらの関数も、変更するオブジェクトを表す場所を取得します。
C/C++ では次のようになります。
void ObjectParameteri(int loc, ObjectParameters eParam, int value)
{
if(g_objs[loc] == NULL)
return;
switch(eParam)
{
case OBJECT_COUNT:
g_objs[loc]->count = value;
break;
case OBJECT_OPACITY:
g_objs[loc]->opacity = (float)value;
break;
default:
//INVALID_ENUM error
break;
}
}
loc
この関数が、現在バインドされている値をどのように設定するかに注目してください。
テクスチャオブジェクトの場合、主なテクスチャ状態変更関数はglTexParameter
テクスチャの状態を変更する他の関数は、glTexImage
関数とそのバリエーション(glCompressedTexImage
、glCopyTexImage
、 最近のglTexStorage
)。さまざまなSubImage
バージョンではテクスチャの内容が変更されていますが、技術的には変更されていません。州関数Image
はテクスチャ ストレージを割り当て、テクスチャの形式を設定します。SubImage
関数はピクセルをコピーするだけです。これはテクスチャの状態とはみなされません。
繰り返しますが、これらはのみテクスチャの状態を変更する関数。glTexEnv
環境の状態を変更しますが、テクスチャ オブジェクトに格納されているものには影響しません。
アクティブテクスチャ
テクスチャの状況はより複雑で、これもまたレガシーな理由から非公開にしておくのが最善です。glActiveTexture
入って来る。
GL_TEXTURE_1D
テクスチャには、ターゲット( 、など)だけではなく、GL_TEXTURE_CUBE_MAP
テクスチャもあります。ユニットC/C++ の例では、次のようになります。
Object *g_objs[MAX_OBJECTS][MAX_LOCATIONS] = {NULL};
int g_currObject = 0;
void BindObject(int loc, Object *obj)
{
g_objs[g_currObject][loc] = obj;
}
void ActiveObject(int currObject)
{
g_currObject = currObject;
}
ここで、2D リストだけでなくObject
、現在のオブジェクトの概念も持っていることに注目してください。現在のオブジェクトを設定する関数があり、現在のオブジェクトの最大数の概念があり、すべてのオブジェクト操作関数は現在のオブジェクトから選択するように調整されています。
現在アクティブなオブジェクトを変更すると、ターゲット位置のセット全体が変わります。したがって、現在のオブジェクト 0 にバインドするものを現在のオブジェクト 4 に切り替えると、まったく別のオブジェクトが変更されます。
テクスチャ オブジェクトとのこの類似性は完璧です...ほぼ。
glActiveTexture
整数ではなく、調査員理論上は から までの任意の値を取ることができることを意味しますGL_TEXTURE0
。GL_TEXTURE31
ただし、理解しておかなければならないことが 1 つあります。
それは間違いです!
が取ることができる実際の範囲glActiveTexture
は によって決まりますGL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
。これは、実装で許可される同時マルチテクスチャの最大数です。これらはそれぞれ、異なるシェーダ ステージごとに異なるグループに分割されます。たとえば、GL 3.x クラスのハードウェアでは、16 個の頂点シェーダ テクスチャ、16 個のフラグメント シェーダ テクスチャ、および 16 個のジオメトリ シェーダ テクスチャが得られます。したがって、 はGL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
48 になります。
しかし、48人の調査員はいません。だからglActiveTexture
調査員は実際には必要ありません。正しい呼び出し方法glActiveTexture
は次のとおりです。
glActiveTexture(GL_TEXTURE0 + i);
ここでi
は 0 から までの数値ですGL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
。
レンダリング
では、これらすべてはレンダリングとどのような関係があるのでしょうか?
シェーダーを使用する場合、サンプラー ユニフォームをテクスチャ イメージ ユニット ( glUniform1i(samplerLoc, i)
、 はi
イメージ ユニット) に設定します。これは、 で使用した数値を表しますglActiveTexture
。サンプラーは、サンプラー タイプに基づいてターゲットを選択します。したがって、 はターゲットsampler2D
から選択しますGL_TEXTURE_2D
。これが、サンプラーにさまざまなタイプがある理由の 1 つです。
これは、2つのGLSLサンプラーを異なる種類同じテクスチャ イメージ ユニットを使用する複数のオブジェクトをレンダリングすることはできません。ただし、これは OpenGL によって禁止されており、レンダリングしようとするとエラーが発生します。