【问题标题】:Blitted OpenGL Textures take less memory and CPUBlitted OpenGL 纹理占用更少的内存和 CPU
【发布时间】:2015-04-16 01:09:12
【问题描述】:

我正在使用 pygame + pyopengl 制作游戏,现在我正在尝试在此背景下制作视频播放器。为此,我使用 ffmpeg 加载不同的视频格式,然后将每一帧转换为 opengl 纹理,如下所示,然后播放视频。

class Texture(object):
    def __init__(self, data, w=0, h=0):
        """
        Initialize the texture from 3 diferents types of data:
        filename = open the image, get its string and produce texture
        surface = get its string and produce texture
        string surface = gets it texture and use w and h provided
        """
        if type(data) == str:
            texture_data = self.load_image(data)

        elif type(data) == pygame.Surface:
            texture_data = pygame.image.tostring(data, "RGBA", True)
            self.w, self.h = data.get_size()

        elif type(data) == bytes:
            self.w, self.h = w, h
            texture_data = data

        self.texID = 0
        self.load_texture(texture_data)

    def load_image(self, data):
        texture_surface = pygame.image.load(data).convert_alpha()
        texture_data = pygame.image.tostring(texture_surface, "RGBA", True)
        self.w, self.h = texture_surface.get_size()

        return texture_data

    def load_texture(self, texture_data):
        self.texID = glGenTextures(1)

        glBindTexture(GL_TEXTURE_2D, self.texID)
        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_RGBA, self.w,
                     self.h, 0, GL_RGBA, GL_UNSIGNED_BYTE,
                     texture_data)

问题是当我加载给定视频的所有纹理时,我的 RAM 超出了天花板,大约 800mb。但是可以通过在加载每个纹理时对其进行 blitting 来解决此问题,如下所示。

def render():
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
    glLoadIdentity()
    glDisable(GL_LIGHTING)
    glEnable(GL_TEXTURE_2D)
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
    glClearColor(0, 0, 0, 1.0)

def Draw(texture, top, left, bottom, right):
    """
    Draw the image on the Opengl Screen
    """
    # Make sure he is looking at the position (0,0,0)
    glBindTexture(GL_TEXTURE_2D, texture.texID)
    glBegin(GL_QUADS)

    # The top left of the image must be the indicated position
    glTexCoord2f(0.0, 1.0)
    glVertex2f(left, top)

    glTexCoord2f(1.0, 1.0)
    glVertex2f(right, top)

    glTexCoord2f(1.0, 0.0)
    glVertex2f(right, bottom)

    glTexCoord2f(0.0, 0.0)
    glVertex2f(left, bottom)

    glEnd()

定义更新(t): 使成为() 绘制(t, -0.5, -0.5, 0.5, 0.5)

# Check for basic Events on the pygame interface
for event in pygame.event.get():
    BASIC_Game.QUIT_Event(event)

pygame.display.flip()

虽然这会将 RAM 消耗降低到可接受的值,但它会使加载时间大于视频长度。

我真的不明白为什么 opengl 会这样工作,但是有没有一种方法可以在不先 blitting 的情况下提高纹理效率?

【问题讨论】:

    标签: opengl python-3.x ffmpeg pygame pyopengl


    【解决方案1】:

    根据您现在问题中的代码,我无法确定,但我猜这是因为您正在为每个帧创建一个新的 Texture 实例,这意味着您为视频的每一帧重新调用 glGenTextures(1)。这会在内存中为视频的每一帧分配一个新缓冲区,然后存储该帧的完整未压缩版本。

    当您对图像进行 blit 时,您不会生成新纹理,而只是覆盖旧纹理。这是您想要的解决方案,但您实施它的方式效率低下。

    您可以通过多种方式更改纹理中的数据,而无需在 CPU 上进行 blitting(假设 pygame blitting)以加快速度,其中一些列在此答案中:

    https://stackoverflow.com/a/13248668/1122135

    【讨论】:

    • 嗯,这就是我的意思。现在我正在尝试实现一个 FBO 接口,但我在实现它时遇到了一些麻烦。你有什么教程或示例代码可以推荐吗?
    • Render-to-texture 是那些实际上可能会引入开销的解决方案中的一种,因为它旨在将 3d 场景绘制到纹理上。您应该尝试 glTexSubImage2d,如果不够快,请尝试 PBO
    猜你喜欢
    • 1970-01-01
    • 2014-05-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-15
    • 1970-01-01
    相关资源
    最近更新 更多