glm::vec3 DirectLightingIntegrator::LightPDFEnergy(const Intersection &light_sample_isx, const Intersection &isx, const Ray &light_sample, const glm::vec3 &woW, unsigned int n_light, unsigned int n_brdf)
{
    glm::vec3 ray_color(0, 0, 0);
    Material* M = isx.object_hit->material; //material of point hit
    Geometry* L = light_sample_isx.object_hit; //light source
    float lightPDF = L->RayPDF(light_sample_isx, light_sample);
    //if light pdf is less than zero, return no light
    if (lightPDF <= 0.0f)
    {
        return glm::vec3(0);
    }
    //get BRDFPDF and energy from the material
    float brdfPDF;
    float dummy;

    glm::vec3 M_energy(M->EvaluateScatteredEnergy(isx, woW, light_sample.direction, brdfPDF));
    //terminate early if brdf pdf is zero;
    if (brdfPDF <= 0.0f) return ray_color;

    glm::vec3 L_energy(L->material->EvaluateScatteredEnergy(light_sample_isx, woW, -light_sample.direction, dummy));
    float W = MIS(lightPDF, brdfPDF); //MIS power heuristic weighing function

    ray_color = ComponentMult(L_energy, M_energy); // multiply the energy of the light with BRDF reflected energy
    ray_color = ComponentMult(ComponentMult(ray_color, M->base_color), isx.texture_color);
    ray_color = ray_color*W/lightPDF*glm::abs(glm::dot(isx.normal, light_sample.direction)); // and then do the solid angle PDF and the cosine
    return ray_color;
}
glm::vec3 Integrator::CalculateEnergy(const Intersection &light_sample_isx, const Intersection &isx, const Ray &light_sample, const glm::vec3 &woW)
{
    glm::vec3 ray_color(0, 0, 0);
    Material* M = isx.object_hit->material; //material of point hit
    Geometry* L = light_sample_isx.object_hit; //light source
    float dummy;
     //Intersection isx_light = L->GetIntersection(light_sample);

    ray_color = ComponentMult(L->material->EvaluateScatteredEnergy(light_sample_isx, woW, -light_sample.direction, dummy), M->EvaluateScatteredEnergy(isx, woW, light_sample.direction, dummy)); // multiply the energy of the light with BRDF reflected energy
    ray_color = ray_color/L->RayPDF(light_sample_isx, light_sample)*glm::abs(glm::dot(isx.normal, light_sample.direction)); // and then do the solid angle PDF and the cosine
    ray_color = glm::clamp(ray_color, 0.0f, 1.0f);
    return ray_color;
}
glm::vec3 DirectLightingIntegrator::BxDFPDFEnergy(const Intersection &isx, const glm::vec3 &woW, unsigned int n_light, unsigned int n_brdf)
{
    glm::vec3 ray_color(0, 0, 0);
    glm::vec3 wiW(0, 0, 0);//this will be obtained by sampling BxDf
    Material* M = isx.object_hit->material; //material of point hit
    float brdfPDF;
    float lightPDF;
    float dummy;
    float rand1 = unif_distribution(mersenne_generator);
    float rand2 = unif_distribution(mersenne_generator);
    glm::vec3 M_energy(M->SampleAndEvaluateScatteredEnergy(isx, woW, wiW, brdfPDF, rand1, rand2));
    //use sampled wiW to check if I can hit the light
    Ray shadow_feeler(isx.point, wiW);
    Intersection light_isx = intersection_engine->GetIntersection(shadow_feeler);
    Geometry* L; //this holds the intersected light source


    //terminate early if brdf pdf is zero;
    if (brdfPDF <= 0.0f) return ray_color;
    if (light_isx.object_hit == NULL)//if ray didnt hit anything
        return ray_color;
    if (light_isx.object_hit->material->is_light_source)
    {
        L = light_isx.object_hit;
        lightPDF = L->RayPDF(light_isx, shadow_feeler);
        if (lightPDF <= 0)
        {
            return ray_color;
        }
        glm::vec3 L_energy(L->material->EvaluateScatteredEnergy(light_isx, woW, -shadow_feeler.direction, dummy));
        float W = MIS(brdfPDF, lightPDF);

        ray_color = ComponentMult(L_energy, M_energy);
        ray_color = ComponentMult(ComponentMult(ray_color, M->base_color), isx.texture_color);
        ray_color = ray_color*W/brdfPDF*glm::abs(glm::dot(isx.normal, shadow_feeler.direction));
        return ray_color;
    }
    else
    {
        return ray_color;
    }

}
Exemple #4
0
static unsigned int ray_color(const point3 e, double t,
                              const point3 d,
                              idx_stack *stk,
                              const rectangular_node rectangulars,
                              const sphere_node spheres,
                              const light_node lights,
                              color object_color, int bounces_left)
{
    rectangular_node hit_rec = NULL, light_hit_rec = NULL;
    sphere_node hit_sphere = NULL, light_hit_sphere = NULL;
    double diffuse, specular;
    point3 l, _l, r, rr;
    object_fill fill;

    color reflection_part;
    color refraction_part;
    /* might be a reflection ray, so check how many times we've bounced */
    if (bounces_left == 0) {
        SET_COLOR(object_color, 0.0, 0.0, 0.0);
        return 0;
    }

    /* check for intersection with a sphere or a rectangular */
    intersection ip= ray_hit_object(e, d, t, MAX_DISTANCE, rectangulars,
                                    &hit_rec, spheres, &hit_sphere);
    if (!hit_rec && !hit_sphere)
        return 0;

    /* pick the fill of the object that was hit */
    fill = hit_rec ?
           hit_rec->element.rectangular_fill :
           hit_sphere->element.sphere_fill;

    void *hit_obj = hit_rec ? (void *) hit_rec : (void *) hit_sphere;

    /* assume it is a shadow */
    SET_COLOR(object_color, 0.0, 0.0, 0.0);

    for (light_node light = lights; light; light = light->next) {
        /* calculate the intersection vector pointing at the light */
        subtract_vector(ip.point, light->element.position, l);
        multiply_vector(l, -1, _l);
        normalize(_l);
        /* check for intersection with an object. use ignore_me
         * because we don't care about this normal
        */
        ray_hit_object(ip.point, _l, MIN_DISTANCE, length(l),
                       rectangulars, &light_hit_rec,
                       spheres, &light_hit_sphere);
        /* the light was not block by itself(lit object) */
        if (light_hit_rec || light_hit_sphere)
            continue;

        compute_specular_diffuse(&diffuse, &specular, d, l,
                                 ip.normal, fill.phong_power);

        localColor(object_color, light->element.light_color,
                   diffuse, specular, &fill);
    }

    reflection(r, d, ip.normal);
    double idx = idx_stack_top(stk).idx, idx_pass = fill.index_of_refraction;
    if (idx_stack_top(stk).obj == hit_obj) {
        idx_stack_pop(stk);
        idx_pass = idx_stack_top(stk).idx;
    } else {
        idx_stack_element e = { .obj = hit_obj,
                                .idx = fill.index_of_refraction
                              };
        idx_stack_push(stk, e);
    }

    refraction(rr, d, ip.normal, idx, idx_pass);
    double R = (fill.T > 0.1) ?
               fresnel(d, rr, ip.normal, idx, idx_pass) :
               1.0;

    /* totalColor = localColor +
                    mix((1-fill.Kd) * fill.R * reflection, T * refraction, R)
     */
    if (fill.R > 0) {
        /* if we hit something, add the color */
        int old_top = stk->top;
        if (ray_color(ip.point, MIN_DISTANCE, r, stk, rectangulars, spheres,
                      lights, reflection_part,
                      bounces_left - 1)) {
            multiply_vector(reflection_part, R * (1.0 - fill.Kd) * fill.R,
                            reflection_part);
            add_vector(object_color, reflection_part,
                       object_color);
        }
        stk->top = old_top;
    }
    /* calculate refraction ray */
    if ((length(rr) > 0.0) && (fill.T > 0.0) &&
            (fill.index_of_refraction > 0.0)) {
        normalize(rr);
        if (ray_color(ip.point, MIN_DISTANCE, rr, stk,rectangulars, spheres,
                      lights, refraction_part,
                      bounces_left - 1)) {
            multiply_vector(refraction_part, (1 - R) * fill.T,
                            refraction_part);
            add_vector(object_color, refraction_part,
                       object_color);
        }
    }

    protect_color_overflow(object_color);
    return 1;
}

