Radiance3 RayTracer::L_scatteredSpecularIndirect(const shared_ptr<Surfel>& surfel, const Vector3& wo, int bouncesLeft, Random& rnd) const{
    Radiance3 L(0,0,0);
    if (bouncesLeft > 0){
        G3D::UniversalSurfel::ImpulseArray impulses;

        //Downcast to universalSurfel to allow getting impulses
        const shared_ptr<UniversalSurfel>& u = dynamic_pointer_cast<UniversalSurfel>(surfel);
        debugAssertM(notNull(u), "Encountered a Surfel that was not a UniversalSurfel");
        
        //Find the impulses on the surface
        u->getImpulses(PathDirection::EYE_TO_SOURCE, wo, impulses);

        //For each impulses, recursively computed the radiance from that direction
        for (int i = 0; i < impulses.size(); ++i){
            Vector3 wi = impulses[i].direction;
            Color3 magnitude = impulses[i].magnitude;
            ++m_stats->indirectRays;
            L += L_i(surfel->position, wi, bouncesLeft - 1, rnd) * magnitude;
        }
        
        //If we enable path tracing, also cast a random ray from the surfel
        //Technically it is not SpecularIndirect. But as it is not used often, I'm going to leave it here
        if (m_settings.enablePathTracing){
            Vector3 wi = Vector3::hemiRandom(surfel->shadingNormal, rnd);
            L += L_i(surfel->position, wi, bouncesLeft - 1, rnd) * surfel->finiteScatteringDensity(wi,wo) * abs(wi.dot(surfel->shadingNormal));
        }
    }
    return L;
}
void RayTracer::traceOnePixel(int x, int y, int threadID) {

    //used for constructing viewport
    Vector2 tmp(m_settings.width, m_settings.height);

    Ray primaryRay;

    // If one ray per pixel: (kinda debugging mode with blue color for places with no surfel hit
    if (m_settings.raysPerPixel == 1){
        //Get the primary ray from the pixel x,y
        primaryRay = m_camera->worldRay(x + 0.5f, y + 0.5f, Rect2D(tmp));
        
        //Get the first surfel hit.
        //Can't call L_i unfortunately because we want the blue background for debugging
        const shared_ptr<Surfel>& s = RayTracer::castRay(primaryRay, finf(), 0);

        //If there is a surfel hit, get the direct illumination value and apply to the pixel
        if (s){
            //Call L_scatteredDirect to get direct illumination. Invert primaryRay to get the direction for incident light
            m_image->set(Point2int32(x,y), L_o(s, -primaryRay.direction(), m_settings.recursiveBounces, *(m_rnd[threadID])));
        } else{
            //Set the pixels with no surfel hit. Include this line so we could make it a specific color for debug purposes.
            m_image->set(Point2int32(x,y), Color3(0,0,1));
        }
    } else {
        Radiance3 L(0,0,0);
        //If more than one ray, randomly generate required number of rays within the pixel
        for (int i = 0; i < m_settings.raysPerPixel; ++i){
            primaryRay = m_camera->worldRay(x + m_rnd[threadID]->uniform(), y + m_rnd[threadID]->uniform(), Rect2D(tmp));
            L += L_i(primaryRay.origin(), primaryRay.direction(), m_settings.recursiveBounces, *(m_rnd[threadID]));
        }
        m_image->set(Point2int32(x,y), L/m_settings.raysPerPixel);
    }
}
Beispiel #3
0
void exafmm_kernel::L2L(std::vector<real>& CiL, const std::vector<real>& CjL, const std::array<real, NDIM>& dist,
		const integer N) {
	std::vector<real> Ynm(FMM_P * FMM_P);
	real rho, theta, phi;
	std::vector<real> L_r(N), L_i(N);
	cart2sph(rho, theta, phi, dist);
	evalMultipole(rho, theta, phi, Ynm);
	for (integer j = 0; j != FMM_P; ++j) {
		for (integer k = 0; k <= j; ++k) {
			integer jkp = j * j + j + k;
			integer jkm = j * j + j - k;
#pragma vector aligned
#pragma simd
			for (integer i = 0; i != N; ++i) {
				L_r[i] = L_i[i] = 0.0;
			}
			for (integer n = j; n != FMM_P; ++n) {
				for (integer m = j - n + k; m <= n - j + k; ++m) {
					const integer nn = n * n + n;
					const integer nj = (n - j) * ((n - j) + 1);
					const integer npm = nn + std::abs(m);
					const integer nmm = nn - std::abs(m);
					const integer jnpkm = nj + std::abs(m - k);
					const integer jnmkm = nj - std::abs(m - k);
					const auto Lj_r = CjL.data() + N * npm;
					const auto Lj_i = CjL.data() + N * nmm;
					const real sgn = SGN(m);
					real tmp = std::pow(-real(1.0), real(std::abs(m) - std::abs(k) - std::abs(m - k)) / 2) * Anm[jnpkm] * Anm[jkp]
							/ Anm[npm];
					const real Y_r = Ynm[jnpkm] * tmp;
					const real Y_i = SGN(m-k) * Ynm[jnmkm] * tmp;
#pragma vector aligned
#pragma simd
					for (integer i = 0; i != N; ++i) {
						COMPLEX_MULT_ADD(L_r[i], L_i[i], Y_r, Y_i, Lj_r[i], sgn * Lj_i[i]);
					}
				}
			}
			auto Li_r = CiL.data() + N * jkp;
			auto Li_i = CiL.data() + N * jkm;
#pragma vector aligned
#pragma simd
			for (integer i = 0; i != N; ++i) {
				Li_r[i] = L_r[i];
				Li_i[i] = (k == 0) ? L_r[i] : L_i[i];
			}
		}
	}
}
Beispiel #4
0
Spectrum PhotonVolumeIntegrator::Li(const Scene *scene, const Renderer *renderer,
        const RayDifferential &ray, const Sample *sample, RNG &rng,
        Spectrum *T, MemoryArena &arena) const {
 	
 	VolumeRegion *vr = scene->volumeRegion;
    RainbowVolume* rv = dynamic_cast<RainbowVolume*>(vr);
 	KdTree<Photon>* volumeMap = photonShooter->volumeMap; 

 	float t0, t1;
 	if (!vr || !vr->IntersectP(ray, &t0, &t1) || (t1-t0) == 0.f){
 		*T = 1.f;
 	 	return 0.f;
 	 }
 	// Do single scattering & photon multiple scattering volume integration in _vr_
 	Spectrum Lv(0.);


 	// Prepare for volume integration stepping
 	int nSamples = Ceil2Int((t1-t0) / stepSize);
 	float step = (t1 - t0) / nSamples;
 	Spectrum Tr(1.f);
 	Point p = ray(t0), pPrev;
 	Vector w = -ray.d;
 	t0 += sample->oneD[scatterSampleOffset][0] * step;

 	float *lightNum = arena.Alloc<float>(nSamples);
    LDShuffleScrambled1D(1, nSamples, lightNum, rng);
    float *lightComp = arena.Alloc<float>(nSamples);
    LDShuffleScrambled1D(1, nSamples, lightComp, rng);
    float *lightPos = arena.Alloc<float>(2*nSamples);
    LDShuffleScrambled2D(1, nSamples, lightPos, rng);
 	int sampOffset = 0;

 	ClosePhoton *lookupBuf = new ClosePhoton[nSamples];

 	for (int i = 0; i < nSamples; ++i, t0 += step) {
 		// Advance to sample at _t0_ and update _T_
 		pPrev = p;
 		p = ray(t0);

 		Ray tauRay(pPrev, p - pPrev, 0.f, 1.f, ray.time, ray.depth);

 		Spectrum stepTau = vr->tau(tauRay,.5f * stepSize, rng.RandomFloat());
 		Tr = Exp(-stepTau);

 		// Possibly terminate raymarching if transmittance is small.
 		if (Tr.y() < 1e-3) {
 			const float continueProb = .5f;
 			if (rng.RandomFloat() > continueProb){
 				Tr = 0.f;
 				break;
 			}
 			Tr /= continueProb;
 		}
		
		
 		// Compute single-scattering source term at _p_ & photon mapped MS
 		Spectrum L_i(0.);
 		Spectrum L_d(0.);
 		Spectrum L_ii(0.);
 		
 		// Lv += Tr*vr->Lve(p, w, ray.time);
 		Spectrum ss = vr->sigma_s(p, w, ray.time);
 		Spectrum sa = vr->sigma_a(p, w, ray.time);

 		if (!ss.IsBlack() && scene->lights.size() > 0) {
 			int nLights = scene->lights.size();
 			int ln =
 				min(Floor2Int(lightNum[sampOffset] * nLights),
 				    nLights-1);
 			Light *light = scene->lights[ln];
 			// Add contribution of _light_ due to scattering at _p_
 			float pdf;
 			VisibilityTester vis;
 			Vector wo;

 			LightSample ls(lightComp[sampOffset], lightPos[2*sampOffset],
                           lightPos[2*sampOffset+1]);
            Spectrum L = light->Sample_L(p, 0.f, ls, ray.time, &wo, &pdf, &vis);
            

 			if (!L.IsBlack() && pdf > 0.f && vis.Unoccluded(scene)) {

                Spectrum Ld = L * vis.Transmittance(scene,renderer, NULL, rng, arena);
                if(rv){
                    L_d = rv->rainbowReflection(Ld, ray.d, wo);
                }
                else {
                    L_d = vr->p(p, w, -wo, ray.time) * Ld * float(nLights)/pdf;
                }
 			}
 		}
		// Compute 'indirect' in-scattered radiance from photon map
        if(!rv){
            L_ii += LPhoton(volumeMap, nUsed, lookupBuf, w, p, vr, maxDistSquared, ray.time);
        }
        
		// Compute total in-scattered radiance
		if (sa.y()!=0.0 || ss.y()!=0.0)
			L_i = L_d + (ss/(sa+ss))*L_ii;
		else
			L_i = L_d;

		Spectrum nLv = (sa*vr->Lve(p,w,ray.time)*step) + (ss*L_i*step) + (Tr * Lv)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            ;

		Lv = nLv;
 		sampOffset++;
 	}
 	*T = Tr;
	return Lv;
}