dbf-udg

annotate src/udg.cc @ 13:6a836b1dc31b

foo
author John Tsiombikas <nuclear@member.fsf.org>
date Wed, 20 Feb 2013 05:48:01 +0200
parents 1abbed71e9c9
children
rev   line source
nuclear@12 1 /*
nuclear@13 2 Printblobs - halftoning display hack
nuclear@12 3 Copyright (C) 2013 John Tsiombikas <nuclear@member.fsf.org>
nuclear@12 4
nuclear@12 5 This program is free software: you can redistribute it and/or modify
nuclear@12 6 it under the terms of the GNU General Public License as published by
nuclear@12 7 the Free Software Foundation, either version 3 of the License, or
nuclear@12 8 (at your option) any later version.
nuclear@12 9
nuclear@12 10 This program is distributed in the hope that it will be useful,
nuclear@12 11 but WITHOUT ANY WARRANTY; without even the implied warranty of
nuclear@12 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
nuclear@12 13 GNU General Public License for more details.
nuclear@12 14
nuclear@12 15 You should have received a copy of the GNU General Public License
nuclear@12 16 along with this program. If not, see <http://www.gnu.org/licenses/>.
nuclear@12 17 */
nuclear@0 18 #include <stdio.h>
nuclear@0 19 #include <stdlib.h>
nuclear@11 20 #include <string.h>
nuclear@0 21 #include <math.h>
nuclear@0 22 #include <assert.h>
nuclear@3 23 #include "opengl.h"
nuclear@11 24 #include "udg.h"
nuclear@0 25 #include "sdr.h"
nuclear@0 26 #include "dither_matrix.h"
nuclear@5 27 #include "mballs.h"
nuclear@9 28 #include "dsys.h"
nuclear@11 29 #include "post.h"
nuclear@0 30
nuclear@2 31 #define DITHER_SZ 8
nuclear@0 32 #define DITHER_LEVELS 16
nuclear@0 33
nuclear@1 34 #if DITHER_SZ == 4
nuclear@1 35 #define dither_matrix dither_matrix4
nuclear@1 36 #elif DITHER_SZ == 8
nuclear@3 37 #define dither_matrix halftone_matrix8
nuclear@1 38 #else
nuclear@1 39 #error "invalid dither size"
nuclear@1 40 #endif
nuclear@1 41
nuclear@0 42 struct render_target {
nuclear@0 43 unsigned int fbo;
nuclear@0 44 unsigned int color_tex, depth_buf;
nuclear@0 45 };
nuclear@0 46
nuclear@0 47 bool init();
nuclear@0 48 void cleanup();
nuclear@0 49 void disp();
nuclear@0 50 void idle();
nuclear@0 51 void reshape(int x, int y);
nuclear@0 52 void keyb(unsigned char key, int x, int y);
nuclear@0 53 void mouse(int bn, int state, int x, int y);
nuclear@0 54 void motion(int x, int y);
nuclear@0 55 struct render_target *create_rtarg(int xsz, int ysz);
nuclear@0 56 void destroy_rtarg(struct render_target *rt);
nuclear@11 57 bool parse_args(int argc, char **argv);
nuclear@0 58
nuclear@0 59 int xsz, ysz;
nuclear@8 60 float cam_theta, cam_phi = 25, cam_dist = 11;
nuclear@0 61 unsigned int dither_tex;
nuclear@0 62 struct render_target *rtarg;
nuclear@7 63 unsigned int post_prog, phong_prog;
nuclear@0 64
nuclear@12 65 int opt_blocky = true, opt_regular_render;
nuclear@8 66 bool opt_autorot = true;
nuclear@5 67
nuclear@9 68 struct dsys_demo *demo;
nuclear@11 69 struct dsys_event *evfadein;
nuclear@5 70
nuclear@0 71 int main(int argc, char **argv)
nuclear@0 72 {
nuclear@11 73 glutInitWindowSize(1024, 768);
nuclear@0 74 glutInit(&argc, argv);
nuclear@11 75
nuclear@11 76 if(!parse_args(argc, argv)) {
nuclear@11 77 return 1;
nuclear@11 78 }
nuclear@11 79
nuclear@0 80 glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
nuclear@0 81 glutCreateWindow("DBF UDG compo entry by Nuclear");
nuclear@0 82
nuclear@0 83 glutDisplayFunc(disp);
nuclear@0 84 glutIdleFunc(idle);
nuclear@0 85 glutReshapeFunc(reshape);
nuclear@0 86 glutKeyboardFunc(keyb);
nuclear@0 87 glutMouseFunc(mouse);
nuclear@0 88 glutMotionFunc(motion);
nuclear@0 89
nuclear@0 90 glewInit();
nuclear@0 91
nuclear@0 92 if(!init()) {
nuclear@0 93 return 1;
nuclear@0 94 }
nuclear@0 95
nuclear@0 96 glutMainLoop();
nuclear@0 97 return 0;
nuclear@0 98 }
nuclear@0 99
nuclear@0 100 bool init()
nuclear@0 101 {
nuclear@11 102 if(!(demo = dsys_open("demoscript"))) {
nuclear@11 103 return false;
nuclear@11 104 }
nuclear@11 105 evfadein = dsys_event(demo, "fade_in");
nuclear@11 106 dsys_set_event_eval(evfadein, dsys_eval_sigmoid);
nuclear@11 107
nuclear@11 108 // dump the tile image
nuclear@6 109 FILE *fp = fopen("udg.ppm", "wb");
nuclear@6 110 if(fp) {
nuclear@6 111 fprintf(fp, "P6\n%d %d\n255\n", DITHER_SZ, DITHER_SZ * DITHER_LEVELS);
nuclear@6 112 }
nuclear@6 113
nuclear@6 114 unsigned char *img = new unsigned char[DITHER_SZ * DITHER_SZ * DITHER_LEVELS];
nuclear@6 115 unsigned char *ptr = img;
nuclear@0 116
nuclear@0 117 for(int i=0; i<DITHER_LEVELS; i++) {
nuclear@0 118 float val = (float)i / (float)(DITHER_LEVELS - 1);
nuclear@0 119 for(int y=0; y<DITHER_SZ; y++) {
nuclear@0 120 for(int x=0; x<DITHER_SZ; x++) {
nuclear@0 121 /* (1 + M) / (1 + MxN) */
nuclear@1 122 float thres = (1.0 + dither_matrix[x][y]) / (1.0 + DITHER_SZ * DITHER_SZ);
nuclear@6 123 *ptr++ = val >= thres ? 255 : 0;
nuclear@6 124
nuclear@6 125 if(fp) {
nuclear@6 126 int r = ptr[-1] ? 246 : 10;
nuclear@6 127 int g = ptr[-1] ? 198 : 72;
nuclear@6 128 int b = ptr[-1] ? 141 : 85;
nuclear@6 129 fputc(r, fp);
nuclear@6 130 fputc(g, fp);
nuclear@6 131 fputc(b, fp);
nuclear@6 132 }
nuclear@0 133 }
nuclear@0 134 }
nuclear@0 135 }
nuclear@0 136
nuclear@6 137 if(fp) {
nuclear@6 138 fclose(fp);
nuclear@6 139 }
nuclear@6 140
nuclear@7 141 if(!(phong_prog = create_program_load("sdr/phong.v.glsl", "sdr/phong.p.glsl"))) {
nuclear@7 142 return false;
nuclear@7 143 }
nuclear@7 144
nuclear@7 145 if(!(post_prog = create_program_load("sdr/dither.v.glsl", "sdr/dither.p.glsl"))) {
nuclear@0 146 return false;
nuclear@0 147 }
nuclear@0 148
nuclear@0 149 glGenTextures(1, &dither_tex);
nuclear@0 150 glBindTexture(GL_TEXTURE_2D, dither_tex);
nuclear@0 151 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
nuclear@0 152 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
nuclear@0 153 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
nuclear@0 154 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
nuclear@6 155 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, DITHER_SZ, DITHER_SZ * DITHER_LEVELS, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, img);
nuclear@0 156
nuclear@5 157 if(!mball_init()) {
nuclear@5 158 return false;
nuclear@5 159 }
nuclear@5 160
nuclear@0 161 glEnable(GL_CULL_FACE);
nuclear@0 162 glEnable(GL_DEPTH_TEST);
nuclear@0 163 glEnable(GL_LIGHTING);
nuclear@0 164 glEnable(GL_LIGHT0);
nuclear@8 165 glEnable(GL_LIGHT1);
nuclear@5 166 glEnable(GL_NORMALIZE);
nuclear@0 167
nuclear@10 168
nuclear@12 169 reshape(glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT));
nuclear@0 170 return true;
nuclear@0 171 }
nuclear@0 172
nuclear@0 173 void draw_backdrop()
nuclear@0 174 {
nuclear@0 175 glPushAttrib(GL_ENABLE_BIT);
nuclear@0 176 glDisable(GL_DEPTH_TEST);
nuclear@0 177 glDisable(GL_LIGHTING);
nuclear@0 178
nuclear@0 179 glMatrixMode(GL_MODELVIEW);
nuclear@0 180 glPushMatrix();
nuclear@0 181 glLoadIdentity();
nuclear@0 182 glMatrixMode(GL_PROJECTION);
nuclear@0 183 glPushMatrix();
nuclear@0 184 glLoadIdentity();
nuclear@0 185
nuclear@0 186 glBegin(GL_QUADS);
nuclear@0 187 glColor3f(0, 0, 0);
nuclear@0 188 glVertex2f(-1, -1);
nuclear@0 189 glVertex2f(1, -1);
nuclear@0 190 glColor3f(1, 1, 1);
nuclear@0 191 glVertex2f(1, 1);
nuclear@0 192 glVertex2f(-1, 1);
nuclear@0 193 glEnd();
nuclear@0 194
nuclear@0 195 glPopMatrix();
nuclear@0 196 glMatrixMode(GL_MODELVIEW);
nuclear@0 197 glPopMatrix();
nuclear@0 198
nuclear@0 199 glPopAttrib();
nuclear@0 200 }
nuclear@0 201
nuclear@0 202 void disp()
nuclear@0 203 {
nuclear@0 204 float ldir[] = {-1, 1, 2, 0};
nuclear@8 205 float ldir2[] = {0.0, 0.35, -0.9, 0};
nuclear@8 206
nuclear@8 207 float lcol[] = {1, 1, 1, 1};
nuclear@8 208 float lcol2[] = {0.35, 0.3, 0.15, 1};
nuclear@8 209
nuclear@9 210 dsys_update(demo, dsys_msec_to_dtime(glutGet(GLUT_ELAPSED_TIME)));
nuclear@9 211
nuclear@9 212 float sec = dsys_dtime_to_sec(dsys_time(demo));
nuclear@9 213 float auto_angle = sec * 10.0;
nuclear@9 214
nuclear@5 215 int xres, yres;
nuclear@12 216 if(!opt_blocky) {
nuclear@5 217 xres = xsz;
nuclear@5 218 yres = ysz;
nuclear@5 219 } else {
nuclear@5 220 xres = xsz / DITHER_SZ;
nuclear@5 221 yres = ysz / DITHER_SZ;
nuclear@5 222 }
nuclear@4 223
nuclear@0 224 if(!rtarg) {
nuclear@4 225 printf("(re)creating render target (%dx%d)\n", xres, yres);
nuclear@4 226 if(!(rtarg = create_rtarg(xres, yres))) {
nuclear@0 227 exit(0);
nuclear@0 228 }
nuclear@0 229 }
nuclear@0 230
nuclear@5 231 if(!opt_regular_render) {
nuclear@5 232 glBindFramebufferEXT(GL_FRAMEBUFFER, rtarg->fbo);
nuclear@5 233 }
nuclear@4 234 glViewport(0, 0, xres, yres);
nuclear@0 235
nuclear@0 236 glClearColor(1, 1, 1, 1);
nuclear@0 237 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
nuclear@0 238
nuclear@0 239 draw_backdrop();
nuclear@0 240
nuclear@0 241 glMatrixMode(GL_MODELVIEW);
nuclear@0 242 glLoadIdentity();
nuclear@0 243
nuclear@8 244 glTranslatef(0, 0.8, -cam_dist);
nuclear@0 245 glRotatef(cam_phi, 1, 0, 0);
nuclear@8 246 glRotatef(opt_autorot ? auto_angle : cam_theta, 0, 1, 0);
nuclear@0 247
nuclear@5 248 glLightfv(GL_LIGHT0, GL_POSITION, ldir);
nuclear@8 249 glLightfv(GL_LIGHT0, GL_DIFFUSE, lcol);
nuclear@8 250
nuclear@8 251 glLightfv(GL_LIGHT1, GL_POSITION, ldir2);
nuclear@8 252 glLightfv(GL_LIGHT1, GL_DIFFUSE, lcol2);
nuclear@5 253
nuclear@2 254 const float blue[] = {0.4, 0.45, 1.0, 1};
nuclear@2 255 const float white[] = {1, 1, 1, 1};
nuclear@2 256 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, blue);
nuclear@2 257 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, white);
nuclear@2 258 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 80.0);
nuclear@2 259
nuclear@7 260 bind_program(phong_prog);
nuclear@9 261 mball_render(sec);
nuclear@7 262 bind_program(0);
nuclear@0 263
nuclear@11 264 float tfadein = evfadein ? dsys_event_value(evfadein) : 1.0;
nuclear@11 265 /*if(tfadein < 1.0) {
nuclear@11 266 glEnable(GL_BLEND);
nuclear@11 267 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
nuclear@11 268 overlay(0, 0, 0, 1.0 - tfadein);
nuclear@11 269 glDisable(GL_BLEND);
nuclear@11 270 }*/
nuclear@11 271
nuclear@0 272
nuclear@5 273 if(!opt_regular_render) {
nuclear@5 274 glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
nuclear@5 275 glViewport(0, 0, xsz, ysz);
nuclear@1 276
nuclear@5 277 glClear(GL_COLOR_BUFFER_BIT);
nuclear@0 278
nuclear@7 279 bind_program(post_prog);
nuclear@7 280 set_uniform_int(post_prog, "framebuf", 0);
nuclear@7 281 set_uniform_int(post_prog, "dither_tex", 1);
nuclear@7 282 set_uniform_int(post_prog, "dither_levels", DITHER_LEVELS);
nuclear@7 283 set_uniform_int(post_prog, "dither_size", DITHER_SZ);
nuclear@11 284 set_uniform_float(post_prog, "tfadein", tfadein);
nuclear@0 285
nuclear@5 286 glActiveTextureARB(GL_TEXTURE0);
nuclear@5 287 glBindTexture(GL_TEXTURE_2D, rtarg->color_tex);
nuclear@5 288 glEnable(GL_TEXTURE_2D);
nuclear@5 289 glActiveTextureARB(GL_TEXTURE1);
nuclear@5 290 glBindTexture(GL_TEXTURE_2D, dither_tex);
nuclear@5 291 glEnable(GL_TEXTURE_2D);
nuclear@0 292
nuclear@11 293 overlay(1, 1, 1, 1);
nuclear@0 294
nuclear@5 295 glActiveTextureARB(GL_TEXTURE1);
nuclear@5 296 glDisable(GL_TEXTURE_2D);
nuclear@5 297 glActiveTextureARB(GL_TEXTURE0);
nuclear@5 298 glDisable(GL_TEXTURE_2D);
nuclear@0 299
nuclear@5 300 bind_program(0);
nuclear@5 301 }
nuclear@0 302
nuclear@0 303 glutSwapBuffers();
nuclear@0 304 assert(glGetError() == GL_NO_ERROR);
nuclear@0 305 }
nuclear@0 306
nuclear@0 307 void idle()
nuclear@0 308 {
nuclear@0 309 glutPostRedisplay();
nuclear@0 310 }
nuclear@0 311
nuclear@0 312 void reshape(int x, int y)
nuclear@0 313 {
nuclear@0 314 glViewport(0, 0, x, y);
nuclear@0 315
nuclear@0 316 glMatrixMode(GL_PROJECTION);
nuclear@0 317 glLoadIdentity();
nuclear@0 318 gluPerspective(45.0, (float)x / (float)y, 0.5, 500.0);
nuclear@0 319
nuclear@0 320 if(x != xsz || y != ysz) {
nuclear@0 321 destroy_rtarg(rtarg);
nuclear@0 322 rtarg = 0;
nuclear@0 323 xsz = x;
nuclear@0 324 ysz = y;
nuclear@0 325 }
nuclear@0 326 }
nuclear@0 327
nuclear@0 328 void keyb(unsigned char key, int x, int y)
nuclear@0 329 {
nuclear@0 330 switch(key) {
nuclear@0 331 case 27:
nuclear@0 332 exit(0);
nuclear@4 333
nuclear@8 334 case 'a':
nuclear@8 335 opt_autorot = !opt_autorot;
nuclear@8 336 break;
nuclear@8 337
nuclear@4 338 case 'f':
nuclear@4 339 {
nuclear@4 340 static bool fullscreen;
nuclear@4 341 static int orig_x, orig_y;
nuclear@4 342
nuclear@4 343 fullscreen = !fullscreen;
nuclear@4 344 if(fullscreen) {
nuclear@4 345 orig_x = xsz;
nuclear@4 346 orig_y = ysz;
nuclear@4 347 glutFullScreen();
nuclear@4 348 } else {
nuclear@4 349 glutReshapeWindow(orig_x, orig_y);
nuclear@4 350 }
nuclear@4 351 }
nuclear@4 352 break;
nuclear@5 353
nuclear@5 354 case 'r':
nuclear@5 355 opt_regular_render = !opt_regular_render;
nuclear@5 356 break;
nuclear@5 357
nuclear@12 358 case 'b':
nuclear@12 359 opt_blocky = !opt_blocky;
nuclear@5 360 if(rtarg) {
nuclear@5 361 destroy_rtarg(rtarg);
nuclear@5 362 rtarg = 0;
nuclear@5 363 }
nuclear@5 364 break;
nuclear@12 365
nuclear@12 366 case ' ':
nuclear@12 367 if(dsys_is_running(demo)) {
nuclear@12 368 dsys_stop(demo);
nuclear@12 369 } else {
nuclear@12 370 dsys_start(demo);
nuclear@12 371 }
nuclear@12 372 break;
nuclear@0 373 }
nuclear@0 374 }
nuclear@0 375
nuclear@0 376 bool bnstate[16];
nuclear@0 377 int prev_x, prev_y;
nuclear@0 378
nuclear@0 379 void mouse(int bn, int state, int x, int y)
nuclear@0 380 {
nuclear@0 381 int idx = bn - GLUT_LEFT_BUTTON;
nuclear@0 382
nuclear@0 383 if(idx < (int)(sizeof bnstate / sizeof *bnstate)) {
nuclear@0 384 bnstate[idx] = state == GLUT_DOWN;
nuclear@0 385 }
nuclear@0 386 prev_x = x;
nuclear@0 387 prev_y = y;
nuclear@0 388 }
nuclear@0 389
nuclear@0 390 void motion(int x, int y)
nuclear@0 391 {
nuclear@0 392 int dx = x - prev_x;
nuclear@0 393 int dy = y - prev_y;
nuclear@0 394 prev_x = x;
nuclear@0 395 prev_y = y;
nuclear@0 396
nuclear@0 397 if(bnstate[0]) {
nuclear@0 398 cam_theta = fmod(cam_theta + dx * 0.5, 360.0);
nuclear@0 399 cam_phi += dy * 0.5;
nuclear@0 400 if(cam_phi < -90) {
nuclear@0 401 cam_phi = -90;
nuclear@0 402 }
nuclear@0 403 if(cam_phi > 90) {
nuclear@0 404 cam_phi = 90;
nuclear@0 405 }
nuclear@0 406 }
nuclear@0 407 if(bnstate[2]) {
nuclear@0 408 cam_dist += dy * 0.1;
nuclear@0 409 if(cam_dist < 0) {
nuclear@0 410 cam_dist = 0;
nuclear@0 411 }
nuclear@0 412 }
nuclear@0 413 }
nuclear@0 414
nuclear@0 415 struct render_target *create_rtarg(int xsz, int ysz)
nuclear@0 416 {
nuclear@0 417 struct render_target *rt = new render_target;
nuclear@0 418
nuclear@0 419 glGenFramebuffersEXT(1, &rt->fbo);
nuclear@0 420 glBindFramebufferEXT(GL_FRAMEBUFFER, rt->fbo);
nuclear@0 421
nuclear@0 422 // create the render target texture
nuclear@0 423 glGenTextures(1, &rt->color_tex);
nuclear@0 424 glBindTexture(GL_TEXTURE_2D, rt->color_tex);
nuclear@0 425 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
nuclear@0 426 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
nuclear@1 427 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
nuclear@1 428 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
nuclear@0 429 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, xsz, ysz, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
nuclear@0 430
nuclear@0 431 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->color_tex, 0);
nuclear@0 432
nuclear@0 433 // create depth buffer
nuclear@0 434 glGenRenderbuffersEXT(1, &rt->depth_buf);
nuclear@0 435 glBindRenderbufferEXT(GL_RENDERBUFFER, rt->depth_buf);
nuclear@0 436 glRenderbufferStorageEXT(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, xsz, ysz);
nuclear@0 437
nuclear@0 438 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth_buf);
nuclear@0 439
nuclear@0 440 if(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
nuclear@0 441 fprintf(stderr, "incomplete fbo\n");
nuclear@0 442 return 0;
nuclear@0 443 }
nuclear@0 444
nuclear@0 445 glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
nuclear@0 446 return rt;
nuclear@0 447 }
nuclear@0 448
nuclear@0 449 void destroy_rtarg(struct render_target *rt)
nuclear@0 450 {
nuclear@0 451 if(!rt) {
nuclear@0 452 return;
nuclear@0 453 }
nuclear@0 454 glDeleteFramebuffersEXT(1, &rt->fbo);
nuclear@0 455 glDeleteTextures(1, &rt->color_tex);
nuclear@0 456 glDeleteRenderbuffersEXT(1, &rt->depth_buf);
nuclear@0 457 delete rt;
nuclear@0 458 }
nuclear@11 459
nuclear@11 460 bool parse_args(int argc, char **argv)
nuclear@11 461 {
nuclear@11 462 for(int i=1; i<argc; i++) {
nuclear@12 463 if(strcmp(argv[i], "-noblocky") == 0) {
nuclear@12 464 opt_blocky = false;
nuclear@12 465 } else if(strcmp(argv[i], "-blocky") == 0) {
nuclear@12 466 opt_blocky = true;
nuclear@11 467 } else if(strcmp(argv[i], "-nodither") == 0) {
nuclear@11 468 opt_regular_render = true;
nuclear@11 469 } else {
nuclear@11 470 fprintf(stderr, "invalid argument: %s\n", argv[i]);
nuclear@11 471 return false;
nuclear@11 472 }
nuclear@11 473 }
nuclear@11 474 return true;
nuclear@11 475 }