reprap: Added shadow mapping
[simavr] / examples / board_reprap / src / reprap_gl.c
1 /*
2         reprap_gl.c
3
4         Copyright 2008-2012 Michel Pollet <buserror@gmail.com>
5
6         This file is part of simavr.
7
8         simavr is free software: you can redistribute it and/or modify
9         it under the terms of the GNU General Public License as published by
10         the Free Software Foundation, either version 3 of the License, or
11         (at your option) any later version.
12
13         simavr is distributed in the hope that it will be useful,
14         but WITHOUT ANY WARRANTY; without even the implied warranty of
15         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16         GNU General Public License for more details.
17
18         You should have received a copy of the GNU General Public License
19         along with simavr.  If not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #if __APPLE__
23 #define GL_GLEXT_PROTOTYPES
24 #include <GLUT/glut.h>
25 #include <OpenGL/gl.h>
26 #include <OpenGL/glext.h>
27 #else
28 #define GL_GLEXT_PROTOTYPES
29 #include <GL/gl.h>
30 #include <GL/glut.h>
31 #include <GL/glext.h>
32 #endif
33
34 #include <stdio.h>
35 #include <math.h>
36
37 #include "reprap.h"
38 #include "reprap_gl.h"
39
40 #include "c3.h"
41 #include "c3camera.h"
42 #include "c3driver_context.h"
43 #include "c3stl.h"
44 #include "c3lines.h"
45 #include "c3sphere.h"
46 #include "c3light.h"
47 #include "c3program.h"
48 #include "c3gl.h"
49 #include "c3gl_fbo.h"
50
51 #include <cairo/cairo.h>
52
53 struct cairo_surface_t;
54
55 int _w = 800, _h = 600;
56
57 c3context_p c3 = NULL;
58 c3context_p hud = NULL;
59
60 c3object_p      head = NULL;    // hotend
61 c3texture_p fbo_c3;                     // frame buffer object texture
62 c3program_p fxaa = NULL;        // full screen antialias shader
63 c3program_p scene = NULL;
64 c3gl_fbo_t      fbo;
65 c3gl_fbo_t      shadow;
66
67
68 enum {
69         uniform_ShadowMap = 0,
70         uniform_pixelOffset,
71         uniform_tex0,
72         uniform_shadowMatrix
73 };
74 const char *uniforms_scene[] = {
75                 "shadowMap",
76                 "pixelOffset",
77                 "tex0",
78                 "shadowMatrix",
79                 NULL
80 };
81
82 int glsl_version = 110;
83
84 extern reprap_t reprap;
85
86 static int dumpError(const char * what)
87 {
88         GLenum e;
89         int count = 0;
90         while ((e = glGetError()) != GL_NO_ERROR) {
91                 printf("%s: %s\n", what, gluErrorString(e));
92                 count++;
93         }
94         return count;
95 }
96
97 #define GLCHECK(_w) {_w; dumpError(#_w);}
98
99
100 static void
101 _gl_reshape_cb(int w, int h)
102 {
103     _w  = w;
104     _h = h;
105
106         c3vec2 size = c3vec2f(_w, _h);
107
108         glBindFramebuffer(GL_FRAMEBUFFER, 0);
109     glViewport(0, 0, _w, _h);
110     c3gl_fbo_resize(&fbo, size);
111     c3texture_resize(fbo_c3, size);
112     c3context_view_get_at(c3, 0)->size = size;
113
114     if (fxaa) {
115         glUseProgram((GLuint)fxaa->pid);
116         GLCHECK(glUniform2fv((GLuint)fxaa->params.e[0].pid, 1, size.n));
117         glUseProgram(0);
118     }
119
120     glutPostRedisplay();
121 }
122
123 static void
124 _gl_key_cb(
125                 unsigned char key,
126                 int x,
127                 int y)  /* called on key press */
128 {
129         switch (key) {
130                 case 'q':
131                 //      avr_vcd_stop(&vcd_file);
132                         c3context_dispose(c3);
133                         exit(0);
134                         break;
135                 case 'r':
136                         printf("Starting VCD trace; press 's' to stop\n");
137                 //      avr_vcd_start(&vcd_file);
138                         break;
139                 case 's':
140                         printf("Stopping VCD trace\n");
141                 //      avr_vcd_stop(&vcd_file);
142                         break;
143                 case '1':
144                         if (fbo_c3->geometry.mat.program)
145                                 fbo_c3->geometry.mat.program = NULL;
146                         else
147                                 fbo_c3->geometry.mat.program = fxaa;
148                         glutPostRedisplay();
149                         break;
150         }
151 }
152
153 static void
154 _gl_display_cb(void)            /* function called whenever redisplay needed */
155 {
156         int drawIndexes[] = { 1, 0 };
157         int drawViewStart = c3->root->dirty ? 0 : 1;
158
159         c3vec3 headp = c3vec3f(
160                         stepper_get_position_mm(&reprap.step_x),
161                         stepper_get_position_mm(&reprap.step_y),
162                         stepper_get_position_mm(&reprap.step_z));
163         c3mat4 headmove = translation3D(headp);
164         c3transform_set(head->transform.e[0], &headmove);
165
166         for (int vi = drawViewStart; vi < 2; vi++) {
167                 c3context_view_set(c3, drawIndexes[vi]);
168
169                 /*
170                  * Draw in FBO object
171                  */
172                 c3context_view_p view = c3context_view_get(c3);
173                 glBindFramebuffer(GL_FRAMEBUFFER, (GLuint)view->bid);
174                 // draw (without glutSwapBuffers)
175                 dumpError("glBindFramebuffer fbo");
176                 glViewport(0, 0, view->size.x, view->size.y);
177
178                 c3context_project(c3);
179
180                 glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
181                 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
182
183                 // Set up projection matrix
184                 glMatrixMode(GL_PROJECTION); // Select projection matrix
185                 glLoadMatrixf(view->projection.n);
186
187                 glEnable(GL_CULL_FACE);
188                 glDepthMask(GL_TRUE);
189                 glDepthFunc(GL_LEQUAL);
190                 glEnable(GL_DEPTH_TEST);
191         //      glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
192
193                 //glEnable(GL_ALPHA_TEST);
194                 //glAlphaFunc(GL_GREATER, 1.0f / 255.0f);
195                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Type Of Blending To Use
196
197                 glMatrixMode(GL_MODELVIEW);
198
199
200                 if (view->type == C3_CONTEXT_VIEW_EYE) {
201                 //      glShadeModel(GL_SMOOTH);
202                 //      glEnable(GL_LIGHTING);
203                         glCullFace(GL_BACK);
204                         glEnable(GL_BLEND); // Enable Blending
205
206                         c3context_view_p light = c3context_view_get_at(c3, 1);
207
208                         // This is matrix transform every coordinate x,y,z
209                         // x = x* 0.5 + 0.5
210                         // y = y* 0.5 + 0.5
211                         // z = z* 0.5 + 0.5
212                         // Moving from unit cube [-1,1] to [0,1]
213                         const c3f bias[16] = {
214                                 0.5, 0.0, 0.0, 0.0,
215                                 0.0, 0.5, 0.0, 0.0,
216                                 0.0, 0.0, 0.5, 0.0,
217                                 0.5, 0.5, 0.5, 1.0};
218
219                         c3mat4 b = c3mat4_mul(&light->projection, (c3mat4p)bias);
220                         c3mat4 tex = c3mat4_mul(&light->cam.mtx, &b);
221
222                         GLCHECK(glUseProgram((GLuint)scene->pid));
223                         glUniformMatrix4fv(
224                                         (GLuint)scene->params.e[uniform_shadowMatrix].pid,
225                                         1, GL_FALSE, tex.n);
226                 } else {
227                         glCullFace(GL_FRONT);
228                         glShadeModel(GL_FLAT);
229                         glDisable(GL_LIGHTING);
230                         glDisable(GL_BLEND); // Disable Blending
231                 }
232
233                 c3context_draw(c3);
234         }
235
236         /*
237          * Draw back FBO over the screen
238          */
239         glBindFramebuffer(GL_FRAMEBUFFER, 0);
240         dumpError("glBindFramebuffer 0");
241         glViewport(0, 0, _w, _h);
242
243         glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
244         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
245
246         glDisable(GL_DEPTH_TEST);
247         glDisable(GL_LIGHTING);
248         glDisable(GL_ALPHA_TEST);
249         glDisable(GL_CULL_FACE);
250
251         glUseProgram(0);
252
253         glMatrixMode(GL_PROJECTION); // Select projection matrix
254         glLoadIdentity(); // Start with an identity matrix
255
256         c3mat4 pro = screen_ortho3D(0, _w, 0, _h, 0, 10);
257         glLoadMatrixf(pro.n);
258
259         glMatrixMode(GL_MODELVIEW); // Select modelview matrix
260
261         if (hud->root->dirty) {
262         //      printf("reproject head %.2f,%.2f,%.2f\n", headp.x, headp.y,headp.z);
263                 c3context_project(hud);
264         }
265         c3context_draw(hud);
266
267     glutSwapBuffers();
268 }
269
270 #if !defined(GLUT_WHEEL_UP)
271 #  define GLUT_WHEEL_UP   3
272 #  define GLUT_WHEEL_DOWN 4
273 #endif
274
275
276 int button;
277 c3vec2 move;
278
279 static
280 void _gl_button_cb(
281                 int b,
282                 int s,
283                 int x,
284                 int y)
285 {
286         button = s == GLUT_DOWN ? b : 0;
287         move = c3vec2f(x, y);
288         c3context_view_p view = c3context_view_get_at(c3, 0);
289 //      printf("button %d: %.1f,%.1f\n", b, move.x, move.y);
290         switch (b) {
291                 case GLUT_LEFT_BUTTON:
292                 case GLUT_RIGHT_BUTTON: // call motion
293                         break;
294                 case GLUT_WHEEL_UP:
295                 case GLUT_WHEEL_DOWN:
296                         if (view->cam.distance > 10) {
297                                 const float d = 0.004;
298                                 c3cam_set_distance(&view->cam,
299                                                 view->cam.distance * ((b == GLUT_WHEEL_DOWN) ? (1.0+d) : (1.0-d)));
300                                 c3cam_update_matrix(&view->cam);
301                                 view->dirty = 1;        // resort the array
302                         }
303                         break;
304         }
305 }
306
307 void
308 _gl_motion_cb(
309                 int x,
310                 int y)
311 {
312         c3vec2 m = c3vec2f(x, y);
313         c3vec2 delta = c3vec2_sub(move, m);
314         c3context_view_p view = c3context_view_get_at(c3, 0);
315
316 //      printf("%s b%d click %.1f,%.1f now %d,%d delta %.1f,%.1f\n",
317 //                      __func__, button, move.n[0], move.n[1], x, y, delta.x, delta.y);
318
319         switch (button) {
320                 case GLUT_LEFT_BUTTON: {
321                         c3mat4 rotx = rotation3D(view->cam.side, delta.n[1] / 4);
322                         c3mat4 roty = rotation3D(c3vec3f(0.0, 0.0, 1.0), delta.n[0] / 4);
323                         rotx = c3mat4_mul(&rotx, &roty);
324                         c3cam_rot_about_lookat(&view->cam, &rotx);
325                         c3cam_update_matrix(&view->cam);
326
327                         view->dirty = 1;        // resort the array
328                 }       break;
329                 case GLUT_RIGHT_BUTTON: {
330                         // offset both points, but following the plane
331                         c3vec3 f = c3vec3_mulf(
332                                         c3vec3f(-view->cam.side.y, view->cam.side.x, 0),
333                                         -delta.n[1] / 4);
334                         view->cam.eye = c3vec3_add(view->cam.eye, f);
335                         view->cam.lookat = c3vec3_add(view->cam.lookat, f);
336                         c3cam_movef(&view->cam, delta.n[0] / 8, 0, 0);
337                         c3cam_update_matrix(&view->cam);
338
339                     view->dirty = 1;    // resort the array
340                 }       break;
341         }
342         move = m;
343 }
344
345 // gl timer. if the lcd is dirty, refresh display
346 static void
347 _gl_timer_cb(
348                 int i)
349 {
350         glutTimerFunc(1000 / 24, _gl_timer_cb, 0);
351         glutPostRedisplay();
352 }
353
354 const c3driver_context_t * c3_driver_list[3] = { NULL, NULL };
355
356 int
357 gl_init(
358                 int argc,
359                 char *argv[] )
360 {
361         glutInit(&argc, argv);          /* initialize GLUT system */
362
363         glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH | GLUT_ALPHA);
364         glutInitWindowSize(_w, _h);             /* width=400pixels height=500pixels */
365         /*window =*/ glutCreateWindow("Press 'q' to quit");     /* create window */
366
367         glutDisplayFunc(_gl_display_cb);                /* set window's display callback */
368         glutKeyboardFunc(_gl_key_cb);           /* set window's key callback */
369         glutTimerFunc(1000 / 24, _gl_timer_cb, 0);
370
371         glutMouseFunc(_gl_button_cb);
372         glutMotionFunc(_gl_motion_cb);
373     glutReshapeFunc(_gl_reshape_cb);
374
375         glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
376         glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST);
377
378         // enable color tracking
379         glEnable(GL_COLOR_MATERIAL);
380         // set material properties which will be assigned by glColor
381         glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
382
383         /* setup some lights */
384         GLfloat global_ambient[] = { 0.5f, 0.5f, 0.5f, 1.0f };
385         glLightModelfv(GL_LIGHT_MODEL_AMBIENT, global_ambient);
386
387         if (0) {
388                 GLfloat specular[] = {1.0f, 1.0f, 1.0f , 0.8f};
389                 GLfloat position[] = { 250.0f, -50.0f, 100.0f, 1.0f };
390                 glLightfv(GL_LIGHT1, GL_SPECULAR, specular);
391                 glLightfv(GL_LIGHT1, GL_POSITION, position);
392                 glEnable(GL_LIGHT1);
393         }
394
395         /*
396          * Extract the GLSL version as a numeric value for later
397          */
398         const char * glsl = (const char *)glGetString(GL_SHADING_LANGUAGE_VERSION);
399         {
400                 int M = 0, m = 0;
401                 if (sscanf(glsl, "%d.%d", &M, &m) == 2)
402                         glsl_version = (M * 100) + m;
403
404         }
405         printf("GL_SHADING_LANGUAGE_VERSION %s = %d\n", glsl, glsl_version);
406
407         c3gl_fbo_create(&fbo, c3vec2f(_w, _h), (1 << C3GL_FBO_COLOR)|(1 << C3GL_FBO_DEPTH));
408         // shadow buffer
409
410         c3_driver_list[0] = c3gl_getdriver();
411
412     c3 = c3context_new(_w, _h);
413     c3->driver = c3_driver_list;
414
415     c3cam_p cam = &c3context_view_get_at(c3, 0)->cam;
416         cam->lookat = c3vec3f(100.0, 100.0, 0.0);
417         cam->eye = c3vec3f(100.0, -100.0, 100.0);
418         // associate the framebuffer object with this view
419         c3context_view_get_at(c3, 0)->bid = fbo.fbo;
420         /*
421          * Create a light, attach it to a movable object, and attach a sphere
422          * to it too so it's visible.
423          */
424         {
425                 c3object_p ligthhook = c3object_new(c3->root);
426             c3transform_p pos = c3transform_new(ligthhook);
427
428             pos->matrix = translation3D(c3vec3f(-30.0f, -30.0f, 200.0f));
429
430                 c3light_p light = c3light_new(ligthhook);
431                 light->geometry.name = str_new("light0");
432                 light->color.specular = c3vec4f(1.0f, 1.0f, 1.0f , 0.8f);
433                 light->position = c3vec4f(0, 0, 0, 1.0f );
434
435             {   // light bulb
436                 c3geometry_p g = c3sphere_uv(ligthhook, c3vec3f(0, 0, 0), 3, 10, 10);
437                 g->mat.color = c3vec4f(1.0, 1.0, 0.0, 1.0);
438                 g->hidden = 0;  // hidden from light scenes
439             }
440         }
441         {
442                 c3vec2 size = c3vec2f(1024, 1024);
443                 c3gl_fbo_create(&shadow, size, (1 << C3GL_FBO_DEPTH_TEX));
444
445                 c3context_view_t v = {
446                                 .type = C3_CONTEXT_VIEW_LIGHT,
447                                 .size = size,
448                                 .dirty = 1,
449                                 .index = c3->views.count,
450                                 .bid = shadow.fbo,
451                 };
452                 c3cam_init(&v.cam);
453                 c3vec3 listpos = c3vec3f(-30.0f, -30.0f, 200.0f);
454                 v.cam.eye = listpos;
455                 v.cam.lookat = c3vec3f(100.0, 100.0, 0.0);
456                 c3context_view_array_add(&c3->views, v);
457         }
458
459     {
460         const char *path = "gfx/hb.png";
461         cairo_surface_t * image = cairo_image_surface_create_from_png (path);
462         printf("image = %p %p\n", image, cairo_image_surface_get_data (image));
463         c3texture_p b = c3texture_new(c3->root);
464
465         c3pixels_p dst = c3pixels_new(
466                         cairo_image_surface_get_width (image),
467                         cairo_image_surface_get_height (image),
468                         4, cairo_image_surface_get_stride(image),
469                         cairo_image_surface_get_data (image));
470                 dst->name = str_new(path);
471         dst->normalize = 1;
472         b->geometry.mat.texture = dst;
473         b->size = c3vec2f(200, 200);
474                 b->geometry.mat.color = c3vec4f(1.0, 1.0, 1.0, 1.0);
475 //          c3transform_new(head);
476     }
477     c3pixels_p brass_tex = NULL;
478     {
479         const char *path = "gfx/brass.png";
480         cairo_surface_t * image = cairo_image_surface_create_from_png (path);
481         printf("image = %p %p\n", image, cairo_image_surface_get_data (image));
482
483         c3pixels_p dst = c3pixels_new(
484                         cairo_image_surface_get_width (image),
485                         cairo_image_surface_get_height (image),
486                         4, cairo_image_surface_get_stride(image),
487                         cairo_image_surface_get_data (image));
488                 dst->name = str_new(path);
489         dst->normalize = 1;
490                 c3pixels_array_add(&c3->pixels, dst);
491 //          c3transform_new(head);
492                 brass_tex = dst;
493     }
494     c3pixels_p line_aa_tex = NULL;
495     {
496         const char *path = "gfx/BlurryCircle.png";
497         cairo_surface_t * image = cairo_image_surface_create_from_png (path);
498         printf("image = %p %p\n", image, cairo_image_surface_get_data (image));
499
500 #if 0
501         c3pixels_p dst = &b->pixels;
502         c3pixels_init(dst,
503                         cairo_image_surface_get_width (image),
504                         cairo_image_surface_get_height (image),
505                         1, cairo_image_surface_get_width (image),
506                         NULL);
507         c3pixels_alloc(dst);
508         b->size = c3vec2f(32, 32);
509         b->normalized = 1;
510
511         c3pixels_p src = c3pixels_new(
512                         cairo_image_surface_get_width (image),
513                         cairo_image_surface_get_height (image),
514                         4, cairo_image_surface_get_stride(image),
515                         cairo_image_surface_get_data (image));
516
517         uint32_t * _s = (uint32_t *)src->base;
518         uint8_t * _d = (uint8_t *)dst->base;
519         int max = 0;
520         for (int i = 0; i < dst->h * dst->w; i++)
521                 if ((_s[i] & 0xff) > max)
522                         max = _s[i] & 0xff;
523         for (int i = 0; i < dst->h * dst->w; i++)
524                 *_d++ = ((_s[i] & 0xff) * 255) / max;// + (0xff - max);
525         b->pixels.format = C3PIXEL_A;
526 #else
527         c3pixels_p dst = c3pixels_new(
528                         cairo_image_surface_get_width (image),
529                         cairo_image_surface_get_height (image),
530                         4, cairo_image_surface_get_stride(image),
531                         cairo_image_surface_get_data (image));
532         dst->format = C3PIXEL_ARGB;
533         dst->normalize = 1;
534         dst->name = str_new(path);
535         uint8_t * line = dst->base;
536         for (int y = 0; y < dst->h; y++, line += dst->row) {
537                 uint32_t *p = (uint32_t *)line;
538                 for (int x = 0; x < dst->w; x++, p++) {
539                         uint8_t b = *p;
540                         *p = ((0xff - b) << 24);//|(b << 16)|(b << 8)|(b);
541                 }
542         }
543 #endif
544         line_aa_tex = dst;
545 #if 0
546         c3pixels_p p = dst;
547         printf("struct { int w, h, stride, size, format; uint8_t pix[] } img = {\n"
548                         "%d, %d, %d, %d, %d\n",
549                         p->w, p->h, (int)p->row, p->psize, cairo_image_surface_get_format(image));
550         for (int i = 0; i < 32; i++)
551                 printf("0x%08x ", ((uint32_t*)p->base)[i]);
552         printf("\n");
553 #endif
554     }
555     c3object_p grid = c3object_new(c3->root);
556     {
557         for (int x = 0; x <= 20; x++) {
558                 for (int y = 0; y <= 20; y++) {
559                         c3vec3 p[4] = {
560                                 c3vec3f(-1+x*10,y*10,0.01), c3vec3f(1+x*10,y*10,0.01),
561                                 c3vec3f(x*10,-1+y*10,0.02), c3vec3f(x*10,1+y*10,0.02),
562                         };
563                 c3geometry_p g = c3geometry_new(
564                                 c3geometry_type(C3_LINES_TYPE, 0), grid);
565                 g->mat.color = c3vec4f(0.0, 0.0, 0.0, 0.8);
566                 g->mat.texture = line_aa_tex;
567                         c3lines_init(g, p, 4, 0.2);
568                 }
569         }
570     }
571
572    if (0) {
573                 c3vec3 p[4] = {
574                         c3vec3f(-5,-5,1), c3vec3f(205,-5,1),
575                 };
576         c3geometry_p g = c3geometry_new(
577                         c3geometry_type(C3_LINES_TYPE, 0), grid);
578         g->mat.color = c3vec4f(0.0, 0.0, 0.0, 1.0);
579         g->mat.texture = line_aa_tex;
580         g->line.width = 2;
581
582                 c3vertex_array_insert(&g->vertice,
583                                 g->vertice.count, p, 2);
584
585     }
586     head = c3stl_load("gfx/buserror-nozzle-model.stl", c3->root);
587     c3transform_new(head);
588     if (head->geometry.count > 0) {
589         c3geometry_factor(head->geometry.e[0], 0.1, (20 * M_PI) / 180.0);
590         head->geometry.e[0]->mat.color = c3vec4f(0.6, 0.5, 0.0, 1.0);
591         head->geometry.e[0]->mat.texture = brass_tex;
592     }
593
594 #if 0
595     c3texture_p b = c3texture_new(head);
596     c3pixels_init(&b->pixels, 64, 64, 4, 4 * 64, NULL);
597     b->geometry.dirty = 1;
598     memset(b->pixels.base, 0xff, 10 * b->pixels.row);
599 #endif
600
601
602     hud = c3context_new(_w, _h);
603     hud->driver = c3_driver_list;
604
605     /*
606      * This is the offscreen framebuffer where the 3D scene is drawn
607      */
608     {
609         /*
610          * need to insert a header since there is nothing to detect the version number
611          * reliably without it, and __VERSION__ returns idiocy
612          */
613         char head[128];
614         sprintf(head, "#version %d\n#define GLSL_VERSION %d\n", glsl_version, glsl_version);
615
616         const char *uniforms[] = { "g_Resolution", NULL };
617         fxaa = c3program_new("fxaa", uniforms);
618         c3program_array_add(&hud->programs, fxaa);
619         c3program_load_shader(fxaa, GL_VERTEX_SHADER, head,
620                         "gfx/postproc.vs", C3_PROGRAM_LOAD_UNIFORM);
621         c3program_load_shader(fxaa, GL_FRAGMENT_SHADER, head,
622                         "gfx/postproc.fs", C3_PROGRAM_LOAD_UNIFORM);
623
624         c3texture_p b = c3texture_new(hud->root);
625
626         c3pixels_p dst = c3pixels_new(_w, _h, 4, _w * 4, NULL);
627                 dst->name = str_new("fbo");
628                 dst->texture = fbo.buffers[C3GL_FBO_COLOR].bid;
629                 dst->normalize = 1;
630                 dst->dirty = 0;
631         //      dst->trace = 1;
632         b->geometry.mat.texture = dst;
633         b->geometry.mat.program = fxaa;
634         b->size = c3vec2f(_w, _h);
635                 b->geometry.mat.color = c3vec4f(1.0, 1.0, 1.0, 1.0);
636                 fbo_c3 = b;
637     }
638
639     {
640         /*
641          * need to insert a header since there is nothing to detect the version number
642          * reliably without it, and __VERSION__ returns idiocy
643          */
644         char head[128];
645         sprintf(head, "#version %d\n#define GLSL_VERSION %d\n", glsl_version, glsl_version);
646
647         scene = c3program_new("scene", uniforms_scene);
648         scene->verbose = 1;
649         c3program_array_add(&c3->programs, scene);
650         c3program_load_shader(scene, GL_VERTEX_SHADER, head,
651                         "gfx/scene.vs", C3_PROGRAM_LOAD_UNIFORM);
652         c3program_load_shader(scene, GL_FRAGMENT_SHADER, head,
653                         "gfx/scene.fs", C3_PROGRAM_LOAD_UNIFORM);
654         c3gl_program_load(scene);
655
656                 GLCHECK(glUseProgram((GLuint)scene->pid));
657         GLCHECK(glUniform1i(
658                                         (GLuint)scene->params.e[uniform_ShadowMap].pid, 7));
659                 GLCHECK(glUniform1i(
660                                         (GLuint)scene->params.e[uniform_tex0].pid, 0));
661                 c3vec2 isize = c3vec2f(1.0f / c3->views.e[1].size.x,
662                                         1.0f / c3->views.e[1].size.y);
663                 GLCHECK(glUniform2fv(
664                                         (GLuint)scene->params.e[uniform_pixelOffset].pid, 1,
665                                         isize.n));
666                 glActiveTexture(GL_TEXTURE7);
667                 GLCHECK(glBindTexture(GL_TEXTURE_2D,
668                                         (GLuint)shadow.buffers[C3GL_FBO_DEPTH_TEX].bid));
669                 glActiveTexture(GL_TEXTURE0);
670     }
671     {
672                 c3vec3 p[4] = {
673                         c3vec3f(10,10,0), c3vec3f(800-10,10,0),
674                 };
675         c3geometry_p g = c3geometry_new(
676                         c3geometry_type(C3_LINES_TYPE, 0), hud->root);
677         g->mat.color = c3vec4f(0.5, 0.5, 1.0, .3f);
678         g->mat.texture = line_aa_tex;
679                 c3lines_init(g, p, 2, 10);
680     }
681         return 1;
682 }
683
684 void
685 gl_dispose()
686 {
687         c3context_dispose(c3);
688         c3context_dispose(hud);
689         c3gl_fbo_dispose(&fbo);
690 }
691
692 int
693 gl_runloop()
694 {
695         glutMainLoop();
696         gl_dispose();
697         return 0;
698 }