void Process(const LightPoint &lightPoint){ if(volumeMedia && lightPoint.photonType != Ray::INVOL) return ; if(!volumeMedia && lightPoint.photonType != Ray::OUTVOL) return ; if(!lightPoint.pathThePointIn || lightPoint.indexInThePath < 0) return; Path &lightPath = *lightPoint.pathThePointIn; int index = lightPoint.indexInThePath; /* if (volumeMedia && lightPath[index].insideObject != outRay.insideObject) { printf("aye\n"); return; } if (!volumeMedia && lightPath[index].contactObject != outRay.contactObject) { printf("aye\n"); return; } */ vec3f photonThroughput(1,1,1); for(int i = 0; i < index; i++){ photonThroughput *= lightPath[i].color / lightPath[i].directionProb / lightPath[i].originProb; photonThroughput *= lightPath[i].getCosineTerm(); float dist = (lightPath[i].origin-lightPath[i+1].origin).length(); photonThroughput *= lightPath[i].getRadianceDecay(dist); } photonThroughput /= lightPath[index].originProb; // runs here, photon's f/p is done. Ray photonRay = lightPath[index]; photonRay.direction = lightPath[index-1].direction; vec3f color = photonThroughput * photonRay.getBSDF(outRay); float distSqr = powf((outRay.origin-lightPath[index].origin).length(), 2); if(intensity(color) < 1e-6f) return ; float kernel = Kernel(distSqr, radius*radius); float normalization = volumeMedia ? kernel/(photonsNum*radius*radius*radius) : kernel/(photonsNum*radius*radius); //float normalization = volumeMedia==false ? 1.0 / (photonsNum*PI*radius*radius) : 1.0 / (photonsNum*PI*4.0/3*radius*radius*radius); contrib += color * normalization; }
Ray SceneObject::emit(bool isUniformOrigin , bool isUniformDir) const { Ray ray; if(!areaValues.size()) { ray.direction = vec3f(0, 0, 0); ray.directionProb = 1; ray.color = vec3f(0, 0, 0); return ray; } if (isUniformOrigin) { float rnd = RandGenerator::genFloat()*totalArea; unsigned index = (lower_bound(areaValues.begin(), areaValues.end(), rnd)-areaValues.begin()); if(index >= areaValues.size()) index = areaValues.size() - 1; ray.contactObject = (SceneObject*)this; ray.contactObjectTriangleID = index; ray.origin = genRandTrianglePosition(ray.contactObjectTriangleID); ray.originProb = weight / totalArea; } else { float rnd = RandGenerator::genFloat()*totalEnergy; unsigned index = (lower_bound(energyDensity.begin(), energyDensity.end(), rnd)-energyDensity.begin()); if(index >= energyDensity.size()) index = energyDensity.size() - 1; ray.contactObject = (SceneObject*)this; ray.contactObjectTriangleID = index; ray.origin = genRandTrianglePosition(ray.contactObjectTriangleID); float prob; if (index == 0) prob = energyDensity[index] / totalEnergy; else prob = (energyDensity[index] - energyDensity[index - 1]) / totalEnergy; ray.originProb = weight * prob / areaValues[index]; } UniformSphericalSampler uniformSphericalSampler; CosineSphericalSampler cosineSphericalSampler; LocalFrame lf = ray.contactObject->getAutoGenWorldLocalFrame(ray.contactObjectTriangleID, ray.origin); if (isUniformDir) ray.direction = uniformSphericalSampler.genSample(lf); else ray.direction = cosineSphericalSampler.genSample(lf); if(ray.getContactNormal().dot(ray.direction) < 0) ray.direction = -ray.direction; ray.insideObject = scene->findInsideObject(ray, ray.contactObject); ray.current_tid = scene->getContactTreeTid(ray); ray.color = ray.getBSDF(ray); if(!emissive()) ray.color = vec3f(1, 1, 1); if (isUniformDir) ray.directionProb = uniformSphericalSampler.getProbDensity(lf , ray.direction) * 2.f; else ray.directionProb = cosineSphericalSampler.getProbDensity(lf, ray.direction); ray.directionSampleType = ray.originSampleType = Ray::RANDOM; if(!scene->usingGPU()) { Scene::ObjSourceInformation osi; NoSelfIntersectionCondition condition(scene, ray); float dist = scene->intersect(ray, osi, &condition); if(dist > 0) { ray.intersectDist = dist; ray.intersectObject = scene->objects[osi.objID]; ray.intersectObjectTriangleID = osi.triangleID; } } return ray; }
vec3f IptTracer::colorByConnectingLights(Ray lastRay , Ray ray , bool dirIlluWeight) { Ray lightRay = genEmissiveSurfaceSample(true , false); lightRay.direction = (ray.origin - lightRay.origin); Real dist = lightRay.direction.length(); dist = max(dist , 1e-6f); Real dist2 = dist * dist; lightRay.direction.normalize(); Ray outRay = ray; outRay.direction = -lightRay.direction; vec3f decayFactor = outRay.getRadianceDecay(dist); if(!testVisibility(outRay, lightRay)) return vec3f(0.f); //outRay.direction = -cameraState.lastRay->direction; //vec3f bsdfFactor2 = lightRay.getBSDF(outRay); vec3f bsdfFactor = lastRay.getBSDF(outRay); if (y(bsdfFactor) < 1e-7f) return vec3f(0.f); Real cosAtLight = clampf(lightRay.getContactNormal().dot(lightRay.direction) , 0.f , 1.f); Real cosToLight = clampf(ray.getContactNormal().dot(-lightRay.direction) , 0.f , 1.f); if (cosAtLight < 1e-6f || cosToLight < 1e-6f) return vec3f(0.f); vec3f tmp = lightRay.color * cosAtLight * bsdfFactor * cosToLight / (lightRay.originProb * dist2); //fprintf(fp , "weight = %.8f , bsdfToLightPdf = %.8f , cosAtLight = %.8f ,\ntoLightOriginPdf = %.8f , originProb = %.8f , dist = %.8f\n" , // weightFactor , bsdfToLightPdf , cosAtLight , toLightOriginPdf , lightRay.originProb , dist); vec3f res = tmp * decayFactor; if (dirIlluWeight && useRayMarching) { Real p1 = lightRay.originProb; Real p2 = lightRay.originProb * (cosAtLight / M_PI) * cosToLight / dist2 * (partialPathNum * gatherRadius * gatherRadius * M_PI); Real weightFactor = p1 / (p1 + p2); res *= weightFactor; } if (dirIlluWeight && !useRayMarching) { Real p1 = lastRay.getDirectionSampleProbDensity(outRay); Real p2 = lightRay.originProb * dist2 / cosAtLight; Real weightFactor = p2 / (p1 + p2); res *= weightFactor; } //printf("sur weight = %.8f\n" , weightFactor); /* vec3f resx = camera.eliminateVignetting(res , cameraState.index) * pixelNum; if (cameraState.ray->contactObject)//(resx[0] + resx[1] + resx[2] >= 2) { fprintf(fp , "=====================\n"); fprintf(fp , "cosAtLight = %.8f, cosToLight = %.8f, originPdf = %.8f, pdf = %.8f, weight=%.8f,\nres=(%.10f,%.10f,%.10f)\nbsdf=(%.10f,%.10f,%.10f)\n" , cosAtLight , cosToLight , originProb , pdf , weightFactor , resx[0] , resx[1] , resx[2] , bsdfFactor[0] , bsdfFactor[1] , bsdfFactor[2]); } */ return res; }