发布
社区首页 >问答首页 >如何利用opengl中的纹理来管理内存?

如何利用opengl中的纹理来管理内存?
EN

Stack Overflow用户
提问于 2012-06-26 22:59:22
回答 1查看 32.5K关注 0票数 26

在我的应用程序中,我广泛地使用了glTexImage2D。我复制图像的一些图像,并将其呈现为纹理,我经常在鼠标单击时这样做。我把它作为一个字节数组来呈现。内存正在被消耗,交换内存也被分配。是内存泄露吗?或者是因为glTexImage2D保存了任何引用或其他任何东西。

编辑:

代码语言:javascript
复制
    //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);

我希望你的结束请求和投票会停止现在!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-06-26 23:10:46

假设每次调用glGenTextures时都要用glTexImage2D生成一个新的纹理,那么如果不跟踪生成的所有纹理,就会浪费内存,并泄漏内存。glTexImage2D接收输入数据并存储它的视频卡内存。在调用glTexImage2D之前绑定的纹理名称--使用glGenTextures生成的纹理名称是该视频卡内存块的句柄。

如果您的纹理很大,并且每次使用它时都分配新的内存来存储越来越多的副本,那么您很快就会耗尽内存。解决方案是在应用程序初始化期间调用glTexImage2D一次,并且只在您想要使用它时调用glBindTexture。如果要在单击时更改纹理本身,只需调用glBindTextureglTexImage2D。如果您的新图像与以前的图像大小相同,则可以调用glTexSubImage2D告诉OpenGL覆盖旧的图像数据,而不是删除和上传新的图像数据。

更新

为了响应您的新代码,我正在用一个更具体的答案更新我的答案。您正在错误地处理OpenGL纹理-- glGenTextures的输出是GLuint[],而不是Stringchar[]。对于使用glGenTextures生成的每个纹理,OpenGL都会为纹理返回一个句柄(作为一个无符号整数)。如果您用glTexParameteri提供数据,这个句柄会将您给它的状态存储在图形卡上的内存块上。当您想要更新句柄时,应该由您存储句柄并将其发送给它。如果您覆盖句柄或忘记它,数据仍然保留在图形卡上,但您无法访问它。当你只需要1的时候,你也告诉OpenGL生成3种纹理。

由于texture_data的大小是固定的,您可以使用glTexSubImage2D而不是glTexImage2D来更新纹理。下面是您修改的代码,以避免此问题造成内存泄漏:

代码语言:javascript
复制
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);
票数 53
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11217121

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档