window 最小化时 OpenGL 错误 1286
OpenGL error 1286 when window is minimised
关于我正在使用的一些信息:
- Ancient Potato 集成 GPU(Intel(R) HD Graphics 系列)
- Windows 7
- OpenGL <=3.1
- Python 3.7.0
当我简单地最小化 window:
时我立即得到的错误
$ python main.py
Traceback (most recent call last):
File "main.py", line 71, in <module>
main()
File "main.py", line 60, in main
renderer.render(mesh)
File "...\myproject\renderer.py", line 22, in render
glDrawElements(GL_TRIANGLES, mesh.indices, GL_UNSIGNED_INT, ctypes.c_void_p(0))
File "...\OpenGL\latebind.py", line 41, in __call__
return self._finalCall( *args, **named )
File "...\OpenGL\wrapper.py", line 854, in wrapperCall
raise err
File "...\OpenGL\wrapper.py", line 847, in wrapperCall
result = wrappedOperation( *cArguments )
File "...\OpenGL\error.py", line 232, in glCheckError
baseOperation = baseOperation,
OpenGL.error.GLError: GLError(
err = 1286,
baseOperation = glDrawElements,
pyArgs = (
GL_TRIANGLES,
6,
GL_UNSIGNED_INT,
c_void_p(None),
),
cArgs = (
GL_TRIANGLES,
6,
GL_UNSIGNED_INT,
c_void_p(None),
),
cArguments = (
GL_TRIANGLES,
6,
GL_UNSIGNED_INT,
c_void_p(None),
)
)
当我用谷歌搜索 OpenGL errorcode 1286
时,我发现当帧缓冲区出现问题时,这会在 OpenGL 上下文中发生。这对我来说真的没有任何意义...
# renderer.py
class Renderer:
def __init__(self, colour=(0.0, 0.0, 0.0)):
self.colour = colour
@property
def colour(self):
return self._colour
@colour.setter
def colour(self, new_colour):
glClearColor(*new_colour, 1.0)
self._colour = new_colour
def render(self, mesh):
glBindVertexArray(mesh.vao_id)
glBindTexture(GL_TEXTURE_2D, mesh.texture)
glDrawElements(GL_TRIANGLES, mesh.indices, GL_UNSIGNED_INT, ctypes.c_void_p(0))
def clear(self):
glClear(GL_COLOR_BUFFER_BIT)
因为我正在使用帧缓冲区,我可能做错了什么,但我让一切都按照我想要的方式工作(渲染到纹理,然后使用纹理作为在四边形上渲染的源,也作为源将在下一帧渲染的纹理,基本上使用 GPU 来操作任意数据的网格),如果代码不清楚,我通过交换 FBO 而不是交换纹理来实现:
# bufferedtexture.py (The place where I use Frame Buffer)
class BufferedTexture:
def __init__(self, width, height):
self._width = width
self._height = height
self._textures = glGenTextures(2)
self._buffers = glGenFramebuffers(2)
self._previous_buffer = 0
self._current_buffer = 1
self.init_buffer(0)
self.init_buffer(1)
@property
def width(self):
return self._width
@property
def height(self):
return self._height
@property
def buffer(self):
return self._buffers[self._current_buffer]
@property
def texture(self):
return self._textures[self._previous_buffer]
def init_buffer(self, index):
glBindFramebuffer(GL_FRAMEBUFFER, self._buffers[index])
glBindTexture(GL_TEXTURE_2D, self._textures[index])
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, self.width, self.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, ctypes.c_void_p(0))
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, self._textures[index], 0)
def set_texture_data(self, image_data):
glBindTexture(GL_TEXTURE_2D, self.texture)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, self.width, self.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data)
def swap_buffers(self):
self._previous_buffer = self._current_buffer
self._current_buffer = (self._current_buffer + 1) % 2
def enable(self):
glBindFramebuffer(GL_FRAMEBUFFER, self.buffer)
def disable(self):
glBindFramebuffer(GL_FRAMEBUFFER, 0)
def destroy(self):
glDeleteFramebuffers(self._buffers)
glDeleteTextures(self._textures)
我用的都是这样的:
# main loop
while not window.should_close: # glfwWindowShouldClose(self.hwnd)
shader.enable() # glUseProgram(self._program)
buff.enable() # BufferedTexture object, source above
renderer.clear() # Renderer object, source above
renderer.render(mesh) # By the way, mesh is just a Quad, nothing fancy
buff.disable() # Tells driver that we will be drawing to screen again
buff.swap_buffers()
mesh.texture = buff.texture # give quad the texture that was rendered off-screen
renderer.clear()
renderer.render(mesh)
window.swap_buffers() # glfwSwapBuffers(self.hwnd)
window.poll_events() # glfwPollEvents()
我什至不知道哪里出了问题,同样,只有当我最小化 window 时才会发生这种情况,否则我可以将它留给 运行 几个小时,这很好,但是我最小化它的那一刻就死了...
我什至尝试添加
assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE)
断言(glGetError()== GL_NO_ERROR)
在BufferedTexture.init_buffer结尾快速检查是否是FBO本身的问题,但是...
$ python main.py
<no assertion errors to be found>
<same error once I minimise>
TL;DR
- 一切都按预期正确呈现;
- 没有注意到任何性能方面的问题,没有错误
在我初始化 glfw 和 openGL 的时候抛出或吞下,我
当 PyOpenGL 出现问题时(出于某种原因)一切正常,我自己引发 RuntimeError,而没有发现它;
- OpenGL 程序崩溃:1286 当我最小化 window 时,失去焦点没有任何作用,只有当我最小化它时...
发送帮助。
编辑:
mesh = Mesh(indices, vertices, uvs)
buff = BufferedTexture(800, 600)
with Image.open("cat.jpg") as image:
w, h = image.size # the image is 800x600
img_data = np.asarray(image.convert("RGBA"), np.uint8)
buff.set_texture_data(img_data[::-1])
buff.swap_buffers()
buff.set_texture_data(img_data[::-1])
mesh.texture = buff.texture # this is just GL_TEXTURE_2D object ID
buff.disable()
while not window.should_close:
shader.enable()
#buff.enable()
#renderer.clear()
#renderer.render(mesh)
#buff.disable()
#buff.swap_buffers()
#mesh.texture = buff.texture
renderer.clear()
renderer.render(mesh)
window.swap_buffers()
window.poll_events()
一旦我完全停止使用缓冲区,它就会按预期工作。我希望我的代码有问题。
有人指出(但出于某种原因删除了他们的 answers/comments),window 大小变为 0,最小化时为 0,确实如此,以防止崩溃和资源浪费当 window 最小化时,我这样做了:
为 window 调整大小创建并注册一个回调,这非常简单,因为我只使用一个 window 并且我已经将它设置为单例,回调只是告诉window要不要休眠
def callback(window, width, height):
Window.instance.sleeping = width == 0 or height == 0
(显然)为我自己的 window 注册了回调:
glfwSetFramebufferSizeCallback(self.handle, callback)
当 window 为 "sleeping" 时,我除了轮询事件外什么都不做:
while not window.should_close:
window.poll_events()
if window.sleeping:
time.sleep(0.01)
continue
shader.enable()
buff.enable()
renderer.clear()
renderer.render(mesh)
buff.disable()
buff.swap_buffers()
mesh.texture = buff.texture
renderer.clear()
renderer.render(mesh)
window.swap_buffers()
关于我正在使用的一些信息:
- Ancient Potato 集成 GPU(Intel(R) HD Graphics 系列)
- Windows 7
- OpenGL <=3.1
- Python 3.7.0
当我简单地最小化 window:
时我立即得到的错误$ python main.py
Traceback (most recent call last):
File "main.py", line 71, in <module>
main()
File "main.py", line 60, in main
renderer.render(mesh)
File "...\myproject\renderer.py", line 22, in render
glDrawElements(GL_TRIANGLES, mesh.indices, GL_UNSIGNED_INT, ctypes.c_void_p(0))
File "...\OpenGL\latebind.py", line 41, in __call__
return self._finalCall( *args, **named )
File "...\OpenGL\wrapper.py", line 854, in wrapperCall
raise err
File "...\OpenGL\wrapper.py", line 847, in wrapperCall
result = wrappedOperation( *cArguments )
File "...\OpenGL\error.py", line 232, in glCheckError
baseOperation = baseOperation,
OpenGL.error.GLError: GLError(
err = 1286,
baseOperation = glDrawElements,
pyArgs = (
GL_TRIANGLES,
6,
GL_UNSIGNED_INT,
c_void_p(None),
),
cArgs = (
GL_TRIANGLES,
6,
GL_UNSIGNED_INT,
c_void_p(None),
),
cArguments = (
GL_TRIANGLES,
6,
GL_UNSIGNED_INT,
c_void_p(None),
)
)
当我用谷歌搜索 OpenGL errorcode 1286
时,我发现当帧缓冲区出现问题时,这会在 OpenGL 上下文中发生。这对我来说真的没有任何意义...
# renderer.py
class Renderer:
def __init__(self, colour=(0.0, 0.0, 0.0)):
self.colour = colour
@property
def colour(self):
return self._colour
@colour.setter
def colour(self, new_colour):
glClearColor(*new_colour, 1.0)
self._colour = new_colour
def render(self, mesh):
glBindVertexArray(mesh.vao_id)
glBindTexture(GL_TEXTURE_2D, mesh.texture)
glDrawElements(GL_TRIANGLES, mesh.indices, GL_UNSIGNED_INT, ctypes.c_void_p(0))
def clear(self):
glClear(GL_COLOR_BUFFER_BIT)
因为我正在使用帧缓冲区,我可能做错了什么,但我让一切都按照我想要的方式工作(渲染到纹理,然后使用纹理作为在四边形上渲染的源,也作为源将在下一帧渲染的纹理,基本上使用 GPU 来操作任意数据的网格),如果代码不清楚,我通过交换 FBO 而不是交换纹理来实现:
# bufferedtexture.py (The place where I use Frame Buffer)
class BufferedTexture:
def __init__(self, width, height):
self._width = width
self._height = height
self._textures = glGenTextures(2)
self._buffers = glGenFramebuffers(2)
self._previous_buffer = 0
self._current_buffer = 1
self.init_buffer(0)
self.init_buffer(1)
@property
def width(self):
return self._width
@property
def height(self):
return self._height
@property
def buffer(self):
return self._buffers[self._current_buffer]
@property
def texture(self):
return self._textures[self._previous_buffer]
def init_buffer(self, index):
glBindFramebuffer(GL_FRAMEBUFFER, self._buffers[index])
glBindTexture(GL_TEXTURE_2D, self._textures[index])
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, self.width, self.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, ctypes.c_void_p(0))
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, self._textures[index], 0)
def set_texture_data(self, image_data):
glBindTexture(GL_TEXTURE_2D, self.texture)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, self.width, self.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data)
def swap_buffers(self):
self._previous_buffer = self._current_buffer
self._current_buffer = (self._current_buffer + 1) % 2
def enable(self):
glBindFramebuffer(GL_FRAMEBUFFER, self.buffer)
def disable(self):
glBindFramebuffer(GL_FRAMEBUFFER, 0)
def destroy(self):
glDeleteFramebuffers(self._buffers)
glDeleteTextures(self._textures)
我用的都是这样的:
# main loop
while not window.should_close: # glfwWindowShouldClose(self.hwnd)
shader.enable() # glUseProgram(self._program)
buff.enable() # BufferedTexture object, source above
renderer.clear() # Renderer object, source above
renderer.render(mesh) # By the way, mesh is just a Quad, nothing fancy
buff.disable() # Tells driver that we will be drawing to screen again
buff.swap_buffers()
mesh.texture = buff.texture # give quad the texture that was rendered off-screen
renderer.clear()
renderer.render(mesh)
window.swap_buffers() # glfwSwapBuffers(self.hwnd)
window.poll_events() # glfwPollEvents()
我什至不知道哪里出了问题,同样,只有当我最小化 window 时才会发生这种情况,否则我可以将它留给 运行 几个小时,这很好,但是我最小化它的那一刻就死了...
我什至尝试添加
assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE) 断言(glGetError()== GL_NO_ERROR)
在BufferedTexture.init_buffer结尾快速检查是否是FBO本身的问题,但是...
$ python main.py
<no assertion errors to be found>
<same error once I minimise>
TL;DR
- 一切都按预期正确呈现;
- 没有注意到任何性能方面的问题,没有错误 在我初始化 glfw 和 openGL 的时候抛出或吞下,我 当 PyOpenGL 出现问题时(出于某种原因)一切正常,我自己引发 RuntimeError,而没有发现它;
- OpenGL 程序崩溃:1286 当我最小化 window 时,失去焦点没有任何作用,只有当我最小化它时...
发送帮助。
编辑:
mesh = Mesh(indices, vertices, uvs)
buff = BufferedTexture(800, 600)
with Image.open("cat.jpg") as image:
w, h = image.size # the image is 800x600
img_data = np.asarray(image.convert("RGBA"), np.uint8)
buff.set_texture_data(img_data[::-1])
buff.swap_buffers()
buff.set_texture_data(img_data[::-1])
mesh.texture = buff.texture # this is just GL_TEXTURE_2D object ID
buff.disable()
while not window.should_close:
shader.enable()
#buff.enable()
#renderer.clear()
#renderer.render(mesh)
#buff.disable()
#buff.swap_buffers()
#mesh.texture = buff.texture
renderer.clear()
renderer.render(mesh)
window.swap_buffers()
window.poll_events()
一旦我完全停止使用缓冲区,它就会按预期工作。我希望我的代码有问题。
有人指出(但出于某种原因删除了他们的 answers/comments),window 大小变为 0,最小化时为 0,确实如此,以防止崩溃和资源浪费当 window 最小化时,我这样做了:
为 window 调整大小创建并注册一个回调,这非常简单,因为我只使用一个 window 并且我已经将它设置为单例,回调只是告诉window要不要休眠
def callback(window, width, height):
Window.instance.sleeping = width == 0 or height == 0
(显然)为我自己的 window 注册了回调:
glfwSetFramebufferSizeCallback(self.handle, callback)
当 window 为 "sleeping" 时,我除了轮询事件外什么都不做:
while not window.should_close:
window.poll_events()
if window.sleeping:
time.sleep(0.01)
continue
shader.enable()
buff.enable()
renderer.clear()
renderer.render(mesh)
buff.disable()
buff.swap_buffers()
mesh.texture = buff.texture
renderer.clear()
renderer.render(mesh)
window.swap_buffers()