]> Pileus Git - grits/blob - examples/shader/shader.c
3b5f8c23bf7adae72ffbfff03c0c0d793cf0ef6d
[grits] / examples / shader / shader.c
1 /*
2  * Copyright (C) 2009-2010 Andy Spencer <andy753421@gmail.com>
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 #define GL_GLEXT_PROTOTYPES
19 #include <gtk/gtk.h>
20 #include <gtk/gtkgl.h>
21 #include <gdk/gdkkeysyms.h>
22 #include <GL/gl.h>
23 #include <GL/glext.h>
24
25 gchar *gl_program_log(guint program, int *_len)
26 {
27         gchar *buf = NULL;
28         int len = 0;
29         glGetProgramiv(program, GL_INFO_LOG_LENGTH, &len);
30         if (len > 0) {
31                 buf = g_malloc(len);
32                 glGetProgramInfoLog(program, len, &len, buf);
33         }
34         if (_len)
35                 *_len = len;
36         return buf;
37 }
38
39 void on_key_press(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
40 {
41         g_message("key-press");
42         if (event->keyval == GDK_q)
43                 gtk_main_quit();
44 }
45
46 gboolean on_expose(GtkWidget *drawing, GdkEventExpose *event, gpointer _)
47 {
48         glClearColor(0.5, 0.5, 1.0, 1.0);
49         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
50
51         glMatrixMode(GL_PROJECTION);
52         glLoadIdentity();
53         glOrtho(-1,1, -1,1, 10,-10);
54         glMatrixMode(GL_MODELVIEW);
55         glLoadIdentity();
56         glTranslatef(0, 0, -5);
57
58         glEnable(GL_COLOR_MATERIAL);
59         glDisable(GL_TEXTURE_2D);
60         glColor3f(1.0, 1.0, 1.0);
61         glBegin(GL_QUADS);
62         glVertex3f(-0.25, -0.75, 0.0);
63         glVertex3f(-0.25,  0.75, 0.0);
64         glVertex3f( 0.25,  0.75, 0.0);
65         glVertex3f( 0.25, -0.75, 0.0);
66         glEnd();
67
68         /* Test projection */
69         gdouble model[16], proj[16];
70         gint view[4];
71         glGetDoublev (GL_MODELVIEW_MATRIX,  model);
72         glGetDoublev (GL_PROJECTION_MATRIX, proj);
73         glGetIntegerv(GL_VIEWPORT,          view);
74         gdouble x=0.25, y=-0.75, z=0.0;
75         gdouble px, py, pz;
76         gluProject(x, y, z, model, proj, view, &px, &py, &pz);
77         g_message("%f,%f,%f -> %f,%f,%f", x, y, z, px, py, pz);
78
79         /* Textures */
80         glDisable(GL_COLOR_MATERIAL);
81         glEnable(GL_TEXTURE_2D);
82         glEnable(GL_BLEND);
83
84         /* Flush */
85         GdkGLDrawable *gldrawable = gdk_gl_drawable_get_current();
86         if (gdk_gl_drawable_is_double_buffered(gldrawable))
87                 gdk_gl_drawable_swap_buffers(gldrawable);
88         else
89                 glFlush();
90         return FALSE;
91 }
92
93 gboolean on_configure(GtkWidget *drawing, GdkEventConfigure *event, gpointer _)
94 {
95         glViewport(0, 0,
96                 drawing->allocation.width,
97                 drawing->allocation.height);
98         return FALSE;
99 }
100
101 int main(int argc, char **argv)
102 {
103         gtk_init(&argc, &argv);
104
105         GtkWidget   *window   = gtk_window_new(GTK_WINDOW_TOPLEVEL);
106         GtkWidget   *drawing  = gtk_drawing_area_new();
107         GdkGLConfig *glconfig = gdk_gl_config_new_by_mode((GdkGLConfigMode)(
108                         GDK_GL_MODE_RGBA   | GDK_GL_MODE_DEPTH |
109                         GDK_GL_MODE_DOUBLE | GDK_GL_MODE_ALPHA));
110         g_signal_connect(window,  "destroy",         G_CALLBACK(gtk_main_quit), NULL);
111         g_signal_connect(window,  "key-press-event", G_CALLBACK(on_key_press),  NULL);
112         g_signal_connect(drawing, "expose-event",    G_CALLBACK(on_expose),     NULL);
113         g_signal_connect(drawing, "configure-event", G_CALLBACK(on_configure),  NULL);
114         gtk_widget_set_gl_capability(drawing, glconfig, NULL, TRUE, GDK_GL_RGBA_TYPE);
115         gtk_container_add(GTK_CONTAINER(window), drawing);
116         gtk_widget_show_all(window);
117
118         /* OpenGL setup */
119         GdkGLContext  *glcontext  = gtk_widget_get_gl_context(GTK_WIDGET(drawing));
120         GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(GTK_WIDGET(drawing));
121
122         /* Setup shader */
123         gdk_gl_drawable_gl_begin(gldrawable, glcontext);
124
125         gchar *source;
126         gboolean status = g_file_get_contents("shader.glsl", &source, NULL, NULL);
127         if (!status)
128                 g_error("Failed to load shader");
129
130         guint program = glCreateProgram();
131         if (!program)
132                 g_error("Error creating program");
133
134         guint shader = glCreateShader(GL_VERTEX_SHADER_ARB);
135         if (!shader)
136                 g_error("Error creating shader");
137
138         glShaderSource(shader, 1, (const gchar**)&source, NULL);
139         if (glGetError())
140                 g_error("Error setting shader source");
141
142         glCompileShader(shader);
143         if (glGetError())
144                 g_error("Error compiling shader");
145
146         glAttachShader(program, shader);
147         if (glGetError())
148                 g_error("Error attaching shader");
149
150         glLinkProgram(program);
151         if (glGetError())
152                 g_error("Error linking program");
153
154         glUseProgram(program);
155         if (glGetError())
156                 g_error("Error using program:\n%s", gl_program_log(program, NULL));
157
158         /* Run */
159         gtk_main();
160
161         /* Clean up */
162         glDetachShader(program, shader);
163         glDeleteShader(shader);
164         glDeleteProgram(program);
165
166         gdk_gl_drawable_gl_end(gldrawable);
167         return 0;
168 }