2

プログラムに2番目のsampler2DRectテクスチャを追加しようとしています。2番目のテクスチャに別々のシェーダーファイルを使用しています。それ以外の場合は、最初のテクスチャを表示するために機能したのと同じコードを使用しています。しかし、2番目のテクスチャを表示しようとすると、代わりに最初のテクスチャが表示されているため、理由がわかりません。API呼び出しの1つを間違って行ったか、重要なことを省略した可能性がありますが、何も試みても問題は解決しません。

GLエラーは報告されておらず、gDEBuggerは疑わしいものを何も表示しません。

問題はコードのどこかにあると思いますが、2番目のテクスチャを描画するために使用しているセクションは次のとおりです(最初のテクスチャを描画するために機能するコードとほぼ同じです)。

Test_World_Pause_Menu::Test_World_Pause_Menu(int resolution_width, int resolution_height)
    : _shaders("shaders/pause_menu.vert", "shaders/pause_menu.frag"),
      _vao_id( new GLuint[1] ),
      _mvp_id( new GLint[1] ),
      _pm_tex_id( new GLuint[1] ),
      _mvp( glm::ortho(0.0f, (GLfloat)resolution_width, 0.0f, (GLfloat)resolution_height, -1.0f, 1.0f) ),
      _pm_vertices_buffer( new GLuint[1] ),
      _pm_vertices( new GLfloat[12] ),
      _pm_colors_buffer( new GLuint[1] ),
      _pm_colors( new GLfloat[16] ),
      _pm_tex_coords_buffer( new GLuint[1] ),
      _pm_tex_coords( new GLfloat[8] ),
      _pm_normals_buffer( new GLuint[1] ),
      _pm_normals( new GLfloat[12] )
{
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);  // set alpha blending mode

    // begin pause menu initialization
    _pm_image.loadFromFile("resources/levels/test_00/pause_menu/pause_menu.png");
    _pm_image.flipVertically();

    unsigned int pm_location_x = 0;
    unsigned int pm_location_y = _pm_image.getSize().y;
    unsigned int pm_width = _pm_image.getSize().x;
    unsigned int pm_height = _pm_image.getSize().y;

    _pm_vertices[0] = pm_location_x; _pm_vertices[1] = pm_location_y; _pm_vertices[2] = 0.0f;
    _pm_vertices[3] = pm_location_x; _pm_vertices[4] = pm_location_y - pm_height; _pm_vertices[5] = 0.0f;
    _pm_vertices[6] = pm_location_x + pm_width; _pm_vertices[7] = pm_location_y - pm_height; _pm_vertices[8] = 0.0f;
    _pm_vertices[9] = pm_location_x + pm_width; _pm_vertices[10] = pm_location_y; _pm_vertices[11] = 0.0f;

    _pm_colors[0] = 1.0f; _pm_colors[1] = 1.0f; _pm_colors[2] = 1.0f; _pm_colors[3] = 0.0f;
    _pm_colors[4] = 1.0f; _pm_colors[5] = 1.0f; _pm_colors[6] = 1.0f; _pm_colors[7] = 0.0f;
    _pm_colors[8] = 1.0f; _pm_colors[9] = 1.0f; _pm_colors[10] = 1.0f; _pm_colors[11] = 0.0f;
    _pm_colors[12] = 1.0f; _pm_colors[13] = 1.0f; _pm_colors[14] = 1.0f; _pm_colors[15] = 0.0f;

    _pm_tex_coords[0] = 0.0f; _pm_tex_coords[1] = pm_height;
    _pm_tex_coords[2] = 0.0f; _pm_tex_coords[3] = 0.0f;
    _pm_tex_coords[4] = pm_width; _pm_tex_coords[5] = 0.0f;
    _pm_tex_coords[6] = pm_width; _pm_tex_coords[7] = pm_height;

    _pm_normals[0] = 0.0f; _pm_normals[1] = 0.0f; _pm_normals[2] = 0.0f;
    _pm_normals[3] = 0.0f; _pm_normals[4] = 0.0f; _pm_normals[5] = 0.0f;
    _pm_normals[6] = 0.0f; _pm_normals[7] = 0.0f; _pm_normals[8] = 0.0f;
    _pm_normals[9] = 0.0f; _pm_normals[10] = 0.0f; _pm_normals[11] = 0.0f;

    glGenVertexArrays(1, &_vao_id[0]); // generate VAO
    glBindVertexArray(_vao_id[0]);     // bind VAO

    // vertices
    glEnableVertexAttribArray((GLuint)0);
    glGenBuffers(1, &_pm_vertices_buffer[0]);
    glBindBuffer(GL_ARRAY_BUFFER, _pm_vertices_buffer[0]);
    glBufferData(GL_ARRAY_BUFFER, 12 * sizeof(GLfloat), _pm_vertices.get(), GL_STATIC_DRAW);
    glVertexAttribPointer((GLuint)0, 3, GL_FLOAT, GL_FALSE, 0, 0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glEnableVertexAttribArray(0);

    // normals (inexplicably needed even though it won't be used in the shaders)
    glEnableVertexAttribArray((GLuint)1);
    glGenBuffers(1, &_pm_normals_buffer[0]);
    glBindBuffer(GL_ARRAY_BUFFER, _pm_normals_buffer[0]);
    glBufferData(GL_ARRAY_BUFFER, 12 * sizeof(GLfloat), _pm_normals.get(), GL_STATIC_DRAW);
    glVertexAttribPointer((GLuint)1, 3, GL_FLOAT, GL_FALSE, 0, 0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glEnableVertexAttribArray(0);

    // texture
    glEnableVertexAttribArray((GLuint)2);
    glGenBuffers(1, &_pm_tex_coords_buffer[0]);
    glBindBuffer(GL_ARRAY_BUFFER, _pm_tex_coords_buffer[0]);
    glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(GLfloat), _pm_tex_coords.get(), GL_STATIC_DRAW);
    glVertexAttribPointer((GLuint)2, 2, GL_FLOAT, GL_FALSE, 0, 0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    glGenTextures(1, &_pm_tex_id[0]);
    glBindTexture(GL_TEXTURE_RECTANGLE, _pm_tex_id[0]);

    glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGBA, pm_width, pm_height,
            0, GL_RGBA, GL_UNSIGNED_BYTE, _pm_image.getPixelsPtr());

    glEnableVertexAttribArray(0);

    // colors
    glEnableVertexAttribArray((GLuint)3);
    glGenBuffers(1, &_pm_colors_buffer[0]);
    glBindBuffer(GL_ARRAY_BUFFER, _pm_colors_buffer[0]);
    glBufferData(GL_ARRAY_BUFFER, 16 * sizeof(GLfloat), _pm_colors.get(), GL_STATIC_DRAW);
    glVertexAttribPointer((GLuint)3, 4, GL_FLOAT, GL_FALSE, 0, 0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glEnableVertexAttribArray(0);

    // unbind buffers
    glBindVertexArray(0);

    _mvp_id[0] = glGetUniformLocation(_shaders.id(), "mvpMatrix");
    _pm_tex_id[0] = glGetUniformLocation(_shaders.id(), "pauseMenuTex");
// end pause menu initialization
}

void Test_World_Pause_Menu::display()
{
    glEnable(GL_BLEND);
    glDisable(GL_DEPTH_TEST);

    _shaders.bind();

        glUniformMatrix4fv(_mvp_id[0], 1, GL_FALSE, &_mvp[0][0]);

// begin pause menu rendering
        glUniform1i(_pm_tex_id[0], 0);

        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, _pm_tex_id[0]);

        glBindVertexArray(_vao_id[0]);     // bind the VAO

        // draw the contents of the bound VAO
        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

        glBindVertexArray(0); // unbind the VAO
// end pause menu rendering

    _shaders.unbind();

    glDisable(GL_BLEND);
    glEnable(GL_DEPTH_TEST);

    return;
}

