サーチ…


テクスチャの基礎

テクスチャは、特定のデータエントリだけでなく、複数のエントリを混合(補間)するサンプルポイントにも便利なアクセスを可能にするデータストレージの一形態です。

OpenGLではテクスチャは多くのものに使用できますが、最も一般的には画像をポリゴン(たとえば三角形)にマッピングしています。テクスチャを三角形(または別のポリゴン)にマッピングするには、各頂点にテクスチャのどの部分が対応しているかを伝える必要があります。ポリゴンの各頂点にテクスチャ座標を割り当て、そのポリゴンのすべてのフラグメント間に補間します。テクスチャの座標は、通常、下の図に示すように、x軸とy軸の範囲は0〜1です。

テクスチャ座標

この三角形のテクスチャ座標は次のようになります。

GLfloat texCoords[] = {
    0.0f, 0.0f,  // Lower-left corner  
    1.0f, 0.0f,  // Lower-right corner
    0.5f, 1.0f   // Top-center corner
};

これらの座標をVBO(頂点バッファオブジェクト)に入れ、シェーダの新しい属性を作成します。頂点の位置には少なくとも1つの属性を既に持っていて、テクスチャ座標の別の属性を作成する必要があります。


テクスチャの生成

最初に行うことは、符号なしint テクスチャに格納されるIDによって参照されるテクスチャオブジェクトを生成することです。

GLuint texture;
glGenTextures(1, &texture); 

その後、すべての後続のテクスチャコマンドがこのテクスチャを構成するようにバインドする必要があります。

glBindTexture(GL_TEXTURE_2D, texture); 

画像を読み込む

イメージをロードするには、独自のイメージローダーを作成するか、Java c ++またはTWLのPNGDecoderSOIL (Simple OpenGL Image Library)などのイメージロードライブラリを使用できます。

SOILを使用してイメージをロードする例は次のようになります。

int width, height;
unsigned char* image = SOIL_load_image("image.png", &width, &height, 0, SOIL_LOAD_RGB); 

これで、このイメージをテクスチャオブジェクトに割り当てることができます:

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);

その後、テクスチャオブジェクトのバインドを解除する必要があります。

glBindTexture(GL_TEXTURE_2D, 0); 

テクスチャ座標のラップパラメータ

上で見たように、テクスチャの左下隅にはUV(st)座標(0,0)があり、テクスチャの右上隅には座標(1,1)がありますが、メッシュのテクスチャ座標は任意の範囲。これを処理するには、テクスチャ座標がどのようにテクスチャにラップされるかを定義する必要があります。

テクスチャ座標のラップパラメータは、 GL_TEXTURE_WRAP_SGL_TEXTURE_WRAP_T 、およびGL_TEXTURE_WRAP_Rを使用してglTextureParameterで設定できます。

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

可能なパラメータは次のとおりです。

  • GL_CLAMP_TO_EDGEはテクスチャ座標を[1 / 2N、 GL_CLAMP_TO_EDGE / 2N]の範囲にクランプする。ここでNは方向のテクスチャのサイズである。

  • GL_CLAMP_TO_BORDER同じしGL_CLAMP_TO_EDGEが、クランプケースでは、フェッチされたテクセルデータがで指定された色で置換されてGL_TEXTURE_BORDER_COLOR

  • GL_REPEATは、テクスチャ座標の整数部分を無視する。テクスチャがタイルされています。

繰り返しテクスチャ

  • GL_MIRRORED_REPEAT :テクスチャ座標の整数部分が偶数の場合、それは無視されます。対照的に、テクスチャ座標の整数部分が奇数である場合、テクスチャ座標は1-frac(s)に設定される。 fract(s)はテクスチャ座標の小数部分です。これにより、2回ごとにテクスチャが反映されます。

ミラーテクスチャ

  • GL_MIRROR_CLAMP_TO_EDGEは、GL_CLAMP_TO_EDGEのようにクランプされる座標をテクスチャの1回のGL_MIRRORED_REPEATに対してGL_MIRRORED_REPEATのようにテクスチャ座標をGL_CLAMP_TO_EDGE

GL_TEXTURE_WRAP_SGL_TEXTURE_WRAP_TおよびGL_TEXTURE_WRAP_Rのデフォルト値はGL_REPEATです。


テクスチャの適用

最後に行うことは、描画呼び出しの前にテクスチャをバインドすることです。

glBindTexture(GL_TEXTURE_2D, texture);

テクスチャとフレームバッファ

