]> Pileus Git - grits/blob - examples/sorting/sort.c
Update sorting example to use a shader (broken)
[grits] / examples / sorting / sort.c
1 #define GL_GLEXT_PROTOTYPES
2 #include <gtk/gtk.h>
3 #include <gtk/gtkgl.h>
4 #include <gdk/gdkkeysyms.h>
5 #include <GL/gl.h>
6 #include <GL/glu.h>
7 #include <stdlib.h>
8
9 gdouble pos[3];
10 gdouble rot[3];
11 guint tex;
12
13 typedef struct {
14         gfloat xyz[4];
15         gfloat color[4];
16         gfloat texture[4];
17 } __attribute__ ((packed)) vert_t;
18
19 static int sort_cmp(const void *a, const void *b)
20 {
21         vert_t *a_verts = (vert_t*)(((gfloat*)a)+2);
22         vert_t *b_verts = (vert_t*)(((gfloat*)b)+2);
23         gfloat a_sum = a_verts[0].xyz[2] + a_verts[1].xyz[2] + a_verts[2].xyz[2];
24         gfloat b_sum = b_verts[0].xyz[2] + b_verts[1].xyz[2] + b_verts[2].xyz[2];
25         return a_sum == b_sum ? 0 :
26                a_sum <  b_sum ? 1 : -1;
27 }
28
29 static gfloat *sort_start()
30 {
31         int size = 1000000;
32         gfloat *data = g_new0(gfloat, size);
33         glFeedbackBuffer(size, GL_4D_COLOR_TEXTURE, data);
34         glRenderMode(GL_FEEDBACK);
35         g_print("1st = %f\n", data[0]);
36         return data;
37 }
38
39 static void sort_end(gfloat *data)
40 {
41         int vertsize = sizeof(vert_t)/sizeof(gfloat);
42         int nvals = glRenderMode(GL_RENDER);
43
44         /* Set up screen coords */
45         gint view[4];
46         glGetIntegerv(GL_VIEWPORT, view);
47
48         glMatrixMode(GL_PROJECTION);
49         glPushMatrix();
50         glLoadIdentity();
51         glOrtho(view[0],view[2], view[1],view[3], -100,100);
52
53         glMatrixMode(GL_MODELVIEW);
54         glPushMatrix();
55         glLoadIdentity();
56         glDisable(GL_LIGHTING);
57
58         glMatrixMode(GL_TEXTURE);
59         glPushMatrix();
60         glLoadIdentity();
61
62         //glTranslatef(pos[0], pos[1], pos[2]);
63         //glTranslatef(0.05, 0.1, -2);
64         //glRotatef(0.03, 1, 1, 0);
65
66         //gluPerspective(90, 0.8, 0.1, 10);
67
68
69         /* Sort the vertexes (this only works with all-triangles */
70         int trisize = 2*sizeof(gfloat) + 3*sizeof(vert_t);
71         int ntris   = nvals*sizeof(gfloat) / trisize;
72         g_print("%d, %d, %d\n", sizeof(gfloat), trisize, ntris);
73         qsort(data, ntris, trisize, sort_cmp);
74
75         /* Draw the data */
76         for (int i = 0; i < nvals;) {
77                 gfloat token = data[i++];
78                 if (token == GL_POLYGON_TOKEN) {
79                         gfloat n = data[i++];
80                         vert_t *verts = (vert_t*)&data[i];
81                         i += n*vertsize;
82                         //g_print("GL_POLYGON_TOKEN: %f\n", n);
83
84                         /* Draw triangle */
85                         glBegin(GL_TRIANGLES);
86                         for (int j = 0; j < n; j++) {
87                                 g_print("\t%7.2f, %6.2f, %6.2f %6.2f - "
88                                         "%5.2f, %5.2f, %5.2f, %5.2f\n",
89                                         verts[j].xyz[0],
90                                         verts[j].xyz[1],
91                                         verts[j].xyz[2],
92                                         verts[j].xyz[3],
93                                         verts[j].texture[0],
94                                         verts[j].texture[1],
95                                         verts[j].texture[2],
96                                         verts[j].texture[3]);
97                                 glTexCoord4f(
98                                         verts[j].texture[0],
99                                         verts[j].texture[1],
100                                         verts[j].texture[2],
101                                         verts[j].texture[3]);
102                                 glColor4f(
103                                         verts[j].color[0],
104                                         verts[j].color[1],
105                                         verts[j].color[2],
106                                         verts[j].color[3]);
107                                 if (j == 2)
108                                         verts[j].xyz[2] = -100;
109                                 glVertex3f(
110                                         verts[j].xyz[0],
111                                         verts[j].xyz[1],
112                                         verts[j].xyz[2]);
113                         }
114                         glEnd();
115
116                         /* Draw line */
117                         //glDisable(GL_TEXTURE_2D);
118                         //glBegin(GL_LINE_LOOP);
119                         //glColor4f(1,1,1,1);
120                         //for (int j = 0; j < n; j++)
121                         //      glVertex3fv(verts[j].xyz);
122                         //glEnd();
123                 } else {
124                         g_error("Unknown token: %f\n", token);
125                 }
126         }
127         glMatrixMode(GL_PROJECTION);
128         glPopMatrix();
129         glMatrixMode(GL_MODELVIEW);
130         glPopMatrix();
131         glMatrixMode(GL_TEXTURE);
132         glPopMatrix();
133         g_free(data);
134 }
135
136 static gboolean on_expose(GtkWidget *drawing, GdkEventExpose *event, gpointer _)
137 {
138         //glClearColor(0.5, 0.5, 1.0, 1.0);
139         glClearColor(0.0, 0.0, 0.0, 0.0);
140         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
141
142         glEnable(GL_BLEND);
143
144         /* Blend, but broken sorting */
145         //glEnable(GL_DEPTH_TEST);
146         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
147
148         /* No sorting, just add */
149         //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
150         //glBlendFunc(GL_ONE, GL_ONE);
151
152         /* Lighting */
153         float light_ambient[]  = {0.1f, 0.1f, 0.0f, 1.0f};
154         float light_diffuse[]  = {0.9f, 0.9f, 0.9f, 1.0f};
155         float light_position[] = {-30.0f, 50.0f, 40.0f, 1.0f};
156         glLightfv(GL_LIGHT0, GL_AMBIENT,  light_ambient);
157         glLightfv(GL_LIGHT0, GL_DIFFUSE,  light_diffuse);
158         glLightfv(GL_LIGHT0, GL_POSITION, light_position);
159         glEnable(GL_COLOR_MATERIAL);
160         glEnable(GL_LIGHTING);
161         glEnable(GL_LIGHT0);
162
163         glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
164
165         /* Draw teapots */
166         g_print("%f,%f,%f\n", pos[0], pos[1], pos[2]);
167         g_print("%f,%f,%f\n", rot[0], rot[1], rot[2]);
168
169         glMatrixMode(GL_MODELVIEW);
170
171         gfloat *data = sort_start();
172         glLoadIdentity();
173         glTranslatef(pos[0], pos[1], pos[2]);
174         glTranslatef(0.05, 0.1, -2);
175         glRotatef(60, 1, -1, -0.2);
176         glColor4f(1,1,1,1);
177         glDisable(GL_COLOR_MATERIAL);
178         glEnable(GL_TEXTURE_2D);
179         glBindTexture(GL_TEXTURE_2D, tex);
180         glBegin(GL_QUADS);
181         glTexCoord2f(0, 0); glVertex3f(-0.8,  0.5, 0.0);
182         glTexCoord2f(0, 1); glVertex3f(-0.8, -0.5, 0.0);
183         glTexCoord2f(1, 1); glVertex3f( 0.8, -0.5, 0.0);
184         glTexCoord2f(1, 0); glVertex3f( 0.8,  0.5, 0.0);
185         glEnd();
186
187         //glLoadIdentity();
188         //glTranslatef(pos[0], pos[1], pos[2]);
189         //glTranslatef(0.05, 0.1, -2);
190         //glRotatef(30, 1, -1, -0.2);
191         //glColor4f(1.0, 0.2, 0.2, 0.5);
192         ////gdk_gl_draw_teapot(TRUE, 0.5);
193         //gdk_gl_draw_cube(TRUE, 0.5);
194
195         //glLoadIdentity();
196         //glTranslatef(pos[0], pos[1], pos[2]);
197         //glTranslatef(-0.2, 0, -2);
198         //glRotatef(30, 1, -1, -0.2);
199         //glColor4f(0.2, 0.2, 1.0, 0.5);
200         ////gdk_gl_draw_teapot(TRUE, 0.5);
201         //gdk_gl_draw_cube(TRUE, 0.5);
202         sort_end(data);
203
204         /* Flush */
205         GdkGLDrawable *gldrawable = gdk_gl_drawable_get_current();
206         if (gdk_gl_drawable_is_double_buffered(gldrawable))
207                 gdk_gl_drawable_swap_buffers(gldrawable);
208         else
209                 glFlush();
210         return FALSE;
211 }
212
213 static gboolean on_configure(GtkWidget *drawing, GdkEventConfigure *event, gpointer _)
214 {
215         gdouble width  = drawing->allocation.width;
216         gdouble height = drawing->allocation.height;
217         glViewport(0, 0, width, height);
218
219         /* Set up projection */
220         glMatrixMode(GL_PROJECTION);
221         glLoadIdentity();
222         //gluPerspective(90, width/height, 0.1, 10);
223         gluPerspective(90, 0.8, 0.1, 10);
224         //glOrtho(1,-1, -0.7,0.7, -10,10);
225         return FALSE;
226 }
227
228 static gboolean on_key_press(GtkWidget *widget, GdkEventKey *event, gpointer _)
229 {
230         guint kv = event->keyval;
231         if      (kv == GDK_q) gtk_main_quit();
232         else if (kv == GDK_h) pos[0] -= 0.02;
233         else if (kv == GDK_j) pos[1] += 0.02;
234         else if (kv == GDK_k) pos[1] -= 0.02;
235         else if (kv == GDK_l) pos[0] += 0.02;
236         else if (kv == GDK_o) pos[2] -= 0.02;
237         else if (kv == GDK_i) pos[2] += 0.02;
238         else if (kv == GDK_H) rot[2] -= 2.0;
239         else if (kv == GDK_J) rot[0] += 2.0;
240         else if (kv == GDK_K) rot[0] -= 2.0;
241         else if (kv == GDK_L) rot[2] += 2.0;
242         gtk_widget_queue_draw(widget);
243         return FALSE;
244 }
245
246 static guint load_tex(gchar *filename)
247 {
248         GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
249         guchar    *pixels = gdk_pixbuf_get_pixels(pixbuf);
250         int        width  = gdk_pixbuf_get_width(pixbuf);
251         int        height = gdk_pixbuf_get_height(pixbuf);
252         int        alpha  = gdk_pixbuf_get_has_alpha(pixbuf);
253         guint      tex;
254         glGenTextures(1, &tex);
255         glBindTexture(GL_TEXTURE_2D, tex);
256         glTexImage2D(GL_TEXTURE_2D, 0, 4, width, height, 0,
257                         (alpha ? GL_RGBA : GL_RGB), GL_UNSIGNED_BYTE, pixels);
258         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
259         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
260
261         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
262         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
263         g_object_unref(pixbuf);
264         return tex;
265 }
266
267 gchar *gl_program_log(guint program, int *_len)
268 {
269         gchar *buf = NULL;
270         int len = 0;
271         glGetProgramiv(program, GL_INFO_LOG_LENGTH, &len);
272         if (len > 0) {
273                 buf = g_malloc(len);
274                 glGetProgramInfoLog(program, len, &len, buf);
275         }
276         if (_len)
277                 *_len = len;
278         return buf;
279 }
280
281 static void load_shader(gchar *filename)
282 {
283         gchar *source;
284         gboolean status = g_file_get_contents(filename, &source, NULL, NULL);
285         if (!status)
286                 g_error("Failed to load shader");
287
288         guint program = glCreateProgram();
289         if (!program)
290                 g_error("Error creating program");
291
292         guint shader = glCreateShader(GL_VERTEX_SHADER_ARB);
293         if (!shader)
294                 g_error("Error creating shader");
295
296         glShaderSource(shader, 1, (const gchar**)&source, NULL);
297         if (glGetError())
298                 g_error("Error setting shader source");
299
300         glCompileShader(shader);
301         if (glGetError())
302                 g_error("Error compiling shader");
303
304         glAttachShader(program, shader);
305         if (glGetError())
306                 g_error("Error attaching shader");
307
308         glLinkProgram(program);
309         if (glGetError())
310                 g_error("Error linking program");
311
312         glUseProgram(program);
313         if (glGetError())
314                 g_error("Error using program:\n%s", gl_program_log(program, NULL));
315 }
316
317 int main(int argc, char **argv)
318 {
319         gtk_init(&argc, &argv);
320
321         GtkWidget   *window   = gtk_window_new(GTK_WINDOW_TOPLEVEL);
322         GtkWidget   *drawing  = gtk_drawing_area_new();
323         GdkGLConfig *glconfig = gdk_gl_config_new_by_mode((GdkGLConfigMode)(
324                         GDK_GL_MODE_RGBA   | GDK_GL_MODE_DEPTH |
325                         GDK_GL_MODE_DOUBLE | GDK_GL_MODE_ALPHA));
326         g_signal_connect(window,  "destroy",         G_CALLBACK(gtk_main_quit), NULL);
327         g_signal_connect(window,  "key-press-event", G_CALLBACK(on_key_press),  NULL);
328         g_signal_connect(drawing, "expose-event",    G_CALLBACK(on_expose),     NULL);
329         g_signal_connect(drawing, "configure-event", G_CALLBACK(on_configure),  NULL);
330         gtk_widget_set_gl_capability(drawing, glconfig, NULL, TRUE, GDK_GL_RGBA_TYPE);
331         gtk_container_add(GTK_CONTAINER(window), drawing);
332         gtk_widget_show_all(window);
333
334         /* OpenGL setup */
335         GdkGLContext  *glcontext  = gtk_widget_get_gl_context(GTK_WIDGET(drawing));
336         GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(GTK_WIDGET(drawing));
337         gdk_gl_drawable_gl_begin(gldrawable, glcontext);
338
339         /* Load texture */
340         tex = load_tex("flag.png");
341
342         /* Load shader */
343         load_shader("sort.glsl");
344
345         gtk_main();
346
347         gdk_gl_drawable_gl_end(gldrawable);
348 }