Exemplo n.º 1
0
u_int64_t CPU_Worker::AdvancePhotonPath(u_int64_t photonTarget) {



    uint todoPhotonCount = 0;

    PhotonPath* livePhotonPaths = new PhotonPath[rayBuffer->GetSize()];

    rayBuffer->Reset();

    size_t initc = min((int) rayBuffer->GetSize(), (int) photonTarget);

    double start = WallClockTime();


    for (size_t i = 0; i < initc; ++i) {

        int p = rayBuffer->ReserveRay();

        Ray * b = &(rayBuffer->GetRayBuffer())[p];

        engine->InitPhotonPath(engine->ss, &livePhotonPaths[i], b, seedBuffer[i]);
    }

    while (todoPhotonCount < photonTarget) {

        Intersect(rayBuffer);

#ifndef __DEBUG
        omp_set_num_threads(config->max_threads);
        #pragma omp parallel for schedule(guided)
#endif
        for (unsigned int i = 0; i < rayBuffer->GetRayCount(); ++i) {
            PhotonPath *photonPath = &livePhotonPaths[i];
            Ray *ray = &rayBuffer->GetRayBuffer()[i];
            RayHit *rayHit = &rayBuffer->GetHitBuffer()[i];

            if (photonPath->done == true) {
                continue;
            }

            if (rayHit->Miss()) {
                photonPath->done = true;
            } else { // Something was hit

                Point hitPoint;
                Spectrum surfaceColor;
                Normal N, shadeN;

                if (engine->GetHitPointInformation(engine->ss, ray, rayHit, hitPoint, surfaceColor,
                                                   N, shadeN))
                    continue;

                const unsigned int currentTriangleIndex = rayHit->index;
                const unsigned int currentMeshIndex = engine->ss->meshIDs[currentTriangleIndex];

                POINTERFREESCENE::Material *hitPointMat =
                    &engine->ss->materials[engine->ss->meshMats[currentMeshIndex]];

                uint matType = hitPointMat->type;

                if (matType == MAT_AREALIGHT) {
                    photonPath->done = true;
                } else {

                    float fPdf;
                    Vector wi;
                    Vector wo = -ray->d;
                    bool specularBounce = true;

                    float u0 = getFloatRNG(seedBuffer[i]);
                    float u1 = getFloatRNG(seedBuffer[i]);
                    float u2 = getFloatRNG(seedBuffer[i]);

                    Spectrum f;

                    switch (matType) {

                    case MAT_MATTE:
                        engine->ss->Matte_Sample_f(&hitPointMat->param.matte, &wo, &wi, &fPdf, &f,
                                                   &shadeN, u0, u1, &specularBounce);

                        f *= surfaceColor;
                        break;

                    case MAT_MIRROR:
                        engine->ss->Mirror_Sample_f(&hitPointMat->param.mirror, &wo, &wi, &fPdf,
                                                    &f, &shadeN, &specularBounce);
                        f *= surfaceColor;
                        break;

                    case MAT_GLASS:
                        engine->ss->Glass_Sample_f(&hitPointMat->param.glass, &wo, &wi, &fPdf, &f,
                                                   &N, &shadeN, u0, &specularBounce);
                        f *= surfaceColor;

                        break;

                    case MAT_MATTEMIRROR:
                        engine->ss->MatteMirror_Sample_f(&hitPointMat->param.matteMirror, &wo, &wi,
                                                         &fPdf, &f, &shadeN, u0, u1, u2, &specularBounce);
                        f *= surfaceColor;

                        break;

                    case MAT_METAL:
                        engine->ss->Metal_Sample_f(&hitPointMat->param.metal, &wo, &wi, &fPdf, &f,
                                                   &shadeN, u0, u1, &specularBounce);
                        f *= surfaceColor;

                        break;

                    case MAT_MATTEMETAL:
                        engine->ss->MatteMetal_Sample_f(&hitPointMat->param.matteMetal, &wo, &wi,
                                                        &fPdf, &f, &shadeN, u0, u1, u2, &specularBounce);
                        f *= surfaceColor;

                        break;

                    case MAT_ALLOY:
                        engine->ss->Alloy_Sample_f(&hitPointMat->param.alloy, &wo, &wi, &fPdf, &f,
                                                   &shadeN, u0, u1, u2, &specularBounce);
                        f *= surfaceColor;

                        break;

                    case MAT_ARCHGLASS:
                        engine->ss->ArchGlass_Sample_f(&hitPointMat->param.archGlass, &wo, &wi,
                                                       &fPdf, &f, &N, &shadeN, u0, &specularBounce);
                        f *= surfaceColor;

                        break;

                    case MAT_NULL:
                        wi = ray->d;
                        specularBounce = 1;
                        fPdf = 1.f;
                        break;

                    default:
                        // Huston, we have a problem...
                        specularBounce = 1;
                        fPdf = 0.f;
                        break;
                    }

                    if (!specularBounce) // if difuse
                        lookupA->AddFlux(engine->ss, engine->alpha, hitPoint, shadeN, -ray->d,
                                         photonPath->flux, currentPhotonRadius2);

                    if (photonPath->depth < MAX_PHOTON_PATH_DEPTH) {
                        // Build the next vertex path ray
                        if ((fPdf <= 0.f) || f.Black()) {
                            photonPath->done = true;
                        } else {
                            photonPath->depth++;
                            photonPath->flux *= f / fPdf;

                            // Russian Roulette
                            const float p = 0.75f;
                            if (photonPath->depth < 3) {
                                *ray = Ray(hitPoint, wi);
                            } else if (getFloatRNG(seedBuffer[i]) < p) {
                                photonPath->flux /= p;
                                *ray = Ray(hitPoint, wi);
                            } else {
                                photonPath->done = true;
                            }
                        }
                    } else {
                        photonPath->done = true;
                    }
                }
            }
        }

        uint oldc = rayBuffer->GetRayCount();

        rayBuffer->Reset();

        for (unsigned int i = 0; i < oldc; ++i) {

            PhotonPath *photonPath = &livePhotonPaths[i];
            Ray *ray = &rayBuffer->GetRayBuffer()[i];

            if (photonPath->done && todoPhotonCount < photonTarget) {
                todoPhotonCount++;

                Ray n;
                engine->InitPhotonPath(engine->ss, photonPath, &n, seedBuffer[i]);

                livePhotonPaths[i].done = false;

                size_t p = rayBuffer->AddRay(n);
                livePhotonPaths[p] = *photonPath;

            } else if (!photonPath->done) {
                rayBuffer->AddRay(*ray);
            }
        }
    }


//	float MPhotonsSec = todoPhotonCount / ((WallClockTime()-start) * 1000000.f);

    //printf("\nRate: %.3f MPhotons/sec\n",MPhotonsSec);


    profiler->addPhotonTracingTime(WallClockTime() - start);
    profiler->addPhotonsTraced(todoPhotonCount);

    rayBuffer->Reset();

    return todoPhotonCount;
}
Exemplo n.º 2
0
void advance_eye_paths_impl(
    HitPointPosition* const hit_points, //const unsigned hit_points_count
    EyePath*  const eye_paths,            const unsigned eye_paths_count,
    Seed*     const seed_buffer,          //const unsigned seed_buffer_count,
    const PtrFreeScene* const scene,
    const unsigned max_eye_path_depth,
    const unsigned num_threads) {

  #pragma omp parallel for num_threads(num_threads)
  for(unsigned i = 0; i < eye_paths_count; ++i) {
    EyePath& eye_path = eye_paths[i];
    Ray&   ray = eye_path.ray; // rays[i];
    RayHit hit;                // = hits[i];

    while(!eye_path.done) {
      hit.SetMiss();
      scene->intersect(ray, hit);

      if (eye_path.depth > max_eye_path_depth) {
        // make it done
        HitPointPosition& hp = hit_points[eye_path.sample_index];
        hp.type = CONSTANT_COLOR;
        hp.scr_x = eye_path.scr_x;
        hp.scr_y = eye_path.scr_y;
        hp.throughput = Spectrum();

        eye_path.done = true;
      } else {
        eye_path.depth++;
      }

      if (hit.Miss()) {
        // add a hit point
        HitPointPosition& hp = hit_points[eye_path.sample_index];
        hp.type = CONSTANT_COLOR;
        hp.scr_x = eye_path.scr_x;
        hp.scr_y = eye_path.scr_y;

        if (scene->infinite_light.exists || scene->sun_light.exists || scene->sky_light.exists) {
          if (scene->infinite_light.exists) {
            // TODO check this
            helpers::infinite_light_le(hp.throughput, eye_path.ray.d, scene->infinite_light, scene->infinite_light_map);
          }
          if (scene->sun_light.exists) {
            // TODO check this
            helpers::sun_light_le(hp.throughput, eye_path.ray.d, scene->sun_light);
          }
          if (scene->sky_light.exists) {
            // TODO check this
            helpers::sky_light_le(hp.throughput, eye_path.ray.d, scene->sky_light);
          }
          hp.throughput *= eye_path.flux;
        } else {
          hp.throughput = Spectrum();
        }
        eye_path.done = true;
      } else {

        // something was hit
        Point hit_point;
        Spectrum surface_color;
        Normal N, shade_N;

        if (helpers::get_hit_point_information(scene, eye_path.ray, hit, hit_point, surface_color, N, shade_N)) {
          continue;
        }

        // get the material
        const unsigned current_triangle_index = hit.index;
        const unsigned current_mesh_index = scene->mesh_ids[current_triangle_index];
        const unsigned material_index = scene->mesh_materials[current_mesh_index];
        const Material& hit_point_mat = scene->materials[material_index];
        unsigned mat_type = hit_point_mat.type;

        if (mat_type == MAT_AREALIGHT) {
          // add a hit point
          HitPointPosition &hp = hit_points[eye_path.sample_index];

          hp.type = CONSTANT_COLOR;
          hp.scr_x = eye_path.scr_x;
          hp.scr_y = eye_path.scr_y;

          Vector md = - eye_path.ray.d;
          helpers::area_light_le(hp.throughput, md, N, hit_point_mat.param.area_light);
          hp.throughput *= eye_path.flux;
          eye_path.done = true;
        } else {
          Vector wo = - eye_path.ray.d;
          float material_pdf;

          Vector wi;
          bool specular_material = true;
          float u0 = floatRNG(seed_buffer[eye_path.sample_index]);
          float u1 = floatRNG(seed_buffer[eye_path.sample_index]);
          float u2 = floatRNG(seed_buffer[eye_path.sample_index]);
          Spectrum f;


          helpers::generic_material_sample_f(hit_point_mat, wo, wi, N, shade_N, u0, u1, u2, material_pdf, f, specular_material);
          f *= surface_color;

          if ((material_pdf <= 0.f) || f.Black()) {
            // add a hit point
            HitPointPosition& hp = hit_points[eye_path.sample_index];
            hp.type = CONSTANT_COLOR;
            hp.scr_x = eye_path.scr_x;
            hp.scr_y = eye_path.scr_y;
            hp.throughput = Spectrum();
          } else if (specular_material || (!hit_point_mat.diffuse)) {
            eye_path.flux *= f / material_pdf;
            eye_path.ray = Ray(hit_point, wi);
          } else {
            // add a hit point
            HitPointPosition& hp = hit_points[eye_path.sample_index];
            hp.type = SURFACE;
            hp.scr_x = eye_path.scr_x;
            hp.scr_y = eye_path.scr_y;
            hp.material_ss   = material_index;
            hp.throughput = eye_path.flux * surface_color;
            hp.position = hit_point;
            hp.wo = - eye_path.ray.d;
            hp.normal = shade_N;
            eye_path.done = true;
          }
        }
      }
    }
  }
}