Skip to content

Instantly share code, notes, and snippets.

@bachi95
Last active March 25, 2016 05:40
void LightTracer::splatFilmT1(const ScenePtr& scene, const Sample& sample,
const RNG& rng, std::vector<PathVertex>& pathVertices,
ImageTile* tile) const {
const vector<Light*>& lights = scene->getLights();
if (lights.size() == 0) {
return;
}
// get the camera point
const CameraPtr camera = scene->getCamera();
Vector3 nCamera;
float pdfCamera;
Vector3 pCamera = camera->samplePosition(sample, &nCamera, &pdfCamera);
PathVertex cVertex(Color(1.0f / pdfCamera), pCamera,
nCamera, camera.get());
// get the light point
float pickLightPdf;
float pickSample = sample.u1D[mPickLightSampleIndexes[0].offset][0];
int lightIndex = mPowerDistribution->sampleDiscrete(
pickSample, &pickLightPdf);
const Light* light = lights[lightIndex];
LightSample ls(sample, mLightSampleIndexes[0], 0);
Vector3 nLight;
float pdfLightArea;
Vector3 pLight = light->samplePosition(scene, ls, &nLight,
&pdfLightArea);
pathVertices[0] = PathVertex(
Color(1.0f / (pdfLightArea * pickLightPdf)),
pLight, nLight, light);
float pdfLightDirection;
BSDFSample bs(sample, mBSDFSampleIndexes[0], 0);
Vector3 dir = light->sampleDirection(
nLight, bs.uDirection[0], bs.uDirection[1], &pdfLightDirection);
Color throughput = pathVertices[0].throughput *
absdot(nLight, dir) / pdfLightDirection;
Ray ray(pLight, dir, 1e-3f);
// start building a path from light by bouncing around the scene
int lightVertex = 1;
while (lightVertex < mMaxPathLength) {
float epsilon;
Intersection isect;
if (!scene->intersect(ray, &epsilon, &isect)) {
break;
}
const Fragment& frag = isect.fragment;
pathVertices[lightVertex] = PathVertex(throughput, isect);
BSDFSample bs(sample, mBSDFSampleIndexes[lightVertex], 0);
lightVertex += 1;
Vector3 wo = -normalize(ray.d);
Vector3 wi;
float pdfW;
Color f = isect.getMaterial()->sampleBSDF(frag, wo, bs,
&wi, &pdfW, BSDFAll, NULL, BSDFImportance);
if (f == Color::Black || pdfW == 0.0f) {
break;
}
throughput *= f * absdot(wi, frag.getNormal()) / pdfW;
ray = Ray(frag.getPosition(), wi, epsilon);
}
// evaluate path contribution Cs,1
for (int s = 1; s <= lightVertex; ++s) {
const PathVertex& pv = pathVertices[s - 1];
const Vector3& pvPos = pv.fragment.getPosition();
Vector3 filmPixel = camera->worldToScreen(
pv.fragment.getPosition(), pCamera);
if (filmPixel == Camera::sInvalidPixel) {
continue;
}
// occlude test
Vector3 pv2Cam(pCamera - pvPos);
float occludeDistance = length(pv2Cam);
float epsilon = 1e-3f * occludeDistance;
Ray occludeRay(pvPos, normalize(pv2Cam),
epsilon, occludeDistance - epsilon);
if (scene->intersect(occludeRay)) {
continue;
}
Color fsL;
Vector3 wo = normalize(pCamera - pvPos);
if (s > 1) {
Vector3 wi =
normalize(pathVertices[s - 2].fragment.getPosition() - pvPos);
Color f = pv.material->bsdf(pv.fragment, wo, wi,
BSDFAll, BSDFImportance);
fsL = f * light->evalL(pLight, nLight,
pathVertices[1].fragment.getPosition());
} else {
fsL = pv.light->evalL(pLight, nLight, pCamera);
}
float fsE = camera->evalWe(pCamera, pvPos);
float G = absdot(pv.fragment.getNormal(), wo) * absdot(nCamera, wo) /
squaredLength(pvPos - pCamera);
Color pathContribution = fsL * fsE * G *
pv.throughput * cVertex.throughput;
tile->addSample(filmPixel.x, filmPixel.y, pathContribution);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment