示例#1
0
void AggregateTest::Render(const Scene *scene) {
    RNG rng;
    ProgressReporter prog(nIterations, "Aggregate Test");
    // Compute bounding box of region used to generate random rays
    BBox bbox = scene->WorldBound();
    bbox.Expand(bbox.pMax[bbox.MaximumExtent()] -
                bbox.pMin[bbox.MaximumExtent()]);
    Point lastHit;
    float lastEps = 0.f;
    for (int i = 0; i < nIterations; ++i) {
        // Choose random rays, _rayAccel_ and _rayAll_ for testing

        // Choose ray origin for testing accelerator
        Point org(Lerp(rng.RandomFloat(), bbox.pMin.x, bbox.pMax.x),
                  Lerp(rng.RandomFloat(), bbox.pMin.y, bbox.pMax.y),
                  Lerp(rng.RandomFloat(), bbox.pMin.z, bbox.pMax.z));
        if ((rng.RandomUInt() % 4) == 0) org = lastHit;

        // Choose ray direction for testing accelerator
        Vector dir = UniformSampleSphere(rng.RandomFloat(), rng.RandomFloat());
        if ((rng.RandomUInt() % 32) == 0) dir.x = dir.y = 0.f;
        else if ((rng.RandomUInt() % 32) == 0) dir.x = dir.z = 0.f;
        else if ((rng.RandomUInt() % 32) == 0) dir.y = dir.z = 0.f;

        // Choose ray epsilon for testing accelerator
        float eps = 0.f;
        if (rng.RandomFloat() < .25) eps = lastEps;
        else if (rng.RandomFloat() < .25) eps = 1e-3f;
        Ray rayAccel(org, dir, eps);
        Ray rayAll = rayAccel;

        // Compute intersections using accelerator and exhaustive testing
        Intersection isectAccel, isectAll;
        bool hitAccel = scene->Intersect(rayAccel, &isectAccel);
        bool hitAll = false;
        bool inconsistentBounds = false;
        for (u_int j = 0; j < primitives.size(); ++j) {
            if (bboxes[j].IntersectP(rayAll))
                hitAll |= primitives[j]->Intersect(rayAll, &isectAll);
            else if (primitives[j]->Intersect(rayAll, &isectAll))
                inconsistentBounds = true;
        }

        // Report any inconsistencies between intersections
        if (!inconsistentBounds &&
            ((hitAccel != hitAll) || (rayAccel.maxt != rayAll.maxt)))
            Warning("Disagreement: t accel %.16g [%a] t exhaustive %.16g [%a]\n"
                    "Ray: org [%a, %a, %a], dir [%a, %a, %a], mint = %a",
                    rayAccel.maxt, rayAll.maxt, rayAccel.maxt, rayAll.maxt,
                    rayAll.o.x, rayAll.o.y, rayAll.o.z,
                    rayAll.d.x, rayAll.d.y, rayAll.d.z, rayAll.mint);
        if (hitAll) {
            lastHit = rayAll(rayAll.maxt);
            lastEps = isectAll.RayEpsilon;
        }
        prog.Update();
    }
    prog.Done();
}
示例#2
0
void SurfacePointsRenderer::Render(const Scene &scene) {
    // Declare shared variables for Poisson point generation
    BBox octBounds = scene.WorldBound();
    octBounds.Expand(.001f * powf(octBounds.Volume(), 1.f/3.f));
    Octree<SurfacePoint> pointOctree(octBounds);

    // Create scene bounding sphere to catch rays that leave the scene
    Point sceneCenter;
    float sceneRadius;
    scene.WorldBound().BoundingSphere(&sceneCenter, &sceneRadius);
    Transform ObjectToWorld(Translate(sceneCenter - Point(0,0,0)));
    Transform WorldToObject(Inverse(ObjectToWorld));
    Reference<Shape> sph = new Sphere(&ObjectToWorld, &WorldToObject,
        true, sceneRadius, -sceneRadius, sceneRadius, 360.f);
    //Reference<Material> nullMaterial = Reference<Material>(NULL);
    Material nullMaterial;
    GeometricPrimitive sphere(sph, nullMaterial, NULL);
    int maxFails = 2000, repeatedFails = 0, maxRepeatedFails = 0;
    if (PbrtOptions.quickRender) maxFails = max(10, maxFails / 10);
    int totalPathsTraced = 0, totalRaysTraced = 0, numPointsAdded = 0;
    ProgressReporter prog(maxFails, "Depositing samples");
    // Launch tasks to trace rays to find Poisson points
    PBRT_SUBSURFACE_STARTED_RAYS_FOR_POINTS();
    vector<Task *> tasks;
    RWMutex *mutex = RWMutex::Create();
    int nTasks = NumSystemCores();
    for (int i = 0; i < nTasks; ++i)
        tasks.push_back(new SurfacePointTask(scene, pCamera, time, i,
            minDist, maxFails, *mutex, repeatedFails, maxRepeatedFails,
            totalPathsTraced, totalRaysTraced, numPointsAdded, sphere, pointOctree,
            points, prog));
    EnqueueTasks(tasks);
    WaitForAllTasks();
    for (uint32_t i = 0; i < tasks.size(); ++i)
        delete tasks[i];
    RWMutex::Destroy(mutex);
    prog.Done();
    PBRT_SUBSURFACE_FINISHED_RAYS_FOR_POINTS(totalRaysTraced, numPointsAdded);
    if (filename != "") {
        // Write surface points to file
        FILE *f = fopen(filename.c_str(), "w");
        if (!f) {
            Error("Unable to open output file \"%s\" (%s)", filename.c_str(),
                  strerror(errno));
            return;
        }

        fprintf(f, "# points generated by SurfacePointsRenderer\n");
        fprintf(f, "# position (x,y,z), normal (x,y,z), area, rayEpsilon\n");
        for (u_int i = 0; i < points.size(); ++i) {
            const SurfacePoint &sp = points[i];
            fprintf(f, "%g %g %g %g %g %g %g %g\n", sp.p.x, sp.p.y, sp.p.z,
                sp.n.x, sp.n.y, sp.n.z, sp.area, sp.rayEpsilon);
        }
        fclose(f);
    }
}
BBox OrthoCamera::Bounds() const
{
	BBox orig_bound(Point(-1, -1, 0), Point(1, 1, 0));
	// TODO - improve this
	BBox bound;
	for (int i = 1024; i >= 0; i--) {
		// ugly hack, but last thing we do is to sample StartTime, so should be ok
		const_cast<OrthoCamera*>(this)->SampleMotion(Lerp(static_cast<float>(i) / 1024.f, CameraMotion.StartTime(), CameraMotion.EndTime()));
		bound = Union(bound, ScreenToWorld * orig_bound);
	}
	bound.Expand(max(1.f, MachineEpsilon::E(bound)));
	return bound;
}
示例#4
0
TEST_F(BBoxTest, ExpandByNegativeValueWorks) {
    BBox b (Point (1, 1, 1), Point (4, 4, 4));
    float delta = -1.0;

    b.Expand (delta);

    EXPECT_EQ (2, b.pMin.x);
    EXPECT_EQ (2, b.pMin.y);
    EXPECT_EQ (2, b.pMin.z);

    EXPECT_EQ (3, b.pMax.x);
    EXPECT_EQ (3, b.pMax.y);
    EXPECT_EQ (3, b.pMax.z);
}
示例#5
0
TEST_F(BBoxTest, ExpandByPositiveValueWorks) {
    BBox b (Point (2, 2, 2), Point (3, 3, 3));
    float delta = 1.0;

    b.Expand (delta);

    EXPECT_EQ (1, b.pMin.x);
    EXPECT_EQ (1, b.pMin.y);
    EXPECT_EQ (1, b.pMin.z);

    EXPECT_EQ (4, b.pMax.x);
    EXPECT_EQ (4, b.pMax.y);
    EXPECT_EQ (4, b.pMax.z);
}
void HitPoints::Init() {
	// Not using UpdateBBox() because hp->accumPhotonRadius2 is not yet set
	BBox hpBBox = BBox();
	for (u_int i = 0; i < (*hitPoints).size(); ++i) {
		HitPoint *hp = &(*hitPoints)[i];

		if (hp->IsSurface())
			hpBBox = Union(hpBBox, hp->GetPosition());
	}

	// Calculate initial radius
	Vector ssize = hpBBox.pMax - hpBBox.pMin;
	initialPhotonRadius = renderer->sppmi->photonStartRadiusScale *
		((ssize.x + ssize.y + ssize.z) / 3.f) / sqrtf(nSamplePerPass) * 2.f;
	const float photonRadius2 = initialPhotonRadius * initialPhotonRadius;

	// Expand the bounding box by used radius
	hpBBox.Expand(initialPhotonRadius);
	// Update hit points information
	hitPointBBox = hpBBox;
	maxHitPointRadius2 = photonRadius2;

	LOG(LUX_DEBUG, LUX_NOERROR) << "Hit points bounding box: " << hitPointBBox;
	LOG(LUX_DEBUG, LUX_NOERROR) << "Hit points max. radius: " << sqrtf(maxHitPointRadius2);

	// Initialize hit points field
	for (u_int i = 0; i < (*hitPoints).size(); ++i) {
		HitPoint *hp = &(*hitPoints)[i];

		hp->accumPhotonRadius2 = photonRadius2;
	}

	// Allocate hit points lookup accelerator
	switch (renderer->sppmi->lookupAccelType) {
		case HASH_GRID:
			lookUpAccel = new HashGrid(this);
			break;
		case KD_TREE:
			lookUpAccel = new KdTree(this);
			break;
		case HYBRID_HASH_GRID:
			lookUpAccel = new HybridHashGrid(this);
			break;
		case PARALLEL_HASH_GRID:
			lookUpAccel = new ParallelHashGrid(this, renderer->sppmi->parallelHashGridSpare);
			break;
		default:
			assert (false);
	}
}
示例#7
0
BBox PerspectiveCamera::Bounds() const
{
	float lensr = max(LensRadius, 0.f);
	BBox orig_bound(Point(-lensr, -lensr, 0.f),
		Point(lensr, lensr, 0.f));
	// TODO - improve this
	BBox bound;
	for (int i = 1024; i >= 0; i--) {
		// ugly hack, but last thing we do is to sample StartTime, so should be ok
		const_cast<PerspectiveCamera*>(this)->SampleMotion(Lerp(static_cast<float>(i) / 1024.f, CameraMotion.StartTime(), CameraMotion.EndTime()));
		bound = Union(bound, CameraToWorld * orig_bound);
	}
	bound.Expand(max(1.f, MachineEpsilon::E(bound)));
	return bound;
}
示例#8
0
void Worker::InitRadius(uint iteration) {

  BBox* hitPointsbbox = GetHostBBox();

  Vector ssize = hitPointsbbox->pMax - hitPointsbbox->pMin;

  float photonRadius = ((ssize.x + ssize.y + ssize.z) / 3.f) / ((engine->width
      * engine->superSampling + engine->height * engine->superSampling) / 2.f) * 2.f;

  float photonRadius2 = photonRadius * photonRadius;

#if defined USE_SPPMPA || defined USE_PPMPA

  float g = 1;
  for (uint k = 1; k < iteration; k++)
    g *= (k + engine->alpha) / k;

  g /= iteration;

  photonRadius2 = photonRadius2 * g;

  //std::cout << "photon_radius: " << photonRadius2 << '\n';
#endif

#ifdef REBUILD_HASH
  // Expand the bounding box by used radius
  hitPointsbbox->Expand(sqrt(photonRadius2));
#endif
  // Initialize hit points field
  //const float photonRadius2 = photonRadius * photonRadius;

#if defined USE_SPPMPA || defined USE_PPMPA
  currentPhotonRadius2 = photonRadius2;
#else
  for (unsigned int i = 0; i < engine->hitPointTotal; ++i) {

    //HitPointInfo *hpinfo = engine->GetHitPointInfo(i);
    HitPointRadianceFlux *hp = GetHitPoint(i);

    hp->accumPhotonRadius2 = photonRadius2;

  }
#endif

}