在Pygobject GTK3中使用Gtk.GLArea [英] Use of the Gtk.GLArea in Pygobject GTK3

查看:295
本文介绍了在Pygobject GTK3中使用Gtk.GLArea的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

GTK3 python包装的使用文件有一定的限制。我找到了几个常用的小部件示例。我正在尝试使用Gtk.GLArea小部件。 API文档是针对C语言的,我没有太多的运气猜测等效的python调用来使用这个小部件。在这个例子中,小部件是使用以下C代码创建的:

  //创建一个GtkGLArea实例
GtkWidget * gl_area = gtk_gl_area_new();
g_signal_connect(gl_area,render,G_CALLBACK(render),NULL);

然后渲染函数中有openGL命令:

  static gboolean 
render(GtkGLArea * area,GdkGLContext * context)
{
//这个函数内部使用GL是安全的;给定的
// #GdkGLContext已经被赋值为#GtkGLArea使用的可绘制
//表面,并且该视口具有
// //已经被设置为分配的大小

//我们可以通过清除缓冲区
glClearColor(0,0,0,0)开始;
glClear(GL_COLOR_BUFFER_BIT);

//绘制对象
draw_an_object();

//我们完成了绘图;绘制命令将在信号发射链的末端被
//刷新,并且
//缓冲器将被绘制在窗口上
返回TRUE;
}

我的问题是你如何在python中做同样的事情?



这是我的尝试:

  class RootWidget(Gtk.Window):
def __init __(self):
Gtk.Window .__ init __(self,title ='GL Example')
self.set_default_size(800,500)
gl = Gtk.GLArea()
gl.connect(render,self.gl_render)
self.add(gl)


def gl_render(self,gl):
print( gl)
Gtk.glClearColor(0,0,0,1)
Gtk.glClear(Gtk.GL_COLOR_BUFFER_BIT)
return True

您会注意到我添加了Gtk。到gl命令。不知道这是否正确,但python不知道函数中的glClearColor是什么。我对C命名空间并不是很熟悉,但我无法弄清楚C函数如何理解gl命令。该程序确实运行,并在控制台中收到以下错误:


fb设置不受支持



(python.exe:120048):Gdk-WARNING **:在片段
着色器中编译失败:



错误:0:5: 'gl_FragColor':未声明的标识符



错误:0:5:'texture2D':找不到匹配的重载函数(使用
隐式转换)


对此的任何输入都会有用。我希望能够使用opengl命令来绘制一个固定的小部件区域。

编辑:
这是我最近的尝试。在 on_render()函数中,我打印上下文,并且看到上下文属性设置为0x3f133f0>上的< gtk.gdk.Win32GLContext对象。 ; 和调试确实表明这是当前上下文。问题是我仍然得到相同的着色器,Frag_Color和纹理错误,我甚至没有调用任何gl命令。

 进口gi 
gi.require_version('Gtk','3.0')
from gi.repository从OpenGL.GL中导入Gtk
导入*从OpenGL.GLU中导入*
导入*


class MyGLArea(Gtk.GLArea):
def __init __(self ):
Gtk.GLArea .__ init __(self)
self.connect(realize,self.on_realize)


def on_realize(self,area):
ctx = self.get_context()
ctx.make_current()
print(context is {}。format(self.get_property(context)))
err = self.get_error()
if err:
print(err)
return


$ b $ class RootWidget(Gtk.Window) :
def __init __(self):
Gtk.Window .__ init __(self,title ='GL Example')
self.set_default_size(800,500)
gl_area = MyGLArea()
self.add(gl_area)


win = RootWidget()
win.connect(delete-event,Gtk.main_quit)
win。 show_al l()
Gtk.main()

编辑2:
好​​像如果我只是有GLArea小部件的安装问题。似乎很奇怪,因为我使用了30多个不同的Gtk小部件而没有问题。我有错误只是添加小部件,甚至不发送命令。我在Ubuntu python解释器中运行代码,并且在创建小部件时没有任何错误。我对某些GL命令有一些问题,但可能来自我安装的python包装。我仍在寻找相当于pygame或glut的初始化和设置投影函数来设置视口的小部件。如果有人有想法,我很乐意听到他们的意见。以下代码运行时没有错误:

  import gi 
