static void expandPerimeterFrom(map_t *m,TCOD_list_t perim,ray_data_t *r) { if ( r->xloc >= 0 ) { processRay(m,perim,new_ray(m,r->xloc+1,r->yloc),r); } if ( r->xloc <= 0 ) { processRay(m,perim,new_ray(m,r->xloc-1,r->yloc),r); } if ( r->yloc >= 0 ) { processRay(m,perim,new_ray(m,r->xloc,r->yloc+1),r); } if ( r->yloc <= 0 ) { processRay(m,perim,new_ray(m,r->xloc,r->yloc-1),r); } }
//recursive function void World::trace_scene(Scene_info &info, Directional_ray &ray, Directional_ray &spec_light, int rec_ctr, int cur_obj_idx, float min_distance, int i, int j, Vector3d &amb_dir, float factor, Point3d &cur_orig) { if(rec_ctr <= 0) return; for (int o = 0; o < _objects.size(); ++o){ if((o != cur_obj_idx)){//dont hit yourself again if( _tracer->hit(ray, _objects[o], info) ){ //get the color //lambertian shading //calculate the cos value if(_objects[o]->type() == obj_type::Triangle){ Triangle* cur_tri = reinterpret_cast<Triangle*>(_objects[o]); Vector3d tri_normal = cur_tri->get_n(); update_color(info, i, j, tri_normal, amb_dir, 1.f); } else if(_objects[o]->type() == obj_type::Sphere){//sphere Sphere* cur_sph = reinterpret_cast<Sphere*>(_objects[o]); Vector3d normal_hit = info._hit_point - cur_sph->center(); normal_hit.normalize_vector(); if(rec_ctr == MAX_RECURSE_NUM)//first time update_color(info, i, j, normal_hit, amb_dir, 1.f); else//average color update_color(info, i, j, normal_hit, amb_dir, factor); Directional_ray new_ray(ray); Scene_info new_info(info); update_dir_and_org(new_info, new_ray, normal_hit); trace_scene(new_info, new_ray, spec_light, (rec_ctr-1), o, min_distance, i, j, amb_dir, factor/2, cur_orig); //calaulate spec Vector3d view_vec = info._hit_point - cur_orig; view_vec.normalize_vector(); Directional_ray new_spec(spec_light); update_dir_and_org(new_info, new_spec, normal_hit); Vector3d spec_hit = new_spec.get_dir(); update_spec(info, i, j, spec_hit, view_vec, spec_light); } else { //simply copy the color copy_info_color(info, i, j); } } } } }
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 TCOD_map_compute_fov_diamond_raycasting(TCOD_map_t map, int player_x, int player_y, int max_radius, bool light_walls) { map_t *m = (map_t *)map; TCOD_list_t perim=TCOD_list_allocate(m->nbcells); cell_t *c; ray_data_t **r; int nbcells; int r2=max_radius*max_radius; perimidx=0; raymap=(ray_data_t **)calloc(sizeof(ray_data_t*),m->nbcells); raymap2=(ray_data_t *)calloc(sizeof(ray_data_t),m->nbcells); origx=player_x; origy=player_y; expandPerimeterFrom(m,perim,new_ray(m,0,0)); while ( perimidx < TCOD_list_size(perim) ) { ray_data_t *ray=(ray_data_t *)TCOD_list_get(perim,perimidx); int distance = 0; if ( r2 > 0 ) distance = ((ray->xloc * ray->xloc) + (ray->yloc * ray->yloc)); perimidx++; if ( distance <= r2) { merge_input(m, ray); if ( !ray->ignore ) expandPerimeterFrom(m,perim,ray); } else ray->ignore=true; } // set fov data c=m->cells; r=raymap; nbcells=m->nbcells; while ( nbcells!= 0 ) { if ( *r == NULL || (*r)->ignore || ((*r)->xerr > 0 && (*r)->xerr <= (*r)->xob ) || ((*r)->yerr > 0 && (*r)->yerr <= (*r)->yob ) ) { c->fov=0; } else { c->fov=1; } c++; r++; nbcells--; } m->cells[origx+origy*m->width].fov=1; // light walls if ( light_walls ) { int xmin=0, ymin=0, xmax=m->width, ymax=m->height; if ( max_radius > 0 ) { xmin=MAX(0,player_x-max_radius); ymin=MAX(0,player_y-max_radius); xmax=MIN(m->width,player_x+max_radius+1); ymax=MIN(m->height,player_y+max_radius+1); } TCOD_map_postproc(m,xmin,ymin,player_x,player_y,-1,-1); TCOD_map_postproc(m,player_x,ymin,xmax-1,player_y,1,-1); TCOD_map_postproc(m,xmin,player_y,player_x,ymax-1,-1,1); TCOD_map_postproc(m,player_x,player_y,xmax-1,ymax-1,1,1); } free(raymap); free(raymap2); TCOD_list_delete(perim); }
Color Renderer::rayTraceRecursive(Shape* scene, Ray& ray, Lights& lights, int maxReflect) { IntersectResult result; scene->Intersect(ray, &result); if (result.geometry) { Material* pMaterial = result.geometry->material; float reflectiveness = pMaterial->reflectiveness; Color color(0, 0, 0); std::mt19937 eng(4029349); std::uniform_real_distribution<float> fraction_dist; for (int i = 0; i < lights.size(); i++) { Light* pLight = lights[i]; Color c; if (!pLight->shadow) { //no shadow Vector3dF incidenceNormal = pLight->incidenceNormal(result.position); c = pMaterial->Sample(ray, result.position, result.normal, incidenceNormal); } else if (pLight->softshadow) { Vector3dF incidenceCenter = pLight->incidence(result.position); Vector3dF incidenceNormal = incidenceCenter.Normalize(); Vector3dF rayNormal(-incidenceCenter.y, incidenceCenter.x, 0); rayNormal = rayNormal.Normalize(); float disToLight = 0; if (pLight->lightType == LightType_Point) { disToLight = (dynamic_cast<PointLight*>(pLight)->pos - result.position).Length(); } int hitTimes = 0; int raysPerFan = pLight->shadowrays / 4; for (int quadrant = 0; quadrant < 4; quadrant++) { for (int r = 0; r < raysPerFan; r++) { float angle = quadrant * 90.0f + fraction_dist(eng) * 90.f; float dis = fraction_dist(eng) * pLight->radius; //printf("<%.1f, %.1f> ", angle, dis); Vector3dF d = rayNormal.rotate(incidenceNormal, PI * angle / 180.f); Ray shadowrays(result.position, (-incidenceCenter) + d * dis); shadowrays.d = shadowrays.d.Normalize(); IntersectResult _result; scene->Intersect(shadowrays, &_result); if (_result.geometry) { if (disToLight && _result.distance >= disToLight) { continue; } hitTimes++; } } //printf("\n"); } //printf("\n"); c = pMaterial->Sample(ray, result.position, result.normal, incidenceNormal); if (hitTimes > 0) { //printf("%d\n", hitTimes); float black_ratio = hitTimes / (float)pLight->shadowrays; //c = c * ( 1.0f - black_ratio) + Color::Black * black_ratio; c = c.Modulate(Color::White * (1.0f - black_ratio)); c = c.clamp(); } } else { //normal shadow Vector3dF incidenceNormal = pLight->incidenceNormal(result.position); //Is this light visible Ray shadowrays(result.position, -incidenceNormal); IntersectResult _result; scene->Intersect(shadowrays, &_result); bool canSample = true; if (_result.geometry) { if (pLight->lightType == LightType_Point) { float disToLight = (dynamic_cast<PointLight*>(pLight)->pos - result.position).Length(); if (disToLight >= _result.distance) { canSample = false; c = Color::Black; } } else if (pLight->lightType == LightType_Direction) { canSample = false; c = Color::Black; } } if(canSample){ c = pMaterial->Sample(ray, result.position, result.normal, incidenceNormal); } } color = color + c; } color = Color(color * (1.0f - reflectiveness)); if (reflectiveness > 0 && maxReflect > 0) { Vector3dF r = Vector3dF(result.normal * (-2 * (result.normal.Dot(ray.d))) + ray.d); Ray new_ray(result.position, r); Color reflectedColor = rayTraceRecursive(scene, new_ray, lights, maxReflect - 1); assert(reflectedColor.r() >= 0 && reflectedColor.g() >= 0 && reflectedColor.b() >= 0); color = color + reflectedColor * reflectiveness; } return color; } else return Color::Black; }