use of org.sunflow.image.Color in project joons-renderer by joonhyublee.
the class GridPhotonMap method getRadiance.
@Override
public synchronized Color getRadiance(Point3 p, Vector3 n) {
if (!bounds.contains(p)) {
return Color.BLACK;
}
Vector3 ext = bounds.getExtents();
int ix = (int) (((p.x - bounds.getMinimum().x) * nx) / ext.x);
int iy = (int) (((p.y - bounds.getMinimum().y) * ny) / ext.y);
int iz = (int) (((p.z - bounds.getMinimum().z) * nz) / ext.z);
ix = MathUtils.clamp(ix, 0, nx - 1);
iy = MathUtils.clamp(iy, 0, ny - 1);
iz = MathUtils.clamp(iz, 0, nz - 1);
int id = ix + iy * nx + iz * nx * ny;
rwl.readLock().lock();
PhotonGroup center = null;
for (PhotonGroup g = get(ix, iy, iz); g != null; g = g.next) {
if (g.id == id && Vector3.dot(n, g.normal) > NORMAL_THRESHOLD) {
if (g.radiance == null) {
center = g;
break;
}
Color r = g.radiance.copy();
rwl.readLock().unlock();
return r;
}
}
int vol = 1;
while (true) {
int numPhotons = 0;
int ndiff = 0;
Color irr = Color.black();
Color diff = (center == null) ? Color.black() : null;
for (int z = iz - (vol - 1); z <= iz + (vol - 1); z++) {
for (int y = iy - (vol - 1); y <= iy + (vol - 1); y++) {
for (int x = ix - (vol - 1); x <= ix + (vol - 1); x++) {
int vid = x + y * nx + z * nx * ny;
for (PhotonGroup g = get(x, y, z); g != null; g = g.next) {
if (g.id == vid && Vector3.dot(n, g.normal) > NORMAL_THRESHOLD) {
numPhotons += g.count;
irr.add(g.flux);
if (diff != null) {
diff.add(g.diffuse);
ndiff++;
}
// only one valid group can be found,
break;
// skip the others
}
}
}
}
}
if (numPhotons >= numGather || vol >= 3) {
// we have found enough photons
// cache irradiance and return
float area = (2 * vol - 1) / 3.0f * ((ext.x / nx) + (ext.y / ny) + (ext.z / nz));
area *= area;
area *= Math.PI;
irr.mul(1.0f / area);
// upgrade lock manually
rwl.readLock().unlock();
rwl.writeLock().lock();
try {
if (center == null) {
if (ndiff > 0) {
diff.mul(1.0f / ndiff);
}
center = new PhotonGroup(id, n);
center.diffuse.set(diff);
center.next = cellHash[id % cellHash.length];
cellHash[id % cellHash.length] = center;
}
irr.mul(center.diffuse);
center.radiance = irr.copy();
} finally {
rwl.writeLock().unlock();
}
return irr;
}
vol++;
}
}
use of org.sunflow.image.Color in project joons-renderer by joonhyublee.
the class SCParser method parseColor.
private Color parseColor() throws IOException, ParserException, ColorSpecificationException {
if (p.peekNextToken("{")) {
String space = p.getNextToken();
int req = ColorFactory.getRequiredDataValues(space);
if (req == -2) {
UI.printWarning(Module.API, "Unrecognized color space: %s", space);
return null;
} else if (req == -1) {
// array required, parse how many values are required
req = p.getNextInt();
}
Color c = ColorFactory.createColor(space, parseFloatArray(req));
p.checkNextToken("}");
return c;
} else {
float r = p.getNextFloat();
float g = p.getNextFloat();
float b = p.getNextFloat();
return ColorFactory.createColor(null, r, g, b);
}
}
use of org.sunflow.image.Color in project joons-renderer by joonhyublee.
the class GlobalPhotonMap method precomputeRadiance.
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.ceil(Math.log(storedPhotons) / Math.log(2.0));
photons = temp;
hasRadiance = true;
}
use of org.sunflow.image.Color in project joons-renderer by joonhyublee.
the class GlobalPhotonMap method getRadiance.
@Override
public Color getRadiance(Point3 p, Vector3 n) {
if (!hasRadiance || (storedPhotons == 0)) {
return Color.BLACK;
}
float px = p.x;
float py = p.y;
float pz = p.z;
int i = 1;
int level = 0;
int cameFrom;
float dist2;
float maxDist2 = gatherRadius * gatherRadius;
Photon nearest = null;
Photon curr;
Vector3 photN = new Vector3();
float[] dist1d2 = new float[log2n];
int[] chosen = new int[log2n];
while (true) {
while (i < halfStoredPhotons) {
float dist1d = photons[i].getDist1(px, py, pz);
dist1d2[level] = dist1d * dist1d;
i += i;
if (dist1d > 0) {
i++;
}
chosen[level++] = i;
}
curr = photons[i];
dist2 = curr.getDist2(px, py, pz);
if (dist2 < maxDist2) {
Vector3.decode(curr.normal, photN);
float currentDotN = Vector3.dot(photN, n);
if (currentDotN > 0.9f) {
nearest = curr;
maxDist2 = dist2;
}
}
do {
cameFrom = i;
i >>= 1;
level--;
if (i == 0) {
return (nearest == null) ? Color.BLACK : new Color().setRGBE(nearest.data);
}
} while ((dist1d2[level] >= maxDist2) || (cameFrom != chosen[level]));
curr = photons[i];
dist2 = curr.getDist2(px, py, pz);
if (dist2 < maxDist2) {
Vector3.decode(curr.normal, photN);
float currentDotN = Vector3.dot(photN, n);
if (currentDotN > 0.9f) {
nearest = curr;
maxDist2 = dist2;
}
}
i = chosen[level++] ^ 1;
}
}
use of org.sunflow.image.Color in project joons-renderer by joonhyublee.
the class SunSkyLight method getSamples.
public void getSamples(ShadingState state) {
if (Vector3.dot(sunDirWorld, state.getGeoNormal()) > 0 && Vector3.dot(sunDirWorld, state.getNormal()) > 0) {
LightSample dest = new LightSample();
dest.setShadowRay(new Ray(state.getPoint(), sunDirWorld));
dest.getShadowRay().setMax(Float.MAX_VALUE);
dest.setRadiance(sunColor, sunColor);
dest.traceShadow(state);
state.addSample(dest);
}
int n = state.getDiffuseDepth() > 0 ? 1 : numSkySamples;
for (int i = 0; i < n; i++) {
// random offset on unit square, we use the infinite version of
// getRandom because the light sampling is adaptive
double randX = state.getRandom(i, 0, n);
double randY = state.getRandom(i, 1, n);
int x = 0;
while (randX >= colHistogram[x] && x < colHistogram.length - 1) {
x++;
}
float[] rowHistogram = imageHistogram[x];
int y = 0;
while (randY >= rowHistogram[y] && y < rowHistogram.length - 1) {
y++;
}
// sample from (x, y)
float u = (float) ((x == 0) ? (randX / colHistogram[0]) : ((randX - colHistogram[x - 1]) / (colHistogram[x] - colHistogram[x - 1])));
float v = (float) ((y == 0) ? (randY / rowHistogram[0]) : ((randY - rowHistogram[y - 1]) / (rowHistogram[y] - rowHistogram[y - 1])));
float px = ((x == 0) ? colHistogram[0] : (colHistogram[x] - colHistogram[x - 1]));
float py = ((y == 0) ? rowHistogram[0] : (rowHistogram[y] - rowHistogram[y - 1]));
float su = (x + u) / colHistogram.length;
float sv = (y + v) / rowHistogram.length;
float invP = (float) Math.sin(sv * Math.PI) * jacobian / (n * px * py);
Vector3 localDir = getDirection(su, sv);
Vector3 dir = basis.transform(localDir, new Vector3());
if (Vector3.dot(dir, state.getGeoNormal()) > 0 && Vector3.dot(dir, state.getNormal()) > 0) {
LightSample dest = new LightSample();
dest.setShadowRay(new Ray(state.getPoint(), dir));
dest.getShadowRay().setMax(Float.MAX_VALUE);
Color radiance = getSkyRGB(localDir);
dest.setRadiance(radiance, radiance);
dest.getDiffuseRadiance().mul(invP);
dest.getSpecularRadiance().mul(invP);
dest.traceShadow(state);
state.addSample(dest);
}
}
}
Aggregations