我正在尝试用GTK 3编写一个简单的“游戏循环”。我创建了一个GL上下文并尝试清除它。但是,显示的窗口只有一些黑色和白色矩形,可能是“占位符”显示。显然,颜色清除属于主循环,或者只执行一次,但我无法弄清楚如何注册我自己的主循环。我应该覆盖gtk_main还是完全替换它?
#include <gtk/gtk.h>
#include <GL/gl.h>
int main(int argc, char *argv[]) {
GtkWidget *win, *area;
gtk_init(&argc, &argv);
win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(win), "Hello, GNU");
gtk_window_set_position(GTK_WINDOW(win), GTK_WIN_POS_CENTER);
gtk_window_set_default_size(GTK_WINDOW(win), 480, 480);
g_signal_connect(win, "destroy", G_CALLBACK(gtk_main_quit), NULL);
area = gtk_gl_area_new();
gtk_container_add(GTK_CONTAINER(win), area);
gtk_widget_show_all(win);
gtk_gl_area_make_current(GTK_GL_AREA(area));
glClearColor(1,0,0,1);
glClear(GL_COLOR_BUFFER_BIT);
gtk_main();
return 0;
}
g_signal_connect
似乎是相关的,但信号似乎是特定事件,如激活,关闭等。
答案 0 :(得分:3)
不确定OpenGL代码,但是这里有一个示例,您可能可以适应OpenGL,显示了回调如何更新GdkPixbuf。
//g++ test.cpp `pkg-config --cflags gtk+-3.0` `pkg-config --libs gtk+-3.0`
#include <gtk/gtk.h>
int width = 320, height = 240;
GdkPixbuf *pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, width, height);
int rowstride = gdk_pixbuf_get_rowstride (pixbuf);
guchar *pixels = gdk_pixbuf_get_pixels (pixbuf);
GtkImage *image;
inline void drawPixel (int x, int y, char red, char green, char blue)
{
*(pixels + y * rowstride + x * 3) = red;
*(pixels + y * rowstride + x * 3 + 1) = green;
*(pixels + y * rowstride + x * 3 + 2) = blue;
}
gboolean game_loop (GtkWidget *widget, GdkFrameClock *clock, gpointer data)
{
for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
drawPixel(i, j, rand() % 255, rand() % 255, rand() % 255);
}
}
gtk_image_set_from_pixbuf (image, pixbuf);
return 1;
}
int main()
{
gtk_init (NULL, NULL);
GtkWidget *window, *box;
image = GTK_IMAGE (gtk_image_new());
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
gtk_box_pack_start (GTK_BOX (box), GTK_WIDGET(image), TRUE, TRUE, 0);
gtk_container_add (GTK_CONTAINER (window), box);
g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
gtk_widget_add_tick_callback(window, game_loop, NULL, NULL);
gtk_widget_show_all (window);
gtk_main();
}
结果:
答案 1 :(得分:0)
这是演示如何使用OpenGL在Gtk 2中绘制多维数据集:
// gcc cube.c `pkg-config --cflags gtk+-2.0` `pkg-config --libs gtk+-2.0` \
`pkg-config --cflags gtkgl-2.0 gtk+-2.0` `pkg-config --libs gtkgl-2.0 gtk+-2.0`
#include <gtk/gtk.h>
#include <gtkgl/gtkglarea.h>
#include <GL/gl.h>
#include <GL/glu.h>
const int MIN_WIDTH = 640;
const int MIN_HEIGHT = 480;
GtkWidget *glwindow;
GtkWidget *glarea = NULL;
// adapted from: https://www.opengl.org/archives/resources/code/samples/glut_examples/examples/cube.c
GLfloat light_diffuse[] = {1.0, 0.0, 0.0, 1.0}; /* Red diffuse light. */
GLfloat light_position[] = {1.0, 1.0, 1.0, 0.0}; /* Infinite light location. */
GLfloat n[6][3] = { /* Normals for the 6 faces of a cube. */
{-1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 0.0, 0.0},
{0.0, -1.0, 0.0}, {0.0, 0.0, 1.0}, {0.0, 0.0, -1.0} };
GLint faces[6][4] = { /* Vertex indices for the 6 faces of a cube. */
{0, 1, 2, 3}, {3, 2, 6, 7}, {7, 6, 5, 4},
{4, 5, 1, 0}, {5, 6, 2, 1}, {7, 4, 0, 3} };
GLfloat v[8][3]; /* Will be filled in with X,Y,Z vertexes. */
void
drawBox(void)
{
int i;
for (i = 0; i < 6; i++) {
glBegin(GL_QUADS);
glNormal3fv(&n[i][0]);
glVertex3fv(&v[faces[i][0]][0]);
glVertex3fv(&v[faces[i][1]][0]);
glVertex3fv(&v[faces[i][2]][0]);
glVertex3fv(&v[faces[i][3]][0]);
glEnd();
}
}
void
display(void)
{
/* ... DRAW STUFF HERE ... */
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
drawBox();
}
void
init(void)
{
/* Setup cube vertex data. */
v[0][0] = v[1][0] = v[2][0] = v[3][0] = -1;
v[4][0] = v[5][0] = v[6][0] = v[7][0] = 1;
v[0][1] = v[1][1] = v[4][1] = v[5][1] = -1;
v[2][1] = v[3][1] = v[6][1] = v[7][1] = 1;
v[0][2] = v[3][2] = v[4][2] = v[7][2] = 1;
v[1][2] = v[2][2] = v[5][2] = v[6][2] = -1;
/* Enable a single OpenGL light. */
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHTING);
/* Use depth buffering for hidden surface elimination. */
glEnable(GL_DEPTH_TEST);
/* Setup the view of the cube. */
glMatrixMode(GL_PROJECTION);
gluPerspective( /* field of view in degree */ 40.0,
/* aspect ratio */ 1.0,
/* Z near */ 1.0, /* Z far */ 10.0);
glMatrixMode(GL_MODELVIEW);
gluLookAt(0.0, 0.0, 5.0, /* eye is at (0,0,5) */
0.0, 0.0, 0.0, /* center is at (0,0,0) */
0.0, 1.0, 0.); /* up is in positive Y direction */
/* Adjust cube position to be asthetic angle. */
glTranslatef(0.0, 0.0, -1.0);
glRotatef(60, 1.0, 0.0, 0.0);
glRotatef(-20, 0.0, 0.0, 1.0);
}
gint glarea_expose(GtkWidget *widget, GdkEventExpose *event)
{
if (event->count > 0) {
return TRUE;
}
g_print("drawing...\n");
gtk_widget_grab_focus(GTK_WIDGET(glarea));
if (gtk_gl_area_begingl(GTK_GL_AREA(glarea))) {
display();
gtk_gl_area_endgl(GTK_GL_AREA(glarea));
}
gtk_gl_area_swapbuffers(GTK_GL_AREA(glarea));
return TRUE;
}
gint glarea_configure(GtkWidget *widget, GdkEventConfigure *event)
{
if (gtk_gl_area_begingl(GTK_GL_AREA(widget))) {
glViewport(0,0, widget->allocation.width, widget->allocation.height);
gtk_gl_area_endgl(GTK_GL_AREA(widget));
}
return TRUE;
}
GtkWidget *create_gl_window()
{
glwindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
g_signal_connect (glwindow, "delete_event",
G_CALLBACK (gtk_main_quit), NULL);
gtk_quit_add_destroy(1, GTK_OBJECT(glwindow));
glarea = gtk_gl_area_new_vargs(NULL,
GDK_GL_DOUBLEBUFFER,
GDK_GL_RGBA,
GDK_GL_DEPTH_SIZE,1,
GDK_GL_NONE);
if(!glarea) {
return FALSE;
}
gtk_widget_set_events(GTK_WIDGET(glarea),
GDK_EXPOSURE_MASK);
gtk_signal_connect (GTK_OBJECT(glarea), "expose_event",
GTK_SIGNAL_FUNC(glarea_expose), NULL);
gtk_signal_connect (GTK_OBJECT(glarea), "configure_event",
GTK_SIGNAL_FUNC(glarea_configure), NULL);
gtk_signal_connect (GTK_OBJECT(glarea), "delete_event",
GTK_SIGNAL_FUNC(gtk_main_quit), NULL);
gtk_widget_set_usize(glarea, MIN_WIDTH, MIN_HEIGHT);
gtk_quit_add_destroy(1, GTK_OBJECT(glarea));
gtk_container_add(GTK_CONTAINER(glwindow),glarea);
gtk_widget_show(glarea);
gtk_widget_show(glwindow);
GTK_WIDGET_SET_FLAGS(glarea,GTK_CAN_FOCUS);
gtk_widget_grab_focus(GTK_WIDGET(glarea));
init();
return glwindow;
}
int main(int argc, char **argv)
{
gtk_init(&argc, &argv);
glwindow = create_gl_window();
gtk_main();
return 0;
}