示例#1
0
/*
 * path trace across whole screen image.
 */
void
ri_transport_pathtrace(const ri_display_drv_t *ddrv)
{
	int i;
	int x, y;
	int nsamples;			/* nsamples per pixel */
	int ntotalpixels;
	int nfinishedpixels;
	double dcol[3];			/* tempolary color buffer */
	float  fcol[3];
	ri_option_t *opt;		/* rendering options */

	ri_vector_t radiance;

	/* Initialize */
	opt = ri_render_get()->context->option;
	pixwidth  = opt->camera->horizontal_resolution;
	pixheight = opt->camera->vertical_resolution;
	nsamples = opt->pt_nsamples;

	ntotalpixels = pixwidth * pixheight * nsamples;
	nfinishedpixels = 0;

	light = (ri_light_t *)(ri_list_first(ri_render_get()->lightlist)->data);

	get_camera(&cam_pos, &cam_dir, &c2w);

	/* for each pixel, trace nsamples rays. */
	for (x = 0; x < pixwidth; x++) {
		for (y = pixheight - 1; y >= 0; y--) {
			dcol[0] = 0.0; dcol[1] = 0.0; dcol[2] = 0.0;

			for (i = 0; i < nsamples; i++) {
				trace_pixel(&radiance, x, y);
				// add_color(x, y, radiance);
				dcol[0] += (double)radiance.f[0];
				dcol[1] += (double)radiance.f[1];
				dcol[2] += (double)radiance.f[2];

			}

			nfinishedpixels += nsamples;

#if 0
			printf("%f %% finished\r",
				(float)(nfinishedpixels * 100.0 /
					ntotalpixels));
			fflush(stdout);
#endif
	
			fcol[0] = (float)(dcol[0] / (double)nsamples);
			fcol[1] = (float)(dcol[1] / (double)nsamples);
			fcol[2] = (float)(dcol[2] / (double)nsamples);
			ddrv->write(x, pixheight - 1 - y, &fcol[0]);
		}
	}
}
示例#2
0
/**
 * Raytraces some portion of the scene. Should raytrace for about
 * max_time duration and then return, even if the raytrace is not copmlete.
 * The results should be placed in the given buffer.
 * @param buffer The buffer into which to place the color data. It is
 *  32-bit RGBA (4 bytes per pixel), in row-major order.
 * @param max_time, If non-null, the maximum suggested time this
 *  function raytrace before returning, in seconds. If null, the raytrace
 *  should run to completion.
 * @return true if the raytrace is complete, false if there is more
 *  work to be done.
 */
bool Raytracer::raytrace( unsigned char *buffer, real_t* max_time )
{
    // TODO Add any modifications to this algorithm, if needed.

    static long start_time; // used to show how long time ray tracing cost
    if (0 == current_row)
        start_time = clock();

    static const size_t PRINT_INTERVAL = 64;

    // the time in milliseconds that we should stop
    unsigned int end_time = 0;
    bool is_done = false;

    if ( max_time ) {
        // convert duration to milliseconds
        unsigned int duration = (unsigned int) ( *max_time * 1000 );
        end_time = SDL_GetTicks() + duration;
    }

    // until time is up, run the raytrace. we render an entire row at once
    // for simplicity and efficiency.
    for ( ; !max_time || end_time > SDL_GetTicks(); ++current_row ) {

        if ( current_row % PRINT_INTERVAL == 0 ) {
            printf( "Raytracing (row %u)...\n", current_row );
        }

        // we're done if we finish the last row
        is_done = current_row == height;
        // break if we finish
        if ( is_done )
            break;

        for ( size_t x = 0; x < width; ++x ) {
            // trace a pixel
            Color3 color = trace_pixel( scene, x, current_row, width, height );
            // write the result to the buffer, always use 1.0 as the alpha
            color.to_array( &buffer[4 * ( current_row * width + x )] );
        }
    }

    if ( is_done ) {
        printf( "Done raytracing!\n" );
        printf( "Used %d milliseconds.\n", clock()-start_time );
    }


    return is_done;
}
示例#3
0
//  Raytraces some portion of the scene
bool Raytracer::raytrace( unsigned char *buffer, real_t* max_time )
{
    static const size_t PRINT_INTERVAL = 64;

    unsigned int end_time = 0;
    bool is_done;

    if ( max_time ) {
        // convert duration to milliseconds
        unsigned int duration = (unsigned int) ( *max_time * 1000 );
        end_time = SDL_GetTicks() + duration;
    }

    // until time is up, run the raytrace. we render an entire row at once
    for ( ; !max_time || end_time > SDL_GetTicks(); ++current_row ) {

        if ( current_row % PRINT_INTERVAL == 0 ) {
            printf( "Raytracing (row %u)...\n", current_row );
        }

        // we're done if we finish the last row
        is_done = current_row == height;
        if ( is_done )
            break;

        for ( size_t x = 0; x < width; ++x ) {
            // trace a pixel
            Color3 color = trace_pixel( scene, x, current_row, width, height );
            color.to_array( &buffer[4 * ( current_row * width + x )] );
        }
    }

    if ( is_done ) {
        printf( "Done raytracing!\n" );
    }

    return is_done;
}
示例#4
0
/**
 * Performs a raytrace on the given pixel on the current scene.
 * The pixel is relative to the bottom-left corner of the image.
 */
