Scene* mkScene() { Scene* self = Scene_new(); Scene_addLight (self, Sphere_new(Vec3_new(-20, 10, 60), 0.4f, Material_new(255, 255, 255, 0, 0, 0, 0, 0))); Scene_addLight (self, Sphere_new(Vec3_new(30, 15, 100), 0.4f, Material_new(255, 255, 255, 0, 0, 0, 0, 0))); Scene_addSphere(self, Sphere_new(Vec3_new(5, -5, 75), 10, Material_new(180, 100, 30, 0.2, 0.4, 0.7, 0.5, 1.04f))); Scene_addSphere(self, Sphere_new(Vec3_new(-10, -10, 40), 3, Material_new(0, 100, 200, 0.5, 0, 0, 0.9, 1.03f))); Scene_addSphere(self, Sphere_new(Vec3_new(-15, 0, 75), 6, Material_new(250, 250, 250, 0.3, 0.5, 0.8, 0, 0))); Scene_addSphere(self, Sphere_new(Vec3_new(-7, -55, 80), 40, Material_new(0, 100, 100, 0.9, 0.2, 0, 0, 0))); Scene_addSphere(self, Sphere_new(Vec3_new(0, 100, 500), 200, Material_new(250, 250, 250, 0, 0.5, 0.9, 0, 0))); for (int j = 0; j < 4; j++) { float y = -35 + j*20; for (int i = 0; i < 7; i++) { float x = -55 + i*20; Scene_addSphere(self, Sphere_new(Vec3_new(x, y, 200), 8, Material_new(250, 50, 50, 0.9f, 0, 0, 0, 0))); } } return self; }
// Main rendering function. We compute a camera ray for each pixel of the image // trace it and return a color. If the ray hits a sphere, we return the color of the // sphere at the intersection point, else we return the background color. void render(const unsigned size, const Sphere *spheres) { // unsigned width = 640, height = 480; unsigned width = 1024, height = 768; Vec3 *image, *pixel, aux, raydir; Real invWidth = 1 / (Real)width, invHeight = 1 / (Real)height; Real fov = 30, aspectratio = width / (Real)height; Real xx, yy, angle = tan(M_PI * 0.5 * fov / 180.0); unsigned x, y, i; FILE *F; image = malloc(width * height * sizeof(*image)); pixel = image; Vec3_new0(&aux); // Trace rays for (y = 0; y < height; ++y) { for (x = 0; x < width; ++x, ++pixel) { xx = (2 * ((x + 0.5) * invWidth) - 1) * angle * aspectratio; yy = (1 - 2 * ((y + 0.5) * invHeight)) * angle; Vec3_new(&raydir, xx, yy, -1); Vec3_normalize(&raydir); trace(pixel, &aux, &raydir, size, spheres, 0); } } // Save result to a PPM image (keep these flags if you compile under Windows) F = fopen("./untitled.ppm", "wb"); fprintf(F, "P6\n%u %u\n255\n", width, height); for (i = 0; i < width * height; ++i) { fprintf(F, "%c%c%c", (unsigned char)(min(1.0, image[i].x) * 255), (unsigned char)(min(1.0, image[i].y) * 255), (unsigned char)(min(1.0, image[i].z) * 255)); } fclose(F); free(image); }
int main(int argc, char** argv) { SDL_Init(SDL_INIT_VIDEO); SDL_Surface *screen = SDL_SetVideoMode(WIDTH, HEIGHT, DEPTH, SDL_HWSURFACE); SDL_Event event; Screen rscreen = { .width = WIDTH, .height = HEIGHT, .pitch = WIDTH*BPP }; Twister* twister = Twister_new(time(NULL)); Scene *scene = mkScene(); Sphere *moving = Sphere_new(Vec3_new(0, 5, 50), 5.0f, Material_new(100, 180, 100, 0.6, 0.7, 0, 0.5, 1.05f)); Scene_addSphere(scene, moving); while(1) { while(SDL_PollEvent(&event)) { switch(event.type) { case SDL_QUIT: case SDL_KEYDOWN: goto quit; } } SDL_LockSurface(screen); rscreen.pixels = screen->pixels; Screen_render3D(&rscreen, scene); SDL_UnlockSurface(screen); SDL_Flip(screen); moving->center.x += Twister_float(twister) - 0.5; moving->center.y += Twister_float(twister) - 0.5; moving->center.z += Twister_float(twister) - 0.5; } quit: SDL_Quit(); }
Vec3 *Vec3_create(float x, float y, float z) { return Vec3_setValues(Vec3_new(), x, y, z); }
int main(int argc, char **argv) { double timeA, timeB; Sphere *spheres; Vec3 p,c,e; int n; timeA = omp_get_wtime(); n = argc>1 ? atoi(argv[1]) : N; if(n<N)n=100; spheres = malloc(n*sizeof(*spheres)); // position, radius, surface color, reflectivity, transparency, emission color Vec3_new(&p, 0, -10004, -20); Vec3_new1(&c, 0.2); Sphere_new0(&spheres[0], &p, 10000, &c, 0, 0.0); Vec3_new(&p, 0, 0, -20); Vec3_new(&c, 1.00, 0.32, 0.36); Sphere_new0(&spheres[1], &p, 4, &c, 1, 0.5); Vec3_new(&p, 5, -1, -15); Vec3_new(&c, 0.90, 0.76, 0.46); Sphere_new0(&spheres[2], &p, 2, &c, 1, 0.0); Vec3_new(&p, 5, 0, -25); Vec3_new(&c, 0.65, 0.77, 0.97); Sphere_new0(&spheres[3], &p, 3, &c, 1, 0.0); Vec3_new(&p, -5.5, 0, -15); Vec3_new(&c, 0.90, 0.90, 0.90); Sphere_new0(&spheres[4], &p, 3, &c, 1, 0.0); // light Vec3_new(&p, 0, 20, -30); Vec3_new0(&c); Vec3_new1(&e, 3); Sphere_new(&spheres[5], &p, 3, &c, 0, 0, &e); if(n>N){ int i,j,k; Real r,d; Vec3 v; srand48(13); for(i=N;i<n;i++){ k=0; do{ Vec3_new(&p, 12*drand48()-6,9*drand48()-4,-35*drand48()-15); r = 0.1 + drand48(); for(j=0;j<i && r>=0.1;j++){ Vec3_subs(&v,&spheres[j].center,&p); d=Vec3_length(&v)-spheres[j].radius; if(d<r)r=d; } }while(r<0.1 && ++k<1000); if(r>=0.1){ Vec3_new(&c, rand()%4/3.0,rand()%4/3.0,rand()%4/3.0); Sphere_new0(&spheres[i], &p, r, &c, drand48()<0.8?0:1, drand48()<0.8?0:0.8); }else printf("#"); } } if(argc>2){spheres[1].radius=0.4; spheres[1].radius2=0.16;} printf("Calculando...\n"); fflush(stdout); render(n, spheres); timeB = omp_get_wtime(); double timeC = timeB - timeA; printf("Se ha calculado en %f segundos\n",timeC); free(spheres); return 0; }