nuclear@0: #include nuclear@3: #include nuclear@2: #include nuclear@27: #include nuclear@2: #include nuclear@3: #ifndef __APPLE__ nuclear@3: #include nuclear@3: #else nuclear@3: #include nuclear@3: #endif nuclear@3: #include "rt.h" nuclear@12: #include "matrix.h" nuclear@22: #include "scene.h" nuclear@39: #include "ocl.h" John@49: #include "ogl.h" John@49: John@49: #ifdef _MSC_VER John@49: #define snprintf _snprintf John@49: #endif nuclear@0: nuclear@3: void cleanup(); nuclear@3: void disp(); nuclear@3: void reshape(int x, int y); nuclear@3: void keyb(unsigned char key, int x, int y); nuclear@3: void mouse(int bn, int status, int x, int y); nuclear@3: void motion(int x, int y); nuclear@47: bool capture(const char *namefmt); nuclear@2: bool write_ppm(const char *fname, float *fb, int xsz, int ysz); nuclear@2: nuclear@3: static int xsz, ysz; nuclear@3: static bool need_update = true; nuclear@3: nuclear@8: static float cam_theta, cam_phi = 25.0; nuclear@8: static float cam_dist = 10.0; nuclear@8: nuclear@54: static bool dbg_glrender; nuclear@54: static bool dbg_nocl; nuclear@54: static bool dbg_show_kdtree; nuclear@27: static bool dbg_show_obj = true; John@50: bool dbg_frame_time = true; nuclear@13: nuclear@13: static Scene scn; nuclear@39: static unsigned int tex; nuclear@12: nuclear@54: static Light lightlist[] = { nuclear@54: {{-8, 15, 18, 0}, {1, 1, 1, 1}} nuclear@54: }; nuclear@54: nuclear@54: nuclear@54: nuclear@3: int main(int argc, char **argv) nuclear@0: { nuclear@3: glutInitWindowSize(800, 600); nuclear@3: glutInit(&argc, argv); nuclear@13: nuclear@13: int loaded = 0; nuclear@13: for(int i=1; i> 4) & 1) == ((j >> 4) & 1) ? 0xff0000 : 0xff00; nuclear@32: } nuclear@32: } nuclear@27: nuclear@39: glGenTextures(1, &tex); nuclear@39: glBindTexture(GL_TEXTURE_2D, tex); nuclear@3: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); nuclear@3: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); nuclear@3: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); nuclear@3: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); nuclear@39: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F_ARB, xsz, ysz, 0, GL_RGBA, GL_UNSIGNED_BYTE, test_pattern); nuclear@32: delete [] test_pattern; nuclear@2: nuclear@39: if(!init_opencl()) { nuclear@39: return 1; nuclear@39: } nuclear@39: nuclear@39: if(!init_renderer(xsz, ysz, &scn, tex)) { nuclear@39: return 1; nuclear@39: } nuclear@39: atexit(cleanup); nuclear@39: nuclear@3: glutMainLoop(); nuclear@0: return 0; nuclear@0: } nuclear@2: nuclear@3: void cleanup() nuclear@2: { nuclear@41: printf("destroying renderer ...\n"); nuclear@3: destroy_renderer(); nuclear@40: nuclear@41: printf("shutting down OpenCL ...\n"); nuclear@40: destroy_opencl(); nuclear@40: nuclear@41: printf("cleaning up OpenGL resources ...\n"); nuclear@41: glDeleteTextures(1, &tex); nuclear@3: } nuclear@2: nuclear@12: static Matrix4x4 mat, inv_mat, inv_trans; nuclear@12: nuclear@3: void disp() nuclear@3: { nuclear@8: glMatrixMode(GL_MODELVIEW); nuclear@8: glLoadIdentity(); nuclear@8: nuclear@3: if(need_update) { nuclear@12: glPushMatrix(); nuclear@12: glRotatef(-cam_theta, 0, 1, 0); nuclear@12: glRotatef(-cam_phi, 1, 0, 0); nuclear@12: glTranslatef(0, 0, cam_dist); nuclear@8: nuclear@12: glGetFloatv(GL_MODELVIEW_MATRIX, mat.m); nuclear@8: nuclear@12: inv_trans = mat; nuclear@12: inv_trans.m[3] = inv_trans.m[7] = inv_trans.m[11] = 0.0; nuclear@12: inv_trans.m[12] = inv_trans.m[13] = inv_trans.m[14] = 0.0; nuclear@12: inv_trans.m[15] = 1.0; nuclear@12: nuclear@12: set_xform(mat.m, inv_trans.m); nuclear@8: glPopMatrix(); nuclear@8: nuclear@13: if(!dbg_glrender) { nuclear@54: if(dbg_nocl) { nuclear@54: dbg_render(mat.m, inv_trans.m); nuclear@55: print_render_stats(); nuclear@54: } else { nuclear@54: if(!render()) { nuclear@54: exit(1); nuclear@54: } nuclear@58: nuclear@58: if(dbg_frame_time) { nuclear@58: const RenderStats *rstat = get_render_stats(); nuclear@58: printf("render time (msec): %lu\n", rstat->render_time); nuclear@58: } nuclear@13: } nuclear@13: need_update = false; nuclear@12: } nuclear@3: } nuclear@2: nuclear@12: if(dbg_glrender) { nuclear@54: inv_mat = mat; nuclear@54: inv_mat.invert(); nuclear@54: nuclear@12: glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); nuclear@12: glLoadMatrixf(inv_mat.m); nuclear@27: dbg_render_gl(&scn, dbg_show_kdtree, dbg_show_obj); nuclear@12: } else { nuclear@12: glEnable(GL_TEXTURE_2D); nuclear@22: glDisable(GL_LIGHTING); nuclear@2: nuclear@12: glBegin(GL_QUADS); nuclear@12: glColor3f(1, 1, 1); nuclear@12: glTexCoord2f(0, 1); glVertex2f(-1, -1); nuclear@12: glTexCoord2f(1, 1); glVertex2f(1, -1); nuclear@12: glTexCoord2f(1, 0); glVertex2f(1, 1); nuclear@12: glTexCoord2f(0, 0); glVertex2f(-1, 1); nuclear@12: glEnd(); nuclear@2: nuclear@12: glDisable(GL_TEXTURE_2D); nuclear@12: } nuclear@3: nuclear@3: glutSwapBuffers(); nuclear@56: nuclear@56: /* We need to make sure OpenGL has finished with the texture nuclear@56: * before allowing the OpenCL kernel to run again. nuclear@56: */ nuclear@56: glFinish(); nuclear@3: } nuclear@3: nuclear@3: void reshape(int x, int y) nuclear@3: { nuclear@3: glViewport(0, 0, x, y); nuclear@3: nuclear@58: /* TODO reallocate the framebuffer to fit the window */ nuclear@3: } nuclear@3: nuclear@47: void idle() nuclear@47: { nuclear@47: need_update = true; nuclear@47: glutPostRedisplay(); nuclear@47: } nuclear@47: nuclear@3: void keyb(unsigned char key, int x, int y) nuclear@3: { nuclear@3: switch(key) { nuclear@3: case 27: nuclear@3: exit(0); nuclear@3: nuclear@47: case '\b': nuclear@47: { nuclear@47: static bool busyloop; nuclear@47: nuclear@47: busyloop = !busyloop; nuclear@47: printf("%s busy-looping\n", busyloop ? "WARNING: enabling" : "disabling"); nuclear@47: glutIdleFunc(busyloop ? idle : 0); nuclear@47: } nuclear@3: break; nuclear@3: nuclear@12: case 'd': nuclear@12: dbg_glrender = !dbg_glrender; nuclear@12: if(dbg_glrender) { nuclear@21: printf("Debug OpenGL rendering\n"); nuclear@21: } else { nuclear@21: printf("Raytracing\n"); nuclear@12: } nuclear@3: glutPostRedisplay(); nuclear@3: break; nuclear@3: nuclear@27: case 'k': nuclear@27: dbg_show_kdtree = !dbg_show_kdtree; nuclear@27: if(dbg_glrender) { nuclear@27: glutPostRedisplay(); nuclear@27: } nuclear@27: break; nuclear@27: nuclear@27: case 'o': nuclear@27: dbg_show_obj = !dbg_show_obj; nuclear@27: if(dbg_glrender) { nuclear@27: glutPostRedisplay(); nuclear@27: } nuclear@27: break; nuclear@27: nuclear@47: case 's': nuclear@47: { nuclear@47: bool shadows = get_render_option_bool(ROPT_SHAD); nuclear@47: shadows = !shadows; nuclear@47: printf("%s shadows\n", shadows ? "enabling" : "disabling"); nuclear@47: set_render_option(ROPT_SHAD, shadows); nuclear@47: need_update = true; nuclear@47: glutPostRedisplay(); nuclear@47: } nuclear@47: break; nuclear@47: nuclear@47: case 'r': nuclear@47: { nuclear@47: bool refl = get_render_option_bool(ROPT_REFL); nuclear@47: refl = !refl; nuclear@47: printf("%s reflections\n", refl ? "enabling" : "disabling"); nuclear@47: set_render_option(ROPT_REFL, refl); nuclear@47: need_update = true; nuclear@47: glutPostRedisplay(); nuclear@47: } nuclear@47: break; nuclear@47: nuclear@47: case ']': nuclear@47: { nuclear@47: int iter = get_render_option_int(ROPT_ITER); nuclear@47: printf("setting max iterations: %d\n", iter + 1); nuclear@47: set_render_option(ROPT_ITER, iter + 1); nuclear@47: need_update = true; nuclear@47: glutPostRedisplay(); nuclear@47: } nuclear@47: break; nuclear@47: nuclear@47: case '[': nuclear@47: { nuclear@47: int iter = get_render_option_int(ROPT_ITER); nuclear@47: if(iter-- > 0) { nuclear@47: printf("setting max iterations: %d\n", iter); nuclear@47: set_render_option(ROPT_ITER, iter); nuclear@47: need_update = true; nuclear@47: glutPostRedisplay(); nuclear@47: } nuclear@47: } nuclear@47: break; nuclear@47: nuclear@47: case '`': nuclear@47: capture("shot%03d.ppm"); nuclear@47: break; nuclear@47: John@50: case 't': John@50: dbg_frame_time = !dbg_frame_time; John@50: break; John@50: nuclear@54: case 'n': nuclear@54: dbg_nocl = !dbg_nocl; nuclear@54: printf("switching to %s rendering\n", dbg_nocl ? "debug CPU" : "OpenCL"); nuclear@54: need_update = true; nuclear@54: glutPostRedisplay(); nuclear@54: break; nuclear@54: nuclear@3: default: nuclear@3: break; nuclear@3: } nuclear@3: } nuclear@3: nuclear@8: static bool bnstate[32]; nuclear@8: static int prev_x, prev_y; nuclear@8: nuclear@3: void mouse(int bn, int state, int x, int y) nuclear@3: { nuclear@8: if(state == GLUT_DOWN) { nuclear@8: prev_x = x; nuclear@8: prev_y = y; nuclear@8: bnstate[bn] = true; nuclear@8: } else { nuclear@8: bnstate[bn] = false; nuclear@8: } nuclear@3: } nuclear@3: nuclear@8: #define ROT_SCALE 0.5 nuclear@8: #define PAN_SCALE 0.1 nuclear@8: nuclear@3: void motion(int x, int y) nuclear@3: { nuclear@8: int dx = x - prev_x; nuclear@8: int dy = y - prev_y; nuclear@8: prev_x = x; nuclear@8: prev_y = y; nuclear@8: nuclear@8: if(bnstate[0]) { nuclear@8: cam_theta += dx * ROT_SCALE; nuclear@8: cam_phi += dy * ROT_SCALE; nuclear@8: nuclear@12: if(cam_phi < -89) cam_phi = -89; nuclear@8: if(cam_phi > 89) cam_phi = 89; nuclear@8: nuclear@8: need_update = true; nuclear@8: glutPostRedisplay(); nuclear@8: } nuclear@8: if(bnstate[2]) { nuclear@8: cam_dist += dy * PAN_SCALE; nuclear@8: if(cam_dist < 0) cam_dist = 0; nuclear@8: nuclear@8: need_update = true; nuclear@8: glutPostRedisplay(); nuclear@8: } nuclear@2: } nuclear@2: nuclear@47: bool capture(const char *namefmt) nuclear@47: { nuclear@47: static int num; nuclear@47: char fname[256]; nuclear@47: nuclear@47: num++; nuclear@47: snprintf(fname, sizeof fname, namefmt, num); nuclear@47: printf("saving image %s\n", fname); nuclear@47: nuclear@47: float *pixels = new float[4 * xsz * ysz]; nuclear@47: glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, pixels); nuclear@47: nuclear@52: bool res = write_ppm(fname, pixels, xsz, ysz); nuclear@47: if(!res) { nuclear@47: num--; nuclear@47: } nuclear@47: delete [] pixels; nuclear@47: return res; nuclear@47: } nuclear@47: nuclear@2: bool write_ppm(const char *fname, float *fb, int xsz, int ysz) nuclear@2: { nuclear@2: FILE *fp; nuclear@2: nuclear@2: if(!(fp = fopen(fname, "wb"))) { nuclear@2: fprintf(stderr, "write_ppm: failed to open file %s for writing: %s\n", fname, strerror(errno)); nuclear@2: return false; nuclear@2: } nuclear@2: fprintf(fp, "P6\n%d %d\n255\n", xsz, ysz); nuclear@2: nuclear@2: for(int i=0; i