如何在opengl中使用纹理管理内存?

Sha*_*han 18 opengl textures

在我的应用程序中,我广泛使用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);
Run Code Online (Sandbox Code Playgroud)

我希望你的近距离请求和投票现在停止!

Rob*_*ani 44

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

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

UPDATE

为了回应您的新代码,我正在用更具体的答案更新我的答案.你完全以错误的方式处理OpenGL纹理输出glGenTextures是a GLuint[]而不是a 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);
Run Code Online (Sandbox Code Playgroud)

  • 是的,所有处理纹理的方法(以及稍后使用缓冲区对象,着色器,程序等......需要`glGen*`调用的任何东西)只会影响与`glBindTexture`绑定的纹理.这是OpenGL的一般结构.如果你想停止使用那个纹理并且你不想用另一个纹理替换它,你可以通过将0传递给`glBindTexture`而不是纹理句柄来取消绑定. (3认同)