public void getSamples(ShadingState state) { if (storedPhotons == 0) { return; } NearestPhotons np = new NearestPhotons(state.getPoint(), gatherNum, gatherRadius * gatherRadius); locatePhotons(np); if (np.found < 8) { return; } Point3 ppos = new Point3(); Vector3 pdir = new Vector3(); Vector3 pvec = new Vector3(); float invArea = 1.0f / ((float)Math.PI * np.dist2[0]); float maxNDist = np.dist2[0] * 0.05f; float f2r2 = 1.0f / (filterValue * filterValue * np.dist2[0]); float fInv = 1.0f / (1.0f - 2.0f / (3.0f * filterValue)); for (int i = 1; i <= np.found; i++) { Photon phot = np.index[i]; Vector3.decode(phot.dir, pdir); float cos = -Vector3.dot(pdir, state.getNormal()); if (cos > 0.001) { ppos.set(phot.x, phot.y, phot.z); Point3.sub(ppos, state.getPoint(), pvec); float pcos = Vector3.dot(pvec, state.getNormal()); if ((pcos < maxNDist) && (pcos > -maxNDist)) { LightSample sample = new LightSample(); sample.setShadowRay(new Ray(state.getPoint(), pdir.negate())); sample.setRadiance(new Color().setRGBE(np.index[i].power).mul(invArea / cos), Color.BLACK); sample.getDiffuseRadiance().mul((1.0f - (float)Math.Sqrt(np.dist2[i] * f2r2)) * fInv); state.addSample(sample); } } } }
public void getSamples(ShadingState state) { if (storedPhotons == 0) return; NearestPhotons np = new NearestPhotons(state.getPoint(), gatherNum, gatherRadius * gatherRadius); locatePhotons(np); if (np.found < 8) return; Point3 ppos = new Point3(); Vector3 pdir = new Vector3(); Vector3 pvec = new Vector3(); float invArea = 1.0f / ((float)Math.PI * np.dist2[0]); float maxNDist = np.dist2[0] * 0.05f; float f2r2 = 1.0f / (filterValue * filterValue * np.dist2[0]); float fInv = 1.0f / (1.0f - 2.0f / (3.0f * filterValue)); for (int i = 1; i <= np.found; i++) { Photon phot = np.index[i]; Vector3.decode(phot.dir, pdir); float cos = -Vector3.dot(pdir, state.getNormal()); if (cos > 0.001) { ppos.set(phot.x, phot.y, phot.z); Point3.sub(ppos, state.getPoint(), pvec); float pcos = Vector3.dot(pvec, state.getNormal()); if ((pcos < maxNDist) && (pcos > -maxNDist)) { LightSample sample = new LightSample(); sample.setShadowRay(new Ray(state.getPoint(), pdir.negate())); sample.setRadiance(new Color().setRGBE(np.index[i].power).mul(invArea / cos), Color.BLACK); sample.getDiffuseRadiance().mul((1.0f - (float)Math.Sqrt(np.dist2[i] * f2r2)) * fInv); state.addSample(sample); } } } }
private void locatePhotons(NearestPhotons np) { float[] dist1d2 = new float[log2n]; int[] chosen = new int[log2n]; int i = 1; int level = 0; int cameFrom; while (true) { while (i < halfStoredPhotons) { float dist1d = photons[i].getDist1(np.px, np.py, np.pz); dist1d2[level] = dist1d * dist1d; i += i; if (dist1d > 0.0f) { i++; } chosen[level++] = i; } np.checkAddNearest(photons[i]); do { cameFrom = i; i >>= 1; level--; if (i == 0) { return; } } while ((dist1d2[level] >= np.dist2[0]) || (cameFrom != chosen[level])); np.checkAddNearest(photons[i]); i = chosen[level++] ^ 1; } }
private void locatePhotons(NearestPhotons np) { float[] dist1d2 = new float[log2n]; int[] chosen = new int[log2n]; int i = 1; int level = 0; int cameFrom; while (true) { while (i < halfStoredPhotons) { float dist1d = photons[i].getDist1(np.px, np.py, np.pz); dist1d2[level] = dist1d * dist1d; i += i; if (dist1d > 0.0f) i++; chosen[level++] = i; } np.checkAddNearest(photons[i]); do { cameFrom = i; i >>= 1; level--; if (i == 0) return; } while ((dist1d2[level] >= np.dist2[0]) || (cameFrom != chosen[level])); np.checkAddNearest(photons[i]); i = chosen[level++] ^ 1; } }
public void precomputeRadiance() { if (storedPhotons == 0) return; // precompute the radiance for all photons that are neither // leaves nor parents of leaves in the tree. int quadStoredPhotons = halfStoredPhotons / 2; Point3 p = new Point3(); Vector3 n = new Vector3(); Point3 ppos = new Point3(); Vector3 pdir = new Vector3(); Vector3 pvec = new Vector3(); Color irr = new Color(); Color pow = new Color(); float maxDist2 = gatherRadius * gatherRadius; NearestPhotons np = new NearestPhotons(p, numGather, maxDist2); Photon[] temp = new Photon[quadStoredPhotons + 1]; UI.taskStart("Precomputing radiance", 1, quadStoredPhotons); for (int i = 1; i <= quadStoredPhotons; i++) { UI.taskUpdate(i); Photon curr = photons[i]; p.set(curr.x, curr.y, curr.z); Vector3.decode(curr.normal, n); irr.set(Color.BLACK); np.reset(p, maxDist2); locatePhotons(np); if (np.found < 8) { curr.data = 0; temp[i] = curr; continue; } float invArea = 1.0f / ((float)Math.PI * np.dist2[0]); float maxNDist = np.dist2[0] * 0.05f; for (int j = 1; j <= np.found; j++) { Photon phot = np.index[j]; Vector3.decode(phot.dir, pdir); float cos = -Vector3.dot(pdir, n); if (cos > 0.01f) { ppos.set(phot.x, phot.y, phot.z); Point3.sub(ppos, p, pvec); float pcos = Vector3.dot(pvec, n); if ((pcos < maxNDist) && (pcos > -maxNDist)) irr.add(pow.setRGBE(phot.power)); } } irr.mul(invArea); // compute radiance irr.mul(new Color(curr.data)).mul(1.0f / (float)Math.PI); curr.data = irr.toRGBE(); temp[i] = curr; } UI.taskStop(); // resize photon map to only include irradiance photons numGather /= 4; maxRadius = 1.4f * (float)Math.Sqrt(maxPower * numGather); if (gatherRadius > maxRadius) gatherRadius = maxRadius; storedPhotons = quadStoredPhotons; halfStoredPhotons = storedPhotons / 2; log2n = (int)Math.Ceiling(Math.Log(storedPhotons) / Math.Log(2.0)); photons = temp; hasRadiance = true; }
public void precomputeRadiance() { if (storedPhotons == 0) { return; } // precompute the radiance for all photons that are neither // leaves nor parents of leaves in the tree. int quadStoredPhotons = halfStoredPhotons / 2; Point3 p = new Point3(); Vector3 n = new Vector3(); Point3 ppos = new Point3(); Vector3 pdir = new Vector3(); Vector3 pvec = new Vector3(); Color irr = new Color(); Color pow = new Color(); float maxDist2 = gatherRadius * gatherRadius; NearestPhotons np = new NearestPhotons(p, numGather, maxDist2); Photon[] temp = new Photon[quadStoredPhotons + 1]; UI.taskStart("Precomputing radiance", 1, quadStoredPhotons); for (int i = 1; i <= quadStoredPhotons; i++) { UI.taskUpdate(i); Photon curr = photons[i]; p.set(curr.x, curr.y, curr.z); Vector3.decode(curr.normal, n); irr.set(Color.BLACK); np.reset(p, maxDist2); locatePhotons(np); if (np.found < 8) { curr.data = 0; temp[i] = curr; continue; } float invArea = 1.0f / ((float)Math.PI * np.dist2[0]); float maxNDist = np.dist2[0] * 0.05f; for (int j = 1; j <= np.found; j++) { Photon phot = np.index[j]; Vector3.decode(phot.dir, pdir); float cos = -Vector3.dot(pdir, n); if (cos > 0.01f) { ppos.set(phot.x, phot.y, phot.z); Point3.sub(ppos, p, pvec); float pcos = Vector3.dot(pvec, n); if ((pcos < maxNDist) && (pcos > -maxNDist)) { irr.add(pow.setRGBE(phot.power)); } } } irr.mul(invArea); // compute radiance irr.mul(new Color(curr.data)).mul(1.0f / (float)Math.PI); curr.data = irr.toRGBE(); temp[i] = curr; } UI.taskStop(); // resize photon map to only include irradiance photons numGather /= 4; maxRadius = 1.4f * (float)Math.Sqrt(maxPower * numGather); if (gatherRadius > maxRadius) { gatherRadius = maxRadius; } storedPhotons = quadStoredPhotons; halfStoredPhotons = storedPhotons / 2; log2n = (int)Math.Ceiling(Math.Log(storedPhotons) / Math.Log(2.0)); photons = temp; hasRadiance = true; }