dbf-udg

view src/udg.cc @ 8:f0a47f46ee45

lalala
author John Tsiombikas <nuclear@member.fsf.org>
date Mon, 18 Feb 2013 06:53:44 +0200
parents 603656331514
children 7056437a361b
line source
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <math.h>
4 #include <assert.h>
5 #include "opengl.h"
6 #include "sdr.h"
7 #include "dither_matrix.h"
8 #include "scroller.h"
9 #include "mballs.h"
11 #define DITHER_SZ 8
12 #define DITHER_LEVELS 16
14 #if DITHER_SZ == 4
15 #define dither_matrix dither_matrix4
16 #elif DITHER_SZ == 8
17 #define dither_matrix halftone_matrix8
18 #else
19 #error "invalid dither size"
20 #endif
22 struct render_target {
23 unsigned int fbo;
24 unsigned int color_tex, depth_buf;
25 };
27 bool init();
28 void cleanup();
29 void disp();
30 void idle();
31 void reshape(int x, int y);
32 void keyb(unsigned char key, int x, int y);
33 void mouse(int bn, int state, int x, int y);
34 void motion(int x, int y);
35 struct render_target *create_rtarg(int xsz, int ysz);
36 void destroy_rtarg(struct render_target *rt);
38 int xsz, ysz;
39 float cam_theta, cam_phi = 25, cam_dist = 11;
40 unsigned int dither_tex;
41 struct render_target *rtarg;
42 unsigned int post_prog, phong_prog;
44 int opt_highres, opt_regular_render;
45 bool opt_autorot = true;
48 int main(int argc, char **argv)
49 {
50 glutInit(&argc, argv);
51 glutInitWindowSize(1024, 768);
52 glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
53 glutCreateWindow("DBF UDG compo entry by Nuclear");
55 glutDisplayFunc(disp);
56 glutIdleFunc(idle);
57 glutReshapeFunc(reshape);
58 glutKeyboardFunc(keyb);
59 glutMouseFunc(mouse);
60 glutMotionFunc(motion);
62 glewInit();
64 if(!init()) {
65 return 1;
66 }
68 glutMainLoop();
69 return 0;
70 }
72 bool init()
73 {
74 FILE *fp = fopen("udg.ppm", "wb");
75 if(fp) {
76 fprintf(fp, "P6\n%d %d\n255\n", DITHER_SZ, DITHER_SZ * DITHER_LEVELS);
77 }
79 unsigned char *img = new unsigned char[DITHER_SZ * DITHER_SZ * DITHER_LEVELS];
80 unsigned char *ptr = img;
82 for(int i=0; i<DITHER_LEVELS; i++) {
83 float val = (float)i / (float)(DITHER_LEVELS - 1);
84 for(int y=0; y<DITHER_SZ; y++) {
85 for(int x=0; x<DITHER_SZ; x++) {
86 /* (1 + M) / (1 + MxN) */
87 float thres = (1.0 + dither_matrix[x][y]) / (1.0 + DITHER_SZ * DITHER_SZ);
88 *ptr++ = val >= thres ? 255 : 0;
90 if(fp) {
91 int r = ptr[-1] ? 246 : 10;
92 int g = ptr[-1] ? 198 : 72;
93 int b = ptr[-1] ? 141 : 85;
94 fputc(r, fp);
95 fputc(g, fp);
96 fputc(b, fp);
97 }
98 }
99 }
100 }
102 if(fp) {
103 fclose(fp);
104 }
106 if(!(phong_prog = create_program_load("sdr/phong.v.glsl", "sdr/phong.p.glsl"))) {
107 return false;
108 }
110 if(!(post_prog = create_program_load("sdr/dither.v.glsl", "sdr/dither.p.glsl"))) {
111 return false;
112 }
114 glGenTextures(1, &dither_tex);
115 glBindTexture(GL_TEXTURE_2D, dither_tex);
116 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
117 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
118 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
119 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
120 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, DITHER_SZ, DITHER_SZ * DITHER_LEVELS, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, img);
122 if(!init_scroller()) {
123 return false;
124 }
126 if(!mball_init()) {
127 return false;
128 }
130 glEnable(GL_CULL_FACE);
131 glEnable(GL_DEPTH_TEST);
132 glEnable(GL_LIGHTING);
133 glEnable(GL_LIGHT0);
134 glEnable(GL_LIGHT1);
135 glEnable(GL_NORMALIZE);
137 return true;
138 }
140 void draw_backdrop()
141 {
142 glPushAttrib(GL_ENABLE_BIT);
143 glDisable(GL_DEPTH_TEST);
144 glDisable(GL_LIGHTING);
146 glMatrixMode(GL_MODELVIEW);
147 glPushMatrix();
148 glLoadIdentity();
149 glMatrixMode(GL_PROJECTION);
150 glPushMatrix();
151 glLoadIdentity();
153 glBegin(GL_QUADS);
154 glColor3f(0, 0, 0);
155 glVertex2f(-1, -1);
156 glVertex2f(1, -1);
157 glColor3f(1, 1, 1);
158 glVertex2f(1, 1);
159 glVertex2f(-1, 1);
160 glEnd();
162 glPopMatrix();
163 glMatrixMode(GL_MODELVIEW);
164 glPopMatrix();
166 glPopAttrib();
167 /*draw_scroller(glutGet(GLUT_ELAPSED_TIME) / 1000.0); */
168 }
170 void disp()
171 {
172 float ldir[] = {-1, 1, 2, 0};
173 float ldir2[] = {0.0, 0.35, -0.9, 0};
175 float lcol[] = {1, 1, 1, 1};
176 float lcol2[] = {0.35, 0.3, 0.15, 1};
178 int xres, yres;
179 float auto_angle = glutGet(GLUT_ELAPSED_TIME) / 100.0;
181 if(opt_highres) {
182 xres = xsz;
183 yres = ysz;
184 } else {
185 xres = xsz / DITHER_SZ;
186 yres = ysz / DITHER_SZ;
187 }
189 if(!rtarg) {
190 printf("(re)creating render target (%dx%d)\n", xres, yres);
191 if(!(rtarg = create_rtarg(xres, yres))) {
192 exit(0);
193 }
194 }
196 if(!opt_regular_render) {
197 glBindFramebufferEXT(GL_FRAMEBUFFER, rtarg->fbo);
198 }
199 glViewport(0, 0, xres, yres);
201 glClearColor(1, 1, 1, 1);
202 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
204 draw_backdrop();
206 glMatrixMode(GL_MODELVIEW);
207 glLoadIdentity();
209 glTranslatef(0, 0.8, -cam_dist);
210 glRotatef(cam_phi, 1, 0, 0);
211 glRotatef(opt_autorot ? auto_angle : cam_theta, 0, 1, 0);
213 glLightfv(GL_LIGHT0, GL_POSITION, ldir);
214 glLightfv(GL_LIGHT0, GL_DIFFUSE, lcol);
216 glLightfv(GL_LIGHT1, GL_POSITION, ldir2);
217 glLightfv(GL_LIGHT1, GL_DIFFUSE, lcol2);
219 const float blue[] = {0.4, 0.45, 1.0, 1};
220 const float white[] = {1, 1, 1, 1};
221 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, blue);
222 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, white);
223 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 80.0);
225 bind_program(phong_prog);
226 mball_render();
227 bind_program(0);
230 if(!opt_regular_render) {
231 glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
232 glViewport(0, 0, xsz, ysz);
234 glClear(GL_COLOR_BUFFER_BIT);
236 glMatrixMode(GL_PROJECTION);
237 glPushMatrix();
238 glLoadIdentity();
239 glMatrixMode(GL_MODELVIEW);
240 glLoadIdentity();
241 glPushMatrix();
243 glPushAttrib(GL_ENABLE_BIT);
244 glDisable(GL_DEPTH_TEST);
246 bind_program(post_prog);
247 set_uniform_int(post_prog, "framebuf", 0);
248 set_uniform_int(post_prog, "dither_tex", 1);
249 set_uniform_int(post_prog, "dither_levels", DITHER_LEVELS);
250 set_uniform_int(post_prog, "dither_size", DITHER_SZ);
252 glActiveTextureARB(GL_TEXTURE0);
253 glBindTexture(GL_TEXTURE_2D, rtarg->color_tex);
254 glEnable(GL_TEXTURE_2D);
255 glActiveTextureARB(GL_TEXTURE1);
256 glBindTexture(GL_TEXTURE_2D, dither_tex);
257 glEnable(GL_TEXTURE_2D);
259 glBegin(GL_QUADS);
260 glColor3f(0, 1, 0);
261 glTexCoord2f(0, 0); glVertex2f(-1, -1);
262 glTexCoord2f(1, 0); glVertex2f(1, -1);
263 glTexCoord2f(1, 1); glVertex2f(1, 1);
264 glTexCoord2f(0, 1); glVertex2f(-1, 1);
265 glEnd();
267 glActiveTextureARB(GL_TEXTURE1);
268 glDisable(GL_TEXTURE_2D);
269 glActiveTextureARB(GL_TEXTURE0);
270 glDisable(GL_TEXTURE_2D);
272 bind_program(0);
274 glPopAttrib();
276 glMatrixMode(GL_PROJECTION);
277 glPopMatrix();
278 glMatrixMode(GL_MODELVIEW);
279 glPopMatrix();
280 }
282 glutSwapBuffers();
283 assert(glGetError() == GL_NO_ERROR);
284 }
286 void idle()
287 {
288 glutPostRedisplay();
289 }
291 void reshape(int x, int y)
292 {
293 glViewport(0, 0, x, y);
295 glMatrixMode(GL_PROJECTION);
296 glLoadIdentity();
297 gluPerspective(45.0, (float)x / (float)y, 0.5, 500.0);
299 if(x != xsz || y != ysz) {
300 destroy_rtarg(rtarg);
301 rtarg = 0;
302 xsz = x;
303 ysz = y;
304 }
305 }
307 void keyb(unsigned char key, int x, int y)
308 {
309 switch(key) {
310 case 27:
311 exit(0);
313 case 'a':
314 opt_autorot = !opt_autorot;
315 break;
317 case 'f':
318 {
319 static bool fullscreen;
320 static int orig_x, orig_y;
322 fullscreen = !fullscreen;
323 if(fullscreen) {
324 orig_x = xsz;
325 orig_y = ysz;
326 glutFullScreen();
327 } else {
328 glutReshapeWindow(orig_x, orig_y);
329 }
330 }
331 break;
333 case 'r':
334 opt_regular_render = !opt_regular_render;
335 break;
337 case 'h':
338 opt_highres = !opt_highres;
339 if(rtarg) {
340 destroy_rtarg(rtarg);
341 rtarg = 0;
342 }
343 break;
344 }
345 }
347 bool bnstate[16];
348 int prev_x, prev_y;
350 void mouse(int bn, int state, int x, int y)
351 {
352 int idx = bn - GLUT_LEFT_BUTTON;
354 if(idx < (int)(sizeof bnstate / sizeof *bnstate)) {
355 bnstate[idx] = state == GLUT_DOWN;
356 }
357 prev_x = x;
358 prev_y = y;
359 }
361 void motion(int x, int y)
362 {
363 int dx = x - prev_x;
364 int dy = y - prev_y;
365 prev_x = x;
366 prev_y = y;
368 if(bnstate[0]) {
369 cam_theta = fmod(cam_theta + dx * 0.5, 360.0);
370 cam_phi += dy * 0.5;
371 if(cam_phi < -90) {
372 cam_phi = -90;
373 }
374 if(cam_phi > 90) {
375 cam_phi = 90;
376 }
377 }
378 if(bnstate[2]) {
379 cam_dist += dy * 0.1;
380 if(cam_dist < 0) {
381 cam_dist = 0;
382 }
383 }
384 }
386 struct render_target *create_rtarg(int xsz, int ysz)
387 {
388 struct render_target *rt = new render_target;
390 glGenFramebuffersEXT(1, &rt->fbo);
391 glBindFramebufferEXT(GL_FRAMEBUFFER, rt->fbo);
393 // create the render target texture
394 glGenTextures(1, &rt->color_tex);
395 glBindTexture(GL_TEXTURE_2D, rt->color_tex);
396 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
397 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
398 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
399 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
400 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, xsz, ysz, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
402 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->color_tex, 0);
404 // create depth buffer
405 glGenRenderbuffersEXT(1, &rt->depth_buf);
406 glBindRenderbufferEXT(GL_RENDERBUFFER, rt->depth_buf);
407 glRenderbufferStorageEXT(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, xsz, ysz);
409 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth_buf);
411 if(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
412 fprintf(stderr, "incomplete fbo\n");
413 return 0;
414 }
416 glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
417 return rt;
418 }
420 void destroy_rtarg(struct render_target *rt)
421 {
422 if(!rt) {
423 return;
424 }
425 glDeleteFramebuffersEXT(1, &rt->fbo);
426 glDeleteTextures(1, &rt->color_tex);
427 glDeleteRenderbuffersEXT(1, &rt->depth_buf);
428 delete rt;
429 }