glActiveTexture と glBindTexture の違いと関係 質問する

glActiveTexture と glBindTexture の違いと関係 質問する

私が収集した情報によると、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関数とそのバリエーション(glCompressedTexImageglCopyTexImage、 最近の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_TEXTURE0GL_TEXTURE31ただし、理解しておかなければならないことが 1 つあります。

それは間違いです!

が取ることができる実際の範囲glActiveTextureは によって決まりますGL_MAX_COMBINED_TEXTURE_IMAGE_UNITS。これは、実装で許可される同時マルチテクスチャの最大数です。これらはそれぞれ、異なるシェーダ ステージごとに異なるグループに分割されます。たとえば、GL 3.x クラスのハードウェアでは、16 個の頂点シェーダ テクスチャ、16 個のフラグメント シェーダ テクスチャ、および 16 個のジオメトリ シェーダ テクスチャが得られます。したがって、 はGL_MAX_COMBINED_TEXTURE_IMAGE_UNITS48 になります。

しかし、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 によって禁止されており、レンダリングしようとするとエラーが発生します。

おすすめ記事