4

クワッドに白い色として定義された単純なテクスチャを適用して、OpenGL でテクスチャを練習しています。コードは正常にコンパイルおよび実行されますが、クワッドの色は、指定したように白ではなく、単に黒です。

フラグメント シェーダーが適切な種類のサンプリングを行っていないためだと思います。テクスチャから返されるデータのようなものです。関数はすべてゼロであるため、クワッドのテクスチャは黒くなります。私がそう思う理由は、プログラムを実行すると、白の明確な色を作成し、クワッドの頂点の 1 つを少し移動して背景を見ることができるためです (通常はサーフェス全体を埋めるため)。そこに白い背景がはっきりと見え、その上に黒いクワッドがあります。したがって、一部の出力カラーはフラグメント シェーダーから生成されます。提供した小さなピクセル配列は白色のみであるため、これは間違ったカラーです。問題は、私が持っているコードから間違った結果が生成される理由が正確にわからないことです。私は、同じコードまたはそれ以下のコードを使用する本をたどろうとしています。また、さまざまなチュートリアルで調べてみましたが、すべて同じアプローチを使用しているように見えるため、行き詰まっています。

[編集]

問題の一部を追跡しました。glGetError() を使用していくつかのエラー追跡を行ったところ、コードの次の行であることがわかりました。

glTexStorage2D(GL_TEXTURE_2D, 0, GL_RGB8, 4, 4);

2 番目のパラメーターレベルが 0であるため、エラー コード 1282 (無効な操作) が返されます。これを 1 に設定すると、エラーは消えます。問題は次の行になります。

glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_R, GL_FLOAT, myTexture);

levelパラメータを変更しても修正されませんが、同じエラーが返されます。

これは、私が使用するフラグメントおよび頂点シェーダーです。

フラグメントシェーダー

// FRAGMENT SHADER
#version 330

uniform sampler2D tex;

in vec2 vs_tex_coord;

layout (location = 0) out vec4 outputColor;

void main(void)
{
    outputColor = texture(tex, vs_tex_coord);
}

頂点シェーダー

// VERTEX SHADER
#version 330

layout(location = 0) in vec4 position;
layout(location = 1) in vec2 in_tex_coord;

uniform vec2 offset;

out vec2 vs_tex_coord;

void main(void)
{
    vec4 finalOffset = vec4(offset.x, offset.y, 0.0, 0.0);
    gl_Position = position + finalOffset;
    vs_tex_coord = in_tex_coord;
}

テクスチャ オブジェクトの生成と保存に使用するコードは非常に単純です。

glGenTextures(1, &textureHandle);

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

glTexStorage2D(GL_TEXTURE_2D, 0, GL_RGB8, 4, 4);

const GLubyte myTexture[] = {0xFF, 0xFF, 0xFF,   0xFF, 0xFF, 0xFF,   0xFF, 0xFF, 0xFF,    0xFF, 0xFF, 0xFF,
                             0xFF, 0xFF, 0xFF,   0xFF, 0xFF, 0xFF,   0xFF, 0xFF, 0xFF,    0xFF, 0xFF, 0xFF,
                             0xFF, 0xFF, 0xFF,   0xFF, 0xFF, 0xFF,   0xFF, 0xFF, 0xFF,    0xFF, 0xFF, 0xFF,
                             0xFF, 0xFF, 0xFF,   0xFF, 0xFF, 0xFF,   0xFF, 0xFF, 0xFF,    0xFF, 0xFF, 0xFF};

glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_RGB, GL_UNSIGNED_BYTE, myTexture);

myTextureには、各コンポーネントが 4 ビットの RGB の内部形式で 4x4 テクスチャが含まれているだけです。全て白にしました。

次に、次のようにデフォルトのサンプラーを生成するだけです。

glGenSamplers(1, &mySampler);

glBindSampler(0, mySampler);

そして最後にレンダリングします:

glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);

glUseProgram(theProgram);

GLuint samplerLoc = glGetUniformLocation(theProgram, "tex");

if (samplerLoc == -1)
    printf("Location name could not be found...\n");

glUniform1i(samplerLoc, 0);

glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);

glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);

glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);

glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (GLvoid*)(16 * sizeof(float)));

glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

VBOにアップロードする配列は次のとおりです。

const float vertexPositions[] =
{
    // Vertex position
    -0.8f, -1.0f, 0.0f, 1.0f,
     1.0f, -1.0f, 0.0f, 1.0f,
     1.0f,  1.0f, 0.0f, 1.0f,
    -1.0f,  1.0f, 0.0f, 1.0f,

    // Texture coordinates
    0.0f, 0.0f,
    1.0f, 0.0f,
    1.0f, 1.0f,
    0.0f, 1.0f
};

サンプラー オブジェクトを正しく使用していないためですか? 正しく動作させる前に、何らかの設定を行う必要がありますか? 中間ステップを見逃していますか?

興味のある方のために、視覚的な結果は次のとおりです。 ここに画像の説明を入力

意図的に頂点位置の 1 つを少し移動して、白い背景に対して黒いクワッドが見えるように、白くクリアされた背景を確認できます。

4

1 に答える 1

4

さて、いくつかのバグ追跡の後、ついに問題を発見しました! :) 将来この問題に遭遇する人のために、これが(非常に簡単な... ああ!)解決策です。

まず、この行は次のとおりです。

glTexStorage2D(GL_TEXTURE_2D, 0, GL_RGB8, 4, 4);

1281 (無効な操作) の OpenGL エラーが返されました。これは、ミップマップを使用するかどうかに関係なく、ベース イメージに十分なメモリを格納するために、2 番目のパラメーターレベルが少なくとも 1 である必要があるためです (これは、 0)。そのため、0から1に変更すると修正されました。

第二に、この行:

glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_R, GL_FLOAT, myTexture);

上記のスニペットで GL_R と表示されているformatパラメータに問題がありました。これは単純に間違っていました。関数の公式ドキュメントを見ると、それについて次のように述べられています。

format ピクセル データの形式を指定します。次の記号値が受け入れられます: GL_RED、GL_RG、GL_RGB、GL_BGR、GL_RGBA、GL_BGRA、GL_DEPTH_COMPONENT、および GL_STENCIL_INDEX。

以前に glTextStorage2D で指定したタイプは、GL_RGB8を使用します。GL_RGB8 は、GL_RGB の基本内部形式を持ちます。これは正しいバージョンです。

glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_RGB, GL_UNSIGNED_BYTE, myTexture);

これら 2 つの問題を修正すると、テクスチャ化された結果が表示されました :)

于 2013-08-09T22:58:57.417 に答える