void PathCPURenderThread::DirectHitFiniteLight(
		const bool lastSpecular, const Spectrum &pathThrouput,
		const float distance, const BSDF &bsdf, const float lastPdfW,
		Spectrum *radiance) {
	PathCPURenderEngine *engine = (PathCPURenderEngine *)renderEngine;
	Scene *scene = engine->renderConfig->scene;

	float directPdfA;
	const Spectrum emittedRadiance = bsdf.GetEmittedRadiance(scene, &directPdfA);

	if (!emittedRadiance.Black()) {
		float weight;
		if (!lastSpecular) {
			const float lightPickProb = scene->PickLightPdf();
			const float directPdfW = PdfAtoW(directPdfA, distance,
				AbsDot(bsdf.fixedDir, bsdf.shadeN));

			// MIS between BSDF sampling and direct light sampling
			weight = PowerHeuristic(lastPdfW, directPdfW * lightPickProb);
		} else
			weight = 1.f;

		*radiance +=  pathThrouput * weight * emittedRadiance;
	}
}
Example #2
0
void PathHybridState::DirectHitFiniteLight(const Scene *scene, const float distance, const BSDF &bsdf) {
	float directPdfA;
	const Spectrum emittedRadiance = bsdf.GetEmittedRadiance(&directPdfA);

	if (!emittedRadiance.Black()) {
		float weight;
		if (!lastSpecular) {
			const float lightPickProb = scene->PickLightPdf();
			const float directPdfW = PdfAtoW(directPdfA, distance,
				AbsDot(bsdf.hitPoint.fixedDir, bsdf.hitPoint.shadeN));

			// MIS between BSDF sampling and direct light sampling
			weight = PowerHeuristic(lastPdfW, directPdfW * lightPickProb);
		} else
			weight = 1.f;

		sampleResults[0].radiance +=  throuput * weight * emittedRadiance;
	}
}
void LightCPURenderThread::TraceEyePath(Sampler *sampler, vector<SampleResult> *sampleResults) {
	LightCPURenderEngine *engine = (LightCPURenderEngine *)renderEngine;
	Scene *scene = engine->renderConfig->scene;
	PerspectiveCamera *camera = scene->camera;
	Film *film = threadFilm;
	const u_int filmWidth = film->GetWidth();
	const u_int filmHeight = film->GetHeight();

	// Sample offsets
	const u_int sampleBootSize = 11;
	const u_int sampleEyeStepSize = 3;

	Ray eyeRay;
	const float screenX = min(sampler->GetSample(0) * filmWidth, (float)(filmWidth - 1));
	const float screenY = min(sampler->GetSample(1) * filmHeight, (float)(filmHeight - 1));
	camera->GenerateRay(screenX, screenY, &eyeRay,
		sampler->GetSample(9), sampler->GetSample(10));

	Spectrum radiance, eyePathThroughput(1.f, 1.f, 1.f);
	int depth = 1;
	while (depth <= engine->maxPathDepth) {
		const u_int sampleOffset = sampleBootSize + (depth - 1) * sampleEyeStepSize;

		RayHit eyeRayHit;
		BSDF bsdf;
		Spectrum connectionThroughput;
		const bool somethingWasHit = scene->Intersect(device, false,
				sampler->GetSample(sampleOffset), &eyeRay, &eyeRayHit, &bsdf, &connectionThroughput);
		if (!somethingWasHit) {
			// Nothing was hit, check infinite lights (including sun)
			const Spectrum throughput = eyePathThroughput * connectionThroughput;
			if (scene->envLight)
				radiance +=  throughput * scene->envLight->GetRadiance(scene, -eyeRay.d);
			if (scene->sunLight)
				radiance +=  throughput * scene->sunLight->GetRadiance(scene, -eyeRay.d);
			break;
		} else {
			// Something was hit, check if it is a light source
			if (bsdf.IsLightSource())
				radiance = eyePathThroughput * connectionThroughput * bsdf.GetEmittedRadiance(scene);
			else {
				// Check if it is a specular bounce

				float bsdfPdf;
				Vector sampledDir;
				BSDFEvent event;
				float cosSampleDir;
				const Spectrum bsdfSample = bsdf.Sample(&sampledDir,
						sampler->GetSample(sampleOffset + 1),
						sampler->GetSample(sampleOffset + 2),
						&bsdfPdf, &cosSampleDir, &event);
				if (bsdfSample.Black() || ((depth == 1) && !(event & SPECULAR)))
					break;

				// If depth = 1 and it is a specular bounce, I continue to trace the
				// eye path looking for a light source

				eyePathThroughput *= connectionThroughput * bsdfSample * (cosSampleDir / bsdfPdf);
				assert (!eyePathThroughput.IsNaN() && !eyePathThroughput.IsInf());

				eyeRay = Ray(bsdf.hitPoint, sampledDir);
			}

			++depth;
		}
	}

	// Add a sample even if it is black in order to avoid aliasing problems
	// between sampled pixel and not sampled one (in PER_PIXEL_NORMALIZED buffer)
	AddSampleResult(*sampleResults, PER_PIXEL_NORMALIZED,
			screenX, screenY, radiance, (depth == 1) ? 1.f : 0.f);
}