nuclear@0: #include nuclear@8: #include nuclear@2: #include nuclear@0: #include John@14: #include "ogl.h" nuclear@0: #include "ocl.h" nuclear@22: #include "scene.h" nuclear@32: #include "timer.h" nuclear@0: nuclear@12: // kernel arguments nuclear@12: enum { nuclear@12: KARG_FRAMEBUFFER, nuclear@12: KARG_RENDER_INFO, nuclear@12: KARG_FACES, nuclear@12: KARG_MATLIB, nuclear@12: KARG_LIGHTS, nuclear@12: KARG_PRIM_RAYS, nuclear@12: KARG_XFORM, John@14: KARG_INVTRANS_XFORM, nuclear@28: KARG_KDTREE, John@14: John@14: NUM_KERNEL_ARGS nuclear@12: }; John@11: nuclear@2: struct RendInfo { nuclear@22: float ambient[4]; nuclear@2: int xsz, ysz; nuclear@9: int num_faces, num_lights; nuclear@2: int max_iter; nuclear@28: int kd_depth; nuclear@12: }; nuclear@2: nuclear@1: struct Ray { nuclear@8: float origin[4], dir[4]; nuclear@12: }; nuclear@1: nuclear@3: struct Light { nuclear@8: float pos[4], color[4]; nuclear@12: }; nuclear@1: nuclear@3: static Ray get_primary_ray(int x, int y, int w, int h, float vfov_deg); nuclear@3: nuclear@13: static Face *faces; nuclear@3: static Ray *prim_rays; nuclear@3: static CLProgram *prog; nuclear@3: static int global_size; nuclear@3: nuclear@4: static Light lightlist[] = { nuclear@22: {{-8, 15, 18, 0}, {1, 1, 1, 1}} nuclear@4: }; nuclear@4: nuclear@7: nuclear@4: static RendInfo rinf; nuclear@4: nuclear@4: nuclear@13: bool init_renderer(int xsz, int ysz, Scene *scn) nuclear@0: { nuclear@4: // render info nuclear@22: rinf.ambient[0] = rinf.ambient[1] = rinf.ambient[2] = 0.0; nuclear@16: rinf.ambient[3] = 0.0; nuclear@16: nuclear@4: rinf.xsz = xsz; nuclear@4: rinf.ysz = ysz; nuclear@13: rinf.num_faces = scn->get_num_faces(); nuclear@4: rinf.num_lights = sizeof lightlist / sizeof *lightlist; nuclear@4: rinf.max_iter = 6; nuclear@28: rinf.kd_depth = kdtree_depth(scn->kdtree); nuclear@4: nuclear@3: /* calculate primary rays */ nuclear@3: prim_rays = new Ray[xsz * ysz]; nuclear@2: nuclear@2: for(int i=0; iload("rt.cl")) { nuclear@8: return false; nuclear@0: } nuclear@0: nuclear@24: if(!(faces = (Face*)scn->get_face_buffer())) { nuclear@13: fprintf(stderr, "failed to create face buffer\n"); nuclear@13: return false; nuclear@13: } nuclear@13: nuclear@28: const KDNodeGPU *kdbuf = scn->get_kdtree_buffer(); nuclear@28: if(!kdbuf) { nuclear@28: fprintf(stderr, "failed to create kdtree buffer\n"); nuclear@28: return false; nuclear@28: } nuclear@32: // XXX now we can actually destroy the original kdtree and keep only the GPU version nuclear@28: nuclear@3: /* setup argument buffers */ nuclear@12: prog->set_arg_buffer(KARG_FRAMEBUFFER, ARG_WR, xsz * ysz * 4 * sizeof(float)); nuclear@12: prog->set_arg_buffer(KARG_RENDER_INFO, ARG_RD, sizeof rinf, &rinf); John@14: prog->set_arg_buffer(KARG_FACES, ARG_RD, rinf.num_faces * sizeof(Face), faces); John@14: prog->set_arg_buffer(KARG_MATLIB, ARG_RD, scn->get_num_materials() * sizeof(Material), scn->get_materials()); nuclear@12: prog->set_arg_buffer(KARG_LIGHTS, ARG_RD, sizeof lightlist, lightlist); nuclear@12: prog->set_arg_buffer(KARG_PRIM_RAYS, ARG_RD, xsz * ysz * sizeof *prim_rays, prim_rays); nuclear@12: prog->set_arg_buffer(KARG_XFORM, ARG_RD, 16 * sizeof(float)); nuclear@12: prog->set_arg_buffer(KARG_INVTRANS_XFORM, ARG_RD, 16 * sizeof(float)); nuclear@29: prog->set_arg_buffer(KARG_KDTREE, ARG_RD, scn->get_kdtree_buffer_size(), kdbuf); nuclear@12: John@14: if(prog->get_num_args() < NUM_KERNEL_ARGS) { John@14: return false; John@14: } John@14: nuclear@16: if(!prog->build()) { nuclear@16: return false; nuclear@16: } nuclear@16: nuclear@12: delete [] prim_rays; nuclear@2: nuclear@3: global_size = xsz * ysz; nuclear@3: return true; nuclear@3: } nuclear@3: nuclear@3: void destroy_renderer() nuclear@3: { nuclear@3: delete prog; nuclear@3: } nuclear@3: nuclear@3: bool render() nuclear@3: { nuclear@32: long tm0 = get_msec(); nuclear@32: nuclear@3: if(!prog->run(1, global_size)) { nuclear@3: return false; nuclear@0: } John@15: nuclear@32: long tm_run = get_msec() - tm0; nuclear@32: nuclear@13: CLMemBuffer *mbuf = prog->get_arg_buffer(KARG_FRAMEBUFFER); nuclear@12: void *fb = map_mem_buffer(mbuf, MAP_RD); nuclear@13: if(!fb) { nuclear@13: fprintf(stderr, "FAILED\n"); nuclear@13: return false; nuclear@13: } nuclear@13: nuclear@12: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, rinf.xsz, rinf.ysz, GL_RGBA, GL_FLOAT, fb); nuclear@2: unmap_mem_buffer(mbuf); nuclear@32: nuclear@32: long tm_upd = get_msec() - tm0 - tm_run; nuclear@32: nuclear@32: printf("render %ld msec (%ld run, %ld upd)\n", tm_run + tm_upd, tm_run, tm_upd); nuclear@3: return true; nuclear@0: } nuclear@2: nuclear@27: #define MIN(a, b) ((a) < (b) ? (a) : (b)) nuclear@21: static void dbg_set_gl_material(Material *mat) nuclear@21: { nuclear@21: static Material def_mat = {{0.7, 0.7, 0.7, 1}, {0, 0, 0, 0}, 0, 0, 0}; nuclear@21: nuclear@21: if(!mat) mat = &def_mat; nuclear@21: nuclear@21: glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat->kd); nuclear@21: glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat->ks); nuclear@27: glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, MIN(mat->spow, 128.0f)); nuclear@21: } nuclear@21: nuclear@27: void dbg_render_gl(Scene *scn, bool show_tree, bool show_obj) nuclear@8: { nuclear@22: glPushAttrib(GL_ENABLE_BIT | GL_TRANSFORM_BIT | GL_LIGHTING_BIT); nuclear@8: nuclear@21: for(int i=0; iget_materials(); John@14: nuclear@27: int num_faces = scn->get_num_faces(); nuclear@27: int cur_mat = -1; nuclear@21: nuclear@27: for(int i=0; idraw_kdtree(); nuclear@12: } nuclear@12: nuclear@12: glPopMatrix(); nuclear@12: glPopAttrib(); nuclear@22: nuclear@22: assert(glGetError() == GL_NO_ERROR); nuclear@12: } nuclear@12: nuclear@12: void set_xform(float *matrix, float *invtrans) nuclear@12: { nuclear@12: CLMemBuffer *mbuf_xform = prog->get_arg_buffer(KARG_XFORM); nuclear@12: CLMemBuffer *mbuf_invtrans = prog->get_arg_buffer(KARG_INVTRANS_XFORM); nuclear@12: assert(mbuf_xform && mbuf_invtrans); nuclear@12: nuclear@12: float *mem = (float*)map_mem_buffer(mbuf_xform, MAP_WR); nuclear@12: memcpy(mem, matrix, 16 * sizeof *mem); nuclear@12: unmap_mem_buffer(mbuf_xform); nuclear@12: nuclear@12: mem = (float*)map_mem_buffer(mbuf_invtrans, MAP_WR); nuclear@12: memcpy(mem, invtrans, 16 * sizeof *mem); nuclear@12: unmap_mem_buffer(mbuf_invtrans); nuclear@8: } nuclear@8: nuclear@3: static Ray get_primary_ray(int x, int y, int w, int h, float vfov_deg) nuclear@2: { nuclear@2: float vfov = M_PI * vfov_deg / 180.0; nuclear@2: float aspect = (float)w / (float)h; nuclear@2: nuclear@2: float ysz = 2.0; nuclear@2: float xsz = aspect * ysz; nuclear@2: nuclear@2: float px = ((float)x / (float)w) * xsz - xsz / 2.0; nuclear@2: float py = 1.0 - ((float)y / (float)h) * ysz; nuclear@2: float pz = 1.0 / tan(0.5 * vfov); nuclear@2: nuclear@4: px *= 100.0; nuclear@4: py *= 100.0; nuclear@4: pz *= 100.0; nuclear@2: nuclear@18: Ray ray = {{0, 0, 0, 1}, {px, py, -pz, 1}}; nuclear@2: return ray; nuclear@2: }