Example #1
0
File: Matte.cpp Project: dicta/ray
Color Matte::shade(ShadeRecord& sr, const Ray& ray) {
   Vector3D wo = ray.direction * -1;
   Color L = ambientBRDF->rho(sr, wo) * LightManager::instance().getAmbientLight(sr);

   for(LightIter it = LightManager::instance().begin(); it != LightManager::instance().end(); it++) {
      Color power;
      Vector3D wis;

      for(int s = 0; s < (*it)->getNumLightSamples(); s++) {
         Vector3D wi = (*it)->getLightDirection(sr);
         wis += wi;
         float ndotwi = sr.normal.dot(wi);

         if(ndotwi > 0.0) {
            Ray shadowRay(sr.hitPoint, wi);
            bool inShadow = (*it)->inShadow(shadowRay, sr);

            if(!inShadow) {
               power += (*it)->L(sr) * (*it)->G(sr) * ndotwi / (*it)->pdf(sr);
            }
         }
      }

      power = power / (*it)->getNumLightSamples();
      wis.normalize();
      L += diffuseBRDF->f(sr, wo, wis) * power;
   }

   return L;
}
bool ShadowCalculator::inShadow(const Point3D& pointToBeTested, const Point3D& lightPoint) const {

    //Shadow ray calculation.
    ShadowRay shadowRay(pointToBeTested, lightPoint);

    //Calculate intersection
    Intersection *intersectionData = tracer.closestIntersection(*shadowRay.ray);

    //No intersection or intersection with light object.
    if(intersectionData == nullptr || intersectionData->object->isLight == true) {

        return false;
    }

    //Extract t (intersection distance) and d (distance from light).
    float t = intersectionData->t;
    float d = shadowRay.d;

    //Clear pointer.
    delete intersectionData;

    //If the intersection distance is greater than the distance between intersectionPoint and light then the point
    //is NOT in shadow.
    if(t > d) {

        return false;
    }

    //Ok, the point is in shadow.
    return true;
}
RGB TexturedLambertianShader::getDiffuseRadiance(Object3d* p_object, Vector3d p_point, Vector3d p_normal, UVMap p_uv, Vector3d p_viewVec, Scene3d* p_scene) {
	RGB totalRadiance(0,0,0);
	Light* light;

	for(int l = 0; l < p_scene->getLightCount(); l++) {
		light = p_scene->getLights()[l];

		Vector3d lightDirection = -light->getDirectionAt(p_point);
		float cosThetaSurface = lightDirection.dot(p_normal);

			if(cosThetaSurface > -EPSILON) {
				//shadow ray

				Ray shadowRay(p_point, lightDirection);

				float distToLight = light->getDistanceAt(p_point);
				bool intersects = false;
				if(p_scene->kdTree == NULL) {
					intersects = shadowRay.intersects(p_scene->getObjects(), p_scene->getObjectCount(), distToLight);
				} else {
					intersects = p_scene->kdTree->intersects(&shadowRay, distToLight);
				}

				if(!intersects) {
					totalRadiance = totalRadiance + light->getRadianceAt(p_point) * cosThetaSurface;
				}
			}
	}

	RGB c = (map != NULL)? map->getTexel(p_uv.u, p_uv.v) : color;
	return (totalRadiance * c);
}
Example #4
0
RGBColor Matte::shade(ShadeRec& sr) {
	Vector3D wo = -sr.ray.d;
	RGBColor L = ambient_brdf->rho(sr,wo) * sr.w.ambient_ptr->L(sr);
	int numLights = sr.w.lights.size();

	for(int j = 0; j < numLights; j++){
		Vector3D wi = sr.w.lights[j] -> get_direction(sr);
		float ndotwi = sr.normal * wi;

		if(ndotwi > 0.0) {
			bool in_shadow = false;

			if(sr.w.lights[j]->casts_shadows()) {
				Ray shadowRay(sr.hit_point, wi);
				in_shadow = sr.w.lights[j]->in_shadow(shadowRay, sr);
			}

			if(!in_shadow)
				L += diffuse_brdf->f(sr,wo,wi) * sr.w.lights[j]->L(sr) * ndotwi;

			
		}
	}

	return (L);

}
Example #5
0
RGBColor Phong::shade(ShadeRec& sr) {
    Vector3D wo = -sr.ray.d;
    RGBColor L = ambient + emission;

    int numLights = sr.w.lights.size();

    for(int j = 0; j < numLights; j++) {
        Vector3D wi = sr.w.lights[j]->get_direction(sr);
        Vector3D h(wi + wo);
        h.normalize();
        float ndotwi = sr.normal * wi;
        float ndoth = sr.normal * h;
        bool in_shadow = false;

        if(sr.w.lights[j]->casts_shadows())
        {
            Ray shadowRay(sr.hit_point, wi);
            in_shadow = sr.w.lights[j]->in_shadow(shadowRay, sr);
        }

        if(!in_shadow)
        {
            L += diffuse * sr.w.lights[j]->L(sr) * max(0.0, ndotwi) + specular * sr.w.lights[j]->L(sr) * pow(max(ndoth, 0.0), shininess);
        }


    }

    return(L);

}
Example #6
0
ColorRGB RayTracer::trace(const Ray& p_ray, const SceneList& p_scene, int p_bounce)
{
	if (p_bounce > m_settings.maxBounces)
	{
		return m_settings.clearColor;
	}
	
	std::pair<Shape*, float> closestInfo = getClosestShape(p_ray, p_scene);

	if (closestInfo.first != nullptr)
	{
		Point3 intersectionPoint = p_ray.origin + closestInfo.second * p_ray.direction;
		Vector3 intersectionNormal = closestInfo.first->getNormal(intersectionPoint);
		intersectionNormal.normalize();
		
		// Offset to prevent self intersection
		intersectionPoint += 0.0001f * intersectionNormal;
		
		//ColorRGB reflectedColor = ColorRGB(255, 255, 255);
		
		if (closestInfo.first->reflective)
		{
			// Trace reflection ray
			Ray reflectionRay(
				intersectionPoint,
				reflect(p_ray.direction, intersectionNormal));
			
			return trace(reflectionRay, p_scene, p_bounce + 1);
		}
		if (m_settings.lightEnabled == false)
		{
			return closestInfo.first->color.rgb();
		}
		
		// Compute shadow ray 
		const Point3 lightPosition(0, 500, 0);
		
		Vector3 shadowVector = lightPosition - intersectionPoint;
		shadowVector.normalize();
		Ray shadowRay(intersectionPoint, shadowVector);
		
		std::pair<Shape*, float> shadowInfo = getClosestShape(shadowRay, p_scene);
		
		float lightContribution = 0.2f; // Ambient light
		
		if (shadowInfo.first == nullptr)
		{
			// Compute diffuse light factor
			float diffuseFactor = dotProduct(intersectionNormal, shadowRay.direction);
			if (diffuseFactor > 0.0f)
			{
				lightContribution += diffuseFactor;
			}
		}
		return std::min(lightContribution, 1.0f) * closestInfo.first->color.rgb();
	}
	return m_settings.clearColor;
}
Example #7
0
    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;
    }
void InstantRadiosityRenderer::processPixel(uint32_t threadID, uint32_t tileID, const Vec2u& pixel) const {
    PixelSensor pixelSensor(getSensor(), pixel, getFramebufferSize());
    RaySample raySample;
    float positionPdf, directionPdf;
    auto We = pixelSensor.sampleExitantRay(getScene(), getFloat2(threadID), getFloat2(threadID), raySample, positionPdf, directionPdf);

    auto L = zero<Vec3f>();

    if(We != zero<Vec3f>() && raySample.pdf) {
        auto I = getScene().intersect(raySample.value);
        BSDF bsdf(-raySample.value.dir, I, getScene());
        if(I) {
            // Direct illumination
            for(auto& vpl: m_EmissionVPLBuffer) {
                RaySample shadowRay;
                auto Le = vpl.pLight->sampleDirectIllumination(getScene(), vpl.emissionVertexSample, I, shadowRay);

                if(shadowRay.pdf) {
                    auto contrib = We * Le * bsdf.eval(shadowRay.value.dir) * abs(dot(I.Ns, shadowRay.value.dir)) /
                            (vpl.lightPdf * shadowRay.pdf * m_nLightPathCount * raySample.pdf);

                    if(contrib != zero<Vec3f>()) {
                        if(!getScene().occluded(shadowRay.value)) {
                            L += contrib;
                        }
                    }
                }
            }

            // Indirect illumination
            for(auto& vpl: m_SurfaceVPLBuffer) {
                auto dirToVPL = vpl.intersection.P - I.P;
                auto dist = length(dirToVPL);

                if(dist > 0.f) {
                    dirToVPL /= dist;

                    auto fs1 = bsdf.eval(dirToVPL);
                    auto fs2 = vpl.bsdf.eval(-dirToVPL);
                    auto geometricFactor = abs(dot(I.Ns, dirToVPL)) * abs(dot(vpl.intersection.Ns, -dirToVPL)) / sqr(dist);

                    auto contrib = We * vpl.power * fs1 * fs2 * geometricFactor / raySample.pdf;
                    if(contrib != zero<Vec3f>()) {
                        Ray shadowRay(I, vpl.intersection, dirToVPL, dist);
                        if(!getScene().occluded(shadowRay)) {
                            L += contrib;
                        }
                    }
                }
            }
        }
    }

    accumulate(0, getPixelIndex(pixel.x, pixel.y), Vec4f(L, 1.f));
}
Example #9
0
void DirectionalLight::sample(Accelerator *surfaces, Intersection *intersection, Vector *direction, Color *Li) {
	*direction = d;

	/* Shadow testing */
	Ray shadowRay(intersection->point, d);

	if(!surfaces->intersectFast(&shadowRay))
		*Li = Le;
	else
		*Li = Color(0);
}
void PathCPURenderThread::DirectLightSampling(
		const float u0, const float u1, const float u2,
		const float u3, const float u4,
		const Spectrum &pathThrouput, const BSDF &bsdf,
		const int depth, Spectrum *radiance) {
	PathCPURenderEngine *engine = (PathCPURenderEngine *)renderEngine;
	Scene *scene = engine->renderConfig->scene;
	
	if (!bsdf.IsDelta()) {
		// Pick a light source to sample
		float lightPickPdf;
		const LightSource *light = scene->SampleAllLights(u0, &lightPickPdf);

		Vector lightRayDir;
		float distance, directPdfW;
		Spectrum lightRadiance = light->Illuminate(scene, bsdf.hitPoint,
				u1, u2, u3, &lightRayDir, &distance, &directPdfW);

		if (!lightRadiance.Black()) {
			BSDFEvent event;
			float bsdfPdfW;
			Spectrum bsdfEval = bsdf.Evaluate(lightRayDir, &event, &bsdfPdfW);

			if (!bsdfEval.Black()) {
				const float epsilon = Max(MachineEpsilon::E(bsdf.hitPoint), MachineEpsilon::E(distance));
				Ray shadowRay(bsdf.hitPoint, lightRayDir,
						epsilon,
						distance - epsilon);
				RayHit shadowRayHit;
				BSDF shadowBsdf;
				Spectrum connectionThroughput;
				// Check if the light source is visible
				if (!scene->Intersect(device, false, u4, &shadowRay,
						&shadowRayHit, &shadowBsdf, &connectionThroughput)) {
					const float cosThetaToLight = AbsDot(lightRayDir, bsdf.shadeN);
					const float directLightSamplingPdfW = directPdfW * lightPickPdf;
					const float factor = cosThetaToLight / directLightSamplingPdfW;

					if (depth >= engine->rrDepth) {
						// Russian Roulette
						bsdfPdfW *= Max(bsdfEval.Filter(), engine->rrImportanceCap);
					}

					// MIS between direct light sampling and BSDF sampling
					const float weight = PowerHeuristic(directLightSamplingPdfW, bsdfPdfW);

					*radiance += (weight * factor) * pathThrouput * connectionThroughput * lightRadiance * bsdfEval;
				}
			}
		}
	}
}
Example #11
0
static void appendVPL(const Scene *scene, Random *random,
	VPL &vpl, bool prune, std::deque<VPL> &vpls) {
	prunedVPLs.incrementBase();

	const Sensor *sensor = scene->getSensor();
	Float time = sensor->getShutterOpen()
		+ 0.5f * sensor->getShutterOpenTime();

	if (prune) {
		/* Possibly reject VPLs if they are unlikely to be
		   visible from the camera */
		int nSuccesses = 0, nSamples = 50;
		const Shape *shape;
		Normal n;
		Point2 uv;
		Ray ray;
		Vector2i size = sensor->getFilm()->getCropSize();
		for (int i=0; i<nSamples; ++i) {
			if (sensor->needsTimeSample())
				time = sensor->sampleTime(random->nextFloat());

			sensor->sampleRay(ray, Point2(random->nextFloat() * size.x,
					random->nextFloat() * size.y), Point2(0.5f), time);

			Float t;
			if (scene->rayIntersect(ray, t, shape, n, uv)) {
				Point p = ray(t);
				Vector d = vpl.its.p - p;
				Float length = d.length();
				Ray shadowRay(p, d/length, Epsilon, length*(1-ShadowEpsilon), time);

				if (!scene->rayIntersect(shadowRay))
					++nSuccesses;
			} else {
				++nSuccesses; // be conservative
			}
		}
		/// Have a small chance of acceptance in any case
		Float acceptanceProb = (nSuccesses+1) / (Float) (nSamples+1);
		if (random->nextFloat() < acceptanceProb) {
			vpl.P /= acceptanceProb;
			vpls.push_back(vpl);
		} else {
			++prunedVPLs;
		}
	} else {
		vpls.push_back(vpl);
	}
}
Color PointLight::calculateColor(const Scene &scene, const Ray &ray, float distance, const Vector &normal, MaterialPointer material) const {
  Vector point = ray.getPointAt(distance);

  Color ambientComponent;
  Color diffuseComponent;
  Color specularComponent;

  ambientComponent = componentwiseProduct(material->ambientColor, mAmbientIntensity);
  Color result = ambientComponent;

  Vector shadowRayDirection = mPosition - point;
  float	distanceToLight	= shadowRayDirection.length();
  float	attenuation	= 1 / (mConstantAttenutaionCoefficient + mLinearAttenutaionCoefficient * distanceToLight + mQuadraticAttenutaionCoefficient * distanceToLight * distanceToLight);
  result *= attenuation;

  shadowRayDirection.normalize(); 
  float	shadowRayDotNormal = shadowRayDirection.dotProduct(normal);

  // If the point is not illuminated
  if (shadowRayDotNormal <= 0.0) {
    return result;
  }

  Ray shadowRay(point + shadowRayDirection * EPS_FOR_SHADOW_RAYS, shadowRayDirection);	
  RayIntersection shadowRayIntersection = scene.calculateNearestIntersection(shadowRay);
  
  // If object is not in shadow
  if (!shadowRayIntersection.rayIntersectsWithShape || shadowRayIntersection.distanceFromRayOrigin > distanceToLight) {
    Color diffuseColor = material->diffuseColor;
    diffuseComponent  = componentwiseProduct(diffuseColor, mDiffuseIntensity * attenuation * shadowRayDotNormal);

    Vector lightReflect = shadowRayDirection - normal * 2 * shadowRayDirection.dotProduct(normal);
    lightReflect.normalize();

    Vector cameraDirection = ray.getOriginPosition() - point;
    cameraDirection.normalize();

    float	cosLightReflect = cameraDirection.dotProduct(lightReflect);
    if (cosLightReflect > 0.0) {
      Color specularColor = material->specularColor; 
      specularComponent	= componentwiseProduct(specularColor, mSpecularIntensity * powf(cosLightReflect, material->specularPower) * attenuation);
    }				
  }

  result += (diffuseComponent + specularComponent);
  return result;
}
Example #13
0
QVector3D WhittedRenderer::trace(const Ray& primaryRay, int depth, const QList<Shape*>& shapes, const QList<Light*>& lights)
{
    double minDist = std::numeric_limits<double>::max();
    Shape* closestShape = nullptr;

    QVector3D shaded;
    if (m_grid->intersect(primaryRay, closestShape, minDist)) {
        auto material = closestShape->material();
        shaded = material->ambientReflectivity() * m_ambientLightColor * material->colorVector();
        QColor color = material ? material->color() : QColor(40, 40, 40);
        QVector3D diffuseColor(color.redF(), color.greenF(), color.blueF());
        QVector4D hitPoint = primaryRay.along(minDist);
        QVector4D normalVector = closestShape->surfaceNormal(hitPoint, primaryRay);
        QVector4D viewVector = -primaryRay.direction();
        foreach(Light* light, lights) {

            QVector3D emittance;
            QVector4D lightVector;
            light->sample(lightVector, emittance);
            lightVector = lightVector - hitPoint;
            float lightVectorLengthSquared = lightVector.lengthSquared();
            float lightVectorLength = sqrt(lightVectorLengthSquared);
            lightVector.normalize();

            Ray shadowRay(hitPoint, lightVector);
            double t;
            Shape* blockingShape;
            bool shadowRayHit = m_grid->intersect(shadowRay, blockingShape, t);
            if (!shadowRayHit || (shadowRayHit && (lightVectorLengthSquared < t * t))) {
                // Diffuse
                float dot = fmax(0.0f, QVector4D::dotProduct(lightVector, normalVector)) * material->diffuseReflectivity();
                emittance *= 1 / (1 + 0.2 * lightVectorLength + 0.08 * lightVectorLengthSquared);
                shaded += dot * QVector3D(emittance.x() * diffuseColor.x(),
                                          emittance.y() * diffuseColor.y(),
                                          emittance.z() * diffuseColor.z());

                // Specular
                if (material->specularReflectivity() > 0.0) {
                    QVector4D reflectedLightVector = MathUtils::reflect(-lightVector, normalVector); // lightVector and normalVector are already normalized
                    float dot = QVector4D::dotProduct(reflectedLightVector, viewVector);
                    if (dot > 0.0)
                        shaded += material->specularReflectivity() * pow(dot, material->shininess()) * emittance;
                }
            }
        }
Example #14
0
Vec3f Leafcutter::EvalutateLight(const DirLight& light, DifferentialGeometry& dp, const Vec3f &wo, Material *ms)
{
    Vec3f wi = -light.normal;
    BxdfUnion msu;
    ms->SampleReflectance(dp, msu);
    Vec3f brdf = msu.EvalSmoothCos(wo, wi, dp);
    Vec3f estimate = brdf;

    if(!estimate.IsZero()) 
    {
        Ray shadowRay(dp.P, wi, RAY_INFINITY, 0.0f);
        if(!_engine->IntersectAny(shadowRay))
        {
            return light.le * estimate;
        }
    }
    return Vec3f::Zero();
}
Example #15
0
// ---------------------------------------------------------------- shade
RGBColor SV_Matte::shade(ShadeRec& sr)
{
	//Vector3D 	wo 			= -sr.ray.d;	// wo is the inverse eye ray direction 
	//RGBColor 	L 			= ambient_brdf->rho(sr,wo) * sr.w.ambient_ptr->L(sr);	// ambient light
	//size_t 		num_lights	= sr.w.lights.size();
	//
	//for (size_t j = 0; j < num_lights; j++)
	//{
	//	Vector3D wi = sr.w.lights[j]->get_direction(sr);
	//	//wi.normalizeThis();
	//	double ndotwi = sr.normal * wi;
	//	if(ndotwi> 0.0)
	//		L += ( diffuse_brdf->f(sr, wo, wi) + specula_brdf->f(sr, wo, wi) ) * sr.w.lights[j]->L(sr) * ndotwi;	// diffuse and specular
	//}
	//
	//return (L);

	Vector3D wo = -sr.ray.d;
	RGBColor L = ambient_brdf->rho(sr,wo) * sr.w.ambient_ptr->L(sr);	// ambient light

	size_t numLights = sr.w.lights.size();

	for(size_t j = 0;j < numLights;j++) {
		Vector3D wi = sr.w.lights[j]->get_direction(sr);
		//wi.normalizeThis();
		double ndotwi = sr.normal * wi;

		if(ndotwi> 0.0) {
			bool in_shadow = false;
			
			if(sr.w.lights[j]->casts_shadows()) {
				Point3D new_hit_point = sr.hit_point + Vector3D(sr.normal * EPSILON);
				Ray shadowRay(new_hit_point,wi);
				//Ray shadowRay(sr.hit_point,wi);
				in_shadow = sr.w.lights[j]->in_shadow(shadowRay,sr);
			}
			
			if(!in_shadow)
				L += ( diffuse_brdf->f(sr,wo,wi) * ndotwi + specula_brdf->f(sr, wo, wi) ) * sr.w.lights[j]->L(sr);
		}
	}

	return L;
}
Example #16
0
	float3 trace(const Ray& ray, int depth)
	{
        Hit hit = firstIntersect(ray);

        // If ray hits nothing, we return the aurora borealis
		if(hit.t < 0) {
            return ray.dir * ray.dir * float3(0,1,0.6);
        }
        
        float3 lightSum = {0,0,0};

        for(LightSource *l : lightSources) {
            float3 li = l->getLightDirAt(ray.origin);
            float dist = l->getDistanceFrom(hit.position);
            int maxDepth = 5;

            // Deals with shadows
            Ray shadowRay(hit.position + (hit.normal*0.1), li);
            Hit shadowHit = firstIntersect(shadowRay);
            if(shadowHit.t > 0 && shadowHit.t < dist)
                continue;
            
            // Handles types of materials differently
            if(depth > maxDepth) return lightSum;
            if(hit.material->reflective){   // for smooth surface
                float3 reflectionDir = hit.material->reflect(ray.dir, hit.normal);
                Ray reflectedRay(hit.position + hit.normal*0.1, reflectionDir );
                lightSum += trace(reflectedRay, depth+1)
                        * hit.material->getReflectance(ray.dir, hit.normal);
            }
            if(hit.material->refractive) {  // for smooth surface
                float3 refractionDir = hit.material->refract(ray.dir, hit.normal);
                Ray refractedRay(hit.position - hit.normal*0.1, refractionDir );
                lightSum += trace(refractedRay, depth+1) * (float3(1,1,1) - hit.material->getReflectance(ray.dir, hit.normal));
            } else {                        // for rough surface
                lightSum += hit.material->shade(hit.normal, -ray.dir, l->getLightDirAt(hit.position),
                                           l->getPowerDensityAt(hit.position));
            }
        }
        
		return lightSum;
	}
Vector3D PointLight::LightIntensity(Scene& scene, IntersectResult intersect, const PerspectiveCamera& cam)
{
	Vector3D delta = mPosition - intersect.mPosition;
	float rr = Length2(delta);
	float r = sqrt(rr);
	float r1 = 1.0 / r;
	Vector3D inverseDire = Normalize(delta);

	if (mIsShadow) {
		Ray shadowRay(intersect.mPosition, inverseDire);
		IntersectResult shadowResult = scene.Intersect(shadowRay);
		if (shadowResult.mIsHit && shadowResult.mDistance <= r) {
			return -(this->mColor * this->mShadowReducingFactor);
		}
	}

	float diffuseAttenuation = 1.0 / (mAttenuation.x + mAttenuation.y * r + mAttenuation.z * rr);
	float specularAttenuation = 1.0 / (mAttenuation.x + mAttenuation.y * r + mAttenuation.z * rr);
	Vector3D colorRes;

	// Diffuse Material
	float NdotL = Dot(intersect.mNormal, inverseDire);

	// std::cout << NdotL << std::endl;
	if (NdotL > 0) {
		colorRes = colorRes + 
			intersect.mPrimitive->GetDiffuseColor() * this->mColor * NdotL * diffuseAttenuation;
	}
	
	// Specular Material
	Vector3D Vo = cam.GetPosition() - intersect.mPosition;
	Vector3D V = Normalize(Vo);
	Vector3D h = Normalize(V + inverseDire);
	float NdotH = Dot(intersect.mNormal, h);
	if (NdotH > 0) {
		colorRes = colorRes + 
			intersect.mPrimitive->GetSpecularColor() * this->mColor * powf(NdotH, intersect.mPrimitive->GetShininess()) * specularAttenuation;
	}

	return colorRes;
}
Example #18
0
RGBColor Matte::area_light_shade(ShadeRec& sr){
	
	Vector3D	wo = -sr.ray.d;
	RGBColor	L  = ambient_brdf->rho(sr, wo) * sr.w.ambient_ptr->L(sr);
	int			numLights = sr.w.lights.size();

	for( int j = 0; j < numLights; j++){

		Vector3D wi = sr.w.lights[j]->get_direction(sr);
		float ndotwi = sr.normal * wi;

		if (ndotwi > 0.0){

			bool in_shadow = false;

			if (sr.w.lights[j]->casts_shadows()){

				Ray shadowRay(sr.hit_point, wi);
				in_shadow = sr.w.lights[j]->in_shadow(shadowRay, sr);
			}

			if(!in_shadow){
				RGBColor lf, ll, lg;
				float fpdf;
				lf = diffuse_brdf->f(sr, wo, wi);
				ll = sr.w.lights[j]->L(sr);
				lg = sr.w.lights[j]->G(sr);
				fpdf = sr.w.lights[j]->pdf(sr);

				L += lf * ll * lg * ndotwi / fpdf;

				//L+= diffuse_brdf->f(sr, wo, wi) * sr.w.lights[j]->L(sr) 
				//	* sr.w.lights[j]->G(sr) * ndotwi / sr.w.lights[j]->pdf(sr);
			}
		}
	}


	return L;
}
Example #19
0
RGBVec World::traceRay(const Ray &ray, double t_min, int depth) {
	IntersectionDatum idat = testIntersection(ray, t_min, scenery);
	
	if (!idat.intersected)
		return bg_colour; 

	RGBVec result_vec;

	ShadableObject *obj = static_cast<ShadableObject *>(idat.intersectedObj);
	double t = idat.coefficient;	

	// compute lighting/shading
	for (std::vector<Light>::iterator lptr = lighting.begin(); lptr != lighting.end(); lptr++) {
		vec3 p = ray.intersectionPoint(t);
		vec3 n = obj->surfaceNormal(p);
		vec3 v = (ray.origin - lptr->pos).normalised();
		vec3 l = (lptr->pos - p).normalised();

		Ray shadowRay(p,l);
	
		// if we're not in shadow w.r.t this light
		if (!shadows_enabled || !traceShadowRay(shadowRay, scenery)) {
			result_vec += obj->material.shade(*lptr, n, v, l); 
		}

		if (reflections_enabled && obj->material.reflective && depth < MAX_TRACE_DEPTH) {
			// recursively trace reflection rays:
			
			vec3 d = ray.direction;
			Ray reflected(p, d - n.scaled(2 * d.dot(n)));
			RGBVec reflectedColour = traceRay(reflected, REFLECTION_EPS, depth + 1);
			if (reflectedColour.r() == 0.0 && reflectedColour.g() == 0.0 && reflectedColour.b() == 0.0) continue;
			RGBVec k_m = obj->material.specular_colour;
			result_vec += reflectedColour.multiplyColour(k_m);
		}

	}
	
	return result_vec; 
}	
Example #20
0
SLfloat SLLightRect::shadowTestMC(SLRay* ray, // ray of hit point
                                  const SLVec3f& L, // vector from hit point to light
                                  const SLfloat lightDist) // distance to light
{
    SLVec3f SP; // vector hit point to sample point in world coords

    SLfloat randX = rnd01();
    SLfloat randY = rnd01();

    // choose random point on rect as sample
    SP.set(updateAndGetWM().multVec(SLVec3f((randX*_width)-(_width*0.5f), (randY*_height)-(_height*0.5f), 0)) - ray->hitPoint);
    SLfloat SPDist = SP.length();
    SP.normalize();
    SLRay shadowRay(SPDist, SP, ray);

    SLScene::current->root3D()->hitRec(&shadowRay);

    if (shadowRay.length >= SPDist - FLT_EPSILON)
        return 1.0f;
    else
        return 0.0f;
}
Example #21
0
Vec3f Leafcutter::EvalutateLight(const OrientedLight& light, DifferentialGeometry& dp, const Vec3f &wo, Material *ms)
{
    Vec3f wi = (light.position - dp.P).GetNormalized();
    float maxDist = (light.position - dp.P).GetLength();
    float cosAngle = max(0.0f, light.normal % (-wi));
    float lenSqrEst = max(0.1f, (light.position - dp.P).GetLengthSqr());
    //float lenSqrEst = (light.position - dp.P).GetLengthSqr();
    BxdfUnion msu;
    ms->SampleReflectance(dp, msu);
    Vec3f brdf = msu.EvalSmoothCos(wo, wi, dp);
    Vec3f estimate = brdf * cosAngle / lenSqrEst;

    if(!estimate.IsZero()) 
    {
        Ray shadowRay(dp.P, wi, maxDist, 0.0f);
        if(!_engine->IntersectAny(shadowRay))
        {
            return light.le * estimate;
        }
    }
    return Vec3f::Zero();
}
Example #22
0
glm::vec3 Matte::areaLightShade(const ShadeRec& sr)const
{
	glm::vec3 incoming = -sr.ray.getDirection();
	glm::vec3 ambientColor = ambientBrdf->rho(sr,incoming);
	glm::vec3 color = sr.world.getAmbient()->L(sr);
	color.x *= ambientColor.x;
	color.y *= ambientColor.y;
	color.z *= ambientColor.z;
	int numLights = sr.world.lights.size();

	for(int i=0;i<numLights;i++)
	{
		glm::vec3 reflected = sr.world.lights[i]->getDirection(sr);
		float nDotI = glm::dot(sr.normal,reflected);

		if(nDotI > 0.0)
		{
			bool inShadow = false;

			if(hasShadows && sr.world.lights[i]->castsShadows())
			{
				Ray shadowRay(sr.hitPoint,reflected);
				inShadow = sr.world.lights[i]->inShadow(shadowRay,sr);
			}

			if(!inShadow)
			{
				glm::vec3 diffuseColor = diffuseBrdf->f(sr,incoming,reflected);
				glm::vec3 lightColor = sr.world.lights[i]->L(sr) * sr.world.lights[i]->G(sr) * nDotI / sr.world.lights[i]->pdf(sr);
				lightColor.x *= diffuseColor.x;
				lightColor.y *= diffuseColor.y;
				lightColor.z *= diffuseColor.z;
				color += lightColor;
			}
		}
	}
	return color;
}
Example #23
0
Colour Raytracer::helpShade(Ray3D& ray, LightListNode* curLight, int n, float k)
{  
	Vector3D shadowDir;
	shadowDir = curLight->light->get_position() - ray.intersection.point;
	shadowDir[0] += k;
    shadowDir[1] += k;
    shadowDir[2] += k;
	shadowDir.normalize();
	Point3D shadowOrigin = ray.intersection.point + 0.01*shadowDir;

	Ray3D shadowRay(shadowOrigin , shadowDir);
	traverseScene(_root, shadowRay);
	
	// Compute non-shadow colour
	curLight->light->shade(ray);
	
	// If ray intersects another object  it falls in a shadow
	if (!shadowRay.intersection.none) 
		return (1/n)*ray.col;
	else{
		return Colour(0,0,0);
	}
}
Example #24
0
float3 directLight(
	Rand& rand, 
	const RTScene& scene, 
	const PathVertex& vertex,
	const ShadingCS& shadingCS)
{
	//TODO: this does not work for multiple lights!
	auto & light = scene.accl->lights[0];
	float3 lightPos;
	float lightPdf; 
	//t is already incorporated into pdf
	float lightT;
	float3 wiDirectWorld;
	//sample the light
	light.sample(rand, vertex.position, &lightPos, &wiDirectWorld, &lightPdf, &lightT);

	//see if we're occluded
	Ray shadowRay(vertex.position, wiDirectWorld);
	//we cannot ignore the light here, as we need to differentiate b/t hit empty space
	//and hit light

	IntersectionQuery shadowQuery(shadowRay);	
	Intersection sceneIsect;
	Intersection lightIsect;
	intersectScene(scene, shadowQuery, &sceneIsect, &lightIsect);
	bool hitLight = hitLightFirst(sceneIsect, lightIsect) 
		&& lightIsect.lightId == light.id;
	if(hitLight && facing(vertex.position, vertex.normal, lightIsect.position, lightIsect.normal))
	{
		float3 wiDirect = shadingCS.local(wiDirectWorld);
		float3 brdfEval = vertex.material->eval(wiDirect, shadingCS.local(vertex.woWorld));
		float3 cosTheta = float3(dot(vertex.normal, wiDirectWorld));
		float3 le = light.material.emission;
		return le * brdfEval * cosTheta / lightPdf;
	}
	return float3(0);
}
Example #25
0
glm::vec3 Phong::shade(const ShadeRec& sr)const
{
	glm::vec3 incoming(-sr.ray.getDirection());
	glm::vec3 ambient = sr.world.getAmbient()->L(sr);
	glm::vec3 color = ambientBrdf->rho(sr,incoming);
	color.x *= ambient.x;
	color.y *= ambient.y;
	color.z *= ambient.z;

	int numLights = sr.world.lights.size();

	for(int i=0;i<numLights;i++)
	{
		glm::vec3 reflected(sr.world.lights[i]->getDirection(sr));
		float nDotI = glm::dot(sr.normal,reflected);
		if(nDotI > 0.0)
		{
			bool inShadow = false;
			if(hasShadows && sr.world.lights[i]->castsShadows())
			{
				Ray shadowRay(sr.hitPoint,reflected);
				inShadow = sr.world.lights[i]->inShadow(shadowRay,sr);
			}

			if(!inShadow)
			{
				glm::vec3 gainedColor(diffuseBrdf->f(sr,incoming,reflected) + specularBrdf->f(sr,incoming,reflected));
				glm::vec3 lightColor = sr.world.lights[i]->L(sr) * nDotI;
				lightColor.x *= gainedColor.x;
				lightColor.y *= gainedColor.y;
				lightColor.z *= gainedColor.z;
				color += lightColor;
			}
		}
	}
	return color;
}
Example #26
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;
}
Example #27
0
Color pathTrace(const Ray& ray,
                ShapeSet& scene,
                std::list<Shape*>& lights,
                Rng& rng,
                size_t lightSamplesHint,
                size_t maxRayDepth,
                size_t pixelSampleIndex,
                Sampler **bounceSamplers)
{
    // Accumulate total incoming radiance in 'result'
    Color result = Color(0.0f, 0.0f, 0.0f);
    // As we get through more and more bounces, we track how much the light is
    // diminished through each bounce
    Color throughput = Color(1.0f, 1.0f, 1.0f);
    
    // Start with the initial ray from the camera
    Ray currentRay = ray;
    
    // While we have bounces left we can still take...
    size_t numBounces = 0;
    while (numBounces < maxRayDepth)
    {
        // Trace the ray to see if we hit anything
        Intersection intersection(currentRay);
        if (!scene.intersect(intersection))
        {
            // No hit, return black (background)
            break;
        }
        
        // Add in emission when directly visible or via a specular bounce
        if (numBounces == 0)
        {
            result += throughput * intersection.m_pMaterial->emittance();
        }
        
        // Evaluate the material and intersection information at this bounce
        Point position = intersection.position();
        Vector normal = intersection.m_normal;
        Vector outgoing = -currentRay.m_direction;
        Brdf* pBrdf = NULL;
        float brdfWeight = 1.0f;
        Color matColor = intersection.m_pMaterial->evaluate(position,
                                                            normal,
                                                            outgoing,
                                                            pBrdf,
                                                            brdfWeight);
        // No BRDF?  We can't evaluate lighting, so bail.
        if (pBrdf == NULL)
        {
            return result;
        }
        
        // Evaluate direct lighting at this bounce.
        // For each light...
        for (std::list<Shape*>::iterator iter = lights.begin();
             iter != lights.end();
             ++iter)
        {
            // Set up samplers for evaluating this light
            StratifiedRandomSampler lightSampler(lightSamplesHint, lightSamplesHint, rng);
            StratifiedRandomSampler brdfSampler(lightSamplesHint, lightSamplesHint, rng);
            
            // Sample the light (with stratified random sampling to reduce noise)
            Color lightResult = Color(0.0f, 0.0f, 0.0f);
            size_t numLightSamples = lightSampler.total2DSamplesAvailable();
            for (size_t lightSampleIndex = 0; lightSampleIndex < numLightSamples; ++lightSampleIndex)
            {
                // Sample the light using MIS between the light and the BRDF.
                // This means we ask the light for a direction, and the likelihood
                // of having sampled that direction (the PDF).  Then we ask the
                // BRDF what it thinks of that direction (its PDF), and weight
                // the light sample with MIS.
                //
                // Then, we ask the BRDF for a direction, and the likelihood of
                // having sampled that direction (the PDF).  Then we ask the
                // light what it thinks of that direction (its PDF, and whether
                // that direction even runs into the light at all), and weight
                // the BRDF sample with MIS.
                //
                // By doing both samples and asking both the BRDF and light for
                // their PDF for each one, we can combine the strengths of both
                // sampling methods and get the best of both worlds.  It does
                // cost an extra shadow ray and evaluation, though, but it is
                // generally such an improvement in quality that it is very much
                // worth the overhead.
                
                // Ask the light for a random position/normal we can use for lighting
                Light *pLightShape = dynamic_cast<Light*>(*iter);
                float lsu, lsv;
                lightSampler.sample2D(lightSampleIndex, lsu, lsv);
                Point lightPoint;
                Vector lightNormal;
                float lightPdf = 0.0f;
                pLightShape->sampleSurface(position,
                                           normal,
                                           lsu, lsv,
                                           lightPoint,
                                           lightNormal,
                                           lightPdf);
                
                if (lightPdf > 0.0f)
                {   
                    // Ask the BRDF what it thinks of this light position (for MIS)
                    Vector lightIncoming = position - lightPoint;
                    float lightDistance = lightIncoming.normalize();
                    float brdfPdf = 0.0f;
                    float brdfResult = pBrdf->evaluateSA(lightIncoming,
                                                         outgoing,
                                                         normal,
                                                         brdfPdf);
                    if (brdfResult > 0.0f && brdfPdf > 0.0f)
                    {
                        // Fire a shadow ray to make sure we can actually see the light position
                        Ray shadowRay(position, -lightIncoming, lightDistance - kRayTMin);
                        if (!scene.doesIntersect(shadowRay))
                        {
                            // The light point is visible, so let's add that
                            // contribution (mixed by MIS)
                            float misWeightLight = powerHeuristic(1, lightPdf, 1, brdfPdf);
                            lightResult += pLightShape->emitted() *
                                           intersection.m_colorModifier * matColor *
                                           brdfResult *
                                           std::fabs(dot(-lightIncoming, normal)) *
                                           misWeightLight / (lightPdf * brdfWeight);
                        }
                    }
                }
                
                // Ask the BRDF for a sample direction
                float bsu, bsv;
                brdfSampler.sample2D(lightSampleIndex, bsu, bsv);
                Vector brdfIncoming;
                float brdfPdf = 0.0f;
                float brdfResult = pBrdf->sampleSA(brdfIncoming,
                                                   outgoing,
                                                   normal,
                                                   bsu,
                                                   bsv,
                                                   brdfPdf);
                if (brdfPdf > 0.0f && brdfResult > 0.0f)
                {
                    Intersection shadowIntersection(Ray(position, -brdfIncoming));
                    bool intersected = scene.intersect(shadowIntersection);
                    if (intersected && shadowIntersection.m_pShape == pLightShape)
                    {
                        // Ask the light what it thinks of this direction (for MIS)
                        lightPdf = pLightShape->intersectPdf(shadowIntersection);
                        if (lightPdf > 0.0f)
                        {
                            // BRDF chose the light, so let's add that
                            // contribution (mixed by MIS)
                            float misWeightBrdf = powerHeuristic(1, brdfPdf, 1, lightPdf);
                            lightResult += pLightShape->emitted() * 
                                           intersection.m_colorModifier * matColor * brdfResult *
                                           std::fabs(dot(-brdfIncoming, normal)) * misWeightBrdf /
                                           (brdfPdf * brdfWeight);
                        }
                    }
                }
            }
            // Average light samples
            if (numLightSamples)
            {
                lightResult /= numLightSamples;
            }
            
            // Add direct lighting at this bounce (modified by how much the
            // previous bounces have dimmed it)
            result += throughput * lightResult;
        }
        
        // Sample the BRDF to find the direction the next leg of the path goes in
        float brdfSampleU, brdfSampleV;
        bounceSamplers[numBounces]->sample2D(pixelSampleIndex, brdfSampleU, brdfSampleV);
        Vector incoming;
        float incomingBrdfPdf = 0.0f;
        float incomingBrdfResult = pBrdf->sampleSA(incoming,
                                                   outgoing,
                                                   normal,
                                                   brdfSampleU,
                                                   brdfSampleV,
                                                   incomingBrdfPdf);

        if (incomingBrdfPdf > 0.0f)
        {
            currentRay.m_origin = position;
            currentRay.m_direction = -incoming;
            currentRay.m_tMax = kRayTMax;
            // Reduce lighting effect for the next bounce based on this bounce's BRDF
            throughput *= intersection.m_colorModifier * matColor * incomingBrdfResult *
                          (std::fabs(dot(-incoming, normal)) /
                          (incomingBrdfPdf * brdfWeight));
        }
        else
        {
            break; // BRDF is zero, stop bouncing
        }
        
        numBounces++;
    }
    
    // This represents an estimate of the total light coming in along the path
    return result;
}
Example #28
0
    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;

    }
Example #29
0
void LightTracer::traceSample(PathSampleGenerator &sampler)
{
    float lightPdf;
    const Primitive *light = chooseLightAdjoint(sampler, lightPdf);
    const Medium *medium = light->extMedium().get();

    PositionSample point;
    if (!light->samplePosition(sampler, point))
        return;
    DirectionSample direction;
    if (!light->sampleDirection(sampler, point, direction))
        return;
    sampler.advancePath();

    Vec3f throughput(point.weight/lightPdf);

    LensSample splat;
    if (_settings.minBounces == 0 && !light->isInfinite() && _scene->cam().sampleDirect(point.p, sampler, splat)) {
        Ray shadowRay(point.p, splat.d);
        shadowRay.setFarT(splat.dist);

        Vec3f transmission = generalizedShadowRay(shadowRay, medium, nullptr, 0);
        if (transmission != 0.0f) {
            Vec3f value = throughput*transmission*splat.weight
                    *light->evalDirectionalEmission(point, DirectionSample(splat.d));
            _splatBuffer->splatFiltered(splat.pixel, value);
        }
    }
    sampler.advancePath();

    Ray ray(point.p, direction.d);
    throughput *= direction.weight;

    VolumeScatterEvent volumeEvent;
    SurfaceScatterEvent surfaceEvent;
    IntersectionTemporary data;
    IntersectionInfo info;
    Medium::MediumState state;
    state.reset();
    Vec3f emission(0.0f);

    int bounce = 0;
    bool wasSpecular = true;
    bool didHit = _scene->intersect(ray, data, info);
    while ((didHit || medium) && bounce < _settings.maxBounces - 1) {
        bool hitSurface = true;
        if (medium) {
            volumeEvent = VolumeScatterEvent(&sampler, throughput, ray.pos(), ray.dir(), ray.farT());
            if (!medium->sampleDistance(volumeEvent, state))
                break;
            throughput *= volumeEvent.weight;
            volumeEvent.weight = Vec3f(1.0f);
            hitSurface = volumeEvent.t == volumeEvent.maxT;
            if (hitSurface && !didHit)
                break;
        }

        if (hitSurface) {
            surfaceEvent = makeLocalScatterEvent(data, info, ray, &sampler);

            Vec3f weight;
            Vec2f pixel;
            if (surfaceLensSample(_scene->cam(), surfaceEvent, medium, bounce + 1, ray, weight, pixel))
                _splatBuffer->splatFiltered(pixel, weight*throughput);

            if (!handleSurface(surfaceEvent, data, info, medium, bounce,
                    true, false, ray, throughput, emission, wasSpecular, state))
                break;
        } else {
            volumeEvent.p += volumeEvent.t*volumeEvent.wi;

            Vec3f weight;
            Vec2f pixel;
            if (volumeLensSample(_scene->cam(), volumeEvent, medium, bounce + 1, ray, weight, pixel))
                _splatBuffer->splatFiltered(pixel, weight*throughput);

            if (!handleVolume(volumeEvent, medium, bounce,
                    true, false, ray, throughput, emission, wasSpecular, state))
                break;
        }

        if (throughput.max() == 0.0f)
            break;
        if (std::isnan(ray.dir().sum() + ray.pos().sum()))
            break;
        if (std::isnan(throughput.sum()))
            break;

        sampler.advancePath();
        bounce++;
        if (bounce < _settings.maxBounces)
            didHit = _scene->intersect(ray, data, info);
    }
}
Example #30
0
rgbColor whittedRayTracer::_L(ray& r, const int& depth) const{
    if(depth > MAX_DEPTH){
        return rgbColor(0.f);
    }

    const intersection isect = parent.intersect(r);
    //return rgbColor(0, isect.debugInfo / 1e8, 0);

    if(!isect.hit){
        return rgbColor(0.f);
    }else if(isect.li != NULL){
        return isect.li->L(r);
    }

    material& mat = isect.li ? *isect.li->getMaterial().get() : *isect.s->getMaterial().get();
    const vec3& normal = isect.shadingNormal;
    const bsdf& bsdf = mat.getBsdf(isect.uv);
    const vec3 wo = worldToBsdf(-r.direction, isect);

    bxdfType sampledType;
    rgbColor colorSum(0.f);

    if(isect.s->getMaterial()->isEmissive()){
        return mat.Le();
    }

    // Diffuse calculations.
    float lightPdf = 0.f;
    for(int i=0; i<parent.numLights(); ++i){
        const light& li = parent.getLight(i);
        if(li.isPointSource()){
            vec3 lightDir;
            const rgbColor Li = li.sampleL(r.origin, lightDir, sampleUniform(), sampleUniform(), lightPdf);
            const float lightDist = norm(lightDir);
            lightDir = normalize(lightDir);

            // Test for shadowing early.
            ray shadowRay(r.origin, lightDir);
            shadowRay.tMax = lightDist;
            if(!parent.intersectB(shadowRay)){
                const vec3 wi = worldToBsdf(lightDir, isect);
                const rgbColor f = bsdf.f(wo, wi, bxdfType(DIFFUSE | GLOSSY | REFLECTION)) + mat.Le();
                colorSum += f * dot(normal, lightDir) * (Li / lightPdf);
            }
        }else{
            rgbColor areaContrib(0.f);

            for(int j=0; j<areaSamples; ++j){
                vec3 lightDir;

                const rgbColor Li = li.sampleL(r.origin, lightDir, sampleUniform(), sampleUniform(), lightPdf);

                ray shadowRay(r.origin, normalize(lightDir));
                shadowRay.tMax = norm(lightDir) + EPSILON;

                if(!parent.intersectB(shadowRay) && li.intersect(shadowRay).hit){
                    lightDir = normalize(lightDir);
                    const vec3 wi = worldToBsdf(lightDir, isect);

                    const rgbColor f = bsdf.f(wo, wi, bxdfType(DIFFUSE | GLOSSY | REFLECTION)) + mat.Le();
                    areaContrib += f * dot(normal, lightDir) * (Li / lightPdf);
                }
            }
            colorSum += areaContrib / (float)areaSamples;
        }
    }

    // Trace specular rays.
    vec3 specDir;
    float pdf;
    const rgbColor fr =
        bsdf.sampleF(sampleUniform(), sampleUniform(), sampleUniform(),
                wo, specDir, bxdfType(GLOSSY | SPECULAR | REFLECTION), sampledType, pdf);

    if(!fr.isBlack()){
        specDir = bsdfToWorld(specDir, isect);
        ray r2(r.origin, specDir);
        colorSum += (fr / pdf) * _L(r2, depth+1) * abs(dot(specDir, normal));
    }

    const rgbColor ft =
        bsdf.sampleF(sampleUniform(), sampleUniform(), sampleUniform(),
                wo, specDir, bxdfType(GLOSSY | SPECULAR | TRANSMISSION), sampledType, pdf);

    if(!ft.isBlack()){
        specDir = bsdfToWorld(specDir, isect);
        ray r2(r.origin, specDir);
        colorSum += (ft / pdf) * _L(r2, depth+1) * abs(dot(specDir, normal));
    }

    if(!isFinite(colorSum.avg())) {
        return ERROR_COLOR;
    } else {
        return colorSum;
    }
}