コード例 #1
0
void CaptureParticleWorker::handleSurfaceInteraction(int depth, int nullInteractions,
		bool caustic, const Intersection &its, const Medium *medium,
		const Spectrum &weight) {

	if (its.isSensor()) {
		if (!m_bruteForce && !caustic)
			return;

		const Sensor *sensor = its.shape->getSensor();
		if (sensor != m_sensor)
			return;

		Vector wi = its.toWorld(its.wi);
		Point2 uv;
		Spectrum value = sensor->eval(its, wi, uv) * weight;
		if (value.isZero())
			return;

		m_workResult->put(uv, (Float *) &value[0]);
		return;
	}

	if (m_bruteForce || (depth >= m_maxPathDepth && m_maxPathDepth > 0))
		return;

	int maxInteractions = m_maxPathDepth - depth - 1;

	DirectSamplingRecord dRec(its);
	Spectrum value = weight * m_scene->sampleAttenuatedSensorDirect(
			dRec, its, medium, maxInteractions,
			m_sampler->next2D(), m_sampler);

	if (value.isZero())
		return;

	const BSDF *bsdf = its.getBSDF();

	Vector wo = dRec.d;
	BSDFSamplingRecord bRec(its, its.toLocal(wo), EImportance);

	/* Prevent light leaks due to the use of shading normals -- [Veach, p. 158] */
	Vector wi = its.toWorld(its.wi);
	Float wiDotGeoN = dot(its.geoFrame.n, wi),
		  woDotGeoN = dot(its.geoFrame.n, wo);
	if (wiDotGeoN * Frame::cosTheta(bRec.wi) <= 0 ||
		woDotGeoN * Frame::cosTheta(bRec.wo) <= 0)
		return;

	/* Adjoint BSDF for shading normals -- [Veach, p. 155] */
	Float correction = std::abs(
		(Frame::cosTheta(bRec.wi) * woDotGeoN)/
		(Frame::cosTheta(bRec.wo) * wiDotGeoN));
	value *= bsdf->eval(bRec) * correction;

	/* Splat onto the accumulation buffer */
	m_workResult->put(dRec.uv, (Float *) &value[0]);
}
コード例 #2
0
ファイル: direct_mats.cpp プロジェクト: valdersoul/NoriV2
    Color3f Li(const Scene *scene, Sampler *sampler, const Ray3f &ray) const {
        /* Find the surface that is visible in the requested direction */
        Intersection its;

        //check if the ray intersects the scene
        if (!scene->rayIntersect(ray, its)) {
            //check if a distant disk light is set
            const Emitter* distantsDisk = scene->getDistantEmitter();
            if(distantsDisk == nullptr ) return Color3f(0.0f);

            //sample the distant disk light
            return distantsDisk->sampleL(ray.d);
        }

        //get the radiance of hitten object
        Color3f Le(0.0f, 0.0f, 0.0f);
        if (its.mesh->isEmitter()  ) {
            const Emitter* areaLightEM = its.mesh->getEmitter();
            const areaLight* aEM = static_cast<const areaLight *> (areaLightEM);
            Le = aEM->sampleL(-ray.d, its.shFrame.n, its);
        }

        //get the asigned BSDF
        const BSDF* curBSDF = its.mesh->getBSDF();

        Color3f Ld(0.0f, 0.0f, 0.0f);
        Color3f f(0.0f, 0.0f, 0.0f);
        Color3f totalLight(0.0f, 0.0f, 0.0f);

        //transform to the local frame
        //create a BRDF Query
        BSDFQueryRecord query = BSDFQueryRecord(its.toLocal(-ray.d), Vector3f(0.0f), EMeasure::ESolidAngle);

        //sample the BRDF
        Color3f mats =  curBSDF->sample(query, sampler->next2D());

        if(mats.maxCoeff() > 0.0f) {
            //Check for the light source
            Vector3f wo = its.toWorld(query.wo);
            Ray3f shadowRay(its.p, wo);
            Intersection itsShadow;
            if (scene->rayIntersect(shadowRay, itsShadow)) {
                //intersection check if mesh is emitter
                if(itsShadow.mesh->isEmitter()){
                    Ld = itsShadow.mesh->getEmitter()->radiance();
                }
            } else {
                //check for distant disk light
                const Emitter* distantsDisk = scene->getDistantEmitter();
                if(distantsDisk != nullptr ) Ld = distantsDisk->sampleL(wo);
            }

            totalLight += Ld * mats;
        }

        return Le + totalLight;
    }
コード例 #3
0
void CaptureParticleWorker::handleSurfaceInteraction(int depth,
		bool caustic, const Intersection &its, const Medium *medium,
		const Spectrum &weight) {
	const ProjectiveCamera *camera = static_cast<const ProjectiveCamera *>(m_camera.get());
	Point2 screenSample;

	if (camera->positionToSample(its.p, screenSample)) {
		Point cameraPosition = camera->getPosition(screenSample);
	
		Float t = dot(camera->getImagePlaneNormal(), its.p-cameraPosition);
		if (t < camera->getNearClip() || t > camera->getFarClip())
			return;

		if (its.isMediumTransition()) 
			medium = its.getTargetMedium(cameraPosition - its.p);

		Spectrum transmittance = m_scene->getTransmittance(its.p,
				cameraPosition, its.time, medium);

		if (transmittance.isZero())
			return;

		const BSDF *bsdf = its.shape->getBSDF();
		Vector wo = cameraPosition - its.p;
		Float dist = wo.length(); wo /= dist;

		BSDFQueryRecord bRec(its, its.toLocal(wo));
		bRec.quantity = EImportance;

		Float importance; 
		if (m_isPerspectiveCamera)
			importance = ((const PerspectiveCamera *) camera)->importance(screenSample) / (dist * dist);
		else
			importance = 1/camera->areaDensity(screenSample);

		Vector wi = its.toWorld(its.wi);

		/* Prevent light leaks due to the use of shading normals -- [Veach, p. 158] */
		Float wiDotGeoN = dot(its.geoFrame.n, wi),
			  woDotGeoN = dot(its.geoFrame.n, wo);
		if (wiDotGeoN * Frame::cosTheta(bRec.wi) <= 0 || 
			woDotGeoN * Frame::cosTheta(bRec.wo) <= 0)
			return;

		/* Adjoint BSDF for shading normals -- [Veach, p. 155] */
		Float correction = std::abs(
			(Frame::cosTheta(bRec.wi) * woDotGeoN)/
			(Frame::cosTheta(bRec.wo) * wiDotGeoN));

		/* Splat onto the accumulation buffer */
		Ray ray(its.p, wo, 0, dist, its.time);
		Spectrum sampleVal = weight * bsdf->fCos(bRec) 
			* transmittance * (importance * correction);

		m_workResult->splat(screenSample, sampleVal, m_filter);
	}
}
コード例 #4
0
ファイル: rectangle.cpp プロジェクト: akaterin/ray-tracer
	void fillIntersectionRecord(const Ray &ray,
			const void *temp, Intersection &its) const {
		const Float *data = static_cast<const Float *>(temp);
		its.shFrame = its.geoFrame = m_frame;
		its.shape = this;
		its.dpdu = m_dpdu;
		its.dpdv = m_dpdv;
		its.uv = Point2(0.5f * (data[0]+1), 0.5f * (data[1]+1));
		its.p = ray(its.t);
		its.wi = its.toLocal(-ray.d);
 		its.hasUVPartials = false;
		its.instance = NULL;
		its.time = ray.time;
	}
