如何在OpenGL中使用纹理管理内存? [英] how to manage memory with texture in opengl?
问题描述
在我的应用程序中,我广泛使用glTexImage2D.我复制图像的某些图像并将其渲染为纹理,每次单击鼠标时都经常这样做.我将其作为字节数组进行渲染.内存已被消耗and尽,交换内存也已分配.是内存泄漏吗?还是由于glTexImage2D保留了任何引用或其他任何内容.
In my application I am using extensively glTexImage2D. I copy some image of an image and render it as a texture, I do it frequently at every mouse click. I give it as a byte array for rendering. The memory is being eaten up and the swap memory is also allocated. Is it a memory leak? or is it due to the fact that glTexImage2D holds any references or anything else.
//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);
我希望您的亲密请求和反对投票现在能够停止!
I hope your close requests and down voting would stop now!
推荐答案
假定您每次调用glTexImage2D
时都使用glGenTextures
生成新纹理,那是在浪费内存,如果不使用,则会泄漏它跟踪您生成的所有纹理. glTexImage2D
获取输入数据并将其存储在视频卡存储器中.在调用glTexImage2D
之前绑定的纹理名称-用glGenTextures
生成的纹理名称是该视频卡内存块的句柄.
Assuming you're generating a new texture with glGenTextures
every time you call glTexImage2D
, you are wasting memory, and leaking it if you don't keep track of all the textures you generate. glTexImage2D
takes the input data and stores it video card memory. The texture name that you bind before calling glTexImage2D
- the one you generate with glGenTextures
is a handle to that chunk of video card memory.
如果纹理很大,并且每次使用它时都在分配新的内存来存储越来越多的副本,那么您很快就会用完内存.解决方案是在应用程序初始化期间调用glTexImage2D
一次,并且仅在要使用它时才调用glBindTexture
.如果要在单击时更改纹理本身,请仅调用glBindTexture
和glTexImage2D
.如果新图像的大小与先前图像的大小相同,则可以调用glTexSubImage2D
告诉OpenGL覆盖旧图像数据,而不是删除它并上传新图像.
If your texture is large and you're allocating new memory to store more and more copies of it every time you use it, then you will quickly run out of memory. The solution is to call glTexImage2D
once during your application's initialization and only call glBindTexture
when you want to use it. If you want to change the texture itself when you click, only call glBindTexture
and glTexImage2D
. If your new image is the same size as the previous image, you can call glTexSubImage2D
to tell OpenGL to overwrite the old image data instead of deleting it and uploading the new one.
更新
为响应您的新代码,我将使用更具体的答案来更新我的答案.您完全用错误的方式处理OpenGL纹理glGenTextures
的输出是GLuint[]
,而不是String
或char[]
.对于使用glGenTextures
生成的每个纹理,OpenGL会为您提供纹理的句柄(无符号整数).如果您使用glTexImage[1/2/3]D
为其提供数据,则此句柄会存储您使用glTexParameteri
为其提供的状态以及图形卡上的大量内存.您需要存储句柄并在要更新它时向它发送新数据.如果您覆盖手柄或忘记了它,数据仍会保留在图形卡上,但您将无法访问它.您还告诉OpenGL仅需要1时就生成3个纹理.
In response to your new code, I'm updating my answer with a more specific answer. You're dealing with OpenGL textures in the wrong way entirely The output of glGenTextures
is a GLuint[]
and not a String
or char[]
. For every texture you generate with glGenTextures
, OpenGL gives you back a handle (as an unsigned integer) to a texture. This handle stores the state you give it with glTexParameteri
as well a chunk of memory on the graphics card if you give it data with glTexImage[1/2/3]D
. It's up to you to store the handle and send it new data when you want to update it. If you overwrite the handle or forget about it, the data still stays on the graphics card but you can't access it. You're also telling OpenGL to generate 3 textures when you only need 1.
由于texture_data
具有固定大小,因此可以使用glTexSubImage2D
而不是glTexImage2D
更新纹理.这是修改您的代码,以避免此问题引起的内存泄漏:
Seeing as texture_data
is of a fixed size, you can update the texture with glTexSubImage2D
instead of glTexImage2D
. Here is your code modified to avoid the memory leak from this issue:
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);
这篇关于如何在OpenGL中使用纹理管理内存?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!