clray

annotate src/rt.cc @ 12:85fd61f374d9

fixed the bloody intersection bug
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 03 Aug 2010 13:06:59 +0100
parents d9a1bab1c3f5
children 407935b73af3
rev   line source
nuclear@0 1 #include <stdio.h>
nuclear@8 2 #include <string.h>
nuclear@2 3 #include <math.h>
nuclear@0 4 #include <assert.h>
nuclear@12 5
nuclear@12 6 #ifndef __APPLE__
nuclear@12 7 #include <GL/gl.h>
nuclear@12 8 #include <GL/glu.h>
nuclear@12 9 #else
nuclear@12 10 #include <OpenGL/gl.h>
nuclear@12 11 #include <OpenGL/glu.h>
nuclear@12 12 #endif
nuclear@12 13
nuclear@0 14 #include "ocl.h"
nuclear@9 15 #include "mesh.h"
nuclear@0 16
nuclear@12 17 // kernel arguments
nuclear@12 18 enum {
nuclear@12 19 KARG_FRAMEBUFFER,
nuclear@12 20 KARG_RENDER_INFO,
nuclear@12 21 KARG_FACES,
nuclear@12 22 KARG_MATLIB,
nuclear@12 23 KARG_LIGHTS,
nuclear@12 24 KARG_PRIM_RAYS,
nuclear@12 25 KARG_XFORM,
nuclear@12 26 KARG_INVTRANS_XFORM
nuclear@12 27 };
John@11 28
nuclear@2 29 struct RendInfo {
nuclear@2 30 int xsz, ysz;
nuclear@9 31 int num_faces, num_lights;
nuclear@2 32 int max_iter;
nuclear@12 33 };
nuclear@2 34
nuclear@1 35 struct Ray {
nuclear@8 36 float origin[4], dir[4];
nuclear@12 37 };
nuclear@1 38
nuclear@3 39 struct Light {
nuclear@8 40 float pos[4], color[4];
nuclear@12 41 };
nuclear@1 42
nuclear@3 43 static Ray get_primary_ray(int x, int y, int w, int h, float vfov_deg);
nuclear@3 44
nuclear@3 45 static Ray *prim_rays;
nuclear@3 46 static CLProgram *prog;
nuclear@3 47 static int global_size;
nuclear@3 48
nuclear@9 49 static Face faces[] = {
nuclear@9 50 {/* face0 */
nuclear@9 51 {
nuclear@12 52 {{-1, 0, 0, 0}, {0, 0, -1, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}},
nuclear@12 53 {{0, 1, 0, 0}, {0, 0, -1, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}},
nuclear@12 54 {{1, 0, 0, 0}, {0, 0, -1, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}
nuclear@9 55 },
nuclear@12 56 {0, 0, -1, 0}, 0, {0, 0, 0}
nuclear@9 57 },
nuclear@9 58 {/* face1 */
nuclear@9 59 {
nuclear@12 60 {{-5, 0, -3, 0}, {0, 1, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}},
nuclear@12 61 {{0, 0, 3, 0}, {0, 1, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}},
nuclear@12 62 {{5, 0, -3, 0}, {0, 1, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}
nuclear@9 63 },
nuclear@12 64 {0, 1, 0, 0}, 1, {0, 0, 0}
nuclear@9 65 }
nuclear@9 66 };
nuclear@9 67
nuclear@9 68 static Material matlib[] = {
nuclear@12 69 {{1, 0, 0, 1}, {1, 1, 1, 1}, 0, 0, 60.0, 0},
nuclear@12 70 {{0.2, 0.8, 0.3, 1}, {0, 0, 0, 0}, 0, 0, 0, 0}
nuclear@4 71 };
nuclear@4 72
nuclear@4 73 static Light lightlist[] = {
nuclear@12 74 {{-10, 10, -20, 0}, {1, 1, 1, 1}}
nuclear@4 75 };
nuclear@4 76
nuclear@7 77
nuclear@4 78 static RendInfo rinf;
nuclear@4 79
nuclear@4 80
nuclear@12 81 bool init_renderer(int xsz, int ysz)
nuclear@0 82 {
nuclear@4 83 // render info
nuclear@4 84 rinf.xsz = xsz;
nuclear@4 85 rinf.ysz = ysz;
nuclear@9 86 rinf.num_faces = sizeof faces / sizeof *faces;
nuclear@4 87 rinf.num_lights = sizeof lightlist / sizeof *lightlist;
nuclear@4 88 rinf.max_iter = 6;
nuclear@4 89
nuclear@3 90 /* calculate primary rays */
nuclear@3 91 prim_rays = new Ray[xsz * ysz];
nuclear@2 92
nuclear@2 93 for(int i=0; i<ysz; i++) {
nuclear@2 94 for(int j=0; j<xsz; j++) {
nuclear@2 95 prim_rays[i * xsz + j] = get_primary_ray(j, i, xsz, ysz, 45.0);
nuclear@2 96 }
nuclear@0 97 }
nuclear@0 98
nuclear@2 99 /* setup opencl */
nuclear@3 100 prog = new CLProgram("render");
nuclear@3 101 if(!prog->load("rt.cl")) {
nuclear@8 102 return false;
nuclear@0 103 }
nuclear@0 104
nuclear@3 105 /* setup argument buffers */
nuclear@12 106 prog->set_arg_buffer(KARG_FRAMEBUFFER, ARG_WR, xsz * ysz * 4 * sizeof(float));
nuclear@12 107 prog->set_arg_buffer(KARG_RENDER_INFO, ARG_RD, sizeof rinf, &rinf);
nuclear@12 108 prog->set_arg_buffer(KARG_FACES, ARG_RD, sizeof faces, faces);
nuclear@12 109 prog->set_arg_buffer(KARG_MATLIB, ARG_RD, sizeof matlib, matlib);
nuclear@12 110 prog->set_arg_buffer(KARG_LIGHTS, ARG_RD, sizeof lightlist, lightlist);
nuclear@12 111 prog->set_arg_buffer(KARG_PRIM_RAYS, ARG_RD, xsz * ysz * sizeof *prim_rays, prim_rays);
nuclear@12 112 prog->set_arg_buffer(KARG_XFORM, ARG_RD, 16 * sizeof(float));
nuclear@12 113 prog->set_arg_buffer(KARG_INVTRANS_XFORM, ARG_RD, 16 * sizeof(float));
nuclear@12 114
nuclear@12 115 delete [] prim_rays;
nuclear@2 116
nuclear@3 117 global_size = xsz * ysz;
nuclear@3 118 return true;
nuclear@3 119 }
nuclear@3 120
nuclear@3 121 void destroy_renderer()
nuclear@3 122 {
nuclear@3 123 delete prog;
nuclear@3 124 }
nuclear@3 125
nuclear@3 126 bool render()
nuclear@3 127 {
nuclear@3 128 if(!prog->run(1, global_size)) {
nuclear@3 129 return false;
nuclear@0 130 }
nuclear@0 131
nuclear@3 132 CLMemBuffer *mbuf = prog->get_arg_buffer(0);
nuclear@12 133 void *fb = map_mem_buffer(mbuf, MAP_RD);
nuclear@12 134 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, rinf.xsz, rinf.ysz, GL_RGBA, GL_FLOAT, fb);
nuclear@2 135 unmap_mem_buffer(mbuf);
nuclear@3 136 return true;
nuclear@0 137 }
nuclear@2 138
nuclear@12 139 void dbg_render_gl()
nuclear@8 140 {
nuclear@12 141 glPushAttrib(GL_ENABLE_BIT | GL_TRANSFORM_BIT);
nuclear@8 142
nuclear@12 143 glDisable(GL_TEXTURE_2D);
nuclear@12 144 glEnable(GL_DEPTH_TEST);
nuclear@12 145
nuclear@12 146 glMatrixMode(GL_PROJECTION);
nuclear@12 147 glPushMatrix();
nuclear@12 148 glLoadIdentity();
nuclear@12 149 gluPerspective(45.0, (float)rinf.xsz / (float)rinf.ysz, 0.5, 1000.0);
nuclear@12 150
nuclear@12 151 glBegin(GL_TRIANGLES);
nuclear@12 152 for(int i=0; i<rinf.num_faces; i++) {
nuclear@12 153 Material *mat = matlib + faces[i].matid;
nuclear@12 154 glColor3f(mat->kd[0], mat->kd[1], mat->kd[2]);
nuclear@12 155
nuclear@12 156 for(int j=0; j<3; j++) {
nuclear@12 157 float *pos = faces[i].v[j].pos;
nuclear@12 158 glVertex3f(pos[0], pos[1], pos[2]);
nuclear@12 159 }
nuclear@12 160 }
nuclear@12 161 glEnd();
nuclear@12 162
nuclear@12 163 glPopMatrix();
nuclear@12 164 glPopAttrib();
nuclear@12 165 }
nuclear@12 166
nuclear@12 167 void set_xform(float *matrix, float *invtrans)
nuclear@12 168 {
nuclear@12 169 CLMemBuffer *mbuf_xform = prog->get_arg_buffer(KARG_XFORM);
nuclear@12 170 CLMemBuffer *mbuf_invtrans = prog->get_arg_buffer(KARG_INVTRANS_XFORM);
nuclear@12 171 assert(mbuf_xform && mbuf_invtrans);
nuclear@12 172
nuclear@12 173 float *mem = (float*)map_mem_buffer(mbuf_xform, MAP_WR);
nuclear@12 174 memcpy(mem, matrix, 16 * sizeof *mem);
nuclear@12 175 printf("-- xform:\n");
nuclear@12 176 for(int i=0; i<16; i++) {
nuclear@12 177 printf("%2.3f\t", mem[i]);
nuclear@12 178 if(i % 4 == 3) putchar('\n');
nuclear@12 179 }
nuclear@12 180 unmap_mem_buffer(mbuf_xform);
nuclear@12 181
nuclear@12 182 mem = (float*)map_mem_buffer(mbuf_invtrans, MAP_WR);
nuclear@12 183 memcpy(mem, invtrans, 16 * sizeof *mem);
nuclear@12 184 printf("-- inverse-transpose:\n");
nuclear@12 185 for(int i=0; i<16; i++) {
nuclear@12 186 printf("%2.3f\t", mem[i]);
nuclear@12 187 if(i % 4 == 3) putchar('\n');
nuclear@12 188 }
nuclear@12 189 unmap_mem_buffer(mbuf_invtrans);
nuclear@8 190 }
nuclear@8 191
nuclear@3 192 static Ray get_primary_ray(int x, int y, int w, int h, float vfov_deg)
nuclear@2 193 {
nuclear@2 194 float vfov = M_PI * vfov_deg / 180.0;
nuclear@2 195 float aspect = (float)w / (float)h;
nuclear@2 196
nuclear@2 197 float ysz = 2.0;
nuclear@2 198 float xsz = aspect * ysz;
nuclear@2 199
nuclear@2 200 float px = ((float)x / (float)w) * xsz - xsz / 2.0;
nuclear@2 201 float py = 1.0 - ((float)y / (float)h) * ysz;
nuclear@2 202 float pz = 1.0 / tan(0.5 * vfov);
nuclear@2 203
nuclear@4 204 px *= 100.0;
nuclear@4 205 py *= 100.0;
nuclear@4 206 pz *= 100.0;
nuclear@2 207
nuclear@12 208 Ray ray = {{0, 0, 0, 1}, {px, py, -pz, 1}};
nuclear@2 209 return ray;
nuclear@2 210 }