コード例 #5
0
ファイル: bsdf.hpp プロジェクト: ennis/path-tracer
	virtual Vec sample(
		Intersection const &isect,
		float u1,
		float u2,
		Vec& WiW, 
		float& pdfResult,
		int &bxdfType) const 
	{
		pdfResult = 1.f;	// should be a dirac?
		Vec Wi = perfectSpecularReflection(isect.toLocal(isect.WoW));
		WiW = isect.toWorld(Wi);
		bxdfType = BxDF_SPECULAR;
		return isect.texSample * fresnelCoef(Wi, m_R0);
	}
コード例 #6
0
ファイル: bsdf.hpp プロジェクト: ennis/path-tracer
	virtual Vec sample(
		Intersection const &isect, 
		float u1, float u2, 
		Vec& WiW, 
		float& pdfResult,
		int &bxdfType) const 
	{
		Vec WoL = isect.toLocal(isect.WoW);
		Vec result;
		if (WoL.z() < 0.f) {
			Vec Wi = perfectSpecularRefraction(-WoL, 1.f / m_ior);
			result = Vec(1.f, 1.f, 1.f) * fresnelCoef(Wi * Vec(1.f, 1.f, -1.f), m_r0);
			WiW = isect.toWorld(-Wi);
		} else {
			Vec Wi = perfectSpecularRefraction(WoL, m_ior);
			result = Vec(1.f, 1.f, 1.f) * fresnelCoef(Wi * Vec(1.f, 1.f, -1.f), m_r0);
			WiW = isect.toWorld(Wi);
		}
		bxdfType = BxDF_SPECULAR;
		pdfResult = 1.f;
		return result;
	}
コード例 #7
0
ファイル: path_mis.cpp プロジェクト: valdersoul/NoriV2
    Color3f Li(const Scene *scene, Sampler *sampler, const Ray3f &ray) const {
        /* Find the surface that is visible in the requested direction */
        Intersection its;

        //check if the ray intersects the scene
        if (!scene->rayIntersect(ray, its)) {
            //check if a distant disk light is set
            const Emitter* distantsDisk = scene->getDistantEmitter();
            if(distantsDisk == nullptr ) return Color3f(0.0f);

            //sample the distant disk light
            Vector3f d = ray.d;
            return distantsDisk->sampleL(d);
        }

        //get the Number of lights from the scene
        const  std::vector<Emitter *> lights = scene->getEmitters();
        uint32_t nLights = lights.size();

        Color3f tp(1.0f, 1.0f, 1.0f);
        Color3f L(0.0f, 0.0f, 0.0f);
        Ray3f pathRay(ray.o, ray.d);

        bool deltaFlag = true;

        while(true) {

            if (its.mesh->isEmitter() && deltaFlag) {
                const Emitter* areaLightEM = its.mesh->getEmitter();
                const areaLight* aEM = static_cast<const areaLight *> (areaLightEM);
                L += tp * aEM->sampleL(-pathRay.d, its.shFrame.n, its);
            }

            //Light sampling
            //randomly select a lightsource
            uint32_t var = uint32_t(std::min(sampler->next1D()*nLights, float(nLights) - 1.0f));

            //init the light color
            Color3f Li(0.0f, 0.0f, 0.0f);
            Color3f Ld(1.0f, 1.0f, 1.0f);

            //create a sample for the light
            const BSDF* curBSDF = its.mesh->getBSDF();
            const Point2f lightSample = sampler->next2D();
            VisibilityTester vis;
            Vector3f wo;
            float lightpdf;
            float bsdfpdf;
            Normal3f n = its.shFrame.n;

            deltaFlag = curBSDF->isDeltaBSDF();

            //sample the light

            {
                Li = lights[var]->sampleL(its.p, Epsilon, lightSample , &wo, &lightpdf, &vis);
                lightpdf /= float(nLights);
                //check if the pdf of the sample is greater than 0 and if the color is not black
                if(lightpdf > 0 && Li.maxCoeff() != 0.0f) {
                    //calculate the cosine term wi in my case the vector to the light
                    float cosTerm = std::abs(n.dot(wo));
                    const BSDFQueryRecord queryEM = BSDFQueryRecord(its.toLocal(- pathRay.d), its.toLocal(wo), EMeasure::ESolidAngle, sampler);
                    Color3f f = curBSDF->eval(queryEM);

                    if(f.maxCoeff() > 0.0f && f.minCoeff() >= 0.0f && vis.Unoccluded(scene)) {
                        bsdfpdf = curBSDF->pdf(queryEM);
                        float weight = BalanceHeuristic(float(1), lightpdf, float(1), bsdfpdf);
                        if(curBSDF->isDeltaBSDF())  weight = 1.0f;
                        if(bsdfpdf > 0.0f) {
                            Ld = (weight * f * Li * cosTerm) / lightpdf;
                            L += tp * Ld;
                        } else {
                            //cout << "bsdfpdf = " << bsdfpdf  << endl;
                            //cout << "f = " << f  << endl;
                        }
                    }
                }
            }

            //Material part
            BSDFQueryRecord queryMats = BSDFQueryRecord(its.toLocal(-pathRay.d), Vector3f(0.0f), EMeasure::ESolidAngle, sampler);

            Color3f fi =  curBSDF->sample(queryMats, sampler->next2D());
            bsdfpdf = curBSDF->pdf(queryMats);
            lightpdf = 0.0f;
            if(fi.maxCoeff() > 0.0f && fi.minCoeff() >= 0.0f) {
                if(bsdfpdf > 0.0f) {
                    Ray3f shadowRay(its.p, its.toWorld(queryMats.wo));
                    Intersection lightIsect;

                     if (scene->rayIntersect(shadowRay, lightIsect)) {
                         if(lightIsect.mesh->isEmitter()){
                            const Emitter* areaLightEMcur = lightIsect.mesh->getEmitter();
                            const areaLight* aEMcur = static_cast<const areaLight *> (areaLightEMcur);

                            Li = aEMcur->sampleL(-shadowRay.d, lightIsect.shFrame.n, lightIsect);
                            lightpdf = aEMcur->pdf(its.p, (lightIsect.p - its.p).normalized(), lightIsect.p, Normal3f(lightIsect.shFrame.n));
                         }
                     } else {
                         const Emitter* distantsDisk = scene->getDistantEmitter();
                         if(distantsDisk != nullptr ) {
                             //check if THIS is right!
                             Li = distantsDisk->sampleL(lightIsect.toWorld(queryMats.wo));
                             lightpdf = distantsDisk->pdf(Point3f(0.0f), wo, Point3f(0.0f), Normal3f(0.0f));
                         }
                     }
                     lightpdf /= float(nLights);
                     //calculate the weights
                     float weight = BalanceHeuristic(float(1), bsdfpdf, float(1), lightpdf);


                     //check if the lightcolor is not black
                     if(Li.maxCoeff() > 0.0f  && lightpdf > 0.0f ) {
                         //wo in my case the vector to the light
                         Ld = weight * Li * fi;
                         L += tp * Ld;
                     }
                }



                 tp *= fi;
            } else {
                break;
            }

            wo = its.toWorld(queryMats.wo);
            pathRay = Ray3f(its.p, wo);

            if (!scene->rayIntersect(pathRay, its)) {
                const Emitter* distantsDisk = scene->getDistantEmitter();
                if(distantsDisk != nullptr ) {
                    //sample the distant disk light
                    Vector3f d = pathRay.d;
                    L += tp * distantsDisk->sampleL(d);
                }


                break;
            }

            float maxCoeff = tp.maxCoeff();
            float q = std::min(0.99f, maxCoeff);
            if(q < sampler->next1D()){
                break;
            }
            tp /= q;
        }

        return L;

    }
