src/raytracer.cc
branchpyrit
changeset 22 76b7bd51d64a
parent 21 79b516a3803d
child 25 b8232edee786
equal deleted inserted replaced
21:79b516a3803d 22:76b7bd51d64a
    13 #include <malloc.h>
    13 #include <malloc.h>
    14 #include "raytracer.h"
    14 #include "raytracer.h"
    15 
    15 
    16 // Hammersley spherical point distribution
    16 // Hammersley spherical point distribution
    17 // http://www.cse.cuhk.edu.hk/~ttwong/papers/udpoint/udpoints.html
    17 // http://www.cse.cuhk.edu.hk/~ttwong/papers/udpoint/udpoints.html
    18 Vector3 Raytracer::SphereDistribute(int i, int n, float extent, Vector3 &normal)
    18 Vector3 Raytracer::SphereDistribute(int i, int n, Float extent, Vector3 &normal)
    19 {
    19 {
    20 	float p, t, st, phi, phirad;
    20 	Float p, t, st, phi, phirad;
    21 	int kk;
    21 	int kk;
    22 
    22 
    23 	t = 0;
    23 	t = 0;
    24 	for (p=0.5, kk=i; kk; p*=0.5, kk>>=1)
    24 	for (p=0.5, kk=i; kk; p*=0.5, kk>>=1)
    25 	if (kk & 1)
    25 	if (kk & 1)
    29 	phi = (i + 0.5) / n;
    29 	phi = (i + 0.5) / n;
    30 	phirad =  phi * 2.0 * M_PI;
    30 	phirad =  phi * 2.0 * M_PI;
    31 
    31 
    32 	st = sqrt(1.0 - t*t);
    32 	st = sqrt(1.0 - t*t);
    33 
    33 
    34 	float x, y, z, xx, yy, zz, q;
    34 	Float x, y, z, xx, yy, zz, q;
    35 	x = st * cos(phirad);
    35 	x = st * cos(phirad);
    36 	y = st * sin(phirad);
    36 	y = st * sin(phirad);
    37 	z = t;
    37 	z = t;
    38 
    38 
    39 	// rotate against Y axis
    39 	// rotate against Y axis
    73 	Light &light)
    73 	Light &light)
    74 {
    74 {
    75 	Colour I = Colour();
    75 	Colour I = Colour();
    76 	Vector3 L = light.pos - P;
    76 	Vector3 L = light.pos - P;
    77 	L.normalize();
    77 	L.normalize();
    78 	float L_dot_N = dot(L, N);
    78 	Float L_dot_N = dot(L, N);
    79 	float R_dot_V = dot(R, V);
    79 	Float R_dot_V = dot(R, V);
    80 
    80 
    81 	Colour col = mat.texture.colour; //mat.texture.evaluate(P);
    81 	Colour col = mat.texture.colour; //mat.texture.evaluate(P);
    82 
    82 
    83 	// diffuse
    83 	// diffuse
    84 	I = mat.diffuse * col * light.colour * L_dot_N;
    84 	I = mat.diffuse * col * light.colour * L_dot_N;
    89 	return I;
    89 	return I;
    90 }
    90 }
    91 
    91 
    92 Colour Raytracer::raytrace(Ray &ray, int depth, Shape *origin_shape)
    92 Colour Raytracer::raytrace(Ray &ray, int depth, Shape *origin_shape)
    93 {
    93 {
    94 	float nearest_distance = FLT_MAX; //Infinity
    94 	Float nearest_distance = Inf;
    95 	Shape *nearest_shape = top->nearest_intersection(origin_shape, ray, nearest_distance);
    95 	Shape *nearest_shape = top->nearest_intersection(origin_shape, ray, nearest_distance);
    96 
    96 
    97 	if (nearest_shape == NULL) {
    97 	if (nearest_shape == NULL) {
    98 		return bg_colour;
    98 		return bg_colour;
    99 	} else {
    99 	} else {
   104 
   104 
   105 		vector<Light*>::iterator light;
   105 		vector<Light*>::iterator light;
   106 		for (light = lights.begin(); light != lights.end(); light++) {
   106 		for (light = lights.begin(); light != lights.end(); light++) {
   107 			Vector3 jo, L = (*light)->pos - P; // direction vector to light
   107 			Vector3 jo, L = (*light)->pos - P; // direction vector to light
   108 			L.normalize();
   108 			L.normalize();
   109 			float L_dot_N = dot(L, normal);
   109 			Float L_dot_N = dot(L, normal);
   110 			if (L_dot_N > 0) {
   110 			if (L_dot_N > 0) {
   111 				// test if this light is occluded (sharp shadows)
   111 				// test if this light is occluded (sharp shadows)
   112 				if ((*light)->cast_shadows) {
   112 				if ((*light)->cast_shadows) {
   113 					Ray shadow_ray = Ray(P, L);
   113 					Ray shadow_ray = Ray(P, L);
   114 					float dist = FLT_MAX;
   114 					Float dist = FLT_MAX;
   115 					if (top->nearest_intersection(nearest_shape, shadow_ray, dist))
   115 					if (top->nearest_intersection(nearest_shape, shadow_ray, dist))
   116 						continue;
   116 						continue;
   117 				}
   117 				}
   118 
   118 
   119 				// shading function
   119 				// shading function
   135 		/* ... */
   135 		/* ... */
   136 
   136 
   137 		// ambient occlusion
   137 		// ambient occlusion
   138 		if (ao_samples)
   138 		if (ao_samples)
   139 		{
   139 		{
   140 			float miss = 0;
   140 			Float miss = 0;
   141 			for (int i = 0; i < ao_samples; i++) {
   141 			for (int i = 0; i < ao_samples; i++) {
   142 				Vector3 dir = SphereDistribute(i, ao_samples, ao_angle, normal);
   142 				Vector3 dir = SphereDistribute(i, ao_samples, ao_angle, normal);
   143 				Ray ao_ray = Ray(P, dir);
   143 				Ray ao_ray = Ray(P, dir);
   144 				float dist = ao_distance;
   144 				Float dist = ao_distance;
   145 				Shape *shape_in_way = top->nearest_intersection(nearest_shape, ao_ray, dist);
   145 				Shape *shape_in_way = top->nearest_intersection(nearest_shape, ao_ray, dist);
   146 				if (shape_in_way == NULL)
   146 				if (shape_in_way == NULL)
   147 					miss += 1.0;
   147 					miss += 1.0;
   148 				else
   148 				else
   149 					miss += dist / ao_distance;
   149 					miss += dist / ao_distance;
   150 			}
   150 			}
   151 			float ao_intensity = miss / ao_samples;
   151 			Float ao_intensity = miss / ao_samples;
   152 			acc = acc * ao_intensity;
   152 			acc = acc * ao_intensity;
   153 		}
   153 		}
   154 
   154 
   155 		return acc;
   155 		return acc;
   156 	}
   156 	}
   158 
   158 
   159 static void *renderrow(void *data)
   159 static void *renderrow(void *data)
   160 {
   160 {
   161 	RenderrowData *d = (RenderrowData*) data;
   161 	RenderrowData *d = (RenderrowData*) data;
   162 	int subsample = d->rt->getSubsample();
   162 	int subsample = d->rt->getSubsample();
   163 	float subsample2 = 1.0/(subsample*subsample);
   163 	Float subsample2 = 1.0/(subsample*subsample);
   164 	int ww = d->w*3;
   164 	int ww = d->w*3;
   165 	Vector3 dir = d->dfix;
   165 	Vector3 dir = d->dfix;
   166 	for (int x = 0; x < d->w; x += subsample) {
   166 	for (int x = 0; x < d->w; x += subsample) {
   167 		// generate a ray from eye passing through this pixel
   167 		// generate a ray from eye passing through this pixel
   168 #if OVERSAMPLING
   168 #if OVERSAMPLING
   169 		// 5x oversampling
   169 		// 5x oversampling
   170 		Colour c = Colour();
   170 		Colour c = Colour();
   171 
   171 
   172 		for (int i = 0; i < 5; i++)
   172 		for (int i = 0; i < 5; i++)
   173 		{
   173 		{
   174 			float osax[] = {0.0, -0.4, +0.4, +0.4, -0.4};
   174 			Float osax[] = {0.0, -0.4, +0.4, +0.4, -0.4};
   175 			float osay[] = {0.0, -0.4, -0.4, +0.4, +0.4};
   175 			Float osay[] = {0.0, -0.4, -0.4, +0.4, +0.4};
   176 			Vector3 tmpdir = dir + osax[i]*d->dx + osay[i]*d->dy;
   176 			Vector3 tmpdir = dir + osax[i]*d->dx + osay[i]*d->dy;
   177 			tmpdir.normalize();
   177 			tmpdir.normalize();
   178 			Ray ray(d->eye, tmpdir);
   178 			Ray ray(d->eye, tmpdir);
   179 			c += d->rt->raytrace(ray, 0, NULL);
   179 			c += d->rt->raytrace(ray, 0, NULL);
   180 		}
   180 		}
   202 			tmpdir = dir + (subsample-1)*d->dy;
   202 			tmpdir = dir + (subsample-1)*d->dy;
   203 			tmpdir.normalize();
   203 			tmpdir.normalize();
   204 			ray.dir = tmpdir;
   204 			ray.dir = tmpdir;
   205 			Colour c3 = d->rt->raytrace(ray, 0, NULL);
   205 			Colour c3 = d->rt->raytrace(ray, 0, NULL);
   206 			// are the colors similar?
   206 			// are the colors similar?
   207 			float m = (c-c2).mag2();
   207 			Float m = (c-c2).mag2();
   208 			m = max(m, (c2-c3).mag2());
   208 			m = max(m, (c2-c3).mag2());
   209 			m = max(m, (c3-c4).mag2());
   209 			m = max(m, (c3-c4).mag2());
   210 			m = max(m, (c4-c).mag2());
   210 			m = max(m, (c4-c).mag2());
   211 			if (m < 0.001)
   211 			if (m < 0.001)
   212 			{
   212 			{
   213 				// interpolate
   213 				// interpolate
   214 				float *i = d->iter;
   214 				Float *i = d->iter;
   215 				for (int x = 0; x < subsample; x++)
   215 				for (int x = 0; x < subsample; x++)
   216 				{
   216 				{
   217 					for (int y = 0; y < subsample; y++)
   217 					for (int y = 0; y < subsample; y++)
   218 					{
   218 					{
   219 						ic = c*(subsample-x)*(subsample-y)*subsample2
   219 						ic = c*(subsample-x)*(subsample-y)*subsample2
   300 	pthread_exit((void *)d);
   300 	pthread_exit((void *)d);
   301 #endif
   301 #endif
   302 	return (void *)d;
   302 	return (void *)d;
   303 }
   303 }
   304 
   304 
   305 void Raytracer::render(int w, int h, float *buffer)
   305 void Raytracer::render(int w, int h, Float *buffer)
   306 {
   306 {
   307 	if (!camera || !top || !buffer)
   307 	if (!camera || !top || !buffer)
   308 		return;
   308 		return;
   309 
   309 
   310 	RenderrowData *d;
   310 	RenderrowData *d;
   311 
   311 
   312 	float S = 0.5/w;
   312 	Float S = 0.5/w;
   313 	Vector3 dfix = camera->u*(-w/2.0*S/camera->f)
   313 	Vector3 dfix = camera->u*(-w/2.0*S/camera->f)
   314 		+ camera->v*(h/2.0*S/camera->f) + camera->p;
   314 		+ camera->v*(h/2.0*S/camera->f) + camera->p;
   315 	Vector3 dx = camera->u * (S/camera->f);
   315 	Vector3 dx = camera->u * (S/camera->f);
   316 	Vector3 dy = camera->v * (-S/camera->f);
   316 	Vector3 dy = camera->v * (-S/camera->f);
   317 
   317 
   370 void Raytracer::addlight(Light *light)
   370 void Raytracer::addlight(Light *light)
   371 {
   371 {
   372 	lights.push_back(light);
   372 	lights.push_back(light);
   373 }
   373 }
   374 
   374 
   375 void Raytracer::ambientocclusion(int samples, float distance, float angle)
   375 void Raytracer::ambientocclusion(int samples, Float distance, Float angle)
   376 {
   376 {
   377 	ao_samples = samples;
   377 	ao_samples = samples;
   378 	ao_distance = distance;
   378 	ao_distance = distance;
   379 	ao_angle = angle;
   379 	ao_angle = angle;
   380 	if (ao_distance == 0)
   380 	if (ao_distance == 0)