我之前曾问过一个关于尝试在PyGObject中使用GLArea小部件的问题(Use of the Gtk.GLArea in Pygobject GTK3)。我从来没有得到python版本来绘制命令所以我认为我试图更好地理解它的c版本。使用Ubuntu 16,因为Gtk3都包括在内,我试了一下。以下代码编译并运行时没有错误或警告,但不会绘制包含的GL_LINES指令。真正奇怪的是改变glClearColor会改变背景并且GL_LINES在同一个函数中。正如您所看到的,我使用的是包含Ubuntu的epoxy / gl库,我认为这相当于GL / gl。有什么想法吗?
/*to compile ->
gcc `pkg-config --cflags gtk+-3.0` -o gl_area gl_area.c `pkg-config --libs gtk+-3.0 epoxy`*/
#include <math.h>
#include <gtk/gtk.h>
#include <epoxy/gl.h>
#include <stdio.h>
gint init(GtkWidget *widget)
{
/* Setup the viewport*/
glViewport(0, 0, gtk_widget_get_allocated_width (widget),
gtk_widget_get_allocated_height(widget));
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0,100, 100,0, -1,1);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
printf("ran init method\n");
return TRUE;
}
/* When widget is exposed it's contents are redrawn. */
static gboolean
render (GtkGLArea *area, GdkGLContext *context)
{
/* OpenGL functions can be called only if make_current returns true */
/* Draw simple triangle */
glClearColor(.3,.3,.3,1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor4f(1,1,1,1);
glBegin(GL_LINES);
{
glVertex2f(0,0);
glVertex2f(10000,10000);
glVertex2f(0,0);
glVertex2f(-10000,-10000);
glVertex2f(0,0);
glVertex2f(10000,-10000);
glVertex2f(0,0);
glVertex2f(-10000,10000);
}
glEnd();
printf("ran render method\n");
return TRUE;
}
/* When glarea widget size changes, viewport size is set to match the new size */
gint reshape(GtkWidget *widget, GdkEventConfigure *event)
{
/* OpenGL functions can be called if context is current */
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
printf("ran rehsape method\n");
glViewport(0, 0, gtk_widget_get_allocated_width (widget),
gtk_widget_get_allocated_height(widget));
return TRUE;
}
int main(int argc, char **argv)
{
/* initialize gtk */
gtk_init(&argc, &argv);
/* Create new top level window. */
GtkWidget *window = gtk_window_new( GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "GL Area Test");
gtk_window_set_default_size (GTK_WINDOW(window),
640,
480);
gtk_container_set_border_width(GTK_CONTAINER(window), 10);
/* Quit main if got delete event */
g_signal_connect(G_OBJECT(window),
"delete-event",
G_CALLBACK(gtk_main_quit),
NULL);
/* Create new OpenGL widget. */
GtkWidget *glarea = gtk_gl_area_new ();
/* Do initialization when widget has been realized. */
g_signal_connect(glarea, "realize", G_CALLBACK(init), NULL);
/* When window is resized viewport needs to be resized also. */
g_signal_connect(glarea, "configure-event", G_CALLBACK(reshape), NULL);
/* Render signal should be sent once the context is set to current. */
g_signal_connect (glarea, "render", G_CALLBACK (render), NULL);
/* set minimum size */
gtk_widget_set_size_request(glarea, 100,100);
/* put glarea into window and show it all */
gtk_container_add(GTK_CONTAINER(window), glarea);
gtk_widget_show_all (window);
gtk_main();
return 0;
}
答案 0 :(得分:0)
好的,我对openGL和着色器的使用有很多了解。基本上,GLArea所遇到的问题是命令不在一个被绑定的数组中。到当前上下文的活动缓冲区。这个tut帮了很大忙:https://www.youtube.com/watch?v=Q_kFcRlLTk0我修改了演示代码以简化它并将着色器源代码作为字符串引入c代码中。事实上,它将从演示应用程序打开,并有滑块以矩阵旋转三角形。我试着把它提炼到最基本的窗口。这确实可以编译运行而不会出错。现在我将在PyGObject中尝试它。
/* OpenGL Area
*
* GtkGLArea is a widget that allows custom drawing using OpenGL calls.
*/
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <gtk/gtk.h>
#include <epoxy/gl.h>
const GLchar *FRAGMENT_SOURCE =
"#version 330\n"
"in vec4 inputColor;\n"
"out vec4 outputColor;\n"
"void main() {\n"
"outputColor = vec4(1.0f, 0.0f, 0.0f, 0.0f);\n" //constant red. I know it's a poor shader
"}";
const GLchar *VERTEX_SOURCE =
"#version 330\n"
"in vec4 position;\n"
"void main()\n{gl_Position = position;\n"
"}";
/* the GtkGLArea widget */
static GtkWidget *gl_area = NULL;
/* The object we are drawing */
static const GLfloat vertex_data[] = {
0.f, 0.5f, 0.f, 1.f,
0.5f, -0.366f, 0.f, 1.f,
-0.5f, -0.366f, 0.f, 1.f,
};
/* Initialize the GL buffers */
static void
init_buffers (GLuint *vao_out,
GLuint *buffer_out)
{
GLuint vao, buffer;
/* We only use one VAO, so we always keep it bound */
glGenVertexArrays (1, &vao);
glBindVertexArray (vao);
/* This is the buffer that holds the vertices */
glGenBuffers (1, &buffer);
glBindBuffer (GL_ARRAY_BUFFER, buffer);
glBufferData (GL_ARRAY_BUFFER, sizeof (vertex_data), vertex_data, GL_STATIC_DRAW);
glBindBuffer (GL_ARRAY_BUFFER, 0);
if (vao_out != NULL)
*vao_out = vao;
if (buffer_out != NULL)
*buffer_out = buffer;
}
/* Create and compile a shader */
static GLuint
create_shader (int type)
{
GLuint shader;
int status;
shader = glCreateShader (type);
if (type== GL_FRAGMENT_SHADER){
glShaderSource (shader, 1, &FRAGMENT_SOURCE, NULL);}
if (type== GL_VERTEX_SHADER){
glShaderSource (shader, 1, &VERTEX_SOURCE, NULL);}
glCompileShader (shader);
glGetShaderiv (shader, GL_COMPILE_STATUS, &status);
if (status == GL_FALSE)
{
int log_len;
char *buffer;
glGetShaderiv (shader, GL_INFO_LOG_LENGTH, &log_len);
buffer = g_malloc (log_len + 1);
glGetShaderInfoLog (shader, log_len, NULL, buffer);
g_warning ("Compile failure in %s shader:\n%s",
type == GL_VERTEX_SHADER ? "vertex" : "fragment",
buffer);
g_free (buffer);
glDeleteShader (shader);
return 0;
}
return shader;
}
/* Initialize the shaders and link them into a program */
static void
init_shaders (GLuint *program_out)
{
GLuint vertex, fragment;
GLuint program = 0;
int status;
vertex = create_shader (GL_VERTEX_SHADER);
if (vertex == 0)
{
*program_out = 0;
return;
}
fragment = create_shader (GL_FRAGMENT_SHADER);
if (fragment == 0)
{
glDeleteShader (vertex);
*program_out = 0;
return;
}
program = glCreateProgram ();
glAttachShader (program, vertex);
glAttachShader (program, fragment);
glLinkProgram (program);
glGetProgramiv (program, GL_LINK_STATUS, &status);
if (status == GL_FALSE)
{
int log_len;
char *buffer;
glGetProgramiv (program, GL_INFO_LOG_LENGTH, &log_len);
buffer = g_malloc (log_len + 1);
glGetProgramInfoLog (program, log_len, NULL, buffer);
g_warning ("Linking failure:\n%s", buffer);
g_free (buffer);
glDeleteProgram (program);
program = 0;
goto out;
}
glDetachShader (program, vertex);
glDetachShader (program, fragment);
out:
glDeleteShader (vertex);
glDeleteShader (fragment);
if (program_out != NULL)
*program_out = program;
}
static GLuint position_buffer;
static GLuint program;
/* We need to set up our state when we realize the GtkGLArea widget */
static void
realize (GtkWidget *widget)
{
GdkGLContext *context;
gtk_gl_area_make_current (GTK_GL_AREA (widget));
if (gtk_gl_area_get_error (GTK_GL_AREA (widget)) != NULL)
return;
context = gtk_gl_area_get_context (GTK_GL_AREA (widget));
init_buffers (&position_buffer, NULL);
init_shaders (&program);
}
/* We should tear down the state when unrealizing */
static void
unrealize (GtkWidget *widget)
{
gtk_gl_area_make_current (GTK_GL_AREA (widget));
if (gtk_gl_area_get_error (GTK_GL_AREA (widget)) != NULL)
return;
glDeleteBuffers (1, &position_buffer);
glDeleteProgram (program);
}
static void
draw_triangle (void)
{
/* Use our shaders */
glUseProgram (program);
/* Use the vertices in our buffer */
glBindBuffer (GL_ARRAY_BUFFER, position_buffer);
glEnableVertexAttribArray (0);
glVertexAttribPointer (0, 4, GL_FLOAT, GL_FALSE, 0, 0);
/* Draw the three vertices as a triangle */
glDrawArrays (GL_TRIANGLES, 0, 3);
/* We finished using the buffers and program */
glDisableVertexAttribArray (0);
glBindBuffer (GL_ARRAY_BUFFER, 0);
glUseProgram (0);
}
static gboolean
render (GtkGLArea *area,
GdkGLContext *context)
{
if (gtk_gl_area_get_error (area) != NULL)
return FALSE;
/* Clear the viewport */
glClearColor (0.0, 0.0, 0.0, 1.0);
glClear (GL_COLOR_BUFFER_BIT);
/* Draw our object */
draw_triangle ();
/* Flush the contents of the pipeline */
glFlush ();
return TRUE;
}
static void
on_axis_value_change (void)
{
gtk_widget_queue_draw (gl_area);
}
int main(int argc, char **argv)
{
GtkWidget *window, *box;
/* initialize gtk */
gtk_init(&argc, &argv);
/* Create new top level window. */
window = gtk_window_new( GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size (GTK_WINDOW(window),1000,1000);
gtk_window_set_title(GTK_WINDOW(window), "GL Area");
gtk_container_set_border_width(GTK_CONTAINER(window), 10);
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE);
g_object_set (box, "margin", 12, NULL);
gtk_box_set_spacing (GTK_BOX (box), 6);
gtk_container_add (GTK_CONTAINER (window), box);
gl_area = gtk_gl_area_new ();
gtk_box_pack_start (GTK_BOX(box), gl_area,1,1, 0);
/* We need to initialize and free GL resources, so we use
* the realize and unrealize signals on the widget
*/
g_signal_connect (gl_area, "realize", G_CALLBACK (realize), NULL);
g_signal_connect (gl_area, "unrealize", G_CALLBACK (unrealize), NULL);
/* The main "draw" call for GtkGLArea */
g_signal_connect (gl_area, "render", G_CALLBACK (render), NULL);
/* Quit form main if got delete event */
g_signal_connect(G_OBJECT(window), "delete-event",
G_CALLBACK(gtk_main_quit), NULL);
gtk_widget_show_all(GTK_WIDGET(window));
gtk_main();
return 0;
}