如何解决Python OpenGL内存泄漏问题?

问题描述

我正在尝试绘制一些框线并在屏幕上呈现一些文本。但是我观察到内存(RAM)仅在进行6次绘制调用时才逐渐增加。我有8 GB RAM。当我运行程序时,内存使用量在1分钟内从4.2变为6。这是完整的代码。

from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GL import shaders

from shader import *

import glfw
import freetype
import glm

import numpy as np
from PIL import Image
import math

class CharacterSlot:
    def __init__(self,texture,glyph):
        self.texture = texture
        self.textureSize = (glyph.bitmap.width,glyph.bitmap.rows)

        if isinstance(glyph,freetype.GlyphSlot):
            self.bearing = (glyph.bitmap_left,glyph.bitmap_top)
            self.advance = glyph.advance.x
        elif isinstance(glyph,freetype.BitmapGlyph):
            self.bearing = (glyph.left,glyph.top)
            self.advance = None
        else:
            raise RuntimeError('unknown glyph type')

def _get_rendering_buffer(xpos,ypos,w,h,zfix=0.0):
    return np.asarray([
        xpos,ypos + h,xpos,1,xpos + w,0
    ],np.float32)

def init_chars(shaderProgram,window_height,window_width,font_size=24,fontfile = "Vera.ttf"):
    glUseProgram(shaderProgram)
    
    #get projection
    shader_projection = glGetUniformLocation(shaderProgram,"projection")
    W = window_width
    H = window_height
    projection = glm.ortho(-W/2,W/2,-H/2,H/2)
    glUniformMatrix4fv(shader_projection,GL_FALSE,glm.value_ptr(projection))
    
    #disable byte-alignment restriction
    glPixelStorei(GL_UNPACK_ALIGNMENT,1)

    face = freetype.Face(fontfile)
    face.set_char_size(font_size*64 )

    #load first 128 characters of ASCII set
    Characters = dict()
    for i in range(0,128):
        face.load_char(chr(i))
        glyph = face.glyph
        
        #generate texture
        texture = glGenTextures(1)
        glBindTexture(GL_TEXTURE_2D,texture)
        glTexImage2D(GL_TEXTURE_2D,GL_RED,glyph.bitmap.width,glyph.bitmap.rows,GL_UNSIGNED_BYTE,glyph.bitmap.buffer)

        #texture options
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE)
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_TEXTURE_MIN_FILTER,GL_LINEAR)
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR)

        #now store character for later use
        Characters[chr(i)] = CharacterSlot(texture,glyph)

    glBindTexture(GL_TEXTURE_2D,0)    
    glUseProgram(0)
    
    return Characters
    
def render_text(window,shaderProgram,text,x,y,scale,Characters,color=(170,250,255)):
    r,g,b = color
    
    glUseProgram(shaderProgram)

    #configure VAO/VBO for texture quads
    VAO = glGenVertexArrays(1)
    glBindVertexArray(VAO)
    
    VBO = glGenBuffers(1)
    glBindBuffer(GL_ARRAY_BUFFER,VBO)
    glBufferData(GL_ARRAY_BUFFER,6 * 4 * 4,None,GL_STATIC_DRAW)
    glEnableVertexAttribArray(0)
    glVertexAttribPointer(0,4,GL_FLOAT,None)
    glBindBuffer(GL_ARRAY_BUFFER,0)
    glBindVertexArray(0)
    
    glUniform3f(glGetUniformLocation(shaderProgram,"textColor"),r/255,g/255,b/255) 
    glActiveTexture(GL_TEXTURE0)
    glBindVertexArray(VAO)
    
    for c in text:
        ch = Characters[c]
        w,h = ch.textureSize
        w = w*scale
        h = h*scale
        vertices = _get_rendering_buffer(x,h)

        #render glyph texture over quad
        glBindTexture(GL_TEXTURE_2D,ch.texture)
        #update content of VBO memory
        glBindBuffer(GL_ARRAY_BUFFER,VBO)
        glBufferSubData(GL_ARRAY_BUFFER,vertices.nbytes,vertices)

        glBindBuffer(GL_ARRAY_BUFFER,0)
        #render quad
        glDrawArrays(GL_TRIANGLES,6)
        #now advance cursors for next glyph (note that advance is number of 1/64 pixels)
        x += (ch.advance>>6)*scale

    glBindTexture(GL_TEXTURE_2D,0);
    glUseProgram(0)

    #UNBIND and DELETE VAO/VBO
    glBindVertexArray(0)
    glBindBuffer(GL_ARRAY_BUFFER,0)
    glDeleteBuffers(1,id(VBO))
    glDeleteBuffers(1,id(VAO))
    

def triangle(shaderProgram,window,x=0,y=0):
    vertices = [-0.5,-0.5,0.0,0.5,0.0]
    vertices = np.array(vertices,dtype=np.float32)

    VBO = glGenBuffers(1)
    glBindBuffer(GL_ARRAY_BUFFER,vertices,GL_STATIC_DRAW)

    glVertexAttribPointer(0,3,None)
    glEnableVertexAttribArray(0)

    #use shader program
    glUseProgram(shaderProgram)

    #accessing ourColor variable from shaderProgram
    vertexColorLoc = glGetUniformLocation(shaderProgram,"ourColor")
    glUniform4f(vertexColorLoc,255,28/255.0,20/255.0,0.7);

    #transform matrix
    transform = glm.mat4(1)
    transform = glm.translate(transform,glm.vec3(x,0))
    MVP = glGetUniformLocation(shaderProgram,"MVP")
    glUniformMatrix4fv(MVP,glm.value_ptr(transform))

    #drawing trangle 
    glLineWidth(3)
    glDrawArrays(GL_TRIANGLES,3)
    
    glUseProgram(0)

    #UNBIND and DELETE VAO/VBO
    glBindVertexArray(0)
    glBindBuffer(GL_ARRAY_BUFFER,id(VBO))
   

def main():
    glfw.init()
    window = glfw.create_window(640,640,"EXAMPLE PROGRAM",None)    
    glfw.make_context_current(window)
    
    #initliaze shader programs
    shaderProgram = get_shaderProgram()
    text_shaderProgram = get_text_shaderProgram()

    #load characters and VAO/VBO for text rendering
    Characters = init_chars(text_shaderProgram,640)
    #window loop
    while not glfw.window_should_close(window):
        glfw.poll_events()

        #screen
        glClearColor(0,1)
        glClear(GL_COLOR_BUFFER_BIT)
        glEnable(GL_BLEND)
        glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA)

        #draw functions
        
        render_text(window,text_shaderProgram,"TRIANGLE",-50,-200,Characters)
        render_text(window,"A",180,"B",-160,-180,"C",150,Characters)
        
        triangle(shaderProgram,window)
        triangle(shaderProgram,x=0.5,y=0.5)
        #swap buffers 
        glfw.swap_buffers(window)
        glfw.swap_interval(1)
        
    glfw.terminate()
    
if __name__ == '__main__':
    main()

着色器程序为here。但是我认为问题出在缓冲对象中。我试图通过下面的代码解除绑定VAO / VBO并删除缓冲区。但是我看不到任何变化。

    #UNBIND and DELETE VAO/VBO
    glBindVertexArray(0)
    glBindBuffer(GL_ARRAY_BUFFER,id(VAO))

以下是相关的problem,其中已接受的答案表明 glGenBuffers 会导致内存泄漏。替代功能 glCreateBuffers 在pyopengl中不可用。我该如何解决这个问题?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)