コード例 #8
0
ファイル: MisPathTracer.cpp プロジェクト: FallenShard/vesper
    Spectrum MisPathTracer::Li(const Scene* scene, Sampler& sampler, Ray3f& ray) const
    {
        Spectrum L(0.f);

        Intersection its;

        Spectrum throughput(1.f);
        bool isSpecular = true;

        while (true)
        {
            if (!scene->rayIntersect(ray, its))
                break;

            if (isSpecular && its.shape->getEmitter())
            {
                EmitterSample emittanceSample(ray.o, its.p, its.shFrame.n);
                L += throughput * its.shape->getEmitter()->eval(emittanceSample);
            }

            if (its.shape->getBSDF()->getType() != BSDFType::Delta)
            {
                EmitterSample emSam(its.p);
                auto lightSpec = scene->sampleEmitter(its, sampler, emSam);

                float cosFactor = its.shFrame.n.dot(emSam.wi);
                if (!(cosFactor <= 0.f || lightSpec.isZero() || scene->rayIntersect(emSam.shadowRay)))
                {
                    BSDFSample bsdfSam(its.p, its.toLocal(-ray.d), its.toLocal(emSam.wi));
                    bsdfSam.measure = Measure::SolidAngle;
                    auto bsdfSpec = its.shape->getBSDF()->eval(bsdfSam);

                    float pdfEm = emSam.pdf;
                    float pdfBsdf = its.shape->getBSDF()->pdf(bsdfSam);
                    L += throughput * bsdfSpec * lightSpec * cosFactor * miWeight(pdfEm, pdfBsdf);
                }
            }

            BSDFSample bsdfSample(its.p, its.toLocal(-ray.d));
            auto bsdf = its.shape->getBSDF()->sample(bsdfSample, sampler);
            Intersection bsdfIts;
            Ray3f bsdfRay(its.p, its.toWorld(bsdfSample.wo));
            if (scene->rayIntersect(bsdfRay, bsdfIts) && bsdfIts.shape->getEmitter())
            {
                const auto* em = bsdfIts.shape->getEmitter();
                
                EmitterSample emSam(its.p, bsdfIts.p, bsdfIts.shFrame.n);
                emSam.wi = bsdfRay.d;
                auto lightSpec = em->eval(emSam);

                float pdfBsdf = its.shape->getBSDF()->pdf(bsdfSample);
                float pdfEm = em->pdf(emSam) * scene->getEmitterPdf();
                if (pdfBsdf + pdfEm > 0.f)
                    L += throughput * bsdf * lightSpec * miWeight(pdfBsdf, pdfEm);
            }

            isSpecular = its.shape->getBSDF()->getType() == BSDFType::Delta;
            throughput *= bsdf;
            ray = bsdfRay;

            float q = 1.f - std::min(throughput.maxCoeff(), 0.99f);
            if (sampler.next1D() > q)
                throughput /= (1.f - q);
            else
                break;
        }

        return L;
    }