gi.require_version('Gtk','3.0')
from gi.repository从OpenGL.GL中导入Gtk
导入*从OpenGL.GLU导入*
*


class MyGLArea(Gtk.GLArea):
def __init __(self):
Gtk.GLArea .__ init __(self)
self.connect(realize,self.on_realize)
self.connect(render, self.render)


def on_realize(self,area):
ctx = self.get_context()
ctx.make_current()
err = self.get_error()
if err:
print(error is {}。format(err))

def render(self,area,ctx):
glClearColor(1,0,0,1)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
返回True

class RootWidget(Gtk.Window):
def __init __(self):
Gtk.Window .__ init __(self,title ='GL Example')
self.set_default_size(800 ,500)
gl_area = MyGLArea()
self.add(gl_area)
$ b $ win = RootWidget()
win.connect(delete-event,Gtk .main_quit)
win.show_all()
Gtk.main()


解决方案

使用Windows的多功能一体化安装程序我注意到OpenGL扩展到GTK +有一个选项。现在它按预期工作。
以下是一些工作代码:

$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ gi.require_version('Gtk','3.0' )从gi.repository中导入
从OpenGL.GL中导入Gtk
从OpenGL.GL中导入*
导入着色器
导入numpy作为np

FRAGMENT_SOURCE =' ''
#version 330
in vec4 inputColor;
out vec4 outputColor;
void main(){
outputColor = vec4(1.0,0.0,0.0,1.0); //常量为红色。我知道这是一个可怜的着色器
};'''

VERTEX_SOURCE ='''
#version 330
in vec4 position;
void main(){
gl_Position = position;
}'''

class MyGLArea(Gtk.GLArea):
def __init __(self):
Gtk.GLArea .__ init __(self)
self.connect(realize,self.on_realize)
self.connect(render,self.on_render)

def on_realize(self,area):
ctx = self.get_context()
print(已实现,ctx)

def on_render(self,area,ctx):
ctx.make_current()
glClearColor 0,0,0,1)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
VERTEX_SHADER_PROG = shaders.compileShader(VERTEX_SOURCE,GL_VERTEX_SHADER)
FRAGMENT_SHADER_PROG = shaders.compileShader(FRAGMENT_SOURCE,GL_FRAGMENT_SHADER)
self.shader_prog = shaders.compileProgram(VERTEX_SHADER_PROG,FRAGMENT_SHADER_PROG)
self.create_object()

高清create_object(个体经营):
#创建一个新的VAO(顶点数组对象)绑定
vertex_array_object = glGenVertexArrays (1)
glBindVertexArray(vertex_array_object)
#生成缓冲区来承载我们的顶点
vertex_buffer = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER,vertex_buffer)
#获取位置在我们着色器的参数中的'位置'并绑定它。
位置= glGetAttribLocation(self.shader_prog, '位置')
glEnableVertexAttribArray(位置)
#在缓冲器
glVertexAttribPointer(位置,3描述的位置数据布局,GL_FLOAT,假,0,ctypes.c_void_p(0))
#将数据发送到缓冲区
vertices = np.array([ - 0.6,-0.6,0.0,
0.0,0.6,0.0 ,
0.6,-0.6,0.0,
0.7,-0.1,0.0,
0.8,0.1,0.0,
0.9,-0.1,0.0
],dtype = np.float32)
glBufferData(GL_ARRAY_BUFFER,96,顶点GL_STATIC_DRAW)
#第一解除绑定的VAO(重要)
glBindVertexArray(0)
#解除绑定其他的东西
glDisableVertexAttribArray(position)




glBindBuffer(GL_ARRAY_BUFFER,0)
self.display(vertex_array_object)

def display(self,vert):
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glUseProgram(self.shader_prog)
glBindVertexArray(垂直)
(4,8 GL_TRIANGLES,0,3)
(4,8 GL_TRIANGLES,4,3)
glBindVertexArray( 0)
glUseProgram(0)

class RootWidget(Gtk.Window):
def __init __(self):
Gtk.Window .__ init __(self,title = '实施例GL')
self.set_default_size(800,500)
gl_area = MyGLArea()
gl_area.set_has_depth_buffer(假)
gl_area.set_has_stencil_buffer(假)
self.add(gl_area)

win = RootWidget()
win.connect(delete-event,Gtk.main_quit)
win.show_all()
Gtk.main()



The documentation for use of the python wrappers for GTk3 are somewhat limited. I have found several of the common widget examples. I am trying to use the Gtk.GLArea widget. The API documentation is for C and I have not had much luck guessing the equivalent python calls to use this widget. In the example the widget is created using the following C code:

 // create a GtkGLArea instance
GtkWidget *gl_area = gtk_gl_area_new ();
g_signal_connect (gl_area, "render", G_CALLBACK (render), NULL);

Then the render function has openGL commands in it:

static gboolean
render (GtkGLArea *area, GdkGLContext *context)
{
  // inside this function it's safe to use GL; the given
  // #GdkGLContext has been made current to the drawable
  // surface used by the #GtkGLArea and the viewport has
  // already been set to be the size of the allocation

  // we can start by clearing the buffer
  glClearColor (0, 0, 0, 0);
  glClear (GL_COLOR_BUFFER_BIT);

  // draw your object
  draw_an_object ();

  // we completed our drawing; the draw commands will be
  // flushed at the end of the signal emission chain, and
  // the buffers will be drawn on the window
  return TRUE;
}

My question is how do you do the equivalent in python?

This is my attempt:

class RootWidget(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self, title='GL Example')
        self.set_default_size(800,500)
        gl = Gtk.GLArea()
        gl.connect("render", self.gl_render)
        self.add(gl)


    def gl_render(self, gl):
        print(gl)
        Gtk.glClearColor(0,0,0,1)
        Gtk.glClear(Gtk.GL_COLOR_BUFFER_BIT)
        return True

You'll notice I added Gtk. to the gl commands. Not sure if this is correct but python has no idea what a glClearColor is in the function. I'm not super familiar with C namespaces but I can't figure out how the C function would understand what the gl commands are, either. The program does run and I receive the following errors in the console:

fb setup not supported

(python.exe:120048): Gdk-WARNING **: Compile failure in fragment shader:

ERROR: 0:5: 'gl_FragColor' : undeclared identifier

ERROR: 0:5: 'texture2D' : no matching overloaded function found (using implicit conversion)

Any input on this would be useful. My hope is to be able to use opengl commands to draw in a fixed widget area.

edit: This is my latest attempt. In the on_render() function I print the context and I do see the context property is set to a <gtk.gdk.Win32GLContext object at 0x3f133f0> and debugging does show that that is the current context. Problem is I still get the same shader, Frag_Color, and texture errors and I'm not even calling any gl commands.

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from OpenGL.GL import *
from OpenGL.GLU import *


class MyGLArea(Gtk.GLArea):
    def __init__(self):
        Gtk.GLArea.__init__(self)
        self.connect("realize", self.on_realize)


    def on_realize(self, area):
        ctx = self.get_context()
        ctx.make_current()
        print("The context is {}".format(self.get_property("context")))
        err = self.get_error()
        if err:
            print(err)
        return



class RootWidget(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self, title='GL Example')
        self.set_default_size(800,500)
        gl_area = MyGLArea()
        self.add(gl_area)


win = RootWidget()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()

edit 2: Seems as if I am just having a installation issue with the GLArea widget. Seems odd since I'm using over 30 different Gtk widgets without issue. I have errors just adding the widget and not even sending commands. I ran code in Ubuntu python interpreter and it doesn't have any error creating the widget. I am having some issues with certain GL commands but may be from the python wrapper I installed. I'm still looking for the widget equivalent to pygame's or glut's init and set projection functions to setup the viewport. If anyone got ideas I'd love to hear them. The following code does run without errors:

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from OpenGL.GL import *
from OpenGL.GLU import *


class MyGLArea(Gtk.GLArea):
    def __init__(self):
        Gtk.GLArea.__init__(self)
        self.connect("realize", self.on_realize)
        self.connect("render", self.render)


    def on_realize(self, area):
        ctx = self.get_context()
        ctx.make_current()
        err = self.get_error()
        if err:
            print("The error is {}".format(err))

    def render(self, area, ctx):
        glClearColor(1,0,0,1)
        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
    return True

class RootWidget(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self, title='GL Example')
        self.set_default_size(800,500)
        gl_area = MyGLArea()
        self.add(gl_area)

win = RootWidget()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main() 

解决方案

Using the All-In-One installer for windows I noticed there is an option for OpenGL Extentions to GTK+. Now it works as expected. Here's some working code:

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
from OpenGL.GL import *
from OpenGL.GL import shaders
import numpy as np

FRAGMENT_SOURCE ='''
#version 330
in vec4 inputColor;
out vec4 outputColor;
void main(){
outputColor = vec4(1.0,0.0,0.0,1.0);//constant red. I know it's a poor shader
};'''

VERTEX_SOURCE = '''
#version 330
in vec4 position;
void main(){
gl_Position =  position;
}'''

class MyGLArea(Gtk.GLArea):
    def __init__(self):
        Gtk.GLArea.__init__(self)
        self.connect("realize", self.on_realize)
        self.connect("render", self.on_render)

    def on_realize(self, area):
        ctx = self.get_context()
        print("realized", ctx)

    def on_render(self, area, ctx):
        ctx.make_current()
        glClearColor(0, 0, 0, 1)
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        VERTEX_SHADER_PROG = shaders.compileShader(VERTEX_SOURCE, GL_VERTEX_SHADER)
        FRAGMENT_SHADER_PROG = shaders.compileShader(FRAGMENT_SOURCE, GL_FRAGMENT_SHADER)
        self.shader_prog = shaders.compileProgram(VERTEX_SHADER_PROG, FRAGMENT_SHADER_PROG)
        self.create_object()

    def create_object(self):
        # Create a new VAO (Vertex Array Object) and bind it
        vertex_array_object = glGenVertexArrays(1)
        glBindVertexArray(vertex_array_object)
        # Generate buffers to hold our vertices
        vertex_buffer = glGenBuffers(1)
        glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer)
        # Get the position of the 'position' in parameter of our shader and bind it.
        position = glGetAttribLocation(self.shader_prog, 'position')
        glEnableVertexAttribArray(position)
        # Describe the position data layout in the buffer
        glVertexAttribPointer(position, 3, GL_FLOAT, False, 0, ctypes.c_void_p(0))
        # Send the data over to the buffer
        vertices = np.array([-0.6, -0.6, 0.0,
                             0.0, 0.6, 0.0,
                             0.6, -0.6, 0.0,
                             0.7, -0.1, 0.0,
                             0.8, 0.1, 0.0,
                             0.9, -0.1, 0.0
                             ], dtype=np.float32)
        glBufferData(GL_ARRAY_BUFFER, 96, vertices, GL_STATIC_DRAW)
        # Unbind the VAO first (Important)
        glBindVertexArray(0)
        # Unbind other stuff
        glDisableVertexAttribArray(position)




        glBindBuffer(GL_ARRAY_BUFFER, 0)
        self.display(vertex_array_object)

    def display(self, vert):
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        glUseProgram(self.shader_prog)
        glBindVertexArray(vert)
        glDrawArrays(GL_TRIANGLES, 0, 3)
        glDrawArrays(GL_TRIANGLES, 4, 3)
        glBindVertexArray(0)
        glUseProgram(0)

class RootWidget(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self, title='GL Example')
        self.set_default_size(800, 500)
        gl_area = MyGLArea()
        gl_area.set_has_depth_buffer(False)
        gl_area.set_has_stencil_buffer(False)
        self.add(gl_area)

win = RootWidget()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()

这篇关于在Pygobject GTK3中使用Gtk.GLArea的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