编辑2-已解决 看来这是已修复的已知GDK Win32错误。现在,由于我使用的是最新版本的PyGObject多合一安装程序,因此我只需要弄清楚如何修补或更新。
END EDIT 2
我在Win7上使用Pygobject,并且在创建多个顶层窗口时,如果使用GLArea小部件,则gl命令似乎都在我创建的最后一个窗口上绘制。我正在分别编译着色器。我从on_render()方法内部调用gl代码,这应该意味着GLArea的上下文是最新的。我什至尝试调用具有相同结果的make_current()方法。甚至更奇怪的是,最后一个窗口绘制似乎“窃取”了Gtk.Widget的上下文,并且所有Windows窗口小部件都绘制在一个上。这似乎是Windows上gtk的一个错误,但是我没有足够的经验说我没有违反某些gl或gtk规则。我还找到了相关的GTK +帖子,所以我想这可能是一个重复的问题。 GTK3 + OpenGL for windows: multiple GtkGLArea (ie. OpenGL contexts) 那条帖子没有答案。
编辑1
我在linux(Mint 18.1)中尝试了此确切的代码,并且可以正常工作。我还在单个窗口上尝试了多个GLAreas,并且没有问题。我调试了render方法,以查看正在使用的上下文,窗口和眩光对象。它们都符合应有的条件。我试图查看所有上下文是否具有相同的窗口,但事实并非如此。即使上下文的窗口不同并且正确的上下文是“当前”,窗口系统似乎也绘制在同一窗口上。
END EDIT1
这是我的代码:
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk, GObject
settings = Gtk.Settings.get_default()
settings.set_property("gtk-application-prefer-dark-theme", True)
from OpenGL.GL import *
from OpenGL.GL import shaders
import numpy as np
class MyGLArea(Gtk.GLArea):
def __init__(self, window):
self.window = window # use for to to context and window
super(MyGLArea, self).__init__()
self.shader_prog = None
self.realized = False
self.vao = None
self.data_loaded = None
self.vert_data = None
self.connect("realize", self.on_realize)
self.connect("render", self.on_render)
def compile_shaders(self):
vert_source = '''
#version 410
in vec4 vert;
in vec4 in_color;
out vec4 color;
void main () {
color = in_color;
gl_Position = vert;
}
'''
vert_shader = shaders.compileShader(vert_source, GL_VERTEX_SHADER)
frag_source = '''
#version 410
in vec4 color;
out vec4 fColor;
void main () {
fColor = color;
}'''
frag_shader = shaders.compileShader(frag_source, GL_FRAGMENT_SHADER)
self.shader_prog = shaders.compileProgram(vert_shader, frag_shader)
def on_realize(self, area):
self.realized = True
def on_render(self, area, context):
if not self.shader_prog:
self.compile_shaders()
if not self.vao:
self.vao = glGenVertexArrays(1)
if not self.data_loaded:
# make some verts
self.vert_data = np.array([-0.6, -0.6, 0.0, 1.0,
0.0, 0.6, 0.0, 1.0,
0.6, -0.6, 0.0, 1.0,
-0.6, -0.6, 0.0, 1.0,
], dtype=np.float32)
# Generate buffer to hold vertices
vbo = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, vbo)
glBufferData(GL_ARRAY_BUFFER, len(self.vert_data) * sizeof(GLfloat), None, GL_STATIC_DRAW)
glBindVertexArray(self.vao)
# bind buffer
glBindBuffer(GL_ARRAY_BUFFER, vbo)
#stuff buffer
glBufferSubData(GL_ARRAY_BUFFER,
0 * sizeof(GLfloat), #offset
len(self.vert_data) * sizeof(GLfloat),
self.vert_data)
vert_ID = glGetAttribLocation(self.shader_prog, 'vert')
glVertexAttribPointer(vert_ID, 4, GL_FLOAT, 0, 0, ctypes.c_void_p(0))
glEnableVertexAttribArray(vert_ID)
glBindBuffer(GL_ARRAY_BUFFER, 0)
glBindVertexArray(0)
self.data_loaded = True
#draw every render
glBindVertexArray(self.vao)
color_ID = glGetAttribLocation(self.shader_prog, 'in_color')
# set color
if color_ID >= 0:
glVertexAttrib4f(color_ID, 1.0,0.0,0.0,1.0)
else:
print('gl color attrib failure')
glUseProgram(self.shader_prog)
glLineWidth(2)
glDrawArrays(GL_LINE_STRIP, 0, len(self.vert_data)/4)
glBindVertexArray(0)
glUseProgram(0)
for x in range(3):
win = Gtk.Window()
win.connect("delete-event", Gtk.main_quit)
box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
box.pack_start(MyGLArea(win), 1, 1, 0)
box.pack_start(Gtk.Label('WTF???'), 0, 0, 0)
win.set_title(str(win))
win.add(box)
win.show_all()
Gtk.main()