テクスチャ内のイメージをフレームバッファに添付することができます。これにより、そのテクスチャに直接レンダリングできます。

glGenFramebuffers (1, &framebuffer);
glBindFramebuffer (GL_FRAMEBUFFER, framebuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER,
                       GL_COLOR_ATTACHMENT0,
                       GL_TEXTURE_2D,
                       texture,
                       0);

注:定義されていない動作を呼び出すため、同じレンダリングタスクで同じテクスチャから読み書きすることはできません。しかし、あなたはこのためにレンダリング呼び出しの間にglTextureBarrier()使うことができます。

テクスチャデータを読み込む

関数glGetTexImageテクスチャデータを読むことができます:

char *outBuffer = malloc(buf_size);

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);

glGetTexImage(GL_TEXTURE_2D,
              0,
              GL_RGBA,
              GL_UNSIGNED_BYTE,
              outBuffer);

注:テクスチャの種類とフォーマットは一例であり、異なっていてもかまいません。

PBOの使用

あなたがするバッファをバインドする場合GL_PIXEL_UNPACK_BUFFERその後、 data内のパラメータglTexImage2Dそのバッファへのオフセットされます。

つまり、glTexImage2Dは、アプリケーションのメモリからすべてのデータがコピーされてから返されるのを待つ必要がなくなり、メインスレッドのオーバーヘッドが削減されます。

glGenBuffers(1, &pbo);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
glBufferData(GL_PIXEL_UNPACK_BUFFER, width*height*3, NULL, GL_STREAM_DRAW);
void* mappedBuffer = glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);

//write data into the mapped buffer, possibly in another thread.
int width, height;
unsigned char* image = SOIL_load_image("image.png", &width, &height, 0, SOIL_LOAD_RGB);
memcpy(mappedBuffer, image, width*height*3);
SOIL_free_image(image);

// after reading is complete back on the main thread
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);

しかし、PBOが本当に輝くのは、レンダリングの結果をアプリケーションメモリに読み込む必要がある場合です。それにバインドバッファに画素データを読み出すGL_PIXEL_PACK_BUFFERその後のデータパラメータglGetTexImageそのバッファにオフセットされます。

glGenBuffers(1, &pbo);
glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
glBufferData(GL_PIXEL_PACK_BUFFER, buf_size, NULL, GL_STREAM_COPY);

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);

glGetTexImage(GL_TEXTURE_2D,
              0,
              GL_RGBA,
              GL_UNSIGNED_BYTE,
              null);
//ensure we don't try and read data before the transfer is complete
GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);

// then regularly check for completion
GLint result;
glGetSynciv(sync, GL_SYNC_STATUS, sizeof(result), NULL, &result);
if(result == GL_SIGNALED){
    glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
    void* mappedBuffer = glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);

    //now mapped buffer contains the pixel data

    glUnmapBuffer(GL_PIXEL_PACK_BUFFER);

}

GLSLシェーダでのテクスチャの使用

頂点シェーダはテクスチャ座標を頂点属性として受け付け、座標をフラグメントシェーダに転送します。デフォルトでは、フラグメントが三角形の位置に基づいて適切に補間された座標を受け取ることも保証されます:

layout (location = 0) in vec3 position;
layout (location = 1) in vec2 texCoordIn;

out vec2 texCoordOut;

void main()
{
    gl_Position = vec4(position, 1.0f);
    texCoordOut = texCoordIn;
}

フラグメントシェーダは、 texCoord出力変数を入力変数として受け入れます。 uniform sampler2D宣言することによって、フラグメントシェーダにテクスチャを追加することができます。テクスチャの断片をサンプリングするには、2つのパラメータを持つビルトイン関数textureを使用します。最初にサンプルを取りたいテクスチャと、2番目のテクスチャはこのテクスチャの座標です。

in vec2 texCoordOut;

out vec4 color;

uniform sampler2D image;

void main()
{
    color = texture(image, texCoordOut);
}

imageは直接テクスチャIDではありません。サンプリングされるテクスチャユニットの IDです。次に、テクスチャはプログラムに直接バインドされていません。テクスチャユニットにバインドされています。これは、最初にテクスチャユニットアクティブにすることによって達成さglActiveTexture呼び出した後、およびglBindTexture 、この特定のテクスチャユニットに影響を与えます。しかし、デフォルトのテクスチャユニットはテクスチャユニット0であるため、1つのテクスチャを使用するプログラムは、この呼び出しを省略すると簡単になります。



Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow