Exemplo n.º 1
0
Spectrum BidirIntegrator::Li(const Scene *scene,
		const RayDifferential &ray,
		const Sample *sample, float *alpha) const {
	Spectrum L(0.);
	// Generate eye and light sub-paths
	BidirVertex eyePath[MAX_VERTS], lightPath[MAX_VERTS];
	int nEye = generatePath(scene, ray, sample, eyeBSDFOffset,
		eyeBSDFCompOffset, eyePath, MAX_VERTS);
	if (nEye == 0) {
		*alpha = 0.;
		return L;
	}
	*alpha = 1;
	// Choose light for bidirectional path
	int lightNum = Floor2Int(sample->oneD[lightNumOffset][0] *
		scene->lights.size());
	lightNum = min(lightNum, (int)scene->lights.size() - 1);
	Light *light = scene->lights[lightNum];
	float lightWeight = float(scene->lights.size());
	// Sample ray from light source to start light path
	Ray lightRay;
	float lightPdf;
	float u[4];
	u[0] = sample->twoD[lightPosOffset][0];
	u[1] = sample->twoD[lightPosOffset][1];
	u[2] = sample->twoD[lightDirOffset][0];
	u[3] = sample->twoD[lightDirOffset][1];
	Spectrum Le = light->Sample_L(scene, u[0], u[1], u[2], u[3],
		&lightRay, &lightPdf);
	if (lightPdf == 0.) return 0.f;
	Le = lightWeight / lightPdf;
	int nLight = generatePath(scene, lightRay, sample, lightBSDFOffset,
		lightBSDFCompOffset, lightPath, MAX_VERTS);
	// Connect bidirectional path prefixes and evaluate throughput
	Spectrum directWt(1.0);
	for (int i = 1; i <= nEye; ++i) {
		// Handle direct lighting for bidirectional integrator
		directWt /= eyePath[i-1].rrWeight;
		L += directWt *
			UniformSampleOneLight(scene, eyePath[i-1].p, eyePath[i-1].ng, eyePath[i-1].wi,
			eyePath[i-1].bsdf, sample, directLightOffset[i-1], directLightNumOffset[i-1],
			directBSDFOffset[i-1], directBSDFCompOffset[i-1]) /
			weightPath(eyePath, i, lightPath, 0);
		directWt *= eyePath[i-1].bsdf->f(eyePath[i-1].wi, eyePath[i-1].wo) *
			AbsDot(eyePath[i-1].wo, eyePath[i-1].ng) /
			eyePath[i-1].bsdfWeight;
		for (int j = 1; j <= nLight; ++j)
			L += Le * evalPath(scene, eyePath, i, lightPath, j) /
				weightPath(eyePath, i, lightPath, j);
	}
	return L;
}
glm::vec3 BidirectionalIntegrator::TraceRay(Ray r, unsigned int depth)
{
    Intersection isx = intersection_engine->GetIntersection(r);
    if(isx.t < 0)
        return glm::vec3(0);
    else if(isx.object_hit->material->is_light_source)
    {
        return isx.object_hit->material->base_color * isx.texture_color;
    }

    glm::vec3 resultColor(0);

    for(Geometry* light : scene->lights)
    {
        std::vector<PathNode> eyePath = generateEyePath(r);
        std::vector<PathNode> lightPath = generateLightPath(light);

        if(!eyePath.empty() && !lightPath.empty())
        {
            PathNode* node = &lightPath[0];
            float lightPdf = light->RayPDF(node->isx,Ray(node->isx.point,node->dirIn_world));
            glm::vec3 Le(0);
            if(lightPdf != 0)
                Le = light->material->base_color * light->material->intensity / lightPdf;

            glm::vec3 directWt(1.0f);
            for(int i=1;i<=eyePath.size();i++)
            {
                node = &eyePath[i-1];

                Ray ray(light->transform.position(), - node->dirIn_world);
                resultColor += directWt * EstimateDirectLight(node->isx, ray, light) / WeightPath(i,0);
                directWt *= node->F * glm::abs(glm::dot(node->dirOut_world,node->isx.normal)) / node->pdf;

                for(int j=1;j<=lightPath.size();j++)
                {
                    resultColor += Le * EvaluatePath(eyePath,i,lightPath,j) / WeightPath(i,j);
                }
            }
        }
        else
        {
            continue;
        }

    }
    return resultColor;
}