これに使用しているシェーダーは次のとおりです。

バーテックスシェーダー

#version 150

in vec4 in_Position;
in vec3 in_Normal;
in vec2 in_UV;
in vec4 in_Color;

uniform mat4 mvpMatrix;

smooth out vec3 vVaryingNormal;
smooth out vec2 vVaryingTexCoord;
smooth out vec4 vVaryingColor;

void main(void) 
{
    vVaryingNormal = in_Normal;
    vVaryingTexCoord = in_UV;
    vVaryingColor = in_Color;

    gl_Position = mvpMatrix * in_Position;
}

フラグメントシェーダー

#version 150

smooth in vec3 vVaryingNormal;
smooth in vec2 vVaryingTexCoord;
smooth in vec4 vVaryingColor;

uniform sampler2DRect pauseMenuTex;

out vec4 out_Color;

void main(void)
{ 
    out_Color.a = vVaryingColor.a;
    out_Color += texture(pauseMenuTex, vVaryingTexCoord);
}

私の推測では、ここのどこかでテクスチャの状態を適切に遮断していませんが、私が言ったように、何も問題を解決しようとはしていません。必要に応じて、プログラムの他の部分のコードを投稿できます。

編集:最初のテクスチャの初期化関数とレンダリング関数を削除すると、2番目のテクスチャが正常に表示されるため、このC++コードと最初のテクスチャのコードでAPIが誤って使用されていることは間違いありません。誰かが私の間違ったOpenGLの使用法を特定するのを手伝ってくれますか(おそらくコンストラクターにあります)。

別の編集:さらに調査したところ、2つのオブジェクトのコンストラクターのどちらかが最初に実行された方が、両方の表示ルーチン中にテクスチャーが表示されるものであることがわかりました。

3番目の編集:関連する可能性のあるもの:コンストラクターでglTexImage2D()を呼び出した後、最初のテクスチャをglBindTexture(GL_TEXTURE_RECTANGLE、0)でバインド解除すると、2つの表示ルーチンのいずれかでまったく表示されなくなります。私にはこれは問題のように思えます、そしてそれは私の他の問題に関連しているかもしれません。

4

4 に答える 4

6

あなたの問題はここにあります:

glGenTextures(1, &_pm_tex_id[0]);
...
_pm_tex_id[0] = glGetUniformLocation(_shaders.id(), "pauseMenuTex");

最初のステートメントは、テクスチャオブジェクトを作成し、それをに格納し_pm_tex_id[0]ます。次のステートメントは、テクスチャオブジェクトを均一な位置で上書きします。したがって、テクスチャオブジェクトは失われます。ポインタを取得するために呼び出して、後でそのポインタを上書きするのと同じです。あなたはそれを取り戻すことはできません。new

改訂されたソリューションでコードが「機能」する理由は、(別のスロットで)コンテキストにバインドされたままになっているためです。データで埋めるためにバインドしましたが、バインドを解除することはありません。したがって、コンテキストには、追跡できなくなったテクスチャオブジェクトがまだ含まれています。

テクスチャ名とサンプラーの均一な場所を別々に保存する必要があります。「id」よりも適切な命名規則を使用する必要があります。統一された場所には、OpenGLオブジェクト名と同じ種類の命名規則を使用しないでください。そうすれば、それらを混乱させることはありません。ユニフォームには「id」ではなく「unif」をお勧めします。


間違っていない他のことは、必ずしも役立つとは限りません。

あなたは頻繁に電話します:

glEnableVertexAttribArray(0);

理由もなく。属性0を最初に有効にしたときよりも有効にすることはできません;)

また、1つのアイテムの配列を多数割り当てます。それは本当に不要です。VAOが1つだけ必要な場合は、GLuint変数を作成するだけです。生成する必要がある場合は、そのアドレスを取得してください。

また、あまり多くのメモリ期間を割り当てるのはやめましょう。配列が必要な場合は、を使用しstd::vectorます(現在行っているのとまったく同じ方法で配列へのポインターを取得できます:) &vec[0]。このように、メモリを削除することを覚えておく必要はありません。オブジェクトが破棄されると、C++が自動的に実行します。すでにC++を使用しているので、実際にその言語を使用することもできます。

于 2012-08-29T11:48:29.627 に答える
2

1つはGL_TEXTURE_RECTANGLEにバインドされ、後でGL_TEXTURE_2Dにバインドされます。これらは同じである必要がありますか?

于 2012-08-29T01:44:17.887 に答える
2

まず、コメントを投稿するのに十分な評判がなく、これから言うことについてあなたの質問を編集する気がしなかったので、これがうまくいかない場合は事前に謝罪します。

あなたの解決策(または回避策)は、各テクスチャに独自のテクスチャスロットを与えます。これは、同じシェーダーに複数のテクスチャを渡したい場合を除いて必要ではないため、間違いなく競合が発生しています。

glUniform1i(_pm_tex_id[0], x);シェーダープログラムが(再)作成された後に一度だけ設定する必要があるため、レンダリングプロシージャから削除して、コンストラクターに配置できます。

ティムがさまざまなバインディングコールを見つけた後、これを変更しましたか?OpenGlドキュメントを作成します。

名前付きテクスチャは、作成されると、必要に応じて同じ元のターゲットに再バインドできます。

私は間違いなくそれらを変更して、両方が同一になるようにします(GL_TEXTURE_2Dを選択します)。

他の場所でテクスチャに関連する他のGL_*呼び出しを行っていますか?これは、最初のオブジェクトが描画された後も、古いパラメータがまだぶら下がっているようなにおいがするためです。うまくいけば、これはある程度役立つでしょう。

于 2012-08-29T04:04:38.390 に答える
0

私は問題を解決しましたが、私の解決策がなぜ機能したのか、実際に何をしているのかはわかりませんが、ここにあります:

最初のテクスチャでは、glGenTextures()の呼び出しの上にglActiveTexture(GL_TEXTURE0)を追加しました。

2番目のテクスチャでは、glGenTextures()の呼び出しの上とdisplay()関数の両方でglActiveTexture(GL_TEXTURE1)を使用し、glUniform1i(_pm_tex_id [0]、0)の代わりにglUniform1i(_pm_tex_id [0]、1)を使用しました。 )。

なぜこれが機能したのか誰かに教えてもらえますか?このようにすると、sampler2DRectテクスチャの数が制限されますか?アクティベートできるGL_TEXTUREnの数は非常に限られていると確信しています。

于 2012-08-29T03:16:37.203 に答える