【问题标题】:How can I "blit" my Pygame game onto an OpenGL surface?如何将我的 Pygame 游戏“blit”到 OpenGL 表面上?
【发布时间】:2020-08-07 08:14:43
【问题描述】:

我围绕 Pygame 构建了我的整个游戏,并希望将它放到 Steam 上。最后我了解到,我需要 OpenGL 支持才能运行 Steam 的 Overlay。初始化显示的代码:

screen = pygame.display.set_mode((screen_width, screen_height), HWSURFACE | DOUBLEBUF | OPENGL)

有什么方法可以创建一个 OpenGL 表面并将我的整个游戏 blit 到该表面上,这样我就可以获得 OpenGL 功能(Steam Overlay),而无需重做大量代码并重新创建大量游戏?游戏不使用很多资源,所以我认为不会有太大的延迟(希望如此),所以这绝对是我想尝试的路线。

除了在不同的库中重做游戏之外,我还有其他选择吗?

【问题讨论】:

  • 你可以将“屏幕”表面纹理映射到一个矩形上。 PyGame OpenGL 支持是否使用硬件?否则我会很慢。 BTW:什么是“Steam 的叠加层”?
  • Steam Overlay - 通过 Steam 应用运行游戏时按下 shift+tab 时

标签: python opengl pygame blit


【解决方案1】:

基于这个问题:Draw rectangle over texture OpenGL 讨论了 PyGame 中 OpenGL 矩形的纹理映射 ~

这是一些绘制到“屏幕外”PyGame 表面的代码。在每次主循环迭代中,该表面被转换为 OpenGL 纹理贴图。然后将此纹理贴图映射到填充屏幕的矩形上。

代码是一个相当简单的示例,也许您需要对其进行一些优化。

import pygame
import sys
from OpenGL.GL import *
from pygame.locals import *

# set pygame screen
pygame.init()
pygame.display.set_mode((500, 500), OPENGL | DOUBLEBUF)
pygame.display.init()
info = pygame.display.Info()

#colours
MIDNIGHT = (  15,   0, 100 )
BUTTER   = ( 255, 245, 100 )

# basic opengl configuration
glViewport(0, 0, info.current_w, info.current_h)
glDepthRange(0, 1)
glMatrixMode(GL_PROJECTION)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
glShadeModel(GL_SMOOTH)
glClearColor(0.0, 0.0, 0.0, 0.0)
glClearDepth(1.0)
glDisable(GL_DEPTH_TEST)
glDisable(GL_LIGHTING)
glDepthFunc(GL_LEQUAL)
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)
glEnable(GL_BLEND)


###
### Function to convert a PyGame Surface to an OpenGL Texture
### Maybe it's not necessary to perform each of these operations
### every time.
###
texID = glGenTextures(1)
def surfaceToTexture( pygame_surface ):
    global texID
    rgb_surface = pygame.image.tostring( pygame_surface, 'RGB')
    glBindTexture(GL_TEXTURE_2D, texID)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP)
    surface_rect = pygame_surface.get_rect()
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, surface_rect.width, surface_rect.height, 0, GL_RGB, GL_UNSIGNED_BYTE, rgb_surface)
    glGenerateMipmap(GL_TEXTURE_2D)
    glBindTexture(GL_TEXTURE_2D, 0)


# create pygame clock
clock = pygame.time.Clock()

# make an offscreen surface for drawing PyGame to
offscreen_surface = pygame.Surface((info.current_w, info.current_h))
text_font = pygame.font.Font( None, 30 ) # some default font

done = False
while not done:
    # get quit event
    for event in pygame.event.get():
        if event.type == QUIT:
            done = True

    # Do all the PyGame operations to the offscreen surface
    # So any backgrounds, sprites, etc. will get drawn to the offscreen
    # rather than to the default window/screen.
    offscreen_surface.fill( MIDNIGHT )
    # write some nonsense to put something changing on the screen
    words = text_font.render( "β-Moé-Moé count: "+str( pygame.time.get_ticks() ), True, BUTTER )
    offscreen_surface.blit( words, (50, 250) )


    # prepare to render the texture-mapped rectangle
    glClear(GL_COLOR_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)

    # draw texture openGL Texture
    surfaceToTexture( offscreen_surface )
    glBindTexture(GL_TEXTURE_2D, texID)
    glBegin(GL_QUADS)
    glTexCoord2f(0, 0); glVertex2f(-1, 1)
    glTexCoord2f(0, 1); glVertex2f(-1, -1)
    glTexCoord2f(1, 1); glVertex2f(1, -1)
    glTexCoord2f(1, 0); glVertex2f(1, 1)
    glEnd()

    pygame.display.flip()
    clock.tick(60)

pygame.quit()

【讨论】:

  • 谢谢!那行得通!由于之前的纹理,我肯定需要考虑优化它确实会在更改游戏视图时产生一点延迟。我将不得不在那里研究我的选择。再次感谢!
猜你喜欢
  • 1970-01-01
  • 2022-11-04
  • 2013-02-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-05
  • 2015-01-31
相关资源
最近更新 更多