clray
diff rt.cl @ 9:a09622aaa043
moving to triangles
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 24 Jul 2010 06:28:17 +0100 |
parents | deaf85acf6af |
children | 85fd61f374d9 |
line diff
1.1 --- a/rt.cl Fri Jul 23 19:48:43 2010 +0100 1.2 +++ b/rt.cl Sat Jul 24 06:28:17 2010 +0100 1.3 @@ -1,14 +1,25 @@ 1.4 struct RendInfo { 1.5 int xsz, ysz; 1.6 - int num_sph, num_lights; 1.7 + int num_faces, num_lights; 1.8 int max_iter; 1.9 }; 1.10 1.11 -struct Sphere { 1.12 +struct Vertex { 1.13 float4 pos; 1.14 + float4 normal; 1.15 + float2 tex; 1.16 +}; 1.17 + 1.18 +struct Face { 1.19 + struct Vertex v[3]; 1.20 + float4 normal; 1.21 + int matid; 1.22 +}; 1.23 + 1.24 +struct Material { 1.25 float4 kd, ks; 1.26 - float radius; 1.27 - float spow, kr, kt; 1.28 + float kr, kt; 1.29 + float spow; 1.30 }; 1.31 1.32 struct Light { 1.33 @@ -22,22 +33,25 @@ 1.34 struct SurfPoint { 1.35 float t; 1.36 float4 pos, norm; 1.37 - global const struct Sphere *obj; 1.38 + global const struct Face *obj; 1.39 + global const struct Material *mat; 1.40 }; 1.41 1.42 #define EPSILON 1e-6 1.43 1.44 float4 shade(struct Ray ray, struct SurfPoint sp, 1.45 global const struct Light *lights, int num_lights); 1.46 -bool intersect(struct Ray ray, global const struct Sphere *sph, struct SurfPoint *sp); 1.47 +bool intersect(struct Ray ray, global const struct Face *face, struct SurfPoint *sp); 1.48 float4 reflect(float4 v, float4 n); 1.49 float4 transform(float4 v, global const float *xform); 1.50 struct Ray transform_ray(global const struct Ray *ray, global const float *xform); 1.51 +float4 calc_bary(float4 pt, global const struct Face *face); 1.52 1.53 1.54 kernel void render(global float4 *fb, 1.55 global const struct RendInfo *rinf, 1.56 - global const struct Sphere *sphlist, 1.57 + global const struct Face *faces, 1.58 + global const struct Material *matlib, 1.59 global const struct Light *lights, 1.60 global const struct Ray *primrays, 1.61 global const float *xform) 1.62 @@ -50,13 +64,14 @@ 1.63 sp0.t = FLT_MAX; 1.64 sp0.obj = 0; 1.65 1.66 - for(int i=0; i<rinf->num_sph; i++) { 1.67 - if(intersect(ray, sphlist + i, &sp) && sp.t < sp0.t) { 1.68 + for(int i=0; i<rinf->num_faces; i++) { 1.69 + if(intersect(ray, faces + i, &sp) && sp.t < sp0.t) { 1.70 sp0 = sp; 1.71 } 1.72 } 1.73 1.74 if(sp0.obj) { 1.75 + sp0.mat = matlib + sp0.obj->matid; 1.76 fb[idx] = shade(ray, sp0, lights, rinf->num_lights); 1.77 } else { 1.78 fb[idx] = (float4)(0, 0, 0, 0); 1.79 @@ -75,49 +90,46 @@ 1.80 float4 vref = reflect(vdir, sp.norm); 1.81 1.82 float diff = fmax(dot(ldir, sp.norm), 0.0f); 1.83 - float spec = powr(fmax(dot(ldir, vref), 0.0f), sp.obj->spow); 1.84 + float spec = powr(fmax(dot(ldir, vref), 0.0f), sp.mat->spow); 1.85 1.86 - dcol += sp.obj->kd * diff * lights[i].color; 1.87 - scol += sp.obj->ks * spec * lights[i].color; 1.88 + dcol += sp.mat->kd * diff * lights[i].color; 1.89 + scol += sp.mat->ks * spec * lights[i].color; 1.90 } 1.91 1.92 return dcol + scol; 1.93 } 1.94 1.95 bool intersect(struct Ray ray, 1.96 - global const struct Sphere *sph, 1.97 + global const struct Face *face, 1.98 struct SurfPoint *sp) 1.99 { 1.100 - float4 dir = ray.dir; 1.101 - float4 orig = ray.origin; 1.102 - float4 spos = sph->pos; 1.103 + float ndotdir = dot(face->normal, ray.dir); 1.104 + if(fabs(ndotdir) <= EPSILON) { 1.105 + return false; 1.106 + } 1.107 1.108 - float a = dot(dir, dir); 1.109 - float b = 2.0 * dir.x * (orig.x - spos.x) + 1.110 - 2.0 * dir.y * (orig.y - spos.y) + 1.111 - 2.0 * dir.z * (orig.z - spos.z); 1.112 - float c = dot(spos, spos) + dot(orig, orig) + 1.113 - 2.0 * dot(-spos, orig) - sph->radius * sph->radius; 1.114 + float4 pt = face->v[0].pos; 1.115 + float4 vec = pt - ray.origin; 1.116 1.117 - float d = b * b - 4.0 * a * c; 1.118 - if(d < 0.0) return false; 1.119 - 1.120 - float sqrt_d = sqrt(d); 1.121 - float t1 = (-b + sqrt_d) / (2.0 * a); 1.122 - float t2 = (-b - sqrt_d) / (2.0 * a); 1.123 - 1.124 - if(t1 < EPSILON) t1 = t2; 1.125 - if(t2 < EPSILON) t2 = t1; 1.126 - float t = t1 < t2 ? t1 : t2; 1.127 + float ndotvec = dot(face->normal, vec); 1.128 + float t = ndotvec / ndotdir; 1.129 1.130 if(t < EPSILON || t > 1.0) { 1.131 return false; 1.132 } 1.133 + pt = ray.origin + ray.dir * t; 1.134 + 1.135 + float4 bc = calc_bary(pt, face); 1.136 + float bc_sum = bc.x + bc.y + bc.z; 1.137 + 1.138 + if(bc_sum < -EPSILON || bc_sum > 1.0) { 1.139 + return false; 1.140 + } 1.141 1.142 sp->t = t; 1.143 - sp->pos = orig + dir * sp->t; 1.144 - sp->norm = (sp->pos - spos) / sph->radius; 1.145 - sp->obj = sph; 1.146 + sp->pos = pt; 1.147 + sp->norm = face->normal; 1.148 + sp->obj = face; 1.149 return true; 1.150 } 1.151 1.152 @@ -151,3 +163,29 @@ 1.153 res.dir = transform(ray->dir, xform); 1.154 return res; 1.155 } 1.156 + 1.157 +float4 calc_bary(float4 pt, global const struct Face *face) 1.158 +{ 1.159 + float4 bc = {0, 0, 0, 0}; 1.160 + 1.161 + float4 vi = face->v[1].pos - face->v[0].pos; 1.162 + float4 vj = face->v[2].pos - face->v[0].pos; 1.163 + float area = fabs(dot(cross(vi, vj), face->normal) / 2.0); 1.164 + if(area < EPSILON) { 1.165 + return bc; 1.166 + } 1.167 + 1.168 + float4 pv0 = face->v[0].pos - pt; 1.169 + float4 pv1 = face->v[1].pos - pt; 1.170 + float4 pv2 = face->v[2].pos - pt; 1.171 + 1.172 + // calculate the areas of each sub-triangle 1.173 + float a0 = fabs(dot(cross(pv1, pv2), face->normal) / 2.0); 1.174 + float a1 = fabs(dot(cross(pv2, pv0), face->normal) / 2.0); 1.175 + float a2 = fabs(dot(cross(pv0, pv1), face->normal) / 2.0); 1.176 + 1.177 + bc.x = a0 / area; 1.178 + bc.y = a1 / area; 1.179 + bc.z = a2 / area; 1.180 + return bc; 1.181 +}