nuclear@0: #include nuclear@8: #include nuclear@2: #include nuclear@0: #include nuclear@12: nuclear@12: #ifndef __APPLE__ nuclear@12: #include nuclear@12: #include nuclear@12: #else nuclear@12: #include nuclear@12: #include nuclear@12: #endif nuclear@12: nuclear@0: #include "ocl.h" nuclear@9: #include "mesh.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, nuclear@12: KARG_INVTRANS_XFORM nuclear@12: }; John@11: nuclear@2: struct RendInfo { nuclear@2: int xsz, ysz; nuclear@9: int num_faces, num_lights; nuclear@2: int max_iter; 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@13: static Face *create_face_buffer(Mesh **meshes, int num_meshes); 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@12: {{-10, 10, -20, 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@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@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@13: /*Face **/faces = create_face_buffer(&scn->meshes[0], scn->meshes.size()); nuclear@13: if(!faces) { nuclear@13: fprintf(stderr, "failed to create face buffer\n"); nuclear@13: return false; nuclear@13: } nuclear@13: 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); nuclear@13: prog->set_arg_buffer(KARG_FACES, ARG_RD, rinf.num_faces, faces); nuclear@13: prog->set_arg_buffer(KARG_MATLIB, ARG_RD, scn->matlib.size() * sizeof(Material), &scn->matlib[0]); 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@12: 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@13: printf("Running kernel..."); nuclear@13: fflush(stdout); nuclear@3: if(!prog->run(1, global_size)) { nuclear@3: return false; nuclear@0: } nuclear@13: printf("done\n"); nuclear@0: 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@3: return true; nuclear@0: } nuclear@2: nuclear@13: void dbg_render_gl(Scene *scn) nuclear@8: { nuclear@12: glPushAttrib(GL_ENABLE_BIT | GL_TRANSFORM_BIT); nuclear@8: nuclear@12: glDisable(GL_TEXTURE_2D); nuclear@12: glEnable(GL_DEPTH_TEST); nuclear@12: nuclear@12: glMatrixMode(GL_PROJECTION); nuclear@12: glPushMatrix(); nuclear@12: glLoadIdentity(); nuclear@12: gluPerspective(45.0, (float)rinf.xsz / (float)rinf.ysz, 0.5, 1000.0); nuclear@12: nuclear@12: glBegin(GL_TRIANGLES); nuclear@13: int num_faces = scn->get_num_faces(); nuclear@13: for(int i=0; imatlib[faces[i].matid]; nuclear@12: glColor3f(mat->kd[0], mat->kd[1], mat->kd[2]); nuclear@12: nuclear@12: for(int j=0; j<3; j++) { nuclear@12: float *pos = faces[i].v[j].pos; nuclear@12: glVertex3f(pos[0], pos[1], pos[2]); nuclear@12: } nuclear@12: } nuclear@13: nuclear@13: /*for(size_t i=0; imeshes.size(); i++) { nuclear@13: Material *mat = &scn->matlib[scn->meshes[i]->matid]; nuclear@13: nuclear@13: glColor3f(mat->kd[0], mat->kd[1], mat->kd[2]); nuclear@13: for(size_t j=0; jmeshes[i]->faces.size(); j++) { nuclear@13: for(int k=0; k<3; k++) { nuclear@13: float *pos = scn->meshes[i]->faces[j].v[k].pos; nuclear@13: glVertex3f(pos[0], pos[1], pos[2]); nuclear@13: } nuclear@13: } nuclear@13: }*/ nuclear@12: glEnd(); nuclear@12: nuclear@12: glPopMatrix(); nuclear@12: glPopAttrib(); 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@13: /*printf("-- xform:\n"); nuclear@12: for(int i=0; i<16; i++) { nuclear@12: printf("%2.3f\t", mem[i]); nuclear@12: if(i % 4 == 3) putchar('\n'); nuclear@13: }*/ 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@13: /*printf("-- inverse-transpose:\n"); nuclear@12: for(int i=0; i<16; i++) { nuclear@12: printf("%2.3f\t", mem[i]); nuclear@12: if(i % 4 == 3) putchar('\n'); nuclear@13: }*/ 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@12: Ray ray = {{0, 0, 0, 1}, {px, py, -pz, 1}}; nuclear@2: return ray; nuclear@2: } nuclear@13: nuclear@13: static Face *create_face_buffer(Mesh **meshes, int num_meshes) nuclear@13: { nuclear@13: int num_faces = 0; nuclear@13: for(int i=0; ifaces.size(); nuclear@13: } nuclear@13: printf("constructing face buffer with %d faces (out of %d meshes)\n", num_faces, num_meshes); nuclear@13: nuclear@13: Face *faces = new Face[num_faces]; nuclear@13: memset(faces, 0, num_faces * sizeof *faces); nuclear@13: Face *fptr = faces; nuclear@13: nuclear@13: for(int i=0; ifaces.size(); j++) { nuclear@13: *fptr++ = meshes[i]->faces[j]; nuclear@13: } nuclear@13: } nuclear@13: return faces; nuclear@13: }