实现 pyglet 会破坏我曾经工作的帧缓冲区 OpenGL 代码

Posted

技术标签:

【中文标题】实现 pyglet 会破坏我曾经工作的帧缓冲区 OpenGL 代码【英文标题】:Implementing pyglet breaks my once working framebuffer OpenGL code 【发布时间】:2010-03-23 17:58:38 【问题描述】:

这个问题重复了我之前的问题,但是我之前的问题是失败的,因为我没有正确复制一些重要信息,所以我必须重做。

我在调用 OpenGL 函数时遇到错误。也许 pyglet 没有正确初始化 OpenGL?错误发生在之前有效的简单函数中:

 def setup_framebuffer(surface):
   #Create texture if not done already
   if surface.texture is None:
      create_texture(surface)
   #Render child to parent
   if surface.frame_buffer is None:
      surface.frame_buffer =  glGenFramebuffersEXT(1)
   glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, surface.frame_buffer)
   glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, surface.texture, 0)
   glPushAttrib(GL_VIEWPORT_BIT)
   glViewport(0,0,surface._scale[0],surface._scale[1])
   glMatrixMode(GL_PROJECTION)
   glLoadIdentity() #Load the projection matrix
   gluOrtho2D(0,surface._scale[0],0,surface._scale[1])

错误是:

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,surface.frame_buffer) ctypes.ArgumentError: 参数 2: : 错误类型

类型错误?那么现在 glGenFramebuffersEXT(1) 是否给出了错误的类型?为什么会这样?

在调用该函数之前,我初始化了一个管理我的游戏的类实例。下面是 init 方法:

pyglet.options['audio'] = ('alsa','openal','directsound','silent')
  self.keys = [False] * 323
  self.events = []
  self.title = title
  self.game_size = game_size
  self.first_screen = (1280,720) #Take 120 pixels from the height because the menu bar, window bar and dock takes space
  config = pyglet.gl.Config(alpha_size=8,double_buffer=True,sample_buffers=1,samples=4)
  self.window = pyglet.window.Window(game_size[0],game_size[1],title,True,config=config)
  self.window.set_handler('on_draw',self.game_loop)
  self.window.set_handler('on_resize',self.reshaped)
  self.window.set_handler('on_key_press',self.keydown)
  self.window.set_handler('on_key_release',self.keyup)
  self.window.set_handler('on_mouse_press',self.mouse_func)
  glViewport(0,0,self.first_screen[0],self.first_screen[1]) #Creates the viewport which is mapped to the window
  glEnable(GL_BLEND) #Enable alpha blending
  glEnable(GL_TEXTURE_2D) #Enable 2D Textures
  glEnable(GL_MULTISAMPLE) #Enable Multisampling anti-aliasing
  glEnable(GL_POLYGON_SMOOTH) #Enable antialiased polygons
  glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST)
  glHint(GL_LINE_SMOOTH_HINT, GL_NICEST)
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
  glMatrixMode(GL_PROJECTION)
  glLoadIdentity() #Load the projection matrix
  gluOrtho2D(0,1280,720,0) #Set an orthorgraphic view
  self.game_gap = (0,0)
  self.on_exit = on_exit
  self.mod_key = 1024 if sys.platform == "darwin" else 64
  Surface.__init__(self,game_size)
  self.screen_change = True
  self.frames = [time.time()]
  self.fps = 60
  self.last_time = 0
  self.fade_surface = Surface([1280,720])
  pyglet.font.add_file(os.path.dirname(sys.argv[0]) + "/NEUROPOL.ttf")
  pyglet.font.load('NEUROPOL')

Surface 是我创建的一个类,它的行为有点像 pygame.Surface 类,但使用的是 OpenGL 纹理。