コード例 #9
0
void PreviewWorker::processIncoherent(const WorkUnit *workUnit, WorkResult *workResult, 
	const bool &stop) {
	const RectangularWorkUnit *rect = static_cast<const RectangularWorkUnit *>(workUnit);
	ImageBlock *block = static_cast<ImageBlock *>(workResult);

	block->setOffset(rect->getOffset());
	block->setSize(rect->getSize());

	const int sx = rect->getOffset().x, sy = block->getOffset().y;
	const int ex = sx + rect->getSize().x, ey = sy + rect->getSize().y;

	/* Some local variables */
	int pos = 0;
	Intersection its;
	Spectrum value, bsdfVal;
	Vector toVPL;
	Ray primary, secondary;
	int numRays = 0;
	float shutterOpen = m_scene->getCamera()->getShutterOpen();

	for (int y=sy; y<ey; ++y) {
		for (int x=sx; x<ex; ++x) {
			/* Generate a camera ray without normalization */
			primary = Ray(m_cameraO, m_cameraTL 
				+ m_cameraDx * (Float) x
				+ m_cameraDy * (Float) y, shutterOpen);

			++numRays;
			if (!m_kdtree->rayIntersect(primary, its)) {
				block->setPixel(pos++, m_scene->LeBackground(primary)*m_backgroundScale);
				continue;
			}

			if (its.shape->isLuminaire())
				value = its.Le(-primary.d);
			else
				value = Spectrum(0.0f);

			toVPL = m_vpl.its.p - its.p;
			secondary = Ray(its.p, toVPL, ShadowEpsilon, 1-ShadowEpsilon, shutterOpen);
			++numRays;
			if (m_kdtree->rayIntersect(secondary)) {
				block->setPixel(pos++, value);
				continue;
			}
			Float length = toVPL.length();
			toVPL/=length;

			BSDFQueryRecord rr(its, its.toLocal(toVPL));
			rr.wi = normalize(rr.wi);
			bsdfVal = its.shape->getBSDF()->eval(rr);
			length = std::max(length, m_minDist);

			if (m_vpl.type == ESurfaceVPL) {
				BSDFQueryRecord bRec(m_vpl.its, -m_vpl.its.toLocal(toVPL));
				bRec.quantity = EImportance;
				value += m_vpl.P * bsdfVal * m_vpl.its.shape->getBSDF()->eval(bRec) / (length*length);
			} else {
				EmissionRecord eRec(m_vpl.luminaire, 
					ShapeSamplingRecord(m_vpl.its.p, m_vpl.its.shFrame.n), -toVPL);
				eRec.type = EmissionRecord::EPreview;
				value += m_vpl.P * bsdfVal * m_vpl.luminaire->evalDirection(eRec) 
					* ((m_vpl.luminaire->getType() & Luminaire::EOnSurface ?
					dot(m_vpl.its.shFrame.n, -toVPL) : (Float) 1)
					/ (length*length));
			}
			block->setPixel(pos++, value);
		}
	}
	block->setExtra(numRays);
}
コード例 #10
0
void PreviewWorker::processCoherent(const WorkUnit *workUnit, WorkResult *workResult, 
	const bool &stop) {
#if defined(MTS_HAS_COHERENT_RT)
	const RectangularWorkUnit *rect = static_cast<const RectangularWorkUnit *>(workUnit);
	ImageBlock *block = static_cast<ImageBlock *>(workResult);

	block->setOffset(rect->getOffset());
	block->setSize(rect->getSize());

	/* Some constants */
	const int sx = rect->getOffset().x, sy = block->getOffset().y;
	const int ex = sx + rect->getSize().x, ey = sy + rect->getSize().y;
	const int width = rect->getSize().x;
	const SSEVector MM_ALIGN16 xOffset(0.0f, 1.0f, 0.0f, 1.0f);
	const SSEVector MM_ALIGN16 yOffset(0.0f, 0.0f, 1.0f, 1.0f);
	const int pixelOffset[] = {0, 1, width, width+1};
	const __m128 clamping = _mm_set1_ps(1/(m_minDist*m_minDist));
	uint8_t temp[MTS_KD_INTERSECTION_TEMP*4];

	const __m128 camTL[3] = {
		 _mm_set1_ps(m_cameraTL.x),
		 _mm_set1_ps(m_cameraTL.y),
		 _mm_set1_ps(m_cameraTL.z)
	}; 
	const __m128 camDx[3] = {
		 _mm_set1_ps(m_cameraDx.x),
		 _mm_set1_ps(m_cameraDx.y),
		 _mm_set1_ps(m_cameraDx.z)
	}; 
	const __m128 camDy[3] = {
		 _mm_set1_ps(m_cameraDy.x),
		 _mm_set1_ps(m_cameraDy.y),
		 _mm_set1_ps(m_cameraDy.z)
	}; 
	const __m128 lumPos[3] = {
		_mm_set1_ps(m_vpl.its.p.x),
		_mm_set1_ps(m_vpl.its.p.y),
		_mm_set1_ps(m_vpl.its.p.z)
	};
	const __m128 lumDir[3] = {
		_mm_set1_ps(m_vpl.its.shFrame.n.x),
		_mm_set1_ps(m_vpl.its.shFrame.n.y),
		_mm_set1_ps(m_vpl.its.shFrame.n.z)
	};

	/* Some local variables */
	int pos = 0;
	int numRays = 0;
	RayPacket4 MM_ALIGN16 primRay4, secRay4;
	Intersection4 MM_ALIGN16 its4, secIts4;
	RayInterval4 MM_ALIGN16 itv4, secItv4;
	SSEVector MM_ALIGN16 nSecD[3], cosThetaLight, invLengthSquared;
	Spectrum emitted[4], direct[4];
	Intersection its;
	Vector wo, wi;
	its.hasUVPartials = false;

	bool diffuseVPL = false, vplOnSurface = false;
	Spectrum vplWeight;

	if (m_vpl.type == ESurfaceVPL && (m_diffuseSources || m_vpl.its.shape->getBSDF()->getType() == BSDF::EDiffuseReflection)) {
		diffuseVPL = true;
		vplOnSurface = true;
		vplWeight = m_vpl.its.shape->getBSDF()->getDiffuseReflectance(m_vpl.its) * m_vpl.P / M_PI;
	} else if (m_vpl.type == ELuminaireVPL) {
		vplOnSurface = m_vpl.luminaire->getType() & Luminaire::EOnSurface;
		diffuseVPL = m_vpl.luminaire->getType() & Luminaire::EDiffuseDirection;
		EmissionRecord eRec(m_vpl.luminaire, 
			ShapeSamplingRecord(m_vpl.its.p, m_vpl.its.shFrame.n), m_vpl.its.shFrame.n);
		vplWeight = m_vpl.P * m_vpl.luminaire->evalDirection(eRec);
	}

	primRay4.o[0].ps = _mm_set1_ps(m_cameraO.x);
	primRay4.o[1].ps = _mm_set1_ps(m_cameraO.y);
	primRay4.o[2].ps = _mm_set1_ps(m_cameraO.z);
	secItv4.mint.ps = _mm_set1_ps(ShadowEpsilon);

	/* Work on 2x2 sub-blocks */
	for (int y=sy; y<ey; y += 2, pos += width) {
		for (int x=sx; x<ex; x += 2, pos += 2) {
			/* Generate camera rays without normalization */
			const __m128
				xPixel = _mm_add_ps(xOffset.ps, _mm_set1_ps((float) x)),
				yPixel = _mm_add_ps(yOffset.ps, _mm_set1_ps((float) y));

			primRay4.d[0].ps = _mm_add_ps(camTL[0], _mm_add_ps(
				_mm_mul_ps(xPixel, camDx[0]), _mm_mul_ps(yPixel, camDy[0])));
			primRay4.d[1].ps = _mm_add_ps(camTL[1], _mm_add_ps(
				_mm_mul_ps(xPixel, camDx[1]), _mm_mul_ps(yPixel, camDy[1])));
			primRay4.d[2].ps = _mm_add_ps(camTL[2], _mm_add_ps(
				_mm_mul_ps(xPixel, camDx[2]), _mm_mul_ps(yPixel, camDy[2])));

			primRay4.dRcp[0].ps = _mm_div_ps(SSEConstants::one.ps, primRay4.d[0].ps);
			primRay4.dRcp[1].ps = _mm_div_ps(SSEConstants::one.ps, primRay4.d[1].ps);
			primRay4.dRcp[2].ps = _mm_div_ps(SSEConstants::one.ps, primRay4.d[2].ps);

			/* Ray coherence test */
			const int primSignsX = _mm_movemask_ps(primRay4.d[0].ps);
			const int primSignsY = _mm_movemask_ps(primRay4.d[1].ps);
			const int primSignsZ = _mm_movemask_ps(primRay4.d[2].ps);

			const bool primCoherent =
				   (primSignsX == 0 || primSignsX == 0xF)
				&& (primSignsY == 0 || primSignsY == 0xF)
				&& (primSignsZ == 0 || primSignsZ == 0xF);

			/* Trace the primary rays */
			its4.t = SSEConstants::p_inf;
			if (EXPECT_TAKEN(primCoherent)) {
				primRay4.signs[0][0] = primSignsX ? 1 : 0;
				primRay4.signs[1][0] = primSignsY ? 1 : 0;
				primRay4.signs[2][0] = primSignsZ ? 1 : 0;
				m_kdtree->rayIntersectPacket(primRay4, itv4, its4, temp);
			} else {
				m_kdtree->rayIntersectPacketIncoherent(primRay4, itv4, its4, temp);
			}
			numRays += 4;

			/* Generate secondary rays */
			secRay4.o[0].ps = _mm_add_ps(primRay4.o[0].ps, _mm_mul_ps(its4.t.ps, primRay4.d[0].ps));
			secRay4.o[1].ps = _mm_add_ps(primRay4.o[1].ps, _mm_mul_ps(its4.t.ps, primRay4.d[1].ps));
			secRay4.o[2].ps = _mm_add_ps(primRay4.o[2].ps, _mm_mul_ps(its4.t.ps, primRay4.d[2].ps));
			secRay4.d[0].ps = _mm_sub_ps(lumPos[0], secRay4.o[0].ps);
			secRay4.d[1].ps = _mm_sub_ps(lumPos[1], secRay4.o[1].ps);
			secRay4.d[2].ps = _mm_sub_ps(lumPos[2], secRay4.o[2].ps);

			/* Normalization */
			const __m128 
				lengthSquared = _mm_add_ps(_mm_add_ps(
					_mm_mul_ps(secRay4.d[0].ps, secRay4.d[0].ps),
					_mm_mul_ps(secRay4.d[1].ps, secRay4.d[1].ps)),
					_mm_mul_ps(secRay4.d[2].ps, secRay4.d[2].ps)),
				invLength = _mm_rsqrt_ps(lengthSquared);
	
			invLengthSquared.ps = _mm_min_ps(_mm_rcp_ps(lengthSquared), clamping);

			nSecD[0].ps = _mm_mul_ps(secRay4.d[0].ps, invLength);
			nSecD[1].ps = _mm_mul_ps(secRay4.d[1].ps, invLength);
			nSecD[2].ps = _mm_mul_ps(secRay4.d[2].ps, invLength);

			secRay4.dRcp[0].ps = _mm_div_ps(SSEConstants::one.ps, secRay4.d[0].ps);
			secRay4.dRcp[1].ps = _mm_div_ps(SSEConstants::one.ps, secRay4.d[1].ps);
			secRay4.dRcp[2].ps = _mm_div_ps(SSEConstants::one.ps, secRay4.d[2].ps);

			cosThetaLight.ps = _mm_sub_ps(_mm_setzero_ps(),
				_mm_add_ps(_mm_add_ps(
					_mm_mul_ps(nSecD[0].ps, lumDir[0]),
					_mm_mul_ps(nSecD[1].ps, lumDir[1])),
					_mm_mul_ps(nSecD[2].ps, lumDir[2])));
			secItv4.maxt.ps = _mm_set1_ps(1-ShadowEpsilon);

			/* Shading (scalar) --- this is way too much work and should be 
			   rewritten to be smarter in special cases */
			for (int idx=0; idx<4; ++idx) {
				if (EXPECT_NOT_TAKEN(its4.t.f[idx] == std::numeric_limits<float>::infinity())) {
					/* Don't trace a secondary ray */
					secItv4.maxt.f[idx] = 0;
					emitted[idx] = m_scene->LeBackground(Ray(
						Point(primRay4.o[0].f[idx], primRay4.o[1].f[idx], primRay4.o[2].f[idx]),
						Vector(primRay4.d[0].f[idx], primRay4.d[1].f[idx], primRay4.d[2].f[idx]),
						0.0f
					)) * m_backgroundScale;
					memset(&direct[idx], 0, sizeof(Spectrum));
					continue;
				}
				const unsigned int primIndex = its4.primIndex.i[idx];
				const Shape *shape = (*m_shapes)[its4.shapeIndex.i[idx]];
				const BSDF *bsdf = shape->getBSDF();

				if (EXPECT_NOT_TAKEN(!bsdf)) {
					memset(&emitted[idx], 0, sizeof(Spectrum));
					memset(&direct[idx], 0, sizeof(Spectrum));
					continue;
				}

				if (EXPECT_TAKEN(primIndex != KNoTriangleFlag)) {
					const TriMesh *mesh = static_cast<const TriMesh *>(shape);
					const Triangle &t = mesh->getTriangles()[primIndex];
					const Normal *normals = mesh->getVertexNormals();
					const Point2 *texcoords = mesh->getVertexTexcoords();
					const Spectrum *colors = mesh->getVertexColors();
					const TangentSpace * tangents = mesh->getVertexTangents();
					const Float beta  = its4.u.f[idx],
								gamma = its4.v.f[idx],
								alpha = 1.0f - beta - gamma;
					const uint32_t idx0 = t.idx[0], idx1 = t.idx[1], idx2 = t.idx[2];

					if (EXPECT_TAKEN(normals)) {
						const Normal &n0 = normals[idx0],
							  		 &n1 = normals[idx1],
									 &n2 = normals[idx2];
						its.shFrame.n = normalize(n0 * alpha + n1 * beta + n2 * gamma);
					} else {
						const Point *positions = mesh->getVertexPositions();
						const Point &p0 = positions[idx0],
									&p1 = positions[idx1],
									&p2 = positions[idx2];
						Vector sideA = p1 - p0, sideB = p2 - p0;
						Vector n = cross(sideA, sideB);
						Float nLengthSqr = n.lengthSquared();
						if (nLengthSqr != 0)
							n /= std::sqrt(nLengthSqr);
						its.shFrame.n = Normal(n);
					}

					if (EXPECT_TAKEN(texcoords)) {
						const Point2 &t0 = texcoords[idx0],
							  		 &t1 = texcoords[idx1],
									 &t2 = texcoords[idx2];
						its.uv = t0 * alpha + t1 * beta + t2 * gamma;
					} else {
						its.uv = Point2(0.0f);
					}

					if (EXPECT_NOT_TAKEN(colors)) {
						const Spectrum &c0 = colors[idx0],
							  		   &c1 = colors[idx1],
									   &c2 = colors[idx2];
						its.color = c0 * alpha + c1 * beta + c2 * gamma;
					}

					if (EXPECT_NOT_TAKEN(tangents)) {
						const TangentSpace &t0 = tangents[idx0],
							  			   &t1 = tangents[idx1],
										   &t2 = tangents[idx2];
						its.dpdu = t0.dpdu * alpha + t1.dpdu * beta + t2.dpdu * gamma;
						its.dpdv = t0.dpdv * alpha + t1.dpdv * beta + t2.dpdv * gamma;
					}
				} else {
					Ray ray(
						Point(primRay4.o[0].f[idx], primRay4.o[1].f[idx], primRay4.o[2].f[idx]),
						Vector(primRay4.d[0].f[idx], primRay4.d[1].f[idx], primRay4.d[2].f[idx]),
						0.0f
					);
					its.t = its4.t.f[idx];
					shape->fillIntersectionRecord(ray, temp + idx * MTS_KD_INTERSECTION_TEMP + 8, its);
					bsdf = its.shape->getBSDF();
				}

				wo.x = nSecD[0].f[idx]; wo.y = nSecD[1].f[idx]; wo.z = nSecD[2].f[idx];

				if (EXPECT_TAKEN(!shape->isLuminaire())) {
					memset(&emitted[idx], 0, sizeof(Spectrum));
				} else {
					Vector d(-primRay4.d[0].f[idx], -primRay4.d[1].f[idx], -primRay4.d[2].f[idx]);
					emitted[idx] = shape->getLuminaire()->Le(ShapeSamplingRecord(its.p, its.shFrame.n), d);
				}

				if (EXPECT_TAKEN(bsdf->getType() == BSDF::EDiffuseReflection && diffuseVPL)) {
					/* Fast path */
					direct[idx] = (bsdf->getDiffuseReflectance(its) * vplWeight)
						* (std::max((Float) 0.0f, dot(wo, its.shFrame.n))
						* (vplOnSurface ? (std::max(cosThetaLight.f[idx], (Float) 0.0f) * INV_PI) : INV_PI)
						* invLengthSquared.f[idx]);
				} else {
					wi.x = -primRay4.d[0].f[idx];
					wi.y = -primRay4.d[1].f[idx];
					wi.z = -primRay4.d[2].f[idx];
					its.p.x = secRay4.o[0].f[idx];
					its.p.y = secRay4.o[1].f[idx];
					its.p.z = secRay4.o[2].f[idx];
					if (EXPECT_NOT_TAKEN(bsdf->getType() & BSDF::EAnisotropic)) {
						its.shFrame.s = normalize(its.dpdu - its.shFrame.n
							* dot(its.shFrame.n, its.dpdu));
						its.shFrame.t = cross(its.shFrame.n, its.shFrame.s);
					} else {
						coordinateSystem(its.shFrame.n, its.shFrame.s, its.shFrame.t);
					}
					const Float ctLight = cosThetaLight.f[idx];
					wi = normalize(wi);

					its.wi = its.toLocal(wi);
					wo = its.toLocal(wo);

					if (!diffuseVPL) {
						if (m_vpl.type == ESurfaceVPL) {
							BSDFQueryRecord bRec(m_vpl.its, m_vpl.its.toLocal(wi));
							bRec.quantity = EImportance;
							vplWeight = m_vpl.its.shape->getBSDF()->eval(bRec) * m_vpl.P;
						} else {
							EmissionRecord eRec(m_vpl.luminaire, 
								ShapeSamplingRecord(m_vpl.its.p, m_vpl.its.shFrame.n), wi);
							eRec.type = EmissionRecord::EPreview;
							vplWeight = m_vpl.luminaire->evalDirection(eRec) * m_vpl.P;
						}
					}

					if (EXPECT_TAKEN(ctLight >= 0)) {
						direct[idx] = (bsdf->eval(BSDFQueryRecord(its, wo)) * vplWeight
							* ((vplOnSurface ? std::max(ctLight, (Float) 0.0f) : 1.0f) * invLengthSquared.f[idx]));
					} else {
						memset(&direct[idx], 0, sizeof(Spectrum));
					}
				}
				++numRays;
			}

			/* Shoot the secondary rays */
			const int secSignsX = _mm_movemask_ps(secRay4.d[0].ps);
			const int secSignsY = _mm_movemask_ps(secRay4.d[1].ps);
			const int secSignsZ = _mm_movemask_ps(secRay4.d[2].ps);

			const bool secCoherent =
				   (secSignsX == 0 || secSignsX == 0xF)
				&& (secSignsY == 0 || secSignsY == 0xF)
				&& (secSignsZ == 0 || secSignsZ == 0xF);

			/* Shoot the secondary rays */
			secIts4.t = SSEConstants::p_inf;
			if (EXPECT_TAKEN(secCoherent)) {
				secRay4.signs[0][0] = secSignsX ? 1 : 0;
				secRay4.signs[1][0] = secSignsY ? 1 : 0;
				secRay4.signs[2][0] = secSignsZ ? 1 : 0;
				m_kdtree->rayIntersectPacket(secRay4, secItv4, secIts4, temp);
			} else {
				m_kdtree->rayIntersectPacketIncoherent(secRay4, secItv4, secIts4, temp);
			}

			for (int idx=0; idx<4; ++idx) {
				if (EXPECT_TAKEN(secIts4.t.f[idx] == std::numeric_limits<float>::infinity()))
					block->setPixel(pos+pixelOffset[idx], direct[idx]+emitted[idx]);
				else
					block->setPixel(pos+pixelOffset[idx], emitted[idx]);
			}
		}
	}
	block->setExtra(numRays);
#else
	Log(EError, "Coherent raytracing support was not compiled into this binary!");
#endif
}
コード例 #11
0
ファイル: photonmapper.cpp プロジェクト: valdersoul/NoriV2
    void preprocess(const Scene *scene) {
        /* Create a sample generator for the preprocess step */
        Sampler *sampler = static_cast<Sampler *>(
            NoriObjectFactory::createInstance("independent", PropertyList()));

        Emitter* distantsDisk = scene->getDistantEmitter();
        if(distantsDisk != nullptr ) {
            float lngstDir = scene->getBoundingBox().getLongestDirection();
            distantsDisk->setMaxRadius(lngstDir);
        }

        /* Allocate memory for the photon map */
        m_photonMap = std::unique_ptr<PhotonMap>(new PhotonMap());
        m_photonMap->reserve(m_photonCount);

		/* Estimate a default photon radius */
		if (m_photonRadius == 0)
			m_photonRadius = scene->getBoundingBox().getExtents().norm() / 500.0f;

        int storedPhotons = 0;

        const  std::vector<Emitter *> lights = scene->getEmitters();
        int nLights = lights.size();
        Color3f tp(1.0f, 1.0f, 1.0f);

        cout << "Starting to create "<< m_photonCount << " photons!" << endl;
        int percentDone= 0;
        int onePercent = int(floor(m_photonCount / 100.0));

        // create the expected number of photons
        while(storedPhotons < m_photonCount) {
            //uniformly sample 1 light (assuming that we only have area lights)
            int var = int(std::min(sampler->next1D()*nLights, float(nLights) - 1.0f));
            const areaLight* curLight = static_cast<const areaLight *> (lights[var]);

            //sample a photon
            Photon curPhoton;
            Vector3f unQuantDir(0.0f,0.0f,0.0f);
            curLight->samplePhoton(sampler, curPhoton, 1, nLights, unQuantDir);
            Color3f alpha = curPhoton.getPower();
            Color3f tp(1.0f, 1.0f, 1.0f);


            //trace the photon
            Intersection its;
            Ray3f photonRay(curPhoton.getPosition(), unQuantDir);
            m_shootedRays++;
            if (scene->rayIntersect(photonRay, its)) {
                while(true) {
                    const BSDF* curBSDF = its.mesh->getBSDF();


                    if (curBSDF->isDiffuse()) {
                        //store the photon
                        m_photonMap->push_back(Photon(
                            its.p  /* Position */,
                            -photonRay.d /* Direction*/,
                            tp * alpha  /* Power */
                        ));
                        storedPhotons++;
                    }

                    if(!(storedPhotons < m_photonCount)) break;

                    BSDFQueryRecord query = BSDFQueryRecord(its.toLocal(-photonRay.d), Vector3f(0.0f), EMeasure::ESolidAngle);
                    Color3f fi =  curBSDF->sample(query, sampler->next2D());

                    if(fi.maxCoeff() == 0.0f) break;

                    tp *= fi;

                    Vector3f wo = its.toWorld(query.wo);
                    photonRay = Ray3f(its.p, wo);

                    //ray escapes the scene
                    if (!scene->rayIntersect(photonRay, its)) break;

                    //stop critirium russian roulette
                    float q = tp.maxCoeff();
                    if(q < sampler->next1D()) break;
                    tp /= q;
                }

            }
            if(onePercent != 0) {
                if(storedPhotons % onePercent == 0){
                    int percent = int(floor(storedPhotons / onePercent));
                    if(percent % 10 == 0 && percentDone != percent){
                        percentDone = percent;
                        cout << percent << "%" << endl;
                    }
                }
            }
        }

		/* Build the photon map */
        m_photonMap->build();
    }
