OpenGLオブジェクトのすべて
OpenGLオブジェクトの標準モデルは次のとおりです。
オブジェクトには状態があります。それらをと考えてくださいstruct。したがって、次のように定義されたオブジェクトがあるとします。
struct Object
{
int count;
float opacity;
char *name;
};
オブジェクトには特定の値が格納されており、状態があります。OpenGLオブジェクトにも状態があります。
状態の変化
C / C ++では、タイプのインスタンスがある場合、Objectその状態を次のように変更します。obj.count = 5;オブジェクトのインスタンスを直接参照し、変更する特定の状態を取得して、値をそれに押し込みます。
OpenGLでは、これを行う必要はありません。
従来の理由から、説明を残さない方がよいです。OpenGLオブジェクトの状態を変更するには、まずそれをコンテキストにバインドする必要があります。これは、いくつかのfrom of 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_2DGL_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;
}
ここで、Objectsの2Dリストだけでなく、現在のオブジェクトの概念もあることに注意してください。現在のオブジェクトを設定する関数があり、現在のオブジェクトの最大数の概念があり、すべてのオブジェクト操作関数は現在のオブジェクトから選択するように調整されています。
現在アクティブなオブジェクトを変更すると、ターゲットの場所のセット全体が変更されます。したがって、現在のオブジェクト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_UNITS48 になります。
しかし、48の列挙子はありません。これがglActiveTexture実際に列挙子をとらない理由です。正しいコールへの道は、glActiveTexture次のとおりです。
glActiveTexture(GL_TEXTURE0 + i);
ここで、i0との間の数ですGL_MAX_COMBINED_TEXTURE_IMAGE_UNITS。
レンダリング
では、これらすべてがレンダリングとどう関係しているのでしょうか?
シェーダーを使用するときは、サンプラーのユニフォームをテクスチャ画像単位(glUniform1i(samplerLoc, i)、iは画像単位)に設定します。これは、で使用した数を表していますglActiveTexture。サンプラーは、サンプラータイプに基づいてターゲットを選択します。したがってsampler2D、GL_TEXTURE_2Dターゲットから選択します。これが、サンプラーにさまざまなタイプがある理由の1つです。
これは、同じテクスチャイメージユニットを使用する異なるタイプの 2つのGLSLサンプラーを使用できるように、疑わしく聞こえます。しかし、それはできません。OpenGLはこれを禁止し、レンダリングしようとするとエラーが発生します。
GL_TEXTURE0 + i-列挙値を調べて、それが有効かどうかを確認するつもりでした。そして最後の段落-それが合法であるかどうか知りませんでした。優れた!私はあなたのすべての回答をブックマークして、再び参照できるようにします。