nuclear@0: #include nuclear@0: #include nuclear@0: #include nuclear@0: #include nuclear@0: #include "opengl.h" nuclear@0: nuclear@0: #include "gpuscene.h" nuclear@0: #include "sphere.h" nuclear@0: #include "plane.h" nuclear@0: #include "image.h" nuclear@0: #include "rend.h" nuclear@0: #include "glsdr.h" nuclear@0: nuclear@0: static bool init(const char *scene_fname); nuclear@0: static void cleanup(); nuclear@0: static void disp(); nuclear@0: static void draw_text(float r, float g, float b, const char *fmt, ...); nuclear@0: //static void update_texture(const float *fb); nuclear@0: static void idle(); nuclear@0: static void reshape(int x, int y); nuclear@0: static void handle_keys(float dt); nuclear@0: static void keyb(unsigned char key, int x, int y); nuclear@0: static void keyb_up(unsigned char key, int x, int y); nuclear@0: static void skeyb(int key, int x, int y); nuclear@0: static void mouse(int bn, int st, int x, int y); nuclear@0: static void motion(int x, int y); nuclear@0: static void sball_motion(int x, int y, int z); nuclear@0: static void sball_rotate(int x, int y, int z); nuclear@0: static void sball_button(int bn, int state); nuclear@0: nuclear@0: static unsigned int tex; nuclear@0: static long last_fps_upd, first_time = -1; nuclear@0: static long frames, total_frames; nuclear@0: static float fps; nuclear@0: static int xsz = 800; nuclear@0: static int ysz = 450; nuclear@0: //static int tex_xsz, tex_ysz; nuclear@0: nuclear@0: static GPUScene *scn; nuclear@0: static FlyCamera *cam; nuclear@0: nuclear@0: static float img_scale = 1.0f; nuclear@0: static bool keystate[256]; nuclear@0: nuclear@0: static char *scene_fname; nuclear@0: static bool sdr_valid = true; nuclear@0: nuclear@0: int main(int argc, char **argv) nuclear@0: { nuclear@0: glutInit(&argc, argv); nuclear@0: nuclear@0: int num_samples = 1; nuclear@0: nuclear@0: for(int i=1; i= 1\n"); nuclear@0: return 1; nuclear@0: } nuclear@0: } else { nuclear@0: fprintf(stderr, "invalid option: %s\n", argv[i]); nuclear@0: return 1; nuclear@0: } nuclear@0: } else { nuclear@0: if(scene_fname) { nuclear@0: fprintf(stderr, "unexpected argument: %s\n", argv[i]); nuclear@0: return 1; nuclear@0: } nuclear@0: scene_fname = argv[i]; nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: glutInitWindowSize(xsz * img_scale, ysz * img_scale); nuclear@0: glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); nuclear@0: glutCreateWindow("single threaded"); nuclear@0: nuclear@0: glutDisplayFunc(disp); nuclear@0: glutIdleFunc(idle); nuclear@0: glutReshapeFunc(reshape); nuclear@0: glutKeyboardFunc(keyb); nuclear@0: glutKeyboardUpFunc(keyb_up); nuclear@0: glutSpecialFunc(skeyb); nuclear@0: glutMouseFunc(mouse); nuclear@0: glutMotionFunc(motion); nuclear@0: glutSpaceballMotionFunc(sball_motion); nuclear@0: glutSpaceballRotateFunc(sball_rotate); nuclear@0: glutSpaceballButtonFunc(sball_button); nuclear@0: nuclear@0: glewInit(); nuclear@0: nuclear@0: if(!init(scene_fname)) { nuclear@0: return 1; nuclear@0: } nuclear@0: atexit(cleanup); nuclear@0: nuclear@0: glutMainLoop(); nuclear@0: return 0; nuclear@0: } nuclear@0: nuclear@0: static bool init(const char *scene_fname) nuclear@0: { nuclear@0: scn = new GPUScene; nuclear@0: if(!scn->load(scene_fname ? scene_fname : "scene")) { nuclear@0: return false; nuclear@0: } nuclear@0: nuclear@0: cam = new FlyCamera; nuclear@0: cam->input_move(0, 1.5, -10); nuclear@0: cam->input_rotate(25, 0, 0); nuclear@0: scn->set_camera(cam); nuclear@0: nuclear@0: if(!init_renderer(scn, xsz, ysz)) { nuclear@0: return false; nuclear@0: } nuclear@0: nuclear@0: glGenTextures(1, &tex); nuclear@0: glBindTexture(GL_TEXTURE_2D, tex); nuclear@0: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); nuclear@0: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 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@0: nuclear@0: int srgb_capable; nuclear@0: if(GLEW_EXT_framebuffer_sRGB && (glGetIntegerv(GL_FRAMEBUFFER_SRGB_CAPABLE_EXT, &srgb_capable), srgb_capable)) { nuclear@0: printf("enabling sRGB framebuffer\n"); nuclear@0: glEnable(GL_FRAMEBUFFER_SRGB); nuclear@0: } else { nuclear@0: printf("using post shader for gamma correction\n"); nuclear@0: unsigned int post_sdr = create_program_load(0, "sdr/postsdr.glsl"); nuclear@0: if(post_sdr) { nuclear@0: glUseProgram(post_sdr); nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: last_fps_upd = glutGet(GLUT_ELAPSED_TIME); nuclear@0: first_time = last_fps_upd; nuclear@0: total_frames = 0; nuclear@0: return true; nuclear@0: } nuclear@0: nuclear@0: static void cleanup() nuclear@0: { nuclear@0: long interval = glutGet(GLUT_ELAPSED_TIME) - first_time; nuclear@0: printf("average fps: %.2f\n", (float)total_frames / ((float)interval / 1000.0f)); nuclear@0: nuclear@0: glDeleteTextures(1, &tex); nuclear@0: nuclear@0: destroy_renderer(); nuclear@0: delete scn; nuclear@0: } nuclear@0: nuclear@0: static void disp() nuclear@0: { nuclear@0: static long prev_msec; nuclear@0: long interval, msec = glutGet(GLUT_ELAPSED_TIME); nuclear@0: nuclear@0: handle_keys((msec - prev_msec) / 1000.0f); nuclear@0: prev_msec = msec; nuclear@0: nuclear@0: //update_texture(); nuclear@0: if(sdr_valid) { nuclear@0: render_frame(msec); nuclear@0: } else { nuclear@0: glUseProgram(0); nuclear@0: glMatrixMode(GL_MODELVIEW); nuclear@0: glLoadIdentity(); nuclear@0: glMatrixMode(GL_PROJECTION); nuclear@0: glLoadIdentity(); nuclear@0: nuclear@0: glLineWidth(8.0); nuclear@0: glBegin(GL_LINES); nuclear@0: glColor3f(1, 0, 0); nuclear@0: glVertex2f(-1, -1); nuclear@0: glVertex2f(1, 1); nuclear@0: glVertex2f(-1, 1); nuclear@0: glVertex2f(1, -1); nuclear@0: glEnd(); nuclear@0: glLineWidth(1.0); nuclear@0: } nuclear@0: nuclear@0: draw_text(0.8, 0.75, 0, "fps: %.2f", fps); nuclear@0: nuclear@0: glutSwapBuffers(); nuclear@0: frames++; nuclear@0: total_frames++; nuclear@0: nuclear@0: interval = (msec = glutGet(GLUT_ELAPSED_TIME)) - last_fps_upd; nuclear@0: if(interval >= 2000) { nuclear@0: float tm = (float)interval / 1000.0f; nuclear@0: fps = (float)frames / tm; nuclear@0: /*printf("%.2f fps \r", (float)frames / tm); nuclear@0: fflush(stdout);*/ nuclear@0: last_fps_upd = msec; nuclear@0: frames = 0; nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: void draw_text(float r, float g, float b, const char *fmt, ...) nuclear@0: { nuclear@0: char buf[256], *text = buf; nuclear@0: va_list ap; nuclear@0: nuclear@0: va_start(ap, fmt); nuclear@0: vsprintf(buf, fmt, ap); nuclear@0: va_end(ap); nuclear@0: nuclear@0: glUseProgram(0); 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: glOrtho(0, xsz, 0, ysz, -1, 1); nuclear@0: nuclear@0: glColor3f(r, g, b); nuclear@0: glRasterPos2f(2, 4); nuclear@0: while(*text) { nuclear@0: glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, *text++); nuclear@0: } nuclear@0: glColor3f(1, 1, 1); nuclear@0: nuclear@0: glPopMatrix(); nuclear@0: glMatrixMode(GL_MODELVIEW); nuclear@0: glPopMatrix(); nuclear@0: } nuclear@0: nuclear@0: nuclear@0: /* nuclear@0: static void update_texture() nuclear@0: { nuclear@0: int ntx = next_pow2(xsz); nuclear@0: int nty = next_pow2(ysz); nuclear@0: nuclear@0: if(ntx != tex_xsz || nty != tex_ysz) { nuclear@0: tex_xsz = ntx; nuclear@0: tex_ysz = nty; nuclear@0: nuclear@0: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, tex_xsz, tex_ysz, 0, GL_RGB, GL_FLOAT, 0); nuclear@0: } nuclear@0: } nuclear@0: */ nuclear@0: nuclear@0: static void idle() nuclear@0: { nuclear@0: glutPostRedisplay(); nuclear@0: } nuclear@0: nuclear@0: static void reshape(int x, int y) nuclear@0: { nuclear@0: int tx, ty; nuclear@0: nuclear@0: xsz = x / img_scale; nuclear@0: ysz = y / img_scale; nuclear@0: nuclear@0: glViewport(0, 0, x, y); nuclear@0: nuclear@0: /* setup the texture matrix that maps just the visible area nuclear@0: * of the texture to [0, 1] nuclear@0: */ nuclear@0: tx = next_pow2(xsz); nuclear@0: ty = next_pow2(ysz); nuclear@0: nuclear@0: glMatrixMode(GL_TEXTURE); nuclear@0: glLoadIdentity(); nuclear@0: glScalef((float)xsz / tx, (float)ysz / ty, 1.0f); nuclear@0: nuclear@0: resize_renderer(xsz, ysz); nuclear@0: } nuclear@0: nuclear@0: static void handle_keys(float dt) nuclear@0: { nuclear@0: Vector3 move; nuclear@0: float tilt = 0.0f; nuclear@0: float offs = dt * 8.0; nuclear@0: nuclear@0: if(keystate['w']) { nuclear@0: move.z += offs; nuclear@0: } nuclear@0: if(keystate['s']) { nuclear@0: move.z -= offs; nuclear@0: } nuclear@0: if(keystate['d']) { nuclear@0: move.x += offs; nuclear@0: } nuclear@0: if(keystate['a']) { nuclear@0: move.x -= offs; nuclear@0: } nuclear@0: nuclear@0: if(keystate['q']) { nuclear@0: tilt -= dt; nuclear@0: } nuclear@0: if(keystate['e']) { nuclear@0: tilt += dt; nuclear@0: } nuclear@0: nuclear@0: cam->input_move(move.x, move.y, move.z); nuclear@0: cam->input_rotate(0, 0, tilt); nuclear@0: } nuclear@0: nuclear@0: static void keyb(unsigned char key, int x, int y) nuclear@0: { nuclear@0: keystate[key] = true; nuclear@0: nuclear@0: switch(key) { nuclear@0: case 27: nuclear@0: exit(0); nuclear@0: nuclear@0: case '`': nuclear@0: sdr_valid = reload_shader(); nuclear@0: break; nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: static void keyb_up(unsigned char key, int x, int y) nuclear@0: { nuclear@0: keystate[key] = false; nuclear@0: } nuclear@0: nuclear@0: static void skeyb(int key, int x, int y) nuclear@0: { nuclear@0: switch(key) { nuclear@0: case GLUT_KEY_F1: nuclear@0: printf("reinitializing\n"); nuclear@0: cleanup(); nuclear@0: sdr_valid = init(scene_fname); nuclear@0: break; nuclear@0: nuclear@0: default: nuclear@0: break; nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: static int prev_x, prev_y; nuclear@0: nuclear@0: static void mouse(int bn, int st, int x, int y) nuclear@0: { nuclear@0: prev_x = x; nuclear@0: prev_y = y; nuclear@0: } nuclear@0: nuclear@0: static 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: cam->input_rotate(-dy * 0.01, -dx * 0.01, 0); nuclear@0: } nuclear@0: nuclear@0: static void sball_motion(int x, int y, int z) nuclear@0: { nuclear@0: float fx = x * 0.01; nuclear@0: float fy = y * 0.01; nuclear@0: float fz = z * 0.01; nuclear@0: cam->input_move(fx, fy, fz); nuclear@0: } nuclear@0: nuclear@0: static void sball_rotate(int x, int y, int z) nuclear@0: { nuclear@0: float fx = x * 0.00025; nuclear@0: float fy = y * 0.00025; nuclear@0: float fz = z * 0.00025; nuclear@0: cam->input_rotate(fx, fy, fz); nuclear@0: } nuclear@0: nuclear@0: static void sball_button(int bn, int state) nuclear@0: { nuclear@0: } nuclear@0: nuclear@0: nuclear@0: int next_pow2(int x) nuclear@0: { nuclear@0: x--; nuclear@0: x = (x >> 1) | x; nuclear@0: x = (x >> 2) | x; nuclear@0: x = (x >> 4) | x; nuclear@0: x = (x >> 8) | x; nuclear@0: x = (x >> 16) | x; nuclear@0: return x + 1; nuclear@0: }