/** * Render a single ray from a camera. * \param s Scene to render. * \param r Ray being cast. * \param wavelength * \param depth How deep are we in the recursion? * \return Energy of the ray. */ static float render_ray(const struct scene *s, struct ray *r, wavelength_t wavelength, int depth){ if(depth > MAX_DEPTH){ return 0; } struct object *obj = NULL; MEASUREMENTS_RAY_SCENE_INTERSECTION(); float distance = kd_tree_ray_intersection(&(s->tree), r, 0, INFINITY, &obj); if(isnan(distance)){ // If the ray didn't hit anything, it stays black. return 0; } vector_t pointInCameraSpace = vector_add(r->origin, vector_multiply(r->direction, distance)); vector_t pointInObjectSpace = vector_transform(pointInCameraSpace, &(obj->invTransform)); vector_t normalInObjectSpace = obj->get_normal(obj, pointInObjectSpace); vector_t normalInCameraSpace = vector_normalize(vector_transform_direction(normalInObjectSpace, &(obj->transform))); #if DOT_PRODUCT_SHADING (void)wavelength; return fabsf(vector_dot(normalInCameraSpace, r->direction)); #else float energy = 0; /// \todo Surface properties shouldn't be in camera space. if(object_is_light_source(obj)){ energy = (obj->light.energy)(pointInCameraSpace, wavelength, normalInCameraSpace, r->direction); } struct outgoing_direction sample = (obj->surface.sample)(pointInCameraSpace, wavelength, normalInCameraSpace, r->direction); struct ray newRay; ray_from_direction(&newRay, pointInCameraSpace, sample.direction); energy += sample.weight * render_ray(s, &newRay, wavelength, depth + 1); return energy; #endif }
void c_sampler_renderer::render_scene(scene_ptr scene) { ////////////////////////////////////////////////////////////////////////// // Allocate and initialize sample ////////////////////////////////////////////////////////////////////////// sample_ptr origin_sample = sample_ptr(new c_sample(m_sampler, m_surface_integrator, m_volume_integrator, scene)); c_rng rng(2047); int num_pixel_samples = 0; int max_samples = m_sampler->get_max_num_samples(); ray_array_ptr rays(new c_ray[max_samples]); spectrum_array_ptr ls(new c_spectrum[max_samples]); spectrum_array_ptr ts(new c_spectrum[max_samples]); isect_array_ptr isects(new c_intersection[max_samples]); samples_array_ptr samples_array = origin_sample->duplicate(max_samples); while ((num_pixel_samples = m_sampler->get_current_pixel_samples(samples_array, rng)) > 0) { for (int j = 0; j < num_pixel_samples; ++j) { m_camera->generate_ray(samples_array[j], &rays[j]); ls[j] = render_ray(scene, rays[j], &samples_array[j], rng, &isects[j], &ts[j]); assert(!ls[j].has_nan()); m_camera->get_render_target()->add_sample(samples_array[j], ls[j]); } m_report->update(); } m_display->update_display(m_camera->get_render_target()); }
/** * Start rendering a scene. * \param s Scene to render. * \param * \param pixmap Pointer to pixel map with result. * Must be large enough to hold #y0 - #y1 rows. */ void renderer_render(const struct scene *s, const struct renderer_chunk *chunk, struct color *pixmap){ unsigned ymax = chunk->top + chunk->height; // How many meters per pixel. float inc = s->sensorWidth / (float)(s->width - 1); float yy = inc * ((float)(s->height) / 2 - chunk->top); float focus = s->focus / s->focalLength; #if MEASUREMENTS_WITH_WARMUP MEASUREMENTS_WARMUP(); #endif MEASUREMENTS_START(); for(unsigned y = chunk->top; y < ymax; ++y){ float xx = - s->sensorWidth / 2; for(unsigned x = 0; x < s->width; ++x){ color_black(pixmap); for(unsigned i = 0; i < s->raysPerPx; ++i){ struct ray r; // filmPoint = { // -xx - random_number(0, inc), // -yy - random_number(0, inc), // -s->focalLength // } // focusPoint = - (lensCenter - filmPoint) * (s->focus / filmPoint.z) vector_t focusPoint = vector_set( focus * (xx + random_number(0, inc)), focus * (yy + random_number(0, inc)), s->focus); vector_t lensPoint = vector_multiply(vector_random_in_circle(), s->apertureDiameter); ray_from_points(&r, lensPoint, focusPoint); #ifndef MEASUREMENTS_KD_TREE_STATS struct photon p; photon_random_init(&p); p.energy = render_ray(s, &r, p.wavelength, 0); photon_add_to_color(&p, pixmap); #else struct object *obj; MEASUREMENTS_RAY_SCENE_INTERSECTION(); kd_tree_ray_intersection(&(s->tree), &r, &obj); pixmap->r += measurementsObjectIntersectionCounter; pixmap->g += measurementsTreeTraversalCounter; #endif } color_scale(pixmap, 1.0f / s->raysPerPx); //printf("x = %i y = %i pixmap->r = %.2f\n", x, y ,pixmap->r); ++pixmap; xx += inc; } yy -= inc; } MEASUREMENTS_PRINT(); }