nuclear@0: #include nuclear@0: #include nuclear@0: #include nuclear@0: #include nuclear@3: #include "opengl.h" nuclear@0: #include "sdr.h" nuclear@0: #include "dither_matrix.h" nuclear@3: #include "scroller.h" nuclear@5: #include "mballs.h" nuclear@9: #include "dsys.h" nuclear@0: nuclear@2: #define DITHER_SZ 8 nuclear@0: #define DITHER_LEVELS 16 nuclear@0: nuclear@1: #if DITHER_SZ == 4 nuclear@1: #define dither_matrix dither_matrix4 nuclear@1: #elif DITHER_SZ == 8 nuclear@3: #define dither_matrix halftone_matrix8 nuclear@1: #else nuclear@1: #error "invalid dither size" nuclear@1: #endif nuclear@1: nuclear@0: struct render_target { nuclear@0: unsigned int fbo; nuclear@0: unsigned int color_tex, depth_buf; nuclear@0: }; nuclear@0: nuclear@0: bool init(); nuclear@0: void cleanup(); nuclear@0: void disp(); nuclear@0: void idle(); nuclear@0: void reshape(int x, int y); nuclear@0: void keyb(unsigned char key, int x, int y); nuclear@0: void mouse(int bn, int state, int x, int y); nuclear@0: void motion(int x, int y); nuclear@0: struct render_target *create_rtarg(int xsz, int ysz); nuclear@0: void destroy_rtarg(struct render_target *rt); nuclear@0: nuclear@0: int xsz, ysz; nuclear@8: float cam_theta, cam_phi = 25, cam_dist = 11; nuclear@0: unsigned int dither_tex; nuclear@0: struct render_target *rtarg; nuclear@7: unsigned int post_prog, phong_prog; nuclear@0: nuclear@5: int opt_highres, opt_regular_render; nuclear@8: bool opt_autorot = true; nuclear@5: nuclear@9: struct dsys_demo *demo; nuclear@9: nuclear@5: nuclear@0: int main(int argc, char **argv) nuclear@0: { nuclear@0: glutInit(&argc, argv); nuclear@1: glutInitWindowSize(1024, 768); nuclear@0: glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE); nuclear@0: glutCreateWindow("DBF UDG compo entry by Nuclear"); nuclear@0: nuclear@0: glutDisplayFunc(disp); nuclear@0: glutIdleFunc(idle); nuclear@0: glutReshapeFunc(reshape); nuclear@0: glutKeyboardFunc(keyb); nuclear@0: glutMouseFunc(mouse); nuclear@0: glutMotionFunc(motion); nuclear@0: nuclear@0: glewInit(); nuclear@0: nuclear@0: if(!init()) { nuclear@0: return 1; nuclear@0: } nuclear@0: nuclear@0: glutMainLoop(); nuclear@0: return 0; nuclear@0: } nuclear@0: nuclear@0: bool init() nuclear@0: { nuclear@6: FILE *fp = fopen("udg.ppm", "wb"); nuclear@6: if(fp) { nuclear@6: fprintf(fp, "P6\n%d %d\n255\n", DITHER_SZ, DITHER_SZ * DITHER_LEVELS); nuclear@6: } nuclear@6: nuclear@6: unsigned char *img = new unsigned char[DITHER_SZ * DITHER_SZ * DITHER_LEVELS]; nuclear@6: unsigned char *ptr = img; nuclear@0: nuclear@0: for(int i=0; i= thres ? 255 : 0; nuclear@6: nuclear@6: if(fp) { nuclear@6: int r = ptr[-1] ? 246 : 10; nuclear@6: int g = ptr[-1] ? 198 : 72; nuclear@6: int b = ptr[-1] ? 141 : 85; nuclear@6: fputc(r, fp); nuclear@6: fputc(g, fp); nuclear@6: fputc(b, fp); nuclear@6: } nuclear@0: } nuclear@0: } nuclear@0: } nuclear@0: nuclear@6: if(fp) { nuclear@6: fclose(fp); nuclear@6: } nuclear@6: nuclear@7: if(!(phong_prog = create_program_load("sdr/phong.v.glsl", "sdr/phong.p.glsl"))) { nuclear@7: return false; nuclear@7: } nuclear@7: nuclear@7: if(!(post_prog = create_program_load("sdr/dither.v.glsl", "sdr/dither.p.glsl"))) { nuclear@0: return false; nuclear@0: } nuclear@0: nuclear@0: glGenTextures(1, &dither_tex); nuclear@0: glBindTexture(GL_TEXTURE_2D, dither_tex); nuclear@0: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); nuclear@0: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); nuclear@0: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); nuclear@0: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); nuclear@6: glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, DITHER_SZ, DITHER_SZ * DITHER_LEVELS, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, img); nuclear@0: nuclear@3: if(!init_scroller()) { nuclear@3: return false; nuclear@3: } nuclear@3: nuclear@5: if(!mball_init()) { nuclear@5: return false; nuclear@5: } nuclear@5: nuclear@9: if(!(demo = dsys_open("demoscript"))) { nuclear@9: return false; nuclear@9: } nuclear@9: nuclear@0: glEnable(GL_CULL_FACE); nuclear@0: glEnable(GL_DEPTH_TEST); nuclear@0: glEnable(GL_LIGHTING); nuclear@0: glEnable(GL_LIGHT0); nuclear@8: glEnable(GL_LIGHT1); nuclear@5: glEnable(GL_NORMALIZE); nuclear@0: nuclear@0: return true; nuclear@0: } nuclear@0: nuclear@0: void draw_backdrop() nuclear@0: { nuclear@0: glPushAttrib(GL_ENABLE_BIT); nuclear@0: glDisable(GL_DEPTH_TEST); nuclear@0: glDisable(GL_LIGHTING); nuclear@0: nuclear@0: glMatrixMode(GL_MODELVIEW); nuclear@0: glPushMatrix(); nuclear@0: glLoadIdentity(); nuclear@0: glMatrixMode(GL_PROJECTION); nuclear@0: glPushMatrix(); nuclear@0: glLoadIdentity(); nuclear@0: nuclear@0: glBegin(GL_QUADS); nuclear@0: glColor3f(0, 0, 0); nuclear@0: glVertex2f(-1, -1); nuclear@0: glVertex2f(1, -1); nuclear@0: glColor3f(1, 1, 1); nuclear@0: glVertex2f(1, 1); nuclear@0: glVertex2f(-1, 1); nuclear@0: glEnd(); nuclear@0: nuclear@0: glPopMatrix(); nuclear@0: glMatrixMode(GL_MODELVIEW); nuclear@0: glPopMatrix(); nuclear@0: nuclear@0: glPopAttrib(); nuclear@4: /*draw_scroller(glutGet(GLUT_ELAPSED_TIME) / 1000.0); */ nuclear@0: } nuclear@0: nuclear@0: void disp() nuclear@0: { nuclear@0: float ldir[] = {-1, 1, 2, 0}; nuclear@8: float ldir2[] = {0.0, 0.35, -0.9, 0}; nuclear@8: nuclear@8: float lcol[] = {1, 1, 1, 1}; nuclear@8: float lcol2[] = {0.35, 0.3, 0.15, 1}; nuclear@8: nuclear@9: dsys_update(demo, dsys_msec_to_dtime(glutGet(GLUT_ELAPSED_TIME))); nuclear@9: nuclear@9: float sec = dsys_dtime_to_sec(dsys_time(demo)); nuclear@9: float auto_angle = sec * 10.0; nuclear@9: nuclear@5: int xres, yres; nuclear@5: if(opt_highres) { nuclear@5: xres = xsz; nuclear@5: yres = ysz; nuclear@5: } else { nuclear@5: xres = xsz / DITHER_SZ; nuclear@5: yres = ysz / DITHER_SZ; nuclear@5: } nuclear@4: nuclear@0: if(!rtarg) { nuclear@4: printf("(re)creating render target (%dx%d)\n", xres, yres); nuclear@4: if(!(rtarg = create_rtarg(xres, yres))) { nuclear@0: exit(0); nuclear@0: } nuclear@0: } nuclear@0: nuclear@5: if(!opt_regular_render) { nuclear@5: glBindFramebufferEXT(GL_FRAMEBUFFER, rtarg->fbo); nuclear@5: } nuclear@4: glViewport(0, 0, xres, yres); nuclear@0: nuclear@0: glClearColor(1, 1, 1, 1); nuclear@0: glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); nuclear@0: nuclear@0: draw_backdrop(); nuclear@0: nuclear@0: glMatrixMode(GL_MODELVIEW); nuclear@0: glLoadIdentity(); nuclear@0: nuclear@8: glTranslatef(0, 0.8, -cam_dist); nuclear@0: glRotatef(cam_phi, 1, 0, 0); nuclear@8: glRotatef(opt_autorot ? auto_angle : cam_theta, 0, 1, 0); nuclear@0: nuclear@5: glLightfv(GL_LIGHT0, GL_POSITION, ldir); nuclear@8: glLightfv(GL_LIGHT0, GL_DIFFUSE, lcol); nuclear@8: nuclear@8: glLightfv(GL_LIGHT1, GL_POSITION, ldir2); nuclear@8: glLightfv(GL_LIGHT1, GL_DIFFUSE, lcol2); nuclear@5: nuclear@2: const float blue[] = {0.4, 0.45, 1.0, 1}; nuclear@2: const float white[] = {1, 1, 1, 1}; nuclear@2: glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, blue); nuclear@2: glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, white); nuclear@2: glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 80.0); nuclear@2: nuclear@7: bind_program(phong_prog); nuclear@9: mball_render(sec); nuclear@7: bind_program(0); nuclear@0: nuclear@0: nuclear@5: if(!opt_regular_render) { nuclear@5: glBindFramebufferEXT(GL_FRAMEBUFFER, 0); nuclear@5: glViewport(0, 0, xsz, ysz); nuclear@1: nuclear@5: glClear(GL_COLOR_BUFFER_BIT); nuclear@0: nuclear@5: glMatrixMode(GL_PROJECTION); nuclear@5: glPushMatrix(); nuclear@5: glLoadIdentity(); nuclear@5: glMatrixMode(GL_MODELVIEW); nuclear@5: glLoadIdentity(); nuclear@5: glPushMatrix(); nuclear@0: nuclear@5: glPushAttrib(GL_ENABLE_BIT); nuclear@5: glDisable(GL_DEPTH_TEST); nuclear@0: nuclear@7: bind_program(post_prog); nuclear@7: set_uniform_int(post_prog, "framebuf", 0); nuclear@7: set_uniform_int(post_prog, "dither_tex", 1); nuclear@7: set_uniform_int(post_prog, "dither_levels", DITHER_LEVELS); nuclear@7: set_uniform_int(post_prog, "dither_size", DITHER_SZ); nuclear@0: nuclear@5: glActiveTextureARB(GL_TEXTURE0); nuclear@5: glBindTexture(GL_TEXTURE_2D, rtarg->color_tex); nuclear@5: glEnable(GL_TEXTURE_2D); nuclear@5: glActiveTextureARB(GL_TEXTURE1); nuclear@5: glBindTexture(GL_TEXTURE_2D, dither_tex); nuclear@5: glEnable(GL_TEXTURE_2D); nuclear@0: nuclear@5: glBegin(GL_QUADS); nuclear@5: glColor3f(0, 1, 0); nuclear@5: glTexCoord2f(0, 0); glVertex2f(-1, -1); nuclear@5: glTexCoord2f(1, 0); glVertex2f(1, -1); nuclear@5: glTexCoord2f(1, 1); glVertex2f(1, 1); nuclear@5: glTexCoord2f(0, 1); glVertex2f(-1, 1); nuclear@5: glEnd(); nuclear@0: nuclear@5: glActiveTextureARB(GL_TEXTURE1); nuclear@5: glDisable(GL_TEXTURE_2D); nuclear@5: glActiveTextureARB(GL_TEXTURE0); nuclear@5: glDisable(GL_TEXTURE_2D); nuclear@0: nuclear@5: bind_program(0); nuclear@0: nuclear@5: glPopAttrib(); nuclear@0: nuclear@5: glMatrixMode(GL_PROJECTION); nuclear@5: glPopMatrix(); nuclear@5: glMatrixMode(GL_MODELVIEW); nuclear@5: glPopMatrix(); nuclear@5: } nuclear@0: nuclear@0: glutSwapBuffers(); nuclear@0: assert(glGetError() == GL_NO_ERROR); nuclear@0: } nuclear@0: nuclear@0: void idle() nuclear@0: { nuclear@0: glutPostRedisplay(); nuclear@0: } nuclear@0: nuclear@0: void reshape(int x, int y) nuclear@0: { nuclear@0: glViewport(0, 0, x, y); nuclear@0: nuclear@0: glMatrixMode(GL_PROJECTION); nuclear@0: glLoadIdentity(); nuclear@0: gluPerspective(45.0, (float)x / (float)y, 0.5, 500.0); nuclear@0: nuclear@0: if(x != xsz || y != ysz) { nuclear@0: destroy_rtarg(rtarg); nuclear@0: rtarg = 0; nuclear@0: xsz = x; nuclear@0: ysz = y; nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: void keyb(unsigned char key, int x, int y) nuclear@0: { nuclear@0: switch(key) { nuclear@0: case 27: nuclear@0: exit(0); nuclear@4: nuclear@8: case 'a': nuclear@8: opt_autorot = !opt_autorot; nuclear@8: break; nuclear@8: nuclear@4: case 'f': nuclear@4: { nuclear@4: static bool fullscreen; nuclear@4: static int orig_x, orig_y; nuclear@4: nuclear@4: fullscreen = !fullscreen; nuclear@4: if(fullscreen) { nuclear@4: orig_x = xsz; nuclear@4: orig_y = ysz; nuclear@4: glutFullScreen(); nuclear@4: } else { nuclear@4: glutReshapeWindow(orig_x, orig_y); nuclear@4: } nuclear@4: } nuclear@4: break; nuclear@5: nuclear@5: case 'r': nuclear@5: opt_regular_render = !opt_regular_render; nuclear@5: break; nuclear@5: nuclear@5: case 'h': nuclear@5: opt_highres = !opt_highres; nuclear@5: if(rtarg) { nuclear@5: destroy_rtarg(rtarg); nuclear@5: rtarg = 0; nuclear@5: } nuclear@5: break; nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: bool bnstate[16]; nuclear@0: int prev_x, prev_y; nuclear@0: nuclear@0: void mouse(int bn, int state, int x, int y) nuclear@0: { nuclear@0: int idx = bn - GLUT_LEFT_BUTTON; nuclear@0: nuclear@0: if(idx < (int)(sizeof bnstate / sizeof *bnstate)) { nuclear@0: bnstate[idx] = state == GLUT_DOWN; nuclear@0: } nuclear@0: prev_x = x; nuclear@0: prev_y = y; nuclear@0: } nuclear@0: nuclear@0: void motion(int x, int y) nuclear@0: { nuclear@0: int dx = x - prev_x; nuclear@0: int dy = y - prev_y; nuclear@0: prev_x = x; nuclear@0: prev_y = y; nuclear@0: nuclear@0: if(bnstate[0]) { nuclear@0: cam_theta = fmod(cam_theta + dx * 0.5, 360.0); nuclear@0: cam_phi += dy * 0.5; nuclear@0: if(cam_phi < -90) { nuclear@0: cam_phi = -90; nuclear@0: } nuclear@0: if(cam_phi > 90) { nuclear@0: cam_phi = 90; nuclear@0: } nuclear@0: } nuclear@0: if(bnstate[2]) { nuclear@0: cam_dist += dy * 0.1; nuclear@0: if(cam_dist < 0) { nuclear@0: cam_dist = 0; nuclear@0: } nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: struct render_target *create_rtarg(int xsz, int ysz) nuclear@0: { nuclear@0: struct render_target *rt = new render_target; nuclear@0: nuclear@0: glGenFramebuffersEXT(1, &rt->fbo); nuclear@0: glBindFramebufferEXT(GL_FRAMEBUFFER, rt->fbo); nuclear@0: nuclear@0: // create the render target texture nuclear@0: glGenTextures(1, &rt->color_tex); nuclear@0: glBindTexture(GL_TEXTURE_2D, rt->color_tex); nuclear@0: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); nuclear@0: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); nuclear@1: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); nuclear@1: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); nuclear@0: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, xsz, ysz, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); nuclear@0: nuclear@0: glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->color_tex, 0); nuclear@0: nuclear@0: // create depth buffer nuclear@0: glGenRenderbuffersEXT(1, &rt->depth_buf); nuclear@0: glBindRenderbufferEXT(GL_RENDERBUFFER, rt->depth_buf); nuclear@0: glRenderbufferStorageEXT(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, xsz, ysz); nuclear@0: nuclear@0: glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth_buf); nuclear@0: nuclear@0: if(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { nuclear@0: fprintf(stderr, "incomplete fbo\n"); nuclear@0: return 0; nuclear@0: } nuclear@0: nuclear@0: glBindFramebufferEXT(GL_FRAMEBUFFER, 0); nuclear@0: return rt; nuclear@0: } nuclear@0: nuclear@0: void destroy_rtarg(struct render_target *rt) nuclear@0: { nuclear@0: if(!rt) { nuclear@0: return; nuclear@0: } nuclear@0: glDeleteFramebuffersEXT(1, &rt->fbo); nuclear@0: glDeleteTextures(1, &rt->color_tex); nuclear@0: glDeleteRenderbuffersEXT(1, &rt->depth_buf); nuclear@0: delete rt; nuclear@0: }