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 +}