该方法设置了 Window 和 OpenGL(可能不正确,这是问题所在?),在调用它之后,我为我的游戏设置了一些东西,它使用 setup_framebuffer 函数渲染到纹理。然后调用 pyglet.app.run() 应该希望运行我的 game_loop 方法,因为我做了 self.window.set_handler('on_draw,self.game_loop) 但我的游戏在它到达之前崩溃了。

这是我第一次使用 pyglet。该文档没有向我解释我做错了什么。有人可以帮忙吗?

谢谢。

【问题讨论】:

为什么不直接编辑你之前的问题? 现在已经一天了,有人会看吗?我真的不能冒这个遗憾的风险,因为我将它用于我的 A2 计算项目,而 pyglet 似乎是解决一些剩余问题的唯一方法。我只有 4 周的时间来做这件事,而且我还需要写一些关于测试的文章。 您应该更新或删除您之前的问题,以免人们在上面浪费时间。 如果您可以让更多人对此问题投反对票(因为这是同一作者故意欺骗),然后作者删除该问题,他将收到“同行压力”徽章!一起让它成为现实!解雇那些投反对票的人,你们是在帮他一个忙! 【参考方案1】:

glBindFramebufferEXT 需要指向缓冲区的指针。 AFAIK,在这种情况下你必须使用ctypes。

from pyglet.gl import *
from ctypes import c_uint, byref

fb = c_uint()
glGenFramebuffersEXT(1, byref(fb))
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb) 

搜索pyglet mailing list 以获得更好的示例。顺便说一句:

>> glGenFramebuffersEXT(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: this function takes at least 2 arguments (1 given)

编辑: 我应该猜到你在使用 pyOpenGL:

fb = int(glGenFramebuffersEXT(1))
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb)

【讨论】:

我一直在使用 from OpenGL.GL.EXT.framebuffer_object import * 和其他来自 pyOpenGL 的导入。我从中认为 from pyglet.gl import * 提供了相同的功能,但应该有细微的差别。所以 pyglet 带有它自己的与 pyOpenGL 不同的 OpenGL 包装器? “surface.texture = glGenTextures(1) TypeError: 这个函数至少需要 2 个参数(1 个给定)” 非常感谢。感谢您的帮助。 看来我还有更多需要改变的地方。看起来 pyglet 的 OpenGL 接口比 pyOpenGL 更接近其他语言。在某些方面更好,但大多数情况下它很烦人,因为 pyOpenGL 更有意义。无需导入 cTypes 一开始。 是的,pyglet 有它自己的包装器。来自 pyglet docs 的引用:该接口由 pyglet.gl 包提供。要使用它,您需要对 OpenGL、C 和 ctypes 有很好的了解。您可能更喜欢使用 OpenGL 而不使用 ctypes,在这种情况下,您应该研究 PyOpenGL。 PyOpenGL 提供了类似的功能,具有更“Pythonic”的界面,并且无需任何修改即可与 pyglet 一起使用。 “PyOpenGL 提供了类似的功能和更“Pythonic”的接口,并且无需任何修改即可与 pyglet 一起使用必须使用目前没有任何问题的 pyglet 版本。 PyOpenGL 和 pyglet 可以完美地协同工作,我的意思是 PyOpenGL 将愉快地使用通过打开 pyglet 窗口提供的 OpenGL 上下文,并且您可以将使用 pyglet 的 OpenGL 调用与使用 PyOpenGL 的调用交错.但是,其中一个并不是另一个的直接替代品,因为正如您所注意到的,PyOpenGL 提供了更方便的 API。

以上是关于实现 pyglet 会破坏我曾经工作的帧缓冲区 OpenGL 代码的主要内容,如果未能解决你的问题,请参考以下文章

WebGL:在带有深度模板纹理附件的帧缓冲区上未清除颜色

iOS OpenGL ES Analyzer 列出“不存在的帧缓冲区附件”和“缺少帧缓冲区附件”,但 FBO 工作

WebGL:显示深度纹理

如何从 OpenGL 中的帧缓冲区纹理中采样像素?

将模板渲染缓冲区绑定到opengl中的帧缓冲区

获取最大数量的帧缓冲区颜色附件?