2 * Copyright (C) 2009-2010 Andy Spencer <andy753421@gmail.com>
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.
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.
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/>.
18 #define GL_GLEXT_PROTOTYPES
20 #include <gtk/gtkgl.h>
21 #include <gdk/gdkkeysyms.h>
34 } __attribute__ ((packed)) vert_t;
36 static int sort_cmp(const void *a, const void *b)
38 vert_t *a_verts = (vert_t*)(((gfloat*)a)+2);
39 vert_t *b_verts = (vert_t*)(((gfloat*)b)+2);
40 gfloat a_sum = a_verts[0].xyz[2] + a_verts[1].xyz[2] + a_verts[2].xyz[2];
41 gfloat b_sum = b_verts[0].xyz[2] + b_verts[1].xyz[2] + b_verts[2].xyz[2];
42 return a_sum == b_sum ? 0 :
43 a_sum < b_sum ? 1 : -1;
46 static gfloat *sort_start()
49 gfloat *data = g_new0(gfloat, size);
50 glFeedbackBuffer(size, GL_4D_COLOR_TEXTURE, data);
51 glRenderMode(GL_FEEDBACK);
52 g_print("1st = %f\n", data[0]);
56 static void sort_end(gfloat *data)
58 int vertsize = sizeof(vert_t)/sizeof(gfloat);
59 int nvals = glRenderMode(GL_RENDER);
61 /* Set up screen coords */
63 glGetIntegerv(GL_VIEWPORT, view);
65 glMatrixMode(GL_PROJECTION);
68 glOrtho(view[0],view[2], view[1],view[3], -100,100);
70 glMatrixMode(GL_MODELVIEW);
73 glDisable(GL_LIGHTING);
75 glMatrixMode(GL_TEXTURE);
79 //glTranslatef(pos[0], pos[1], pos[2]);
80 //glTranslatef(0.05, 0.1, -2);
81 //glRotatef(0.03, 1, 1, 0);
83 //gluPerspective(90, 0.8, 0.1, 10);
86 /* Sort the vertexes (this only works with all-triangles */
87 int trisize = 2*sizeof(gfloat) + 3*sizeof(vert_t);
88 int ntris = nvals*sizeof(gfloat) / trisize;
89 g_print("%d, %d, %d\n", sizeof(gfloat), trisize, ntris);
90 qsort(data, ntris, trisize, sort_cmp);
93 for (int i = 0; i < nvals;) {
94 gfloat token = data[i++];
95 if (token == GL_POLYGON_TOKEN) {
97 vert_t *verts = (vert_t*)&data[i];
99 //g_print("GL_POLYGON_TOKEN: %f\n", n);
102 glBegin(GL_TRIANGLES);
103 for (int j = 0; j < n; j++) {
104 g_print("\t%7.2f, %6.2f, %6.2f %6.2f - "
105 "%5.2f, %5.2f, %5.2f, %5.2f\n",
113 verts[j].texture[3]);
118 verts[j].texture[3]);
125 verts[j].xyz[2] = -100;
134 //glDisable(GL_TEXTURE_2D);
135 //glBegin(GL_LINE_LOOP);
136 //glColor4f(1,1,1,1);
137 //for (int j = 0; j < n; j++)
138 // glVertex3fv(verts[j].xyz);
141 g_error("Unknown token: %f\n", token);
144 glMatrixMode(GL_PROJECTION);
146 glMatrixMode(GL_MODELVIEW);
148 glMatrixMode(GL_TEXTURE);
153 static gboolean on_expose(GtkWidget *drawing, GdkEventExpose *event, gpointer _)
155 //glClearColor(0.5, 0.5, 1.0, 1.0);
156 glClearColor(0.0, 0.0, 0.0, 0.0);
157 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
161 /* Blend, but broken sorting */
162 //glEnable(GL_DEPTH_TEST);
163 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
165 /* No sorting, just add */
166 //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
167 //glBlendFunc(GL_ONE, GL_ONE);
170 float light_ambient[] = {0.1f, 0.1f, 0.0f, 1.0f};
171 float light_diffuse[] = {0.9f, 0.9f, 0.9f, 1.0f};
172 float light_position[] = {-30.0f, 50.0f, 40.0f, 1.0f};
173 glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
174 glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
175 glLightfv(GL_LIGHT0, GL_POSITION, light_position);
176 glEnable(GL_COLOR_MATERIAL);
177 glEnable(GL_LIGHTING);
180 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
183 g_print("%f,%f,%f\n", pos[0], pos[1], pos[2]);
184 g_print("%f,%f,%f\n", rot[0], rot[1], rot[2]);
186 glMatrixMode(GL_MODELVIEW);
188 gfloat *data = sort_start();
190 glTranslatef(pos[0], pos[1], pos[2]);
191 glTranslatef(0.05, 0.1, -2);
192 glRotatef(60, 1, -1, -0.2);
194 glDisable(GL_COLOR_MATERIAL);
195 glEnable(GL_TEXTURE_2D);
196 glBindTexture(GL_TEXTURE_2D, tex);
198 glTexCoord2f(0, 0); glVertex3f(-0.8, 0.5, 0.0);
199 glTexCoord2f(0, 1); glVertex3f(-0.8, -0.5, 0.0);
200 glTexCoord2f(1, 1); glVertex3f( 0.8, -0.5, 0.0);
201 glTexCoord2f(1, 0); glVertex3f( 0.8, 0.5, 0.0);
205 //glTranslatef(pos[0], pos[1], pos[2]);
206 //glTranslatef(0.05, 0.1, -2);
207 //glRotatef(30, 1, -1, -0.2);
208 //glColor4f(1.0, 0.2, 0.2, 0.5);
209 ////gdk_gl_draw_teapot(TRUE, 0.5);
210 //gdk_gl_draw_cube(TRUE, 0.5);
213 //glTranslatef(pos[0], pos[1], pos[2]);
214 //glTranslatef(-0.2, 0, -2);
215 //glRotatef(30, 1, -1, -0.2);
216 //glColor4f(0.2, 0.2, 1.0, 0.5);
217 ////gdk_gl_draw_teapot(TRUE, 0.5);
218 //gdk_gl_draw_cube(TRUE, 0.5);
222 GdkGLDrawable *gldrawable = gdk_gl_drawable_get_current();
223 if (gdk_gl_drawable_is_double_buffered(gldrawable))
224 gdk_gl_drawable_swap_buffers(gldrawable);
230 static gboolean on_configure(GtkWidget *drawing, GdkEventConfigure *event, gpointer _)
232 gdouble width = drawing->allocation.width;
233 gdouble height = drawing->allocation.height;
234 glViewport(0, 0, width, height);
236 /* Set up projection */
237 glMatrixMode(GL_PROJECTION);
239 //gluPerspective(90, width/height, 0.1, 10);
240 gluPerspective(90, 0.8, 0.1, 10);
241 //glOrtho(1,-1, -0.7,0.7, -10,10);
245 static gboolean on_key_press(GtkWidget *widget, GdkEventKey *event, gpointer _)
247 guint kv = event->keyval;
248 if (kv == GDK_q) gtk_main_quit();
249 else if (kv == GDK_h) pos[0] -= 0.02;
250 else if (kv == GDK_j) pos[1] += 0.02;
251 else if (kv == GDK_k) pos[1] -= 0.02;
252 else if (kv == GDK_l) pos[0] += 0.02;
253 else if (kv == GDK_o) pos[2] -= 0.02;
254 else if (kv == GDK_i) pos[2] += 0.02;
255 else if (kv == GDK_H) rot[2] -= 2.0;
256 else if (kv == GDK_J) rot[0] += 2.0;
257 else if (kv == GDK_K) rot[0] -= 2.0;
258 else if (kv == GDK_L) rot[2] += 2.0;
259 gtk_widget_queue_draw(widget);
263 static guint load_tex(gchar *filename)
265 GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
266 guchar *pixels = gdk_pixbuf_get_pixels(pixbuf);
267 int width = gdk_pixbuf_get_width(pixbuf);
268 int height = gdk_pixbuf_get_height(pixbuf);
269 int alpha = gdk_pixbuf_get_has_alpha(pixbuf);
271 glGenTextures(1, &tex);
272 glBindTexture(GL_TEXTURE_2D, tex);
273 glTexImage2D(GL_TEXTURE_2D, 0, 4, width, height, 0,
274 (alpha ? GL_RGBA : GL_RGB), GL_UNSIGNED_BYTE, pixels);
275 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
276 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
278 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
279 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
280 g_object_unref(pixbuf);
284 gchar *gl_program_log(guint program, int *_len)
288 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &len);
291 glGetProgramInfoLog(program, len, &len, buf);
298 static void load_shader(gchar *filename)
301 gboolean status = g_file_get_contents(filename, &source, NULL, NULL);
303 g_error("Failed to load shader");
305 guint program = glCreateProgram();
307 g_error("Error creating program");
309 guint shader = glCreateShader(GL_VERTEX_SHADER_ARB);
311 g_error("Error creating shader");
313 glShaderSource(shader, 1, (const gchar**)&source, NULL);
315 g_error("Error setting shader source");
317 glCompileShader(shader);
319 g_error("Error compiling shader");
321 glAttachShader(program, shader);
323 g_error("Error attaching shader");
325 glLinkProgram(program);
327 g_error("Error linking program");
329 glUseProgram(program);
331 g_error("Error using program:\n%s", gl_program_log(program, NULL));
334 int main(int argc, char **argv)
336 gtk_init(&argc, &argv);
338 GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
339 GtkWidget *drawing = gtk_drawing_area_new();
340 GdkGLConfig *glconfig = gdk_gl_config_new_by_mode((GdkGLConfigMode)(
341 GDK_GL_MODE_RGBA | GDK_GL_MODE_DEPTH |
342 GDK_GL_MODE_DOUBLE | GDK_GL_MODE_ALPHA));
343 g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
344 g_signal_connect(window, "key-press-event", G_CALLBACK(on_key_press), NULL);
345 g_signal_connect(drawing, "expose-event", G_CALLBACK(on_expose), NULL);
346 g_signal_connect(drawing, "configure-event", G_CALLBACK(on_configure), NULL);
347 gtk_widget_set_gl_capability(drawing, glconfig, NULL, TRUE, GDK_GL_RGBA_TYPE);
348 gtk_container_add(GTK_CONTAINER(window), drawing);
349 gtk_widget_show_all(window);
352 GdkGLContext *glcontext = gtk_widget_get_gl_context(GTK_WIDGET(drawing));
353 GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(GTK_WIDGET(drawing));
354 gdk_gl_drawable_gl_begin(gldrawable, glcontext);
357 tex = load_tex("flag.png");
360 load_shader("sort.glsl");
364 gdk_gl_drawable_gl_end(gldrawable);