コード例 #12
0
ファイル: photonmapper.cpp プロジェクト: valdersoul/NoriV2
    Color3f Li(const Scene *scene, Sampler *sampler, const Ray3f &ray) const {
        /* Find the surface that is visible in the requested direction */
        Intersection its;


        //check if the ray intersects the scene
        if (!scene->rayIntersect(ray, its)) {
            return Color3f(0.0f);
        }

        Color3f tp(1.0f, 1.0f, 1.0f);
        Color3f L(0.0f, 0.0f, 0.0f);
        Ray3f pathRay(ray.o, ray.d);
        while(true) {

            //get the radiance of hitten object

            if (its.mesh->isEmitter() ) {
                const Emitter* areaLightEM = its.mesh->getEmitter();
                const areaLight* aEM = static_cast<const areaLight *> (areaLightEM);
                L += tp * aEM->sampleL(-pathRay.d, its.shFrame.n, its);
            }

            //get the asigned BSDF
            const BSDF* curBSDF = its.mesh->getBSDF();

            //transform to the local frame
            BSDFQueryRecord query = BSDFQueryRecord(its.toLocal(-pathRay.d), Vector3f(0.0f), EMeasure::ESolidAngle);

            //Normal3f n = its.shFrame.n;



            if(curBSDF->isDiffuse()) {
                std::vector<uint32_t> results;
                m_photonMap->search(its.p, m_photonRadius, results);
                Color3f Li(0.0f, 0.0f, 0.0f);
                int k = results.size();
                //cout << k << endl;

                if(k > 0) {

                    //cout << results.size() << " Photons found!" << endl;
                    //get the power from all photons
                    //for (uint32_t i : results)
                    //const Photon &photonk = (*m_photonMap)[k-1];
                    Color3f Lindir(0.0f, 0.0f, 0.0f);
                    for (int i = 0; i < k; ++i)
                    {
                        const Photon &photon = (*m_photonMap)[results[i]];
                        Vector3f wi = its.toLocal(photon.getDirection());
                        Vector3f wo = its.toLocal(its.shFrame.n);
                        BSDFQueryRecord dummy = BSDFQueryRecord(wi, wo, EMeasure::ESolidAngle);
                        Color3f f = curBSDF->eval(dummy);


                        Lindir += (tp * f) * photon.getPower() / (M_PI * m_photonRadius * m_photonRadius);


                    }

                    Li += Lindir;

                    //cout << "Li = " <<  Li.toString() << endl;
                    if(Li.maxCoeff() > 0.0f)
                        L +=  Li  / m_shootedRays;

                }
                break;
            }

            //sample the BRDF
            Color3f fi =  curBSDF->sample(query, sampler->next2D());
            //check for black brdf
            if(fi.maxCoeff() > 0.0f) {
                tp *= fi;
            } else {
                //stop
                // hit a black brdf
                break;
            }
            Vector3f wo = its.toWorld(query.wo);
            pathRay = Ray3f(its.p, wo);

            //ray escapes the scene
            if (!scene->rayIntersect(pathRay, its)) break;


            //stop critirium russian roulette
            float maxCoeff = tp.maxCoeff();
            float q = std::min(0.99f, maxCoeff);
            if(q < sampler->next1D()) break;
            tp /= q;
        }
        return L;
    }
