您好,感谢您花时间阅读本文!
我正在用GTK2/3 + OpenGL编写程序,我得到了两个版本的程序运行:
- (a) GTK+2 + gtkext扩展->工作很棒!
- (b) GTK+3 + LibX11 ->工作正常!
一切看起来都很好,除了(a)中的渲染明显快于(b)中的渲染…我也不知道为什么下面是一些用于创建OpenGL上下文的代码部分的示例:
-
(a)
// To create the context, and the associated GtkWidget GdkGLConfig * glconfig = gdk_gl_config_new_by_mode (GDK_GL_MODE_RGBA | GDK_GL_MODE_DEPTH | GDK_GL_MODE_DOUBLE); GtkWidget * drawing_area = gtk_drawing_area_new (); gtk_widget_set_gl_capability (drawing_area, glconfig, NULL, TRUE, GDK_GL_RGBA_TYPE); g_signal_connect (G_OBJECT (drawing_area), "expose-event", G_CALLBACK (on_expose), data); // And later on to draw using the OpenGL context: gboolean on_expose (GtkWidget * widg, GdkEvent * event, gpointer data) { GdkGLContext * glcontext = gtk_widget_get_gl_context (widg); GdkGLDrawable * gldrawable = gtk_widget_get_gl_drawable (widg); if (gdk_gl_drawable_gl_begin (gldrawable, glcontext)) { // OpenGL instructions to draw here ! gdk_gl_drawable_swap_buffers (view -> gldrawable); gdk_gl_drawable_gl_end (view -> gldrawable); } return TRUE; }
(b) // To create the GtkWidget GtkWidget * drawing_area = gtk_drawing_area_new (); // Next line is required to avoid background flickering gtk_widget_set_double_buffered (drawing_area, FALSE); g_signal_connect (G_OBJECT (drawing_area), "realize", G_CALLBACK(on_realize), data); g_signal_connect (G_OBJECT (drawing_area), "draw", G_CALLBACK(on_expose), data); // To create the OpenGL context GLXContext glcontext; G_MODULE_EXPORT void on_realize (GtkWidget * widg, gpointer data) { GdkWindow * xwin = gtk_widget_get_window (widg); GLint attr_list[] = {GLX_DOUBLEBUFFER, GLX_RGBA, GLX_DEPTH_SIZE, 16, GLX_RED_SIZE, 8, GLX_GREEN_SIZE, 8, GLX_BLUE_SIZE, 8, None}; XVisualInfo * visualinfo = glXChooseVisual (GDK_WINDOW_XDISPLAY (xwin), gdk_screen_get_number (gdk_window_get_screen (xwin)), attr_list); glcontext = glXCreateContext (GDK_WINDOW_XDISPLAY (xwin), visualinfo, NULL, TRUE); xfree (visualinfo); } // To Draw using the OpenGL context G_MODULE_EXPORT gboolean on_expose (GtkWidget * widg, cairo_t * cr, gpointer data) { GdkWindow * win = gtk_widget_get_window (widg); if (glXMakeCurrent (GDK_WINDOW_XDISPLAY (xwin), GDK_WINDOW_XID (xwin), glcontext)) { // OpenGL instructions to draw here ! glXSwapBuffers (GDK_WINDOW_XDISPLAY (win), GDK_WINDOW_XID (win)); } return TRUE; }
试图理解为什么(a)比(b)快,我下载了gtkgleext库的源代码,阅读它们,并发现这些命令与对X11的调用完全相同。现在我的想法是(b)
gtk_widget_set_double_buffered (drawing_area, FALSE);
正在扰乱渲染,然后我无能为力…或者OpenGL上下文之间存在差异,这可能解释了我注意到的行为,如果我在这个方向上跟进,我需要尽可能多地比较两种上下文……到目前为止,我选择了最常用的方式来获取一些信息:
OpenGL Version : 3.0 Mesa 12.0.3
OpenGL Vendor : nouveau
OpenGL Renderer : Gallium 0.4 on NVCF
OpenGL Shading Version : 1.30
Color Bits (R,G,B,A) : 8, 8, 8, 0
Depth Bits : 24
Stencil Bits : 0
Max. Lights Allowed : 8
Max. Texture Size : 16384
Max. Clipping Planes : 8
Max. Modelview Matrix Stacks : 32
Max. Projection Matrix Stacks : 32
Max. Attribute Stacks : 16
Max. Texture Stacks : 10
Total number of OpenGL Extensions : 227
Extensions list:
N°1 : GL_AMD_conservative_depth
N°2 : GL_AMD_draw_buffers_blend
...
但是两种上下文都给出了完全相同的信息…
谢谢你已经来了…现在我的问题是:
是否有一种方法可以输出尽可能多的关于OpenGL上下文的信息,如何输出?
我欢迎对我正在做的事情提出任何其他建议!
s .
PS:我正在为GTK3使用GtkGLArea小部件,但正如这里所说的,我还没有。
[EDIT]一些OpenGL指令:
// OpenGL instructions to draw here !
glLoadIdentity ();
glPushMatrix ();
// d is the depth ... calculated somewhere else
glTranslated (0.0, 0.0, -d);
// Skipping the rotation part for clarity, I am using a quaternion
rotate_camera ();
// r, g, b and a are GLFloat values
glClearColor (r,g,b,a);
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glDisable (GL_LIGHTING);
int i;
// nbds is the number of chemical bonds
GLfloat * lineVertices;
// This is "roughly" what I do to draw chemical bonds, to give you an idea
for (i=0; i<nbds;i++)
{
// get_bonds (i) gives backs a 6 float array
lineVertices = get_bonds(i);
glPushMatrix();
glLineWidth (1.0);
glEnableClientState (GL_VERTEX_ARRAY);
glVertexPointer (3, GL_FLOAT, 0, lineVertices);
glDrawArrays (GL_LINES, 0, 2);
glDisableClientState (GL_VERTEX_ARRAY);
glPopMatrix();
}
glEnable (GL_LIGHTING);
(/编辑)感谢您的建议,"ApiTrace"的想法是惊人的,不仅我发现了一个伟大的工具,但它帮助我得到一些线索,我的问题。使用ApiTrace:
- 我检查了我的程序的两个版本(a)和(b)使用完全相同的OpenGL上下文…我必须补充的是……因此错误不是来自context初始化。
- 我发现在版本(b)中渲染完成了5次,比版本(a)更频繁…即同一帧5次!
我唯一的逻辑结论是版本2和3之间的GTK+信号的差异,在我的程序的版本(a)中,我使用expose-event
,而在版本(b)中,我使用draw
事件(GtkDrawingArea
的新信号)…显然,GTK+库在版本2和3之间的行为有一些不同……我正在想办法绕过它……我将编辑这个答案以提供进一步的信息。
[编辑]Hello world,回答我自己的问题,希望能帮助别人避免和我犯同样的错误。为了重新绘制我的OpenGL窗口,我使用:
void update (GtkWidget * plot)
{
gtk_widget_hide (plot);
gtw_widget_show (plot);
}
我应该用:
gtk_widget_queue_draw (plot);
所有问题都解决了![/EDIT]