how to manage memory with texture in opengl?

后端 未结 1 1122
-上瘾入骨i
-上瘾入骨i 2021-01-31 04:59

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 arr

相关标签:
1条回答
  • 2021-01-31 05:18

    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.

    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.

    UPDATE

    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.

    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);
    
    0 讨论(0)
提交回复
热议问题