如何在OpenGL中使用纹理管理内存? [英] how to manage memory with texture in opengl?

查看:475
本文介绍了如何在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.如果要在单击时更改纹理本身,请仅调用glBindTextureglTexImage2D.如果新图像的大小与先前图像的大小相同,则可以调用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[],而不是Stringchar[].对于使用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