static inline t_color recursive_tracer(t_params p, t_ray *ray, t_objects *sp) { t_f64 inside; t_f64 facingratio; t_f64 fresneleffect; t_vec3f refldir; t_vec3f refdir; t_color reflection; t_color refrac; t_ray rx; if ((inside = dot_vec3f(&ray->dir, &p.nhit) > 0)) p.nhit = scale_vec3f(&p.nhit, -1); facingratio = -dot_vec3f(&ray->dir, &p.nhit); fresneleffect = mix(pow(1 - facingratio, 3), 1, .1); refldir = get_reflection_dir(&p.nhit, &ray->dir); rx = reflected_ray(ray, &refldir, &p.nhit, &p.phit); reflection = trace_ray(&rx, sp, ++p.depth); if (p.sphere->transparency > 0) { refdir = compute_ideal_refractions(ray, inside, p); rx = refracted_ray(ray, &refdir, &p.nhit, &p.phit); refrac = trace_ray(&rx, sp, ++p.depth); } return (defualt_glossy_shading(&reflection, &refrac, fresneleffect, p.sphere)); }
/******* Fonction à écrire par les etudiants ******/ Color trace_ray (Ray ray_) { /** * \todo : recursive raytracing * * La fonction trace_ray() renvoie une couleur obtenue par la somme de l'éclairage direct (couleur calculée par la fonction * compute_direct_lighting()) et des couleurs provenant des reflets et transparences éventuels aux points d'intersection. * Dans la première partie du TP, seul l'éclairage direct sera calculé. Dans la seconde partie, les reflets et transparences seront rajoutés. * * Pour la première étape, la fonction trace_ray() ne calculant que les rayons primaires, l'intersection * entre le rayon et la scène doit être calculée (fonction intersect_scene() du module \ref RayAPI). * S'il n'y a pas d'intersection, une couleur blanche (triplet RGB [1, 1, 1], élément neutre de la multiplication des couleurs) * devra être retournée. * S'il y a une intersection, la couleur retournée sera la couleur résultante de l'éclairage direct du point d'intersection par les * sources lumineuses de la scène et calculée par la fonction compute_direct_lighting() à écrire dans la suite. * * Pour la deuxième étape, à partir des fonctions définies dans le module \ref RayAPI et permettant d'accéder aux informations de * profondeur et d'importance sur le rayon, définir un cas d'arêt dela récursivité et renvoyer si ce cas est vérifié la couleur * résultante de l'éclairage direct. Si la récursivité n'est pas terminée, en utilisant les fonctions définies dans le module \ref LightAPI, * calculer la couleur réfléchie. Pour cela, il faut tester si le matériau est réflechissant et, si c'est le cas, calculer le rayon * réfléchi et le coefficient de réflexion (une couleur). La couleur calculée en lançant le rayon réfléchi devra alors être multipliée par ce coefficient avant d'être ajoutée * à la couleur renvoyée par trace_ray(). * * Pour la troisème étape et de façon très similaire à la réflexion, utiliser les fonctions définies dans le module \ref LightAPI pour calculer la couleur réfractée. * Pour cela, il faut tester si le matériau est transparent et, si c'est le cas, calculer le rayon réfracté et le coefficient de * transparence (une couleur). La couleur calculée en lançant le rayon réfracté devra alors être multipliée par ce coefficient avant * d'être ajoutée à la couleur renvoyée par trace_ray(). * */ Color l = init_color (0.075f, 0.075f, 0.075f); Isect isect_; int isInter = intersect_scene (&ray_, &isect_ ); if (isInter!=0){ l = compute_direct_lighting (ray_, isect_); } if (ray_depth(ray_)>10 || ray_importance(ray_)<0.01f) return (l); //reflection if(isect_has_reflection(isect_)){ Ray refl_ray; Color refl_col = reflect(ray_, isect_, &refl_ray); l = l+refl_col*(trace_ray(refl_ray)); } //refraction if(isect_has_refraction(isect_)){ Ray rafr_ray; Color rafr_col = refract(ray_, isect_, &rafr_ray); if(color_is_black(rafr_col)==0) l = l+rafr_col*(trace_ray(rafr_ray)); } return l; }
/* * Trace a ray, calculating the color of this ray. * This function is called recursively for recursive light. * * @param scene The scene object, which contains all geometries information. * @param recursion The level of recursive light. If the level is larger or * equal to 4, stop recursion. * @param ray_dir Direction vector of ray. * @param ray_pos Start point of ray. * @param tMin Minimum legal time cost for this ray. * @param tMax Maximum legal time cost for this ray. * * @return The color of this ray. */ Color3 Raytracer::trace_ray(Scene const*scene, // geometries const int recursion, // recursion level const Vector3 &ray_dir, const Vector3 &ray_pos, // ray const float tMin, const float tMax // ray range ) { // if this function go beyond the last recursive level, stop and return black color. if (recursion <= 0) return Color3(0, 0, 0); // intersection point information HitVertexInfor hit_vertex; // if not hit any geometry, return background color bool bHit = ray_hit(scene, ray_dir, ray_pos, tMin, tMax, hit_vertex); if (!bHit) return scene->background_color; // if hit, compute color and return it Color3 DI_light (0, 0, 0); Color3 reflected_light(0, 0, 0); Color3 refracted_light(0, 0, 0); // 1. direct illumination if (hit_vertex.refractive_index == 0) DI_light = calculate_DI_light(scene, hit_vertex); // 2. reflection light if (hit_vertex.specular != Color3(0, 0, 0)) // avoid non-necessary reflection calculation { // reflection ray direction Vector3 rfl_ray_dir = normalize( ray_dir - 2 * dot(ray_dir, hit_vertex.normal) * hit_vertex.normal); reflected_light = hit_vertex.specular * hit_vertex.tex_color * trace_ray(scene, recursion-1, rfl_ray_dir, hit_vertex.position, SLOPE_FACTOR, 1000000); } if (hit_vertex.refractive_index == 0) // avoid non-necessary refraction calculation return DI_light + reflected_light; // 3. refraction light Vector3 rfr_ray_dir; // refractive ray direction float R; if (refraction_happened(scene, ray_dir, hit_vertex, rfr_ray_dir, R)) refracted_light = hit_vertex.tex_color * trace_ray(scene, recursion-1, rfr_ray_dir, hit_vertex.position, SLOPE_FACTOR, 1000000); return DI_light + R * reflected_light + (1-R) * refracted_light; }
/******* Fonction à écrire par les etudiants ******/ void compute_image () { /** * \todo : main rendering loop * * Le calcul d'une image de synthèse consiste à calculer une couleur pour tous les pixels d'une image en fonction * d'une modélisation d'un capteur virtuel. * Ce capteur est ici représenté par une Camera qui permet, à partir des coordonnées (x,y) d'un pixel d'une image, * de créer le rayon passant par ce pixel. La manière dont est créé ce rayon dépend de la Camera. * La scène étant crée avec une caméra par défaut de type \b pinhole, la fonction camera_ray() * devra être utilisée afin de créer le rayon primaire. * Ce rayon est ensuite tracé dans la scène (par la fonction trace_ray()) * et la couleur calculée à l'aide de ce rayon doit être stockée sur le pixel (x,y). */ int i,j, img_height, img_width; Ray ray_; Color col_; get_image_resolution(&img_width, &img_height); for(i=0; i<img_width; i++){ for(j=0; j<img_height; j++){ ray_ = camera_ray(i,j); col_ = trace_ray (ray_); set_pixel_color (i, j, col_); } } }
//------------------------------------------------------------------ render_scene // This is the main ray tracing loop over pixels!! Start here. void RenderEngine::render_scene() { Camera *camera = world_ptr->camera_ptr; RGBColor pixel_color; // PART 1: for (int row=0; row < camera->xres; row++){ for (int col=0; col< camera->yres; col++){ Ray curRay = camera->pixRay(row, col); pixel_color = trace_ray(curRay, world_ptr->depth); int index = col * 3 * camera->xres + row*3 ; camera->image[index] = pixel_color.r; camera->image[index+1] = pixel_color.g; camera->image[index+2] = pixel_color.b; } } // Loop over rows and columns of images (pixels) // Compute the ray from camera to the given pixel (see function in Camera class) // trace the ray to get pixel_color (i.e. call trace_ray) // (Do you remember which class stores the depth? If not, find out.) // make sure color is in range (1,0) - see max_to_one() function // set image pixel to this color as follows: //int index = row * 3 * camera->xres + col*3 ; //camera->image[index] = pixel_color.r; //camera->image[index+1] = pixel_color.g; //camera->image[index+2] = pixel_color.b; }
int ray_trace(char* filename) { ray3_t primary_ray; int frame_z = 300; int frame_x = 0; int frame_y = 0; color_t hicolor; for (frame_x = 0; frame_x < frame_width; ++frame_x) { for (frame_y = 0; frame_y < frame_height; ++frame_y) { /* Primary Ray (test ray) */ primary_ray.origin = eye_origin; primary_ray.vector.x = (frame_x - (frame_width/2) - primary_ray.origin.x); primary_ray.vector.y = (frame_y - (frame_height/2) - primary_ray.origin.y); primary_ray.vector.z = (frame_z - primary_ray.origin.z); normalize_vector(&primary_ray.vector); hicolor = trace_ray(&primary_ray, 0); frame_buffer[frame_y][frame_x].r = (uint8_t) (hicolor.r * 0xFF); frame_buffer[frame_y][frame_x].g = (uint8_t) (hicolor.g * 0xFF); frame_buffer[frame_y][frame_x].b = (uint8_t) (hicolor.b * 0xFF); frame_buffer[frame_y][frame_x].a = (uint8_t) (hicolor.a * 0xFF); } } write_bmp(filename, frame_width, frame_height, frame_buffer); return 0; }
bool trace_ray(const Ray& ray, const std::list<Sphere>& world, Color* color) { for (const Sphere& sphere: world) { if (trace_ray(ray, world, sphere, color)) { return true; } } return false; }
int main() { std::list<Sphere> world = { // front to back { { 1, 1, 1 }, .3 }, { { -1, .5, 2 }, .4 }, { { 0, 0, 0 }, 1 }, }; Ray ray; ray.direction = Vec3 { 0, 0, -1 }; const float zoom = 2; const int width = 1920, height = 1080, oversampling = 4; const Color background { 0, 0, 0 }; std::cout << "P3" << std::endl << width << ' ' << height << ' ' << 255 << std::endl; for (float y = 0; y < height; ++y) { std::cerr << '\r' << int(y * 100 / height) << " %"; for (float x = 0; x < width; ++x) { Color color = background; for (int sy = 0; sy < oversampling; ++sy) { for (int sx = 0; sx < oversampling; ++sx) { ray.origin = Vec3 { zoom * ((x * oversampling + sx) / (width * oversampling) * 2 - 1), zoom * height / width * -((y * oversampling + sy) / (height * oversampling) * 2 - 1), 10 }; Color sample = background; trace_ray(ray, world, &sample); color.r += sample.r / (oversampling * oversampling); color.g += sample.g / (oversampling * oversampling); color.b += sample.b / (oversampling * oversampling); } } std::cout << (int)color.r << ' ' << (int)color.g << ' ' << (int)color.b << ' '; } std::cout << std::endl; } }
void cast_ray(int x, int y, t_vec3f *pixel, t_interface *env) { t_vec3f dir; t_ray ray; t_f64 xx; t_f64 yy; xx = (2 * ((x + 0.5) * (1.0 / WIDTH)) - 1) * env->camera.angle * ARATIO; yy = (1 - 2 * ((y + 0.5) * (1.0 / HEIGHT))) * env->camera.angle; dir = new_vec3f(xx, yy, 0); dir = add_vec3f(&dir, &env->camera.up); ray = new_ray(env->camera.pos, normal_vec3f(&dir)); *pixel = trace_ray(&ray, env->objects, 0); }
void raytrace_one_pixel(int i, int j) { double x, y; Vect eye_color; x = 0.5 + (double) i; // the "center" of the pixel y = 0.5 + (double) j; set_pixel_ray_direction(x, y, ray_cam, eye_ray); eye_color[R] = eye_color[G] = eye_color[B] = 0.0; trace_ray(0, 1.0, eye_ray, eye_color); draw_point(i, j, eye_color, ray_cam->im); }
/** * Performs a raytrace on the given pixel on the current scene. * The pixel is relative to the bottom-left corner of the image. * @param scene The scene to trace. * @param x The x-coordinate of the pixel to trace. * @param y The y-coordinate of the pixel to trace. * @param width The width of the screen in pixels. * @param height The height of the screen in pixels. * @return The color of that pixel in the final image. */ Color3 Raytracer::trace_pixel( const Scene* scene, size_t x, size_t y, size_t width, size_t height ) { assert( 0 <= x && x < width ); assert( 0 <= y && y < height ); // get ray direction Vector3 position = m_camera_pos; Vector3 direction = m_camera_dir + // camera direction m_up_step * (y*1.0f-height/2) + // vertical increasement m_right_step * (x*1.0f-width /2); // horizontal increasement direction = normalize(direction); // trace a ray and return its color return trace_ray( scene, 4, direction, position, m_near_clip, m_far_clip ); }
/* render : runs trace_ray over each pixel, writes colors to file f */ void render(FILE *f, stage g) { int x, y; xyz loc; ray r; r.origin = g.c.loc; fprintf(f, "P3 %d %d 255\n", g.c.w, g.c.h); for (y=0; y<g.c.h; y++) { for (x=0; x<g.c.w; x++) { loc = logical_loc(g.c, x, y); r.dir = xyz_sub(loc,r.origin); color_show_bytes(f, trace_ray(g.s, r)); } } }
//------------------------------------------------------------------------------------------- // メインエントリーポイントです. //------------------------------------------------------------------------------------------- int main(int argc, char **argv) { auto w = 1280; // 画像の横幅. auto h = 1080; // 画像の縦幅. auto s = 10000; // s * 1000 photon paths will be traced auto c = new Vector3[ w * h ]; hpbbox.reset(); trace_ray( w, h ); trace_photon( s ); density_estimation( c, s ); save_to_bmp( "image.bmp", w, h, &c[0].x, 2.2 ); delete [] c; c = nullptr; return 0; }
void render(stage g) { int i, j; camera c = g.c; scene sc = g.s; printf("P3\n"); printf("%d %d\n", c.w, c.h); printf("255\n"); for(i=0; i < c.h; i++) { for(j=0; j < c.w; j++) { vec p = {j,i,0}; vec loc = logical_loc(c, p); vec dir = vec_sub(loc, c.loc); vec normdir = vec_norm(dir); ray r = {c.loc, normdir}; rgb col = trace_ray(sc, r); rgb_print_bytes(col); } } }
void raytrace_one_pixel(int i, int j) { double x, y; Vect eye_color; x = 0.5 + (double) i; // the "center" of the pixel y = 0.5 + (double) j; set_pixel_ray_direction(x, y, ray_cam, eye_ray); eye_color[R] = eye_color[G] = eye_color[B] = 0.0; trace_ray(0, 1.0, eye_ray, eye_color); draw_point(i, j, eye_color, ray_cam->im); // image_i++; // if (image_i == ray_cam->im->w) { // image_i = 0; // image_j++; // } // thread_count--; }
void render(msg_block_t *msg, rt_context_t *rtx, uint32_t *frame_buffer) { uint32_t *pixel; float sy = rtx->sheight * 0.5f - rtx->ayc; unsigned int y; for (y = 0; y < rtx->height; y++) { uint32_t *src = frame_buffer + (y * SCALE + rtx->yoff) * msg->fbinfo.line_length / sizeof(uint32_t) + rtx->xoff; pixel = src; float sx = rtx->swidth * -0.5f; unsigned int x; for (x = 0; x < rtx->width; x++) { rtx->ray.pos = rtx->eye; rtx->ray.dir = normalize(vec3_sub(vec3_set(sx, sy, 0.0f), rtx->eye)); vec3_t col = vec3_set(0.0f, 0.0f, 0.0f); unsigned int j; for (j = 0; j < MAXREF; j++) { trace_ray(rtx); if (rtx->hit != NOHIT) { vec3_t p, n; ray_t next; p = vec3_add(rtx->ray.pos, vec3_scale(rtx->ray.dir, rtx->dist)); switch (rtx->obj[rtx->hit].type) { case SPHERE: n = normalize(vec3_sub(p, rtx->obj[rtx->hit].pos)); break; case PLANE: n = rtx->obj[rtx->hit].norm; break; default: break; } next.pos = vec3_add(p, vec3_scale(n, EPSILON)); vec3_t lv = vec3_sub(rtx->light.pos, p); vec3_t l = normalize(lv); next.dir = rtx->ray.dir; int prev_hit_index = rtx->hit; vec3_t hit_obj_col = rtx->obj[rtx->hit].col; float diffuse = dot(n, l); float specular = dot(rtx->ray.dir, vec3_sub(l, vec3_scale(n, 2.0f * diffuse))); diffuse = max(diffuse, 0.0f); specular = max(specular, 0.0f); specular = power_spec(specular); float s1 = 1.0f; float s2 = 1.0f; if (rtx->obj[rtx->hit].flag_shadow) { rtx->ray.dir = l; rtx->ray.pos = next.pos; trace_ray(rtx); int shadow = (rtx->dist < norm(lv)); s1 = shadow ? 0.5f : s1; s2 = shadow ? 0.0f : s2; } col = vec3_add(col, vec3_add(vec3_scale(rtx->light.col, specular * s2), vec3_scale(hit_obj_col, diffuse * s1))); if (!rtx->obj[prev_hit_index].flag_refrect) { break; } rtx->ray.dir = vec3_sub(next.dir, vec3_scale(n, dot(next.dir, n) * 2.0f)); rtx->ray.pos = next.pos; } else { break; } } col = vec3_min(vec3_max(col, 0.0f), 1.0f); uint32_t col2 = 0xff000000 + ((unsigned int)(col.x * 255.0f) << 16) + ((unsigned int)(col.y * 255.0f) << 8) + (unsigned int)(col.z * 255.0f); *pixel = col2; #if SCALE > 1 *(pixel + 1) = col2; #endif #if SCALE > 3 *(pixel + 2) = col2; *(pixel + 3) = col2; #endif pixel += SCALE; sx += rtx->ax; } uint32_t size = rtx->width * SCALE; unsigned int i; for (i = 1; i < SCALE; i++) { uint32_t *dst = src + i * msg->fbinfo.line_length / sizeof(uint32_t); unsigned int j; for (j = 0; j < size; j++) { dst[j] = src[j]; } } sy -= rtx->ay; } }
/******************************************************************************* * For each pixel we must generate a primary ray and test for intersection with * all of the objects in the scene. If there is more than one ray-object * intersection then we must choose the closest intersection (the smallest * positive value of t).To ensure that there are no objects intersected in * front of the image plane (this is called near plane clipping), we keep the * distance of the primary ray to the screen and test all intersections against * this distance. If the t value is less than this distance, then we ignore the * object. * * If there is an intersection then we must compute the shadow rays and the * reflection rays. */ color_t trace_ray(ray3_t* test_ray, int depth) { int occluded = 0; ray3_t shadow_ray; ray3_t reflected_ray; color_t ray_color = { 0.0, 0.0, 0.0, 0.0 }; color_t nul_color = {0.0, 0.0, 0.0, 1.0}; light_t* light_ptr = 0; double intersect_ray_length_curr = 0.0; double intersect_ray_length_close = 0.0; int intersection_exists = 0; colored_sphere_t* sphere_close_ptr = 0; vector3_t intersection; vector3_t intersection_vector; int sphere_index = 0; int light_index = 0; int shadow_index; color_t add_color; /* test ray against all objects in scene, search until closest intersection * is found. */ for (sphere_index = 0; sphere_index < sphere_list_count; ++sphere_index) { colored_sphere_t* sphere_ptr = &sphere_list[sphere_index]; /* test for intersection between ray and scene object */ if (1 == find_ray_sphere_intersect(test_ray, &sphere_ptr->sphere, &intersect_ray_length_curr)) { if (intersect_ray_length_curr < 0.0) continue; if (0 == intersection_exists) { intersection_exists = 1; intersect_ray_length_close = intersect_ray_length_curr; sphere_close_ptr = sphere_ptr; } else if (intersect_ray_length_curr < intersect_ray_length_close) { intersect_ray_length_curr = intersect_ray_length_close; sphere_close_ptr = sphere_ptr; } } } if (1 == intersection_exists) { intersection.x = test_ray->origin.x + test_ray->vector.x * intersect_ray_length_close; intersection.y = test_ray->origin.y + test_ray->vector.y * intersect_ray_length_close; intersection.z = test_ray->origin.z + test_ray->vector.z * intersect_ray_length_close; shadow_ray.origin = intersection; /* Shadow rays are sent towards all light sources to determine if any objects occlude the intersection spot. */ for (light_index = 0; light_index < light_list_count; ++light_index) { occluded = 0; light_ptr = &light_list[light_index]; shadow_ray.vector.x = (light_ptr->origin.x - shadow_ray.origin.x); shadow_ray.vector.y = (light_ptr->origin.y - shadow_ray.origin.y); shadow_ray.vector.z = (light_ptr->origin.z - shadow_ray.origin.z); normalize_vector(&shadow_ray.vector); /* Test intersection to determine if ray is in occlusion. */ for (shadow_index = 0; shadow_index < sphere_list_count; ++shadow_index) { if (1 == find_ray_sphere_intersect(&shadow_ray, &sphere_list[shadow_index].sphere, &intersect_ray_length_curr)) { occluded = 1; break; } } if (occluded == 0) { /* Calculate the total light intensity. */ double light_intensity = calc_dot_product(&shadow_ray.vector, &test_ray->vector); if (light_intensity < 0.0) light_intensity = -light_intensity; ray_color = mix_colors(&nul_color, &sphere_close_ptr->color, light_intensity); if (depth < 4) { reflected_ray.origin.x = intersection.x; reflected_ray.origin.y = intersection.y; reflected_ray.origin.z = intersection.z; intersection_vector.x = (intersection.x - sphere_close_ptr->sphere.center.x); intersection_vector.y = (intersection.y - sphere_close_ptr->sphere.center.y); intersection_vector.z = (intersection.z - sphere_close_ptr->sphere.center.z); normalize_vector(&intersection_vector); calc_reflected_vector(&reflected_ray.vector, &test_ray->vector, &intersection_vector); add_color = trace_ray(&reflected_ray, ++depth); if ((add_color.r != 0x00) || (add_color.g != 0x00) || (add_color.b != 0x00)) { double mix_ratio = calc_dot_product(&reflected_ray.vector, &intersection_vector); if (mix_ratio < 0.0) mix_ratio = -mix_ratio; ray_color = mix_colors(&ray_color, &add_color, mix_ratio); } } } } } return ray_color; }
int main(int argc, char* argv[]) { bool velocity, sym, escvar; int is, n[3], im, nm, order, nshot, ndim, two, na, nb; int nt, nt1, nr, ir, it, i, ia, ib; float t, dt, da=0., a0, amax, db=0., b0, bmax, v0; float x[3], p[3], d[3], o[3], **traj, *slow, **s, *a, *b; raytrace rt; sf_file shots, vel, rays, angles; sf_init (argc,argv); vel = sf_input("in"); rays = sf_output("out"); /* get 2-D grid parameters */ if (!sf_histint(vel,"n1",n)) sf_error("No n1= in input"); if (!sf_histint(vel,"n2",n+1)) sf_error("No n2= in input"); if (!sf_histint(vel,"n3",n+2)) sf_error("No n3= in input"); if (!sf_histfloat(vel,"d1",d)) sf_error("No d1= in input"); if (!sf_histfloat(vel,"d2",d+1)) sf_error("No d2= in input"); if (!sf_histfloat(vel,"d3",d+2)) sf_error("No d3= in input"); if (!sf_histfloat(vel,"o1",o)) o[0]=0.; if (!sf_histfloat(vel,"o2",o+1)) o[1]=0.; if (!sf_histfloat(vel,"o3",o+2)) o[2]=0.; /* additional parameters */ if(!sf_getbool("vel",&velocity)) velocity=true; /* If y, input is velocity; if n, slowness */ if(!sf_getint("order",&order)) order=4; /* Interpolation order */ if (!sf_getint("nt",&nt)) sf_error("Need nt="); /* Number of time steps */ if (!sf_getfloat("dt",&dt)) sf_error("Need dt="); /* Sampling in time */ if (!sf_getbool("sym",&sym)) sym=true; /* if y, use symplectic integrator */ if(!sf_getbool("escvar",&escvar)) escvar=false; /* If y - output escape values, n - trajectories */ /* get shot locations */ if (NULL != sf_getstring("shotfile")) { /* file with shot locations */ shots = sf_input("shotfile"); if (!sf_histint(shots,"n1",&ndim) || 3 != ndim) sf_error("Must have n1=2 in shotfile"); if (!sf_histint(shots,"n2",&nshot)) sf_error("No n2= in shotfile"); s = sf_floatalloc2 (ndim,nshot); sf_floatread(s[0],ndim*nshot,shots); sf_fileclose (shots); } else { nshot = 1; ndim = 3; s = sf_floatalloc2 (ndim,nshot); if (!sf_getfloat("zshot",&s[0][0])) s[0][0]=o[0]; /* shot location in depth (if shotfile is not specified) */ if (!sf_getfloat("yshot",&s[0][1])) s[0][1]=o[1] + 0.5*(n[1]-1)*d[1]; /* shot location inline (if shotfile is not specified) */ if (!sf_getfloat("xshot",&s[0][2])) s[0][2]=o[2] + 0.5*(n[2]-1)*d[2]; /* shot location crossline (if shotfile is not specified) */ sf_warning("Shooting from z=%g, y=%g, x=%g",s[0][0],s[0][1],s[0][2]); } if (NULL != sf_getstring("anglefile")) { /* file with initial angles */ angles = sf_input("anglefile"); if (!sf_histint(angles,"n1",&nr)) sf_error("No n1= in anglefile"); if (!sf_histint(angles,"n2",&two) || 2 != two) sf_error("Need n2=2 in anglefile"); a = sf_floatalloc(nr); b = sf_floatalloc(nr); } else { angles = NULL; if (!sf_getint("na",&na)) sf_error("Need na="); /* Number of azimuths (if anglefile is not specified) */ if (!sf_getint("nb",&nb)) sf_error("Need nb="); /* Number of inclinations (if anglefile is not specified) */ if (!sf_getfloat("a0",&a0)) a0 = 0.; /* First azimuth angle in degrees (if anglefile is not specified) */ if (!sf_getfloat("amax",&amax)) amax=360.; /* Maximum azimuth angle in degrees (if anglefile is not specified) */ if (!sf_getfloat("b0",&b0)) b0 = 0.; /* First inclination angle in degrees (if anglefile is not specified) */ if (!sf_getfloat("bmax",&bmax)) bmax=180.; /* Maximum inclination angle in degrees (if anglefile is not specified) */ /* convert degrees to radians */ a0 *= SF_PI/180.; amax *= SF_PI/180.; b0 *= SF_PI/180.; bmax *= SF_PI/180.; /* figure out angle spacing */ da = (na > 1)? (amax - a0)/(na-1) : 0.; db = (nb > 1)? (bmax - b0)/(nb-1) : 0.; nr = na*nb; a = sf_floatalloc(nr); b = sf_floatalloc(nr); for (ir=ib=0; ib < nb; ib++) { for (ia=0; ia < na; ia++, ir++) { b[ir] = b0 + ib*db; a[ir] = a0 + ia*da; } } } /* specify output dimensions */ nt1 = nt+1; if (escvar) { sf_putint (rays, "n1", 4); sf_putfloat (rays, "o1", 0.0); sf_putfloat (rays, "d1", 1.0); sf_putstring (rays, "label1", "Escape variable"); sf_putstring (rays, "unit1", ""); if (NULL == angles) { sf_putint (rays, "n2", na); sf_putfloat (rays, "d2", da*180.0/SF_PI); sf_putfloat (rays, "o2", a0*180.0/SF_PI); sf_putstring (rays, "label2", "Azimuth"); sf_putstring (rays, "unit2", "Degrees"); sf_putint (rays, "n3", nb); sf_putfloat (rays, "d3", db*180.0/SF_PI); sf_putfloat (rays, "o3", b0*180.0/SF_PI); sf_putstring (rays, "label3", "Inclination"); sf_putstring (rays, "unit3", "Degrees"); sf_putint (rays,"n4",nshot); sf_putfloat (rays, "d4", 1.0); sf_putfloat (rays, "o4", 0.0); sf_putstring (rays, "label4", "Shots"); sf_putstring (rays, "unit4", ""); } else { sf_putint (rays,"n2",nr); sf_putfloat (rays, "d2", 1.0); sf_putfloat (rays, "o2", 0.0); sf_putstring (rays, "label2", "Angles"); sf_putstring (rays, "unit2", ""); sf_putint (rays,"n3",nshot); sf_putfloat (rays, "d3", 1.0); sf_putfloat (rays, "o3", 0.0); sf_putstring (rays, "label3", "Shots"); sf_putstring (rays, "unit3", ""); } } else { sf_putint (rays,"n1",ndim); sf_putint (rays,"n2",nt1); sf_putint (rays,"n3",nr); sf_putint (rays,"n4",nshot); } /* get slowness squared */ nm = n[0]*n[1]*n[2]; slow = sf_floatalloc(nm); sf_floatread(slow,nm,vel); for(im = 0; im < nm; im++){ v0 = slow[im]; slow[im] = velocity? 1./(v0*v0): v0*v0; } /* initialize ray tracing object */ rt = raytrace_init (3, sym, nt, dt, n, o, d, slow, order); free (slow); traj = sf_floatalloc2 (sym? ndim: 2*ndim,nt1); for( is = 0; is < nshot; is++) { /* loop over shots */ /* initialize angles */ if (NULL != angles) { sf_floatread(a,nr,angles); sf_floatread(b,nr,angles); } for (ir = 0; ir < nr; ir++) { /* loop over rays */ /* initialize position */ x[0] = s[is][0]; x[1] = s[is][1]; x[2] = s[is][2]; /* initialize direction */ p[2] = +sinf(a[ir])*sinf(b[ir]); p[1] = -cosf(a[ir])*sinf(b[ir]); p[0] = cosf(b[ir]); it = trace_ray (rt, x, p, traj); if (it < 0) it = -it; /* keep side-exiting rays */ if (escvar) { /* Write escape variables only */ sf_floatwrite (traj[it],ndim,rays); /* z, x, y */ t = it*dt; /* t */ sf_floatwrite (&t, 1, rays); } else { for (i=0; i < nt1; i++) { if (0==it || it > i) { sf_floatwrite (traj[i],ndim,rays); } else { sf_floatwrite (traj[it],ndim,rays); } } } } } exit (0); }
printf("%.2lf %2.lf %.2lf\n",d1,d2,d1/d2); color c = color_expr(d1/d2,0,0); color_show(stdout,c); printf("\n\n *** testing logica_loc *** \n"); xyz_show(stdout,loc1); xyz_show(stdout,loc2); xyz_show(stdout,loc3); printf("\n\n *** testing texture *** \n"); color tx = tex_green(&o1, htpt); color_show(stdout,tx); xyz dirrr = xyz_sub(loc1,cam.loc); xyz_show(stdout,dirrr); ray tr = {cam.loc,dirrr}; color trc = trace_ray(scn,tr); hit_test ht2 = intersect(tr,o1); xyz htpt22 = ht2.hit_point; xyz htpt2 = ray_position(tr,ht2.t); printf("\n\n"); printf("===ray from cam (0,0,-5) to physical (60,51)\nray:"); ray_show(stdout,tr); hit_test_show(stdout,ht2); printf("\n"); xyz_show(stdout,htpt2); xyz_show(stdout,htpt22); printf("\n"); color tx2 = tex_green(&o1, htpt2); color_show(stdout,tx2); printf("\n"); color_show(stdout,trc);
bool trace_ray(const Ray& ray, const std::list<Sphere>& world, const Sphere& sphere, Color* color) { const float a = dot(ray.direction, ray.direction); const Vec3 c2o = ray.origin - sphere.center; const float b = 2 * dot(c2o, ray.direction); const float c = dot(c2o, c2o) - sphere.radius * sphere.radius; const float delta = b * b - 4 * a * c; if (delta < 0) { return false; } const float delta_root = std::sqrt(delta); const float roots[2] = { (-b - delta_root) / (2 * a), (-b + delta_root) / (2 * a), }; if (roots[0] < 0 && roots[1] < 0) { return false; } else if (!color) { return true; } float root; if (roots[0] < 0 || roots[1] < 0) { root = std::max(roots[0], roots[1]); } else { root = std::min(roots[0], roots[1]); } const Vec3 intersection = ray.origin + root * ray.direction; const Vec3 normal = intersection - sphere.center; const Vec3 tan1 = (normal.y != 0 || normal.z != 0) ? cross(normal, Vec3 { 1, 0, 0 }) : Vec3 { 0, 1, 0 }; const Vec3 tan2 = cross(normal, tan1); const unsigned tests = 100; float occlusion = 0; #pragma omp parallel for for (int i = 0; i < tests; ++i) { const float inclination = dis(gen) / 2; const float azimuth = 2 * dis(gen); const Vec3 spherical { std::cos(azimuth) * std::sin(inclination), std::sin(azimuth) * std::sin(inclination), std::cos(inclination), }; const Vec3 direction = spherical.x * tan1 + spherical.y * tan2 + spherical.z * normal; const Ray test_ray { intersection + 0.001f * direction, direction, }; if (trace_ray(test_ray, world, nullptr)) { occlusion += 1.f / tests; } } color->r = color->g = color->b = 255 * (1 - occlusion) * (1 - occlusion); return true; }