src/raytracer.cc
branchpyrit
changeset 4 c73bc405ee7a
parent 0 3547b885df7e
child 5 2d97ea5e711a
equal deleted inserted replaced
3:8f9cb0526c47 4:c73bc405ee7a
     2  * C++ RayTracer
     2  * C++ RayTracer
     3  * file: raytracer.cc
     3  * file: raytracer.cc
     4  *
     4  *
     5  * Radek Brich, 2006
     5  * Radek Brich, 2006
     6  */
     6  */
       
     7 
       
     8 #ifdef PTHREADS
       
     9 #include <pthread.h>
       
    10 #endif
     7 
    11 
     8 #include <stdio.h>
    12 #include <stdio.h>
     9 #include <malloc.h>
    13 #include <malloc.h>
    10 #include <float.h>
    14 #include <float.h>
    11 #include "raytracer.h"
    15 #include "raytracer.h"
   163 
   167 
   164 		return acc;
   168 		return acc;
   165 	}
   169 	}
   166 }
   170 }
   167 
   171 
       
   172 static void *renderrow(void *data)
       
   173 {
       
   174 	RenderrowData *d = (RenderrowData*) data;
       
   175 	for (int x = 0; x < d->w; x++) {
       
   176 		// generate a ray from eye passing through this pixel
       
   177 #if 1
       
   178 		// no oversampling
       
   179 		Vector3 dir = Vector3(d->vx, d->vy, 0) - d->eye;
       
   180 		dir.normalize();
       
   181 		Ray ray(d->eye, dir);
       
   182 		Colour c = d->rt->raytrace(ray, 0, NULL);
       
   183 #else
       
   184 		// 5x oversampling
       
   185 		Vector3 dir = Vector3();
       
   186 		Colour c = Colour();
       
   187 
       
   188 		for (int i = 0; i < 5; i++)
       
   189 		{
       
   190 			float osax[] = {0.0, -0.4, +0.4, +0.4, -0.4};
       
   191 			float osay[] = {0.0, -0.4, -0.4, +0.4, +0.4};
       
   192 			dir = Vector3(d->vx + osax[i] * d->dx,
       
   193 				d->vy + osay[i]*d->dy , 0) - d->eye;
       
   194 			dir.normalize();
       
   195 			Ray ray(d->eye, dir);
       
   196 			c += d->rt->raytrace(ray, 0, NULL);
       
   197 		}
       
   198 		c = c * (1./5);
       
   199 #endif
       
   200 		*(d->iter++) = c.r;
       
   201 		*d->iter++ = c.g;
       
   202 		*d->iter++ = c.b;
       
   203 		d->vx += d->dx;
       
   204 	}
       
   205 #ifdef PTHREADS
       
   206 	pthread_exit((void *)d);
       
   207 #endif
       
   208 }
       
   209 
   168 float *Raytracer::render(int w, int h)
   210 float *Raytracer::render(int w, int h)
   169 {
   211 {
   170 	int x, y;
   212 	float *data;
   171 	float *data, *iter;
       
   172 
   213 
   173 	data = (float *) malloc(w*h*3*sizeof(float));
   214 	data = (float *) malloc(w*h*3*sizeof(float));
   174 	if (!data)
   215 	if (!data)
   175 		return NULL;
   216 		return NULL;
   176 
   217 
   177 	float startx = -1.0 * 4, starty = (float)h/w * 4;
   218 	float startx = -1.0 * 4, starty = (float)h/w * 4;
   178 	float dx = -2*startx/w, dy = -2*starty/h;
   219 	float dx = -2*startx/w, dy = -2*starty/h;
   179 	float vx, vy;
   220 	float vy;
       
   221 	RenderrowData *d;
   180 
   222 
   181 	//srand(time(NULL));
   223 	//srand(time(NULL));
   182 
   224 
   183 	// eye - viewing point
   225 	// eye - viewing point
   184 	Vector3 eye(0, 0, -5);
   226 	Vector3 eye(0, 0, -5);
   185 
   227 
   186 	// for each pixel...
   228 	// for each pixel...
   187 	iter = data;
   229 	vy = starty;
   188 	for (vy = starty, y = 0; y < h; y++) {
   230 
   189 		vx = startx;
   231 #ifdef PTHREADS
   190 		for (x = 0; x < w; x++) {
   232 	int num_threads = 20;
   191 			// generate a ray from eye passing through this pixel
   233 	printf("* pthreads enabled, using %d threads\n", num_threads);
   192 #if 1
   234 	pthread_t threads[num_threads];
   193 			// no oversampling
   235 	for (int t = 0; t < num_threads; t++)
   194 			Vector3 dir = Vector3(vx, vy, 0) - eye;
   236 		threads[t] = NULL;
   195 			dir.normalize();
   237 	int t = 0;
   196 			Ray ray(eye, dir);
   238 #endif
   197 			Colour c = raytrace(ray, 0, NULL);
   239 
       
   240 	printf("* rendering row   0 (  0% done)");
       
   241 	for (int y = 0; y < h; y++) {
       
   242 		d = (RenderrowData*) malloc(sizeof(RenderrowData));
       
   243 		d->rt = this;
       
   244 		d->w = w;
       
   245 		d->vx = startx;
       
   246 		d->vy = vy;
       
   247 		d->dx = dx;
       
   248 		d->dy = dy;
       
   249 		d->eye = eye;
       
   250 		d->iter = data + y*3*w;
       
   251 #ifdef PTHREADS
       
   252 		/* create new thread and increase 't' */
       
   253 		int rc = pthread_create(&threads[t++], NULL, renderrow, (void *)d);
       
   254 		if (rc) {
       
   255 			printf("\nERROR: return code from pthread_create() is %d\n", rc);
       
   256 			exit(1);
       
   257 		}
       
   258 		/* when 't' owerflows, reset it */
       
   259 		if (t >= num_threads)
       
   260 			t = 0;
       
   261 		/* wait for next thread in fifo queue, so the descriptor can be reused;
       
   262 		   this also limits number of running threads */
       
   263 		if (threads[t] != NULL)
       
   264 			if (pthread_join(threads[t], (void**)&d) == 0)
       
   265 				free(d);
   198 #else
   266 #else
   199 			// 5x oversampling
   267 		renderrow((void *)d);
   200 			Vector3 dir = Vector3();
   268 		free(d);
   201 			Colour c = Colour();
   269 #endif
   202 
       
   203 			for (int i = 0; i < 5; i++)
       
   204 			{
       
   205 				float osax[] = {0.0, -0.4, +0.4, +0.4, -0.4};
       
   206 				float osay[] = {0.0, -0.4, -0.4, +0.4, +0.4};
       
   207 				dir = Vector3(vx + osax[i]*dx,
       
   208 					vy + osay[i]*dy , 0) - eye;
       
   209 				dir.normalize();
       
   210 				Ray ray(eye, dir);
       
   211 				c += raytrace(ray, 0, NULL);
       
   212 			}
       
   213 			c = c * (1./5);
       
   214 #endif
       
   215 			*iter++ = c.r;
       
   216 			*iter++ = c.g;
       
   217 			*iter++ = c.b;
       
   218 			vx += dx;
       
   219 		}
       
   220 		vy += dy;
   270 		vy += dy;
   221 		printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b%2d%% done (row %4d)", y*100/(h-1), y);
   271 		printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b%4d (%2d%% done)", y, y*100/(h-1));
   222 	}
   272 	}
   223 	printf("\n");
   273 	printf("\n");
       
   274 
       
   275 #ifdef PTHREADS
       
   276 	printf("* waiting for threads to finish\n");
       
   277 	for (t = 0; t < num_threads; t++)
       
   278 		if (pthread_join(threads[t], (void**)&d) == 0)
       
   279 			free(d);
       
   280 #endif
       
   281 
   224 	return data;
   282 	return data;
   225 }
   283 }
   226 
   284 
   227 void Raytracer::addshape(Shape *shape)
   285 void Raytracer::addshape(Shape *shape)
   228 {
   286 {