コード例 #13
0
ファイル: edge.cpp プロジェクト: akaterin/ray-tracer
bool PathEdge::pathConnectAndCollapse(const Scene *scene, const PathEdge *predEdge,
		const PathVertex *vs, const PathVertex *vt,
		const PathEdge *succEdge, int &interactions) {
	if (vs->isEmitterSupernode() || vt->isSensorSupernode()) {
		Float radianceTransport   = vt->isSensorSupernode() ? 1.0f : 0.0f,
		      importanceTransport = 1-radianceTransport;
		medium = NULL;
		length = 0.0f;
		d = Vector(0.0f);
		pdf[ERadiance]   = radianceTransport;
		pdf[EImportance] = importanceTransport;
		weight[ERadiance] = Spectrum(radianceTransport);
		weight[EImportance] = Spectrum(importanceTransport);
		interactions = 0;
	} else {
		Point vsp = vs->getPosition(), vtp = vt->getPosition();
		d = vsp-vtp;
		length = d.length();
		int maxInteractions = interactions;
		interactions = 0;

		if (length == 0) {
			#if defined(MTS_BD_DEBUG)
				SLog(EWarn, "Tried to connect %s and %s, which are located at exactly the same position!",
					vs->toString().c_str(), vt->toString().c_str());
			#endif
			return false;
		}

		d /= length;
		Float lengthFactor = vs->isOnSurface() ? (1-ShadowEpsilon) : 1;
		Ray ray(vtp, d, vt->isOnSurface() ? Epsilon : 0, length * lengthFactor, vs->getTime());

		weight[ERadiance] = Spectrum(1.0f);
		weight[EImportance] = Spectrum(1.0f);
		pdf[ERadiance] = 1.0f;
		pdf[EImportance] = 1.0f;

		Intersection its;
		Float remaining = length;
		medium = vt->getTargetMedium(succEdge, d);

		while (true) {
			bool surface = scene->rayIntersectAll(ray, its);

			if (surface && (interactions == maxInteractions ||
				!(its.getBSDF()->getType() & BSDF::ENull))) {
				/* Encountered an occluder -- zero transmittance. */
				return false;
			}

			if (medium) {
				Float segmentLength = std::min(its.t, remaining);
				MediumSamplingRecord mRec;
				medium->eval(Ray(ray, 0, segmentLength), mRec);

				Float pdfRadiance = (surface || !vs->isMediumInteraction())
					? mRec.pdfFailure : mRec.pdfSuccess;
				Float pdfImportance = (interactions > 0 || !vt->isMediumInteraction())
					? mRec.pdfFailure : mRec.pdfSuccessRev;

				if (pdfRadiance == 0 || pdfImportance == 0 || mRec.transmittance.isZero()) {
					/* Zero transmittance */
					return false;
				}

				weight[EImportance] *= mRec.transmittance / pdfImportance;
				weight[ERadiance] *= mRec.transmittance / pdfRadiance;
				pdf[EImportance] *= pdfImportance;
				pdf[ERadiance] *= pdfRadiance;
			}

			if (!surface || remaining - its.t < 0)
				break;

			/* Advance the ray */
			ray.o = ray(its.t);
			remaining -= its.t;
			ray.mint = Epsilon;
			ray.maxt = remaining * lengthFactor;

			/* Account for the ENull interaction */
			const BSDF *bsdf = its.getBSDF();
			Vector wo = its.toLocal(ray.d);
			BSDFSamplingRecord bRec(its, -wo, wo, ERadiance);
			bRec.component = BSDF::ENull;
			Float nullPdf = bsdf->pdf(bRec, EDiscrete);
			if (nullPdf == 0)
				return false;

			Spectrum nullWeight = bsdf->eval(bRec, EDiscrete) / nullPdf;

			weight[EImportance] *= nullWeight;
			weight[ERadiance] *= nullWeight;
			pdf[EImportance] *= nullPdf;
			pdf[ERadiance] *= nullPdf;

			if (its.isMediumTransition()) {
				const Medium *expected = its.getTargetMedium(-ray.d);
				if (medium != expected) {
					#if defined(MTS_BD_TRACE)
						SLog(EWarn, "PathEdge::pathConnectAndCollapse(): attempted two connect "
							"two vertices that disagree about the medium in between! "
							"Please check your scene for leaks.");
					#endif
					++mediumInconsistencies;
					return false;
				}
				medium = its.getTargetMedium(ray.d);
			}

			if (++interactions > 100) { /// Just a precaution..
				SLog(EWarn, "pathConnectAndCollapse(): round-off error issues?");
				return false;
			}
		}

		if (medium != vs->getTargetMedium(predEdge, -d)) {
			#if defined(MTS_BD_TRACE)
				SLog(EWarn, "PathEdge::pathConnectAndCollapse(): attempted two connect "
					"two vertices that disagree about the medium in between! "
					"Please check your scene for leaks.");
			#endif
			++mediumInconsistencies;
			return false;
		}
	}

	return true;
}
コード例 #14
0
ファイル: edge.cpp プロジェクト: akaterin/ray-tracer
bool PathEdge::pathConnect(const Scene *scene, const PathEdge *predEdge,
		const PathVertex *vs, Path &result, const PathVertex *vt,
		const PathEdge *succEdge, int maxInteractions, MemoryPool &pool) {
	BDAssert(result.edgeCount() == 0 && result.vertexCount() == 0);

	if (vs->isEmitterSupernode() || vt->isSensorSupernode()) {
		Float radianceTransport   = vt->isSensorSupernode() ? 1.0f : 0.0f,
		      importanceTransport = 1-radianceTransport;
		PathEdge *edge = pool.allocEdge();
		edge->medium = NULL;
		edge->length = 0.0f;
		edge->d = Vector(0.0f);
		edge->pdf[ERadiance]   = radianceTransport;
		edge->pdf[EImportance] = importanceTransport;
		edge->weight[ERadiance] = Spectrum(radianceTransport);
		edge->weight[EImportance] = Spectrum(importanceTransport);
		result.append(edge);
	} else {
		Point vsp = vs->getPosition(), vtp = vt->getPosition();
		Vector d(vsp-vtp);
		Float remaining = d.length();
		d /= remaining;
		if (remaining == 0) {
			#if defined(MTS_BD_DEBUG)
				SLog(EWarn, "Tried to connect %s and %s, which are located at exactly the same position!",
					vs->toString().c_str(), vt->toString().c_str());
			#endif
			return false;
		}

		Float lengthFactor = vs->isOnSurface() ? (1-ShadowEpsilon) : 1;
		Ray ray(vtp, d, vt->isOnSurface() ? Epsilon : 0,
				remaining * lengthFactor, vs->getTime());
		const Medium *medium = vt->getTargetMedium(succEdge,  d);

		int interactions = 0;

		Intersection its;
		while (true) {
			bool surface = scene->rayIntersectAll(ray, its);

			if (surface && (interactions == maxInteractions ||
				!(its.getBSDF()->getType() & BSDF::ENull))) {
				/* Encountered an occluder -- zero transmittance. */
				result.release(pool);
				return false;
			}

			/* Construct an edge */
			PathEdge *edge = pool.allocEdge();
			result.append(edge);
			edge->length = std::min(its.t, remaining);
			edge->medium = medium;
			edge->d = d;

			if (medium) {
				MediumSamplingRecord mRec;
				medium->eval(Ray(ray, 0, edge->length), mRec);
				edge->pdf[ERadiance] = (surface || !vs->isMediumInteraction())
					? mRec.pdfFailure : mRec.pdfSuccess;
				edge->pdf[EImportance] = (interactions > 0 || !vt->isMediumInteraction())
					? mRec.pdfFailure : mRec.pdfSuccessRev;

				if (edge->pdf[ERadiance] == 0 || edge->pdf[EImportance] == 0
						|| mRec.transmittance.isZero()) {
					/* Zero transmittance */
					result.release(pool);
					return false;
				}
				edge->weight[EImportance] = mRec.transmittance / edge->pdf[EImportance];
				edge->weight[ERadiance]   = mRec.transmittance / edge->pdf[ERadiance];
			} else {
				edge->weight[ERadiance] = edge->weight[EImportance] = Spectrum(1.0f);
				edge->pdf[ERadiance] = edge->pdf[EImportance] = 1.0f;
			}

			if (!surface || remaining - its.t < 0)
				break;

			/* Advance the ray */
			ray.o = ray(its.t);
			remaining -= its.t;
			ray.mint = Epsilon;
			ray.maxt = remaining * lengthFactor;

			const BSDF *bsdf = its.getBSDF();

			/* Account for the ENull interaction */
			Vector wo = its.toLocal(ray.d);
			BSDFSamplingRecord bRec(its, -wo, wo, ERadiance);
			bRec.component = BSDF::ENull;
			Float nullPdf = bsdf->pdf(bRec, EDiscrete);
			if (nullPdf == 0) {
				result.release(pool);
				return false;
			}

			PathVertex *vertex = pool.allocVertex();
			vertex->type = PathVertex::ESurfaceInteraction;
			vertex->degenerate = !(bsdf->hasComponent(BSDF::ESmooth)
				|| its.shape->isEmitter() || its.shape->isSensor());
			vertex->measure = EDiscrete;
			vertex->componentType = BSDF::ENull;
			vertex->pdf[EImportance] = vertex->pdf[ERadiance] = nullPdf;
			vertex->weight[EImportance] = vertex->weight[ERadiance]
				= bsdf->eval(bRec, EDiscrete) / nullPdf;
			vertex->rrWeight = 1.0f;
			vertex->getIntersection() = its;
			result.append(vertex);

			if (its.isMediumTransition()) {
				const Medium *expected = its.getTargetMedium(-ray.d);
				if (medium != expected) {
					#if defined(MTS_BD_TRACE)
						SLog(EWarn, "PathEdge::pathConnect(): attempted two connect "
							"two vertices that disagree about the medium in between! "
							"Please check your scene for leaks.");
					#endif
					++mediumInconsistencies;
					result.release(pool);
					return false;
				}
				medium = its.getTargetMedium(ray.d);
			}

			if (++interactions > 100) { /// Just a precaution..
				SLog(EWarn, "pathConnect(): round-off error issues?");
				result.release(pool);
				return false;
			}
		}

		if (medium != vs->getTargetMedium(predEdge, -d)) {
			#if defined(MTS_BD_TRACE)
				SLog(EWarn, "PathEdge::pathConnect(): attempted two connect "
					"two vertices that disagree about the medium in between! "
					"Please check your scene for leaks.");
			#endif
			++mediumInconsistencies;
			result.release(pool);
			return false;
		}
	}

	result.reverse();

	BDAssert(result.edgeCount() == result.vertexCount() + 1);
	BDAssert((int) result.vertexCount() <= maxInteractions || maxInteractions < 0);

	return true;
}
コード例 #15
0
ファイル: direct.cpp プロジェクト: valdersoul/NoriV2
    Color3f Li(const Scene *scene, Sampler *sampler, const Ray3f &ray) const {
        /* Find the surface that is visible in the requested direction */
        Intersection its;
        if (!scene->rayIntersect(ray, its))
            return Color3f(0.0f);

        //get the Normal at the intersection point
        Vector3f n = Vector3f(its.shFrame.n);

        //get the Number of lights from the scene

        const  std::vector<Emitter *> lights = scene->getEmitters();
        uint32_t nLights = lights.size();


        //check for lights
        if(nLights > 0) {

            //get the asigned BSDF
            const BSDF* curBSDF = its.mesh->getBSDF();
            if(curBSDF) {
                Color3f totalLight(0.0f);
                //uterated over all lights
                //std::cout << "start light comp" << std::endl;
                for (uint32_t var = 0; var < nLights; ++var) {

                    VisibilityTester vis;
                    Vector3f wi;
                    float pdf;
                    const Point2f ls;

                    //sample the light
                    Color3f Ld =lights[var]->sampleL(its.p, Epsilon, ls, &wi, &pdf, &vis);

                    //check if the light is visible
                    if(vis.Unoccluded(scene)) {

                        //create a query for the brdf
                        Vector3f wo = - ray.d;

                        //calculate the abs value of n dot wi
                        float costerm = n.dot(wi);

                        //transform to the local frame
                        wo = its.toLocal(wo);
                        wi = its.toLocal(wi);

                        const BSDFQueryRecord query = BSDFQueryRecord(wi, wo, EMeasure::ESolidAngle);

                        //calculate the BSDF
                        Color3f f = curBSDF->eval(query);

                        //add the light up
                        totalLight += (Ld * f * std::abs(costerm));

                    }
                }

                return totalLight;
            }
        }
        return Color3f(0.0f);


    }