Color3 Raytracer::trace_pixel(int recursions, const Ray& ray, float refractive)
{
    size_t num_geometries = scene->num_geometries();
    bool hit_any = false; // if any geometries were hit
    IsectInfo min_info; // everything we're calculating from intersection
    Vector3 intersection_point = Vector3::Zero;

    // run intersection test on every object in scene
    for (size_t i = 0; i < num_geometries; i++)
    {
        IsectInfo info;
        // intersect returns true if there's a hit, false if not, and sets
        // values in info struct
        bool hit = scene->get_geometries()[i]->intersect_ray(ray, info);

        if (hit && info.time < min_info.time) // min_info.time initializes to inf
        {
            min_info = info;
            intersection_point = ray.eye + (min_info.time * ray.dir);
            hit_any = true;
        }
    }

    // found a hit
    if (hit_any)
    {
        Color3 direct;
        Color3 diffuse = Color3::Black;
        Color3 ambient = scene->ambient_light * min_info.ambient;
        float angle = dot(ray.dir, min_info.normal);
        // compute reflected ray
        Ray incident_ray;
        incident_ray.dir = ray.dir - 2 * angle * min_info.normal;
        incident_ray.dir = normalize(incident_ray.dir);
        incident_ray.eye = intersection_point + eps * incident_ray.dir;

        // no-refraction case
        if (min_info.refractive == 0.0)
        {
            diffuse = get_diffuse(incident_ray.eye, min_info.normal,
                    min_info.diffuse, eps);
            direct = min_info.texture * (ambient + diffuse);

            // return direct light and reflected light if we have recursions left
            if (recursions >= max_recursion_depth)
            {
                return direct;
            }

            return direct + min_info.texture * min_info.specular *
                trace_pixel(recursions + 1, incident_ray, refractive);

        }
        // refraction case
        else
        {
            // return black if no more recursions
            if (recursions >= max_recursion_depth)
            {
                return Color3::Black;
            }

            float c;
            Ray transmitted_ray;
            float refract_ratio = refractive / min_info.refractive;

            // negative dot product between ray and normal indicates entering object
            if (angle < 0.0)
            {
                refract(ray.dir, min_info.normal, refract_ratio, &transmitted_ray.dir);
                c = dot(-1.0 * ray.dir, min_info.normal);
            }
            else
            {
                // exiting object
                if (refract(ray.dir, (-1.0 * min_info.normal), min_info.refractive,
                            &transmitted_ray.dir))
                {
                    c = dot(transmitted_ray.dir, min_info.normal);
                }
                // total internal reflection
                else
                {
                    return trace_pixel(recursions + 1, incident_ray, refractive);
                }
            }

            // schlick approximation to fresnel equations
            float R_0 = pow(refract_ratio - 1, 2) / pow(refract_ratio + 1, 2);
            float R = R_0 + (1 - R_0) * pow(1 - c, 5);
            transmitted_ray.eye = intersection_point + eps * transmitted_ray.dir;

            // return reflected and refracted rays
            return R * trace_pixel(recursions + 1, incident_ray, refractive) +
                (1.0 - R) * trace_pixel(recursions + 1, transmitted_ray,
                        min_info.refractive);
        }
    }
    // didn't hit anything - return background color
    else
    {
        return scene->background_color;
    }
}
示例#5
0
Color3 Raytracer::trace_pixel_end(int recursions, const Ray& ray, float refractive, 
        IsectInfo min_info)
{
    Color3 direct;
    Color3 diffuse = Color3::Black;
    Color3 ambient = scene->ambient_light * min_info.ambient;
    float angle = dot(ray.dir, min_info.normal);

    // compute reflected ray
    Vector3 intersection_point = ray.eye + (min_info.time * ray.dir);
    Ray incident_ray;
    incident_ray.dir = ray.dir - 2 * angle * min_info.normal;
    incident_ray.dir = normalize(incident_ray.dir);
    incident_ray.eye = intersection_point + eps * incident_ray.dir;

    // no-refraction case
    if (min_info.refractive == 0.0)
    {
        diffuse = get_diffuse(incident_ray.eye, min_info.normal,
                min_info.diffuse, eps);
        direct = min_info.texture * (ambient + diffuse);

        // return direct light and reflected light if we have recursions left
        if (recursions >= max_recursion_depth)
        {
            return direct;
        }

        return direct + min_info.texture * min_info.specular *
            trace_pixel(recursions + 1, incident_ray, refractive);

    }
    // refraction case
    else
    {
        // return black if no more recursions
        if (recursions >= max_recursion_depth)
        {
            return Color3::Black;
        }

        float c;
        Ray transmitted_ray;
        float refract_ratio = refractive / min_info.refractive;

        // negative dot product between ray and normal indicates entering object
        if (angle < 0.0)
        {
            refract(ray.dir, min_info.normal, refract_ratio, &transmitted_ray.dir);
            c = dot(-1.0 * ray.dir, min_info.normal);
        }
        else
        {
            // exiting object
            if (refract(ray.dir, (-1.0 * min_info.normal), min_info.refractive,
                        &transmitted_ray.dir))
            {
                c = dot(transmitted_ray.dir, min_info.normal);
            }
            // total internal reflection
            else
            {
                return trace_pixel(recursions + 1, incident_ray, refractive);
            }
        }

        // schlick approximation to fresnel equations
        float R_0 = pow(refract_ratio - 1, 2) / pow(refract_ratio + 1, 2);
        float R = R_0 + (1 - R_0) * pow(1 - c, 5);
        transmitted_ray.eye = intersection_point + eps * transmitted_ray.dir;

        // return reflected and refracted rays
        return R * trace_pixel(recursions + 1, incident_ray, refractive) +
            (1.0 - R) * trace_pixel(recursions + 1, transmitted_ray,
                    min_info.refractive);
    }
}