예제 #1
0
// performs a free path sampling, aka. Woodcock tracking
FreePathResult FreePathSampling(const Ray& ray, Flow& flow)
{
	// initialize result data structure to 'no hit' (d > dmax).
	FreePathResult res;
	res.d = std::numeric_limits<double>::max();
	res.dmax = 0;
	res.ftle = 0;

	// first, test if the ray hits the domain at all (hits are sorted, thus if global_hit.y<0 then both are negative)
	Vec2d global_hit;
	if (!flow.IntersectRay(ray, global_hit) || global_hit.y < 0) 
		return res;

	// set extinction coefficient (global upper bound) and entry and exit of the run
	double km = majorantExtinction;
	double dmin = std::max(0.0,global_hit.x);
	res.dmax = global_hit.y;

	// perform the free path run (Alg. 1)
	res.d = dmin - log(1-rnd(rng)) / km;
	while (res.d <= res.dmax && ExtinctionCoefficient(res.ftle = flow.SampleFTLE(ray.Origin + res.d * ray.Direction, startTime, endTime, stepSize, Vec3d(separationDistance))) / km < rnd(rng))
		res.d = res.d - log(1-rnd(rng)) / km;
	return res;
}
예제 #2
0
// =============================================================
// =============================================================
// =============================================================
int main()
{
	printf("Small MCFTLE: Computing...\n");

	// =============================================================
	// initialize
	// =============================================================
	Vec3d eye(1,0.5,2.3), lookAt(1,0.5,0.5), up(0,1,0);		// camera parameters
	double fov = 45.0;
	Camera camera(eye, lookAt, up, fov, screenResolution);	// pinhole camera
	Frame frame(screenResolution);							// stores pixel statistics
	Flow flow;												// vector field
	Timer timer;											// timer to measure runtime

	// =============================================================
	// progressive rendering
	// =============================================================
	for (int it=0; it<maxIterationsPerPixel; ++it)
	{
		timer.tic();	// start runtime measurement

		#ifdef NDEBUG
		#pragma omp parallel for schedule(dynamic,16)
		#endif
		for (int px=0; px<screenResolution.x*screenResolution.y; ++px)
		{
			// select pixel and generate a ray
			Vec2i pxCoord(px%screenResolution.x, px/screenResolution.x);
			Ray viewRay = camera.GenerateRay(pxCoord);

			// intersect ray with domain (entry and exit)
			Vec2d t;
			if (!flow.IntersectRay(viewRay, t))
				continue;

			// free path sampling to find a scattering event
			FreePathResult fprView = FreePathSampling(viewRay, flow);
			
			Vec3d radiance(1,1,1);	// initialize with radiance of the background (white)

			// if we found a scattering event
			if (fprView.d <= fprView.dmax)
			{
				// compute the scattering albedo c
				Vec3d albedo = ScatteringAlbedo(fprView.ftle);

				// compute scattering location x_s and generate shadow ray
				Vec3d x_s = viewRay.Origin + fprView.d * viewRay.Direction;
				Ray shadowRay(x_s, -lightDirection);

				// intersect shadow ray with domain (determine exit)
				if (!flow.IntersectRay(shadowRay, t))
					continue;

				// free path sampling to find a scattering event on the shadow ray
				FreePathResult fprLight = FreePathSampling(shadowRay, flow);

				// if we have scattered, we are in shadow. (actually visibility would be zero now, but for vis purposes we keep a little bit.)
				double visibility = 1;
				if (fprLight.d <= fprLight.dmax)
					visibility = visibility_minimum;

				// phase function
				double phase = 1.0 / (4.0 * M_PI);		// isotropic phase function

				// compute in-scattered radiance
				radiance = albedo * phase * visibility * lightRadiance;
			}
			// add the result to the pixel statistics
			frame.AddPixel(pxCoord, radiance);
		}
		
		timer.toc();	// finish runtime measurement (prints result to console)

		// write intermediate result to file
		frame.ExportPfm("result.pfm");
		frame.ExportBmp("result.bmp", contrast, brightness, gamma_val);
		printf("Iteration: %i / %i\n", it+1, maxIterationsPerPixel);
	}
	printf("\nComplete!\n");
	return 0;
}