# HG changeset patch # User John Tsiombikas # Date 1279949297 -3600 # Node ID a09622aaa0439bf5bdd43116d2eccf87aa12b44f # Parent deaf85acf6aff4694ba2b5f4fb5cbf882ab525a0 moving to triangles diff -r deaf85acf6af -r a09622aaa043 rt.cl --- a/rt.cl Fri Jul 23 19:48:43 2010 +0100 +++ b/rt.cl Sat Jul 24 06:28:17 2010 +0100 @@ -1,14 +1,25 @@ struct RendInfo { int xsz, ysz; - int num_sph, num_lights; + int num_faces, num_lights; int max_iter; }; -struct Sphere { +struct Vertex { float4 pos; + float4 normal; + float2 tex; +}; + +struct Face { + struct Vertex v[3]; + float4 normal; + int matid; +}; + +struct Material { float4 kd, ks; - float radius; - float spow, kr, kt; + float kr, kt; + float spow; }; struct Light { @@ -22,22 +33,25 @@ struct SurfPoint { float t; float4 pos, norm; - global const struct Sphere *obj; + global const struct Face *obj; + global const struct Material *mat; }; #define EPSILON 1e-6 float4 shade(struct Ray ray, struct SurfPoint sp, global const struct Light *lights, int num_lights); -bool intersect(struct Ray ray, global const struct Sphere *sph, struct SurfPoint *sp); +bool intersect(struct Ray ray, global const struct Face *face, struct SurfPoint *sp); float4 reflect(float4 v, float4 n); float4 transform(float4 v, global const float *xform); struct Ray transform_ray(global const struct Ray *ray, global const float *xform); +float4 calc_bary(float4 pt, global const struct Face *face); kernel void render(global float4 *fb, global const struct RendInfo *rinf, - global const struct Sphere *sphlist, + global const struct Face *faces, + global const struct Material *matlib, global const struct Light *lights, global const struct Ray *primrays, global const float *xform) @@ -50,13 +64,14 @@ sp0.t = FLT_MAX; sp0.obj = 0; - for(int i=0; inum_sph; i++) { - if(intersect(ray, sphlist + i, &sp) && sp.t < sp0.t) { + for(int i=0; inum_faces; i++) { + if(intersect(ray, faces + i, &sp) && sp.t < sp0.t) { sp0 = sp; } } if(sp0.obj) { + sp0.mat = matlib + sp0.obj->matid; fb[idx] = shade(ray, sp0, lights, rinf->num_lights); } else { fb[idx] = (float4)(0, 0, 0, 0); @@ -75,49 +90,46 @@ float4 vref = reflect(vdir, sp.norm); float diff = fmax(dot(ldir, sp.norm), 0.0f); - float spec = powr(fmax(dot(ldir, vref), 0.0f), sp.obj->spow); + float spec = powr(fmax(dot(ldir, vref), 0.0f), sp.mat->spow); - dcol += sp.obj->kd * diff * lights[i].color; - scol += sp.obj->ks * spec * lights[i].color; + dcol += sp.mat->kd * diff * lights[i].color; + scol += sp.mat->ks * spec * lights[i].color; } return dcol + scol; } bool intersect(struct Ray ray, - global const struct Sphere *sph, + global const struct Face *face, struct SurfPoint *sp) { - float4 dir = ray.dir; - float4 orig = ray.origin; - float4 spos = sph->pos; + float ndotdir = dot(face->normal, ray.dir); + if(fabs(ndotdir) <= EPSILON) { + return false; + } - float a = dot(dir, dir); - float b = 2.0 * dir.x * (orig.x - spos.x) + - 2.0 * dir.y * (orig.y - spos.y) + - 2.0 * dir.z * (orig.z - spos.z); - float c = dot(spos, spos) + dot(orig, orig) + - 2.0 * dot(-spos, orig) - sph->radius * sph->radius; + float4 pt = face->v[0].pos; + float4 vec = pt - ray.origin; - float d = b * b - 4.0 * a * c; - if(d < 0.0) return false; - - float sqrt_d = sqrt(d); - float t1 = (-b + sqrt_d) / (2.0 * a); - float t2 = (-b - sqrt_d) / (2.0 * a); - - if(t1 < EPSILON) t1 = t2; - if(t2 < EPSILON) t2 = t1; - float t = t1 < t2 ? t1 : t2; + float ndotvec = dot(face->normal, vec); + float t = ndotvec / ndotdir; if(t < EPSILON || t > 1.0) { return false; } + pt = ray.origin + ray.dir * t; + + float4 bc = calc_bary(pt, face); + float bc_sum = bc.x + bc.y + bc.z; + + if(bc_sum < -EPSILON || bc_sum > 1.0) { + return false; + } sp->t = t; - sp->pos = orig + dir * sp->t; - sp->norm = (sp->pos - spos) / sph->radius; - sp->obj = sph; + sp->pos = pt; + sp->norm = face->normal; + sp->obj = face; return true; } @@ -151,3 +163,29 @@ res.dir = transform(ray->dir, xform); return res; } + +float4 calc_bary(float4 pt, global const struct Face *face) +{ + float4 bc = {0, 0, 0, 0}; + + float4 vi = face->v[1].pos - face->v[0].pos; + float4 vj = face->v[2].pos - face->v[0].pos; + float area = fabs(dot(cross(vi, vj), face->normal) / 2.0); + if(area < EPSILON) { + return bc; + } + + float4 pv0 = face->v[0].pos - pt; + float4 pv1 = face->v[1].pos - pt; + float4 pv2 = face->v[2].pos - pt; + + // calculate the areas of each sub-triangle + float a0 = fabs(dot(cross(pv1, pv2), face->normal) / 2.0); + float a1 = fabs(dot(cross(pv2, pv0), face->normal) / 2.0); + float a2 = fabs(dot(cross(pv0, pv1), face->normal) / 2.0); + + bc.x = a0 / area; + bc.y = a1 / area; + bc.z = a2 / area; + return bc; +} diff -r deaf85acf6af -r a09622aaa043 src/mesh.h --- a/src/mesh.h Fri Jul 23 19:48:43 2010 +0100 +++ b/src/mesh.h Sat Jul 24 06:28:17 2010 +0100 @@ -4,19 +4,19 @@ #include struct Vertex { - float pos[3]; - float normal[3]; + float pos[4]; + float normal[4]; float tex[2]; }; struct Face { Vertex v[3]; - float normal[3]; + float normal[4]; int matid; }; struct Material { - float kd[3], ks[3]; + float kd[4], ks[4]; float kr, kt; float spow; }; diff -r deaf85acf6af -r a09622aaa043 src/rt.cc --- a/src/rt.cc Fri Jul 23 19:48:43 2010 +0100 +++ b/src/rt.cc Sat Jul 24 06:28:17 2010 +0100 @@ -3,21 +3,14 @@ #include #include #include "ocl.h" +#include "mesh.h" struct RendInfo { int xsz, ysz; - int num_sph, num_lights; + int num_faces, num_lights; int max_iter; } __attribute__((packed)); -struct Sphere { - float pos[4]; - float kd[4], ks[4]; - float radius; - float spow; - float kr, kt; -} __attribute__((packed)); - struct Ray { float origin[4], dir[4]; } __attribute__((packed)); @@ -32,9 +25,28 @@ static CLProgram *prog; static int global_size; -static Sphere sphlist[] = { - {{0, 0, 0, 1}, {0.7, 0.2, 0.15, 1}, {1, 1, 1, 1}, 1.0, 60, 0, 0}, - {{-0.2, 0.4, -3, 1}, {0.2, 0.9, 0.3, 1}, {1, 1, 1, 1}, 0.25, 40, 0, 0} +static Face faces[] = { + {/* face0 */ + { + {{-1, 0, 0, 1}, {0, 0, -1, 1}, {0, 0}}, + {{0, 1, 0, 1}, {0, 0, -1, 1}, {0, 0}}, + {{1, 0, 0, 1}, {0, 0, -1, 1}, {0, 0}} + }, + {0, 0, -1, 1}, 0 + }, + {/* face1 */ + { + {{-5, 0, -3, 1}, {0, 0, -1, 1}, {0, 0}}, + {{0, 0, 3, 1}, {0, 0, -1, 1}, {0, 0}}, + {{5, 0, -3, 1}, {0, 0, -1, 1}, {0, 0}} + }, + {0, 0, -1, 1}, 1 + } +}; + +static Material matlib[] = { + {{1, 0, 0, 1}, {1, 1, 1, 1}, 0, 0, 60.0}, + {{0.2, 0.8, 0.3, 1}, {0, 0, 0, 0}, 0, 0, 0} }; static Light lightlist[] = { @@ -53,7 +65,7 @@ // render info rinf.xsz = xsz; rinf.ysz = ysz; - rinf.num_sph = sizeof sphlist / sizeof *sphlist; + rinf.num_faces = sizeof faces / sizeof *faces; rinf.num_lights = sizeof lightlist / sizeof *lightlist; rinf.max_iter = 6; @@ -75,10 +87,11 @@ /* setup argument buffers */ prog->set_arg_buffer(0, ARG_WR, xsz * ysz * 4 * sizeof(float), fb); prog->set_arg_buffer(1, ARG_RD, sizeof rinf, &rinf); - prog->set_arg_buffer(2, ARG_RD, sizeof sphlist, sphlist); - prog->set_arg_buffer(3, ARG_RD, sizeof lightlist, lightlist); - prog->set_arg_buffer(4, ARG_RD, xsz * ysz * sizeof *prim_rays, prim_rays); - prog->set_arg_buffer(5, ARG_RD, sizeof xform, &xform); + prog->set_arg_buffer(2, ARG_RD, sizeof faces, faces); + prog->set_arg_buffer(3, ARG_RD, sizeof matlib, matlib); + prog->set_arg_buffer(4, ARG_RD, sizeof lightlist, lightlist); + prog->set_arg_buffer(5, ARG_RD, xsz * ysz * sizeof *prim_rays, prim_rays); + prog->set_arg_buffer(6, ARG_RD, sizeof xform, &xform); global_size = xsz * ysz; return true; @@ -98,16 +111,13 @@ CLMemBuffer *mbuf = prog->get_arg_buffer(0); map_mem_buffer(mbuf, MAP_RD); - /*if(!write_ppm("out.ppm", fb, xsz, ysz)) { - return 1; - }*/ unmap_mem_buffer(mbuf); return true; } void set_xform(float *matrix) { - CLMemBuffer *mbuf = prog->get_arg_buffer(5); + CLMemBuffer *mbuf = prog->get_arg_buffer(6); assert(mbuf); assert(map_mem_buffer(mbuf, MAP_WR) == xform);