use of org.sunflow.math.Vector3 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.math.Vector3 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.math.Vector3 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);
}
}
}
use of org.sunflow.math.Vector3 in project joons-renderer by joonhyublee.
the class SunSkyLight method getDirection.
private Vector3 getDirection(float u, float v) {
Vector3 dest = new Vector3();
double phi = 0, theta = 0;
theta = u * 2 * Math.PI;
phi = v * Math.PI;
double sin_phi = Math.sin(phi);
dest.x = (float) (-sin_phi * Math.cos(theta));
dest.y = (float) Math.cos(phi);
dest.z = (float) (sin_phi * Math.sin(theta));
return dest;
}
use of org.sunflow.math.Vector3 in project joons-renderer by joonhyublee.
the class PerlinModifier method modify.
@Override
public void modify(ShadingState state) {
Point3 p = state.transformWorldToObject(state.getPoint());
p.x *= size;
p.y *= size;
p.z *= size;
Vector3 normal = state.transformNormalWorldToObject(state.getNormal());
double f0 = f(p.x, p.y, p.z);
double fx = f(p.x + .0001, p.y, p.z);
double fy = f(p.x, p.y + .0001, p.z);
double fz = f(p.x, p.y, p.z + .0001);
normal.x -= scale * (fx - f0) / .0001;
normal.y -= scale * (fy - f0) / .0001;
normal.z -= scale * (fz - f0) / .0001;
normal.normalize();
state.getNormal().set(state.transformNormalObjectToWorld(normal));
state.getNormal().normalize();
state.setBasis(OrthoNormalBasis.makeFromW(state.getNormal()));
}
Aggregations