コード例 #16
0
ファイル: path.cpp プロジェクト: shen-yang/nori
	Color3f Li(const Scene *scene, Sampler *sampler, const Ray3f &r) const {
		/* Find the surface that is visible in the requested direction */
		Intersection its;
		Ray3f ray(r);
		if (!scene->rayIntersect(ray, its))
			return Color3f(0.0f);
		Color3f radiance(0.0f);
		
		bool specularBounce = false;
		Color3f pathThroughput(1.0f);
		for ( int bounces = 0; ; ++bounces ) {
			const Luminaire* luminaire = its.mesh->getLuminaire();
			if ((bounces == 0 || specularBounce) && luminaire != NULL) {
				Vector3f wo = (-ray.d).normalized();
				Color3f emission = luminaire->le(its.p, its.shFrame.n, wo);
				radiance += pathThroughput*emission;
			}
			const Texture* texture = its.mesh->getTexture();
			Color3f texel(1.0f);
			if ( texture ) {
				texel = texture->lookUp(its.uv.x(), its.uv.y());
			}
			const BSDF* bsdf = its.mesh->getBSDF();
			// sample illumination from lights, add to path contribution
			if (!bsdf->isSpecular()){
				radiance += pathThroughput*UniformSampleAllLights(scene, ray, its, sampler, m_samplePolicy)*texel;
			}
			// sample bsdf to get new path direction
			BSDFQueryRecord bRec(its.toLocal((-ray.d)).normalized());
			Color3f f = bsdf->sample(bRec, sampler->next2D() );	
			if (f.isZero() ) { // farther path no contribution
				break;
			}
			specularBounce = bsdf->isSpecular();
			Vector3f d = its.toWorld(bRec.wo);
			f *= texel;
			pathThroughput *= f;
			ray = Ray3f(its.p, d );
			// possibly termination
			if (bounces > kSampleDepth) {
#if 0
				float continueProbability = std::min( 0.5f, pathThroughput.y() );
				if ( sampler->next1D() > continueProbability ) {
					break;
				}
#else
				float continueProbability = std::max(f.x(), 
					std::max(f.y(), f.z()));
				if ( sampler->next1D() > continueProbability ) {
					break;
				}
#endif
				pathThroughput /= continueProbability;
			}
			if (bounces == m_maxDepth) {
				break;
			}
			// find next vertex of path
			if ( !scene->rayIntersect(ray, its) ) {
				break;
			}
		}

		return radiance;
	}