// Lambertian! Replace with general BSDF. public virtual void radianceEstimatePrecomputed(RGBColor rad, Vector3D position, Vector3D normal, float initialDist, float maxDist) { NearestPhotons np; // locate the nearest photon float r = initialDist; do { np = new NearestPhotons(1, r, position); locatePhotonsPrecomputed(normal, np, 1); r = (float)(r * 2.0); }while (np.found == 0 && r < maxDist); if (np.found > 0) { Photon p = getPhoton(np.indices[1]); rad.set(p.accumPower); } else { rad.set(0.0f); } }
// Lambertian! Replace with general BSDF. public virtual void radianceEstimate(RGBColor rad, Vector3D position, Vector3D normal, float maxDist, int noPhotons) { //float ALPHA = 0.918f; float MBETA = -1.953f; float DENOMFACTOR = 1.0f / (1.0f - (float)System.Math.Exp(MBETA)); NearestPhotons np = new NearestPhotons(noPhotons, maxDist, position); rad.set(0.0f); // locate the nearest photons locatePhotons(np, 1); // if less than MINPHOTONS return if (np.found < RaytracerPhotonmapping.SceneConstants.MIN_PHOTONS) { return; } Vector3D direction = new Vector3D(); //float mittrs = MBETA / (2.0f * (float) np.dist2[0]); float kdenom = (float)(1.0 / (1.1 * Math.Sqrt(np.dist2[0]))); // sum irrandiance from all photons for (int i = 1; i <= np.found; i++) { float cosNL; Photon p = getPhoton(np.indices[i]); // the toCartesian call and following if can be omitted (for speed) // if the scene does not have any thin surfaces p.toCartesian(direction); cosNL = (float)direction.dot(normal); //cosNL = -1.0f; if (cosNL < 0.0) { //float gaussWeight = 1.0f - (1.0f - (float) System.Math.Exp((float) p.position.distanceSqr(position) * mittrs)) * DENOMFACTOR; float coneWeight = 1.0f - (float)(p.position.distance(position) * kdenom); //rad.add(p.power.scaleNew((- cosNL) * gaussWeight)); //rad.add(p.power.scaleNew((- cosNL))); rad.add(p.power.scaleNew(coneWeight)); } } // estimate of density rad.scale(1.0f / (float)((1.0f - 2.0f / (3.0f * 1.1f)) * System.Math.PI * np.dist2[0])); }
public virtual void locatePhotonsPrecomputed(Vector3D normal, NearestPhotons np, int index) { double dist1, dist2; Photon p = getPhoton(index); if (index < halfStoredPhotons) { dist1 = np.position.get(p.plane) - p.position.get(p.plane); if (dist1 > 0.0) { // if dist1 is positive search right plane locatePhotonsPrecomputed(normal, np, (2 * index) + 1); if (dist1 * dist1 < np.dist2[0]) { locatePhotonsPrecomputed(normal, np, (2 * index)); } } else { // dist1 is negative search left first locatePhotonsPrecomputed(normal, np, (2 * index)); if (dist1 * dist1 < np.dist2[0]) { locatePhotonsPrecomputed(normal, np, (2 * index) + 1); } } } // compute squared distance between current photon and np.position dist2 = p.position.distanceSqr(np.position); //assert(p.precomputedIrradiance); //assert(np.max == 1); Vector3D surfaceDirection = new Vector3D(); p.surfaceToCartesian(surfaceDirection); //System.out.println(normal.dot(surfaceDirection)); if (dist2 < np.dist2[0] && normal.dot(surfaceDirection) > 0.0) { // we found a photon :) Insert it in the candidate list if (np.found < 1) { // heap is not full; use array np.found++; np.dist2[np.found] = dist2; np.indices[np.found] = index; } else { // exchange element if necessary if (np.dist2[0] > dist2) { np.dist2[1] = dist2; np.indices[1] = index; np.dist2[0] = dist2; } } } }
public virtual void locatePhotons(NearestPhotons np, int index) { double dist1, dist2; Photon p = getPhoton(index); if (index < halfStoredPhotons) { dist1 = np.position.get(p.plane) - p.position.get(p.plane); if (dist1 > 0.0) { // if dist1 is positive search right plane locatePhotons(np, (2 * index) + 1); if (dist1 * dist1 < np.dist2[0]) { locatePhotons(np, (2 * index)); } } else { // dist1 is negative search left first locatePhotons(np, (2 * index)); if (dist1 * dist1 < np.dist2[0]) { locatePhotons(np, (2 * index) + 1); } } } // compute squared distance between current photon and np.position dist2 = p.position.distanceSqr(np.position); if (dist2 < np.dist2[0]) { // we found a photon :) Insert it in the candidate list if (np.found < np.max) { // heap is not full; use array np.found++; np.dist2[np.found] = dist2; np.indices[np.found] = index; } else { int j, parent; if (!np.gotHeap) { // build heap int halfFound; int photIndex; double tempDist; halfFound = np.found >> 1; for (int k = halfFound; k >= 1; k--) { parent = k; photIndex = np.indices[k]; tempDist = np.dist2[k]; while (parent < halfFound) { j = parent + parent; if (j < np.found && np.dist2[j] < np.dist2[j + 1]) { j++; } if (tempDist >= np.dist2[j]) { break; } np.dist2[parent] = np.dist2[j]; np.indices[parent] = np.indices[j]; parent = j; } np.dist2[parent] = tempDist; np.indices[parent] = photIndex; } np.gotHeap = true; } // insert new photon into max heap // delete largest element, insert new, and reorder the heap parent = 1; j = 2; while (j <= np.found) { if (j < np.found && np.dist2[j] < np.dist2[j + 1]) { j++; } if (dist2 > np.dist2[j]) { break; } np.dist2[parent] = np.dist2[j]; np.indices[parent] = np.indices[j]; parent = j; j += j; } //!!! if (dist2 < np.dist2[parent]) { np.dist2[parent] = dist2; np.indices[parent] = index; } np.dist2[0] = np.dist2[1]; } } }