From 34322d128e392c5087ae5c9c76e3de8a39d72473 Mon Sep 17 00:00:00 2001 From: Andy Spencer Date: Mon, 25 Jan 2010 07:33:09 +0000 Subject: [PATCH] Adding OpenGL shader (GLSL) example --- examples/shader/.gitignore | 1 + examples/shader/mkfile | 4 + examples/shader/shader.c | 151 ++++++++++++++++++++++++++++++++++++ examples/shader/shader.glsl | 7 ++ 4 files changed, 163 insertions(+) create mode 100644 examples/shader/.gitignore create mode 100644 examples/shader/mkfile create mode 100644 examples/shader/shader.c create mode 100644 examples/shader/shader.glsl diff --git a/examples/shader/.gitignore b/examples/shader/.gitignore new file mode 100644 index 0000000..a47742a --- /dev/null +++ b/examples/shader/.gitignore @@ -0,0 +1 @@ +shader diff --git a/examples/shader/mkfile b/examples/shader/mkfile new file mode 100644 index 0000000..bba13dd --- /dev/null +++ b/examples/shader/mkfile @@ -0,0 +1,4 @@ +PROGS=shader +PKGS=gtkglext-1.0 +defualt:V: shader-run +<$HOME/lib/mkcommon diff --git a/examples/shader/shader.c b/examples/shader/shader.c new file mode 100644 index 0000000..3d6d3d4 --- /dev/null +++ b/examples/shader/shader.c @@ -0,0 +1,151 @@ +#define GL_GLEXT_PROTOTYPES +#include +#include +#include +#include +#include + +gchar *gl_program_log(guint program, int *_len) +{ + gchar *buf = NULL; + int len = 0; + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &len); + if (len > 0) { + buf = g_malloc(len); + glGetProgramInfoLog(program, len, &len, buf); + } + if (_len) + *_len = len; + return buf; +} + +void on_key_press(GtkWidget *widget, GdkEventKey *event, gpointer user_data) +{ + g_message("key-press"); + if (event->keyval == GDK_q) + gtk_main_quit(); +} + +gboolean on_expose(GtkWidget *drawing, GdkEventExpose *event, gpointer _) +{ + glClearColor(0.5, 0.5, 1.0, 1.0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(-1,1, -1,1, 10,-10); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(0, 0, -5); + + glEnable(GL_COLOR_MATERIAL); + glDisable(GL_TEXTURE_2D); + glColor3f(1.0, 1.0, 1.0); + glBegin(GL_QUADS); + glVertex3f(-0.25, -0.75, 0.0); + glVertex3f(-0.25, 0.75, 0.0); + glVertex3f( 0.25, 0.75, 0.0); + glVertex3f( 0.25, -0.75, 0.0); + glEnd(); + + /* Test projection */ + gdouble model[16], proj[16]; + gint view[4]; + glGetDoublev (GL_MODELVIEW_MATRIX, model); + glGetDoublev (GL_PROJECTION_MATRIX, proj); + glGetIntegerv(GL_VIEWPORT, view); + gdouble x=0.25, y=-0.75, z=0.0; + gdouble px, py, pz; + gluProject(x, y, z, model, proj, view, &px, &py, &pz); + g_message("%f,%f,%f -> %f,%f,%f", x, y, z, px, py, pz); + + /* Textures */ + glDisable(GL_COLOR_MATERIAL); + glEnable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + + /* Flush */ + GdkGLDrawable *gldrawable = gdk_gl_drawable_get_current(); + if (gdk_gl_drawable_is_double_buffered(gldrawable)) + gdk_gl_drawable_swap_buffers(gldrawable); + else + glFlush(); + return FALSE; +} + +gboolean on_configure(GtkWidget *drawing, GdkEventConfigure *event, gpointer _) +{ + glViewport(0, 0, + drawing->allocation.width, + drawing->allocation.height); + return FALSE; +} + +int main(int argc, char **argv) +{ + gtk_init(&argc, &argv); + + GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + GtkWidget *drawing = gtk_drawing_area_new(); + GdkGLConfig *glconfig = gdk_gl_config_new_by_mode((GdkGLConfigMode)( + GDK_GL_MODE_RGBA | GDK_GL_MODE_DEPTH | + GDK_GL_MODE_DOUBLE | GDK_GL_MODE_ALPHA)); + g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL); + g_signal_connect(window, "key-press-event", G_CALLBACK(on_key_press), NULL); + g_signal_connect(drawing, "expose-event", G_CALLBACK(on_expose), NULL); + g_signal_connect(drawing, "configure-event", G_CALLBACK(on_configure), NULL); + gtk_widget_set_gl_capability(drawing, glconfig, NULL, TRUE, GDK_GL_RGBA_TYPE); + gtk_container_add(GTK_CONTAINER(window), drawing); + gtk_widget_show_all(window); + + /* OpenGL setup */ + GdkGLContext *glcontext = gtk_widget_get_gl_context(GTK_WIDGET(drawing)); + GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(GTK_WIDGET(drawing)); + + /* Setup shader */ + gdk_gl_drawable_gl_begin(gldrawable, glcontext); + + gchar *source; + gboolean status = g_file_get_contents("shader.glsl", &source, NULL, NULL); + if (!status) + g_error("Failed to load shader"); + + guint program = glCreateProgram(); + if (!program) + g_error("Error creating program"); + + guint shader = glCreateShader(GL_VERTEX_SHADER_ARB); + if (!shader) + g_error("Error creating shader"); + + glShaderSource(shader, 1, (const gchar**)&source, NULL); + if (glGetError()) + g_error("Error setting shader source"); + + glCompileShader(shader); + if (glGetError()) + g_error("Error compiling shader"); + + glAttachShader(program, shader); + if (glGetError()) + g_error("Error attaching shader"); + + glLinkProgram(program); + if (glGetError()) + g_error("Error linking program"); + + glUseProgram(program); + if (glGetError()) + g_error("Error using program:\n%s", gl_program_log(program, NULL)); + + /* Run */ + gtk_main(); + + /* Clean up */ + glDetachShader(program, shader); + glDeleteShader(shader); + glDeleteProgram(program); + + gdk_gl_drawable_gl_end(gldrawable); + return 0; +} diff --git a/examples/shader/shader.glsl b/examples/shader/shader.glsl new file mode 100644 index 0000000..38b76d9 --- /dev/null +++ b/examples/shader/shader.glsl @@ -0,0 +1,7 @@ +void main() +{ + gl_Position = + gl_ModelViewProjectionMatrix * + ( gl_Vertex + 0.5 ); + gl_Position[3] = 1; +} -- 2.43.2