/* @param background_color this is not ambient light */
void raytracing(void* args)
{
    arg *data = (arg*) args;
    point3 u, v, w, d;
    color object_color = { 0.0, 0.0, 0.0 };

    const viewpoint *view = (*data).View;
    color back = { 0.0 , 0.1 , 0.1 };
    uint8_t *pixels = data->pixels;
    int start_j,end_j;

    /*	Separate to count the pixels  */
    if(pthread_equal(pthread_self(),THREAD[0])) {
        start_j = 0;
        end_j = 128;
    } else if(pthread_equal(pthread_self(),THREAD[1])) {
        start_j = 128;
        end_j = 256;
    } else if(pthread_equal(pthread_self(),THREAD[2])) {
        start_j = 256;
        end_j = 384;
    } else if(pthread_equal(pthread_self(),THREAD[3])) {
        start_j = 384;
        end_j = 512;
    }

    /* calculate u, v, w */
    calculateBasisVectors(u, v, w, view);

    idx_stack stk;

    int factor = sqrt(SAMPLES);

    #pragma omp parallel for num_threads(64)	\
    private(stk), private(d),	\
    private(object_color)
    for (int j = start_j ; j < end_j; j++) {
        for (int i = 0 ; i < (*data).row; i++) {
            double r = 0, g = 0, b = 0;
            /* MSAA */
            for (int s = 0; s < SAMPLES; s++) {
                idx_stack_init(&stk);
                rayConstruction(d, u, v, w,
                                i * factor + s / factor,
                                j * factor + s % factor,
                                view,
                                (*data).row * factor, (*data).col * factor);
                if (ray_color(view->vrp, 0.0, d, &stk,(*data).rectangulars,
                              (*data).spheres, (*data).lights, object_color,
                              MAX_REFLECTION_BOUNCES)) {
                    r += object_color[0];
                    g += object_color[1];
                    b += object_color[2];
                } else {
                    r += back[0];
                    g += back[1];
                    b += back[2];
                }
                pixels[((i + (j * (*data).row)) * 3) + 0] = r * 255 / SAMPLES;
                pixels[((i + (j * (*data).row)) * 3) + 1] = g * 255 / SAMPLES;
                pixels[((i + (j * (*data).row)) * 3) + 2] = b * 255 / SAMPLES;
            }
        }
    }
}
Exemple #5
0
void
ray_trace(void)
{
    vec3    forward_vector, right_vector, up_vector;
    int     i, j;
    float   image_plane_width, image_plane_height;
    vec3    color;
    char    buf[128];

    struct timeval  t0, t1;
    float           time_taken;

    fprintf(stderr, "Ray tracing ...");
    gettimeofday(&t0, NULL);

    num_rays_shot = num_shadow_rays_shot = num_triangles_tested = num_bboxes_tested = 0;

    // Compute camera coordinate system from camera position
    // and look-at point
    up_vector = v3_create(0, 0, 1);
    forward_vector = v3_normalize(v3_subtract(scene_camera_lookat, scene_camera_position));
    right_vector = v3_normalize(v3_crossprod(forward_vector, up_vector));
    up_vector = v3_crossprod(right_vector, forward_vector);

    // Compute size of image plane from the chosen field-of-view
    // and image aspect ratio. This is the size of the plane at distance
    // of one unit from the camera position.
    image_plane_height = 2.0 * tan(0.5*VFOV/180*M_PI);
    image_plane_width = image_plane_height * (1.0 * framebuffer_width / framebuffer_height);

    vec3 d, e, u, v, w, ud, vd;
    float l, r, b, t, nx, ny;
    // direction d, origin e
    // ONB u, v, w
    // image plane edges l, r, b, t
    // window size nx, ny
    e = scene_camera_position;
    u = right_vector, v = up_vector, w = v3_negate(forward_vector);
    l = -0.5 * image_plane_width, r = 0.5 * image_plane_width;
    b = 0.5 * image_plane_height, t = -0.5 * image_plane_height;
    nx = framebuffer_width, ny = framebuffer_height;

    // Loop over all pixels in the framebuffer
    for (j = 0; j < ny; j++) {
        for (i = 0; i < nx; i++) {

            ud = v3_multiply(u, (l + (r - l) * ((i + 0.5) / nx)));
            vd = v3_multiply(v, (b + (t - b) * ((j + 0.5) / ny)));
            d = v3_add(v3_add(ud, vd), v3_negate(w));
            color = ray_color(0, e, d);
            put_pixel(i, j, color.x, color.y, color.z);

        }

        sprintf(buf, "Ray-tracing ::: %.0f%% done", 100.0*j/framebuffer_height);
        glutSetWindowTitle(buf);
    }

    // Done!
    gettimeofday(&t1, NULL);

    glutSetWindowTitle("Ray-tracing ::: done");

    // Output some statistics
    time_taken = 1.0 * (t1.tv_sec - t0.tv_sec) + (t1.tv_usec - t0.tv_usec) / 1000000.0;

    fprintf(stderr, " done in %.1f seconds\n", time_taken);
    fprintf(stderr, "... %lld total rays shot, of which %d camera rays and "
            "%lld shadow rays\n", num_rays_shot,
            do_antialiasing ? 4*framebuffer_width*framebuffer_height :
                              framebuffer_width*framebuffer_height,
            num_shadow_rays_shot);
    fprintf(stderr, "... %lld triangles intersection tested "
            "(avg %.1f tri/ray)\n",
        num_triangles_tested, 1.0*num_triangles_tested/num_rays_shot);
    fprintf(stderr, "... %lld bboxes intersection tested (avg %.1f bbox/ray)\n",
        num_bboxes_tested, 1.0*num_bboxes_tested/num_rays_shot);
}
Exemple #6
0
// Returns final color
uint8_t raytrace(vec3 pos, vec3 dir, hit* info) {
    // Finish early if there's no direction
    if (dir.x == 0.0f && dir.y == 0.0f && dir.z == 0.0f) {
        goto nohit;
    }

    vec3 start = pos;

    int x = (int) pos.x;
    int y = (int) pos.y;
    int z = (int) pos.z;

    int x_dir = dir.x >= 0.0f ? 1 : -1;
    int y_dir = dir.y >= 0.0f ? 1 : -1;
    int z_dir = dir.z >= 0.0f ? 1 : -1;

    float dx_off = x_dir > 0 ? 1.0f : 0.0f;
    float dy_off = y_dir > 0 ? 1.0f : 0.0f;
    float dz_off = z_dir > 0 ? 1.0f : 0.0f;

    int x_face = x_dir > 0 ? FACE_LEFT : FACE_RIGHT;
    int y_face = y_dir > 0 ? FACE_BOTTOM : FACE_TOP;
    int z_face = z_dir > 0 ? FACE_BACK : FACE_FRONT;

    int face = FACE_TOP;

    // Assumption is made that the camera is never outside the world
    while (IN_WORLD(x, y, z)) {
        // Determine if block is solid
        if (get_block(x, y, z) != BLOCK_AIR) {
            float dx = start.x - pos.x;
            float dy = start.y - pos.y;
            float dz = start.z - pos.z;
            float dist = dx*dx + dy*dy + dz*dz;

            vec3 relPos = pos;
            relPos.x -= x;
            relPos.y -= y;
            relPos.z -= z;

            // If hit info is requested, no color computation is done
            if (info != NULL) {
                int nx, ny, nz;
                face_normal(face, &nx, &ny, &nz);

                info->hit = true;
                info->x = x;
                info->y = y;
                info->z = z;
                info->nx = nx;
                info->ny = ny;
                info->nz = nz;
                info->dist = dist;

                return 0;
            }

            int tex = tex_index(relPos, face);

            return ray_color(x, y, z, pos, tex, face);
        }

        // Remaining distance inside this block given ray direction
        float dx = x - pos.x + dx_off;
        float dy = y - pos.y + dy_off;
        float dz = z - pos.z + dz_off;

        // Calculate distance for each dimension
        float t1 = dx / dir.x;
        float t2 = dy / dir.y;
        float t3 = dz / dir.z;

        // Find closest hit
        if (t1 <= t2 && t1 <= t3) {
            pos.x += dx;
            pos.y += t1 * dir.y;
            pos.z += t1 * dir.z;
            x += x_dir;
            face = x_face;
        }
        if (t2 <= t1 && t2 <= t3) {
            pos.x += t2 * dir.x;
            pos.y += dy;
            pos.z += t2 * dir.z;
            y += y_dir;
            face = y_face;
        }
        if (t3 <= t1 && t3 <= t2) {
            pos.x += t3 * dir.x;
            pos.y += t3 * dir.y;
            pos.z += dz;
            z += z_dir;
            face = z_face;
        }
    }

nohit:
    if (info != NULL) {
        info->hit = false;
    }

    // Sky color
    return skyColor;
}
Exemple #7
0
void
ray_trace(void)
{
    vec3    forward_vector, right_vector, up_vector;
    int     i, j;
    float   image_plane_width, image_plane_height;
    vec3    color;
    char    buf[128];

    struct timeval  t0, t1;
    float           time_taken;

    fprintf(stderr, "Ray tracing ...");
    gettimeofday(&t0, NULL);

    num_rays_shot = num_shadow_rays_shot = num_triangles_tested = num_bboxes_tested = 0;

    // Compute camera coordinate system from camera position
    // and look-at point
    up_vector = v3_create(0, 0, 1);
    forward_vector = v3_normalize(v3_subtract(scene_camera_lookat, scene_camera_position));
    right_vector = v3_normalize(v3_crossprod(forward_vector, up_vector));
    up_vector = v3_crossprod(right_vector, forward_vector);

    // Compute size of image plane from the chosen field-of-view
    // and image aspect ratio. This is the size of the plane at distance
    // of one unit from the camera position.
    image_plane_height = 2.0 * tan(0.5*VFOV/180*M_PI);
    image_plane_width = image_plane_height * (1.0 * framebuffer_width / framebuffer_height);

    // vector points to the middle of the monitor
    vec3 plane_center = v3_add(scene_camera_position, forward_vector);

    // vector points to the left side of the monitor    
    vec3 le_unnormalized = v3_multiply(right_vector, -(image_plane_width / 2.0));

    // vector points to the up side of the monitor
    vec3 up_unnormalized = v3_multiply(up_vector, image_plane_height / 2.0);
    
    // vector points to the coordinates 0,0 (left up) of the monitor
    vec3 left_up = v3_add(plane_center, v3_add(le_unnormalized, up_unnormalized));
    
    // vector points to right, and has length equal to width of a pixel
    vec3 pixel2pixel_x = v3_multiply(right_vector, (image_plane_width  / framebuffer_width));

    // vector points to down, and has length equal to height of a pixel
    vec3 pixel2pixel_y = v3_multiply(up_vector,  -(image_plane_height / framebuffer_height));
    
    // ANTI-ALIASING LOOP
    if (do_antialiasing) {
    
      // loop over all pixels in the framebuffer
      for (j = 0; j < framebuffer_height; j++) {
          for (i = 0; i < framebuffer_width; i++) {
              // for each pixel, shoot four rays
              vec3 ray_direction_00 = v3_add(v3_add(left_up, v3_multiply(pixel2pixel_y, j + 0.25)), v3_multiply(pixel2pixel_x, i + 0.25));
              vec3 ray_direction_01 = v3_add(v3_add(left_up, v3_multiply(pixel2pixel_y, j + 0.75)), v3_multiply(pixel2pixel_x, i + 0.25));
              vec3 ray_direction_10 = v3_add(v3_add(left_up, v3_multiply(pixel2pixel_y, j + 0.25)), v3_multiply(pixel2pixel_x, i + 0.75));
              vec3 ray_direction_11 = v3_add(v3_add(left_up, v3_multiply(pixel2pixel_y, j + 0.75)), v3_multiply(pixel2pixel_x, i + 0.75));
              
              // for each ray fired, get the difference
              ray_direction_00 = v3_subtract(ray_direction_00, scene_camera_position);
              ray_direction_01 = v3_subtract(ray_direction_01, scene_camera_position);
              ray_direction_10 = v3_subtract(ray_direction_10, scene_camera_position);
              ray_direction_11 = v3_subtract(ray_direction_11, scene_camera_position);        
                       
              // add the colors of the four rays, then divide by four
              color = ray_color(0, scene_camera_position, ray_direction_00);
              color = v3_add(color, ray_color(0, scene_camera_position, ray_direction_01));
              color = v3_add(color, ray_color(0, scene_camera_position, ray_direction_10));
              color = v3_add(color, ray_color(0, scene_camera_position, ray_direction_11));
              color = v3_multiply(color, 0.25);            
              
              // output pixel color
              put_pixel(i, j, color.x, color.y, color.z);
          
          }

          sprintf(buf, "Ray-tracing (AA enabled) ::: %.0f%% done", 100.0*j/framebuffer_height);
          glutSetWindowTitle(buf);
      }
    
    }
    
    // NON-ANTI-ALIASING LOOP
    
    else {

      // loop over all pixels in the framebuffer
      for (j = 0; j < framebuffer_height; j++) {
          for (i = 0; i < framebuffer_width; i++) {
              // select the currently relevant pixel
              vec3 ray_direction = v3_add(v3_add(left_up, v3_multiply(pixel2pixel_y, j + 0.5)), v3_multiply(pixel2pixel_x, i + 0.5));
              
              // get diference between the two points
              ray_direction = v3_subtract(ray_direction, scene_camera_position);
              
              // set color
              color = ray_color(0, scene_camera_position, ray_direction);
              
              // output pixel color
              put_pixel(i, j, color.x, color.y, color.z);
          
          }

          sprintf(buf, "Ray-tracing ::: %.0f%% done", 100.0*j/framebuffer_height);
          glutSetWindowTitle(buf);
      }
    
    }
    
    // set a detailed title, useful for testing
    if (use_bvh && do_antialiasing)
      glutSetWindowTitle("Ray-tracing is done. AA=yes, BVH=yes");
    else if (use_bvh && !do_antialiasing)
      glutSetWindowTitle("Ray-tracing is done. AA=no, BVH=yes");
    else if (!use_bvh && do_antialiasing)
      glutSetWindowTitle("Ray-tracing is done. AA=yes, BVH=no");
    else
      glutSetWindowTitle("Ray-tracing is done. AA=no, BVH=no");
    
    // Done!
    gettimeofday(&t1, NULL); 

    // Output some statistics
    time_taken = 1.0 * (t1.tv_sec - t0.tv_sec) + (t1.tv_usec - t0.tv_usec) / 1000000.0;

    fprintf(stderr, " done in %.1f seconds\n", time_taken);
    fprintf(stderr, "... %d total rays shot, of which %d camera rays and %d shadow rays\n",
        num_rays_shot,
        do_antialiasing ? 4*framebuffer_width*framebuffer_height : framebuffer_width*framebuffer_height,
        num_shadow_rays_shot);
    fprintf(stderr, "... %d triangles intersection tested (avg %.1f tri/ray)\n",
        num_triangles_tested, 1.0*num_triangles_tested/num_rays_shot);
    fprintf(stderr, "... %d bboxes intersection tested (avg %.1f bbox/ray)\n",
        num_bboxes_tested, 1.0*num_bboxes_tested/num_rays_shot);
}
Exemple #8
0
void
ray_trace(void)
{
    vec3    forward_vector, right_vector, up_vector;
    int     i, j;
    float   image_plane_width, image_plane_height;
    vec3    color;
    char    buf[128];

    struct timeval  t0, t1;
    float           time_taken;

    fprintf(stderr, "Ray tracing ...");
    gettimeofday(&t0, NULL);

    num_rays_shot = num_shadow_rays_shot = num_triangles_tested = num_bboxes_tested = 0;

    // Compute camera coordinate system from camera position
    // and look-at point
    up_vector = v3_create(0, 0, 1);
    forward_vector = v3_normalize(v3_subtract(scene_camera_lookat, scene_camera_position));
    right_vector = v3_normalize(v3_crossprod(forward_vector, up_vector));
    up_vector = v3_crossprod(right_vector, forward_vector);

    // Compute size of image plane from the chosen field-of-view
    // and image aspect ratio. This is the size of the plane at distance
    // of one unit from the camera position.
    image_plane_height = 2.0 * tan(0.5*VFOV/180*M_PI);
    image_plane_width = image_plane_height * (1.0 * framebuffer_width / framebuffer_height);

    printf("imageplane: (%f, %f)\n", image_plane_width, image_plane_height);

    // the borders of the image plane in camera coordinates
    float left = -(image_plane_width / 2),
          right = image_plane_width / 2,
          bottom = (image_plane_height / 2),
          top = -image_plane_height / 2;

    // rays are expressed as a location vector and direction vector
    vec3 ray_origin = scene_camera_position;
    float u, v, w;

    // Loop over all pixels in the framebuffer
    for (j = 0; j < framebuffer_height; j++)
    {
        for (i = 0; i < framebuffer_width; i++)
        {
            vec3 directions[4];
            int directions_i = 0;
            float offsets[2];
            int offsets_n;

            // if anti-aliasing is activated, shoot 4 rays through each pixel
            // slightly offset from the center
            if (do_antialiasing) {
                offsets_n = 2;
                offsets[0] = 0.25;
                offsets[1] = 0.75;
            }

            // without anti-aliasing, just send a single ray through the
            // pixel-center
            else {
                offsets_n = 1;
                offsets[0] = 0.5;
            }

            // calculate the [u, v, w] components of the pixel's location
            // relative to the camera
            for (int u_offset = 0; u_offset < offsets_n; ++u_offset) {
                for (int v_offset = 0; v_offset < offsets_n; ++v_offset) {
                    w = 1;
                    u = left + (right - left) * (i + offsets[u_offset]) / framebuffer_width;
                    v = bottom + (top - bottom) * (j + offsets[v_offset]) / framebuffer_height;

                    // the direction of the ray is a a linear combination of the camera
                    // basisvectors
                    directions[directions_i] = v3_add3(v3_multiply(forward_vector, w),
                                                       v3_multiply(right_vector, u),
                                                       v3_multiply(up_vector, v));
                    directions_i += 1;
                }
            }


            // Output average pixel color
            color = v3_create(0.0, 0.0, 0.0);
            int num_directions = do_antialiasing ? 2 * offsets_n : 1;
            for (int dir = 0; dir < num_directions; ++dir) {
                color = v3_add(color, ray_color(0, ray_origin, directions[dir]) );
            }

            color = v3_multiply(color, 1.0 / num_directions);

            put_pixel(i, j, color.x, color.y, color.z);
        }

        sprintf(buf, "Ray-tracing ::: %.0f%% done", 100.0*j/framebuffer_height);
        glutSetWindowTitle(buf);
    }

    // Done!
    gettimeofday(&t1, NULL);

    glutSetWindowTitle("Ray-tracing ::: done");

    // Output some statistics
    time_taken = 1.0 * (t1.tv_sec - t0.tv_sec) + (t1.tv_usec - t0.tv_usec) / 1000000.0;

    fprintf(stderr, " done in %.1f seconds\n", time_taken);
    fprintf(stderr, "... %d total rays shot, of which %d camera rays and %d shadow rays\n",
        num_rays_shot,
        do_antialiasing ? 4*framebuffer_width*framebuffer_height : framebuffer_width*framebuffer_height,
        num_shadow_rays_shot);
    fprintf(stderr, "... %d triangles intersection tested (avg %.1f tri/ray)\n",
        num_triangles_tested, 1.0*num_triangles_tested/num_rays_shot);
    fprintf(stderr, "... %d bboxes intersection tested (avg %.1f bbox/ray)\n",
        num_bboxes_tested, 1.0*num_bboxes_tested/num_rays_shot);
}
Exemple #9
0
void
ray_trace(void)
{
    vec3    forward_vector, right_vector, up_vector;
    int     i, j;
    float   image_plane_width, image_plane_height;
    vec3    color;
    char    buf[128];

    struct timeval  t0, t1;
    float           time_taken;

    fprintf(stderr, "Ray tracing ...");
    gettimeofday(&t0, NULL);

    num_rays_shot = num_shadow_rays_shot = num_triangles_tested = num_bboxes_tested = 0;

    // Compute camera coordinate system from camera position
    // and look-at point
    up_vector = v3_create(0, 0, 1);
    forward_vector = v3_normalize(v3_subtract(scene_camera_lookat, scene_camera_position));
    right_vector = v3_normalize(v3_crossprod(forward_vector, up_vector));
    up_vector = v3_crossprod(right_vector, forward_vector);

    // Compute size of image plane from the chosen field-of-view
    // and image aspect ratio. This is the size of the plane at distance
    // of one unit from the camera position.
    image_plane_height = 2.0 * tan(0.5*VFOV/180*M_PI);
    image_plane_width = image_plane_height * (1.0 * framebuffer_width / framebuffer_height);

    float bottom, left, Us, Vs;

    left = -image_plane_width * 0.5;
    bottom = image_plane_height * 0.5;

    fprintf(stderr, "%d %d\r\n", framebuffer_height, framebuffer_width);

    // Loop over all pixels in the framebuffer
    for (j = 0; j < framebuffer_height; j++)
    {
        for (i = 0; i < framebuffer_width; i++)
        {
            
            if(!do_antialiasing){
                /* With the formula "b + (t−b) * ((j+ 0.5) / ny)" the vector is calculated.
                 * (t-b) equals the negative image_plane_height
                 */
                Us = bottom + (-image_plane_height*(j+0.5)/framebuffer_height);

                /* using the formula: "l + (r−l) * ((i+ 0.5) / nx)" to calculate the vector
                 * (r-l) equals the image_plane_width.
                 */
                Vs = left + (image_plane_width*(i+0.5)/framebuffer_width);

                /*
                /* Calculate the vector through the pixel (for "Ray through pixel")
                 * Using the formula "Us * U + Vs * v + n * w"
                 */
                vec3 UV = v3_add(v3_multiply(up_vector, Us), v3_multiply(right_vector, Vs));
                vec3 ray = v3_add(forward_vector, UV);

                /* Fills the color */
                color = ray_color(0, scene_camera_position, ray);
            } else {
                float Us1 = bottom + (-image_plane_height*(j+0.25)/framebuffer_height);
                float Us2 = bottom + (-image_plane_height*(j+0.75)/framebuffer_height);
                float Vs1 = left + (image_plane_width*(i+0.25)/framebuffer_width);
                float Vs2 = left + (image_plane_width*(i+0.75)/framebuffer_width);
                
                vec3 UV1 = v3_add(v3_multiply(up_vector, Us1), v3_multiply(right_vector, Vs1));
                vec3 UV2 = v3_add(v3_multiply(up_vector, Us2), v3_multiply(right_vector, Vs1));
                vec3 UV3 = v3_add(v3_multiply(up_vector, Us1), v3_multiply(right_vector, Vs2));
                vec3 UV4 = v3_add(v3_multiply(up_vector, Us2), v3_multiply(right_vector, Vs2));
                
                vec3 color1 = ray_color(0, scene_camera_position, v3_add(forward_vector, UV1));
                vec3 color2 = ray_color(0, scene_camera_position, v3_add(forward_vector, UV2));
                vec3 color3 = ray_color(0, scene_camera_position, v3_add(forward_vector, UV3));
                vec3 color4 = ray_color(0, scene_camera_position, v3_add(forward_vector, UV4));
                
                color = v3_multiply( v3_add(v3_add(color1, color2), v3_add(color3, color4)), 0.25 );
            }

            /* Output pixel color */
            put_pixel(i, j, color.x, color.y, color.z);
        }

        sprintf(buf, "Ray-tracing ::: %.0f%% done", 100.0*j/framebuffer_height);
        glutSetWindowTitle(buf);
    }

    // Done!
    gettimeofday(&t1, NULL);

    glutSetWindowTitle("Ray-tracing ::: done");

    // Output some statistics
    time_taken = 1.0 * (t1.tv_sec - t0.tv_sec) + (t1.tv_usec - t0.tv_usec) / 1000000.0;

    fprintf(stderr, " done in %.1f seconds\n", time_taken);
    fprintf(stderr, "... %lld total rays shot, of which %d camera rays and "
            "%lld shadow rays\n", num_rays_shot,
            do_antialiasing ? 4*framebuffer_width*framebuffer_height :
                              framebuffer_width*framebuffer_height,
            num_shadow_rays_shot);
    fprintf(stderr, "... %lld triangles intersection tested "
            "(avg %.1f tri/ray)\n",
        num_triangles_tested, 1.0*num_triangles_tested/num_rays_shot);
    fprintf(stderr, "... %lld bboxes intersection tested (avg %.1f bbox/ray)\n",
        num_bboxes_tested, 1.0*num_bboxes_tested/num_rays_shot);
}
Exemple #10
0
static unsigned int ray_color(const point3 e, double t,
                              const point3 d,
                              idx_stack *stk,
                              const rectangular_node rectangulars,
                              const sphere_node spheres,
                              const light_node lights,
                              color object_color, int bounces_left)
{
    rectangular_node hit_rec = NULL, light_hit_rec = NULL;
    sphere_node hit_sphere = NULL, light_hit_sphere = NULL;
    double diffuse, specular;
    point3 l, _l, r, rr;
    object_fill fill;

    color reflection_part;
    color refraction_part;
    /* might be a reflection ray, so check how many times we've bounced */
    if (bounces_left == 0) {
        SET_COLOR(object_color, 0.0, 0.0, 0.0);
        return 0;
    }

    /* check for intersection with a sphere or a rectangular */
    intersection ip= ray_hit_object(e, d, t, MAX_DISTANCE, rectangulars,
                                    &hit_rec, spheres, &hit_sphere);
    if (!hit_rec && !hit_sphere)
        return 0;

    /* pick the fill of the object that was hit */
    fill = hit_rec ?
           hit_rec->element.rectangular_fill :
           hit_sphere->element.sphere_fill;

    void *hit_obj = hit_rec ? (void *) hit_rec : (void *) hit_sphere;

    /* assume it is a shadow */
    SET_COLOR(object_color, 0.0, 0.0, 0.0);

    for (light_node light = lights; light; light = light->next) {
        /* calculate the intersection vector pointing at the light */
        subtract_vector(ip.point, light->element.position, l);
        multiply_vector(l, -1, _l);
        normalize(_l);
        /* check for intersection with an object. use ignore_me
         * because we don't care about this normal
        */
        ray_hit_object(ip.point, _l, MIN_DISTANCE, length(l),
                       rectangulars, &light_hit_rec,
                       spheres, &light_hit_sphere);
        /* the light was not block by itself(lit object) */
        if (light_hit_rec || light_hit_sphere)
            continue;

        compute_specular_diffuse(&diffuse, &specular, d, l,
                                 ip.normal, fill.phong_power);

        localColor(object_color, light->element.light_color,
                   diffuse, specular, &fill);
    }

    reflection(r, d, ip.normal);
    double idx = idx_stack_top(stk).idx, idx_pass = fill.index_of_refraction;
    if (idx_stack_top(stk).obj == hit_obj) {
        idx_stack_pop(stk);
        idx_pass = idx_stack_top(stk).idx;
    } else {
        idx_stack_element e = { .obj = hit_obj,
                                .idx = fill.index_of_refraction
                              };
        idx_stack_push(stk, e);
    }

    refraction(rr, d, ip.normal, idx, idx_pass);
    double R = (fill.T > 0.1) ?
               fresnel(d, rr, ip.normal, idx, idx_pass) :
               1.0;

    /* totalColor = localColor +
                    mix((1-fill.Kd) * fill.R * reflection, T * refraction, R)
     */
    if (fill.R > 0) {
        /* if we hit something, add the color */
        int old_top = stk->top;
        if (ray_color(ip.point, MIN_DISTANCE, r, stk, rectangulars, spheres,
                      lights, reflection_part,
                      bounces_left - 1)) {
            multiply_vector(reflection_part, R * (1.0 - fill.Kd) * fill.R,
                            reflection_part);
            add_vector(object_color, reflection_part,
                       object_color);
        }
        stk->top = old_top;
    }
    /* calculate refraction ray */
    if ((length(rr) > 0.0) && (fill.T > 0.0) &&
            (fill.index_of_refraction > 0.0)) {
        normalize(rr);
        if (ray_color(ip.point, MIN_DISTANCE, rr, stk,rectangulars, spheres,
                      lights, refraction_part,
                      bounces_left - 1)) {
            multiply_vector(refraction_part, (1 - R) * fill.T,
                            refraction_part);
            add_vector(object_color, refraction_part,
                       object_color);
        }
    }

    protect_color_overflow(object_color);
    return 1;
}

static void *parallel (void* range1)
{
    Thread_range *range = (Thread_range *)range1;

    point3 d;
    idx_stack stk;
    color object_color = { 0.0, 0.0, 0.0 };

    for (int j = range->height1; j < range->height2; j++) {
        for (int i = 0; i < range->ptr->width; i++) {
            double r = 0, g = 0, b = 0;
            /* MSAA */
            for (int s = 0; s < SAMPLES; s++) {
                idx_stack_init(&stk);
                rayConstruction(d, range->ptr->u,
				range->ptr->v, range->ptr->w,
                                i * range->ptr->factor + s / range->ptr->factor,
                                j * range->ptr->factor + s % range->ptr->factor,
                                range->ptr->view,
                                range->ptr->width * range->ptr->factor, 
				range->ptr->height * range->ptr->factor);
                if (ray_color(range->ptr->view->vrp, 0.0, d,
			      &(stk), range->ptr->rectangulars,
			      range->ptr->spheres,
                              range->ptr->lights, object_color,
                              MAX_REFLECTION_BOUNCES)) {
                    r += object_color[0];
                    g += object_color[1];
                    b += object_color[2];
                } else {
                    r += range->ptr->background_color[0];
                    g += range->ptr->background_color[1];
                    b += range->ptr->background_color[2];
                }
                range->ptr->pixels[((i + (j * range->ptr->width)) * 3) + 0] = r * 255 / SAMPLES;
                range->ptr->pixels[((i + (j * range->ptr->width)) * 3) + 1] = g * 255 / SAMPLES;
                range->ptr->pixels[((i + (j * range->ptr->width)) * 3) + 2] = b * 255 / SAMPLES;
            }
        }
    }
	return NULL;
}