web-dev-qa-db-ja.com

openglでテクスチャを使用してメモリを管理する方法

私のアプリケーションでは、glTexImage2Dを幅広く使用しています。画像の一部の画像をコピーしてテクスチャとしてレンダリングします。マウスをクリックするたびに頻繁に実行します。レンダリング用のバイト配列として指定します。メモリが消費され、スワップメモリ​​も割り当てられます。メモリリークですか?または、glTexImage2Dが参照やその他を保持していることが原因です。

編集:

    //I allocate the memory once
    GLuint texName;
    texture_data = new GLubyte[width*height];

    // Each time user click I repeat the following code (this code in in callback)
    // Before this code the texture_data is modified to reflect the changes
    glGenTextures(3, &texname);
    glBindTexture(GL_TEXTURE_2D, texname);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE,texture_data);

クローズのリクエストと投票が停止することを願っています!

20
Shan

glTexImage2Dを呼び出すたびにglGenTexturesを使用して新しいテクスチャを生成しているとすると、メモリを浪費し、生成するすべてのテクスチャを追跡していなければリークします。 glTexImage2Dは入力データを受け取り、ビデオカードメモリに格納します。 glTexImage2Dを呼び出す前にバインドするテクスチャ名-glGenTexturesで生成するテクスチャ名は、そのビデオカードメモリのチャンクへのハンドルです。

テクスチャーが大きく、使用するたびにそのテクスチャーのコピーを保存するために新しいメモリーを割り当てている場合、すぐにメモリー不足になります。解決策は、アプリケーションの初期化中にglTexImage2Dを1回呼び出し、使用したいときにだけglBindTextureを呼び出すことです。クリックしたときにテクスチャ自体を変更する場合は、glBindTextureおよびglTexImage2Dのみを呼び出します。新しい画像が前の画像と同じサイズの場合は、glTexSubImage2Dを呼び出して、古い画像データを削除して新しい画像をアップロードする代わりに上書きするようにOpenGLに指示できます。

[〜#〜]更新[〜#〜]

あなたの新しいコードに応じて、私はより具体的な答えで私の答えを更新しています。 OpenGLテクスチャを完全に間違った方法で処理しているglGenTexturesの出力はGLuint[]であり、Stringchar[]ではありません。 glGenTexturesを使用して生成するすべてのテクスチャについて、OpenGLはハンドルに(符号なし整数として)ハンドルを返します。このハンドルは、glTexParameteriで指定した状態と、glTexImage[1/2/3]Dでデータを指定した場合はグラフィックカード上のメモリのチャンクを格納します。ハンドルを保存して、更新したいときに新しいデータを送信するのは、あなた次第です。ハンドルを上書きしたり忘れたりした場合、データはグラフィックカードに残りますが、アクセスできません。また、1つだけ必要なときに、OpenGLに3つのテクスチャを生成するように指示しています。

texture_dataは固定サイズであるため、glTexSubImage2DではなくglTexImage2Dでテクスチャを更新できます。この問題によるメモリリークを回避するために変更したコードを次に示します。

texture_data = new GLubyte[width*height]();
GLuint texname; //handle to a texture
glGenTextures(1, &texname); //Gen a new texture and store the handle in texname

//These settings stick with the texture that's bound. You only need to set them
//once.
glBindTexture(GL_TEXTURE_2D, texname);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

//allocate memory on the graphics card for the texture. It's fine if
//texture_data doesn't have any data in it, the texture will just appear black
//until you update it.
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB,
    GL_UNSIGNED_BYTE, texture_data);

...

//bind the texture again when you want to update it.
glBindTexture(GL_TEXTURE_2D, texname);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, 0, GL_RGB,
    GL_UNSIGNED_BYTE, texture_data);

...

//When you're done using the texture, delete it. This will set texname to 0 and
//delete all of the graphics card memory associated with the texture. If you
//don't call this method, the texture will stay in graphics card memory until you
//close the application.
glDeleteTextures(1, &texname);
44
Robert Rouhani