use of org.sunflow.math.Point3 in project joons-renderer by joonhyublee.
the class LightServer method calculatePhotons.
boolean calculatePhotons(final PhotonStore map, String type, final int seed, Options options) {
if (map == null) {
return true;
}
if (lights.length == 0) {
UI.printError(Module.LIGHT, "Unable to trace %s photons, no lights in scene", type);
return false;
}
final float[] histogram = new float[lights.length];
histogram[0] = lights[0].getPower();
for (int i = 1; i < lights.length; i++) {
histogram[i] = histogram[i - 1] + lights[i].getPower();
}
UI.printInfo(Module.LIGHT, "Tracing %s photons ...", type);
map.prepare(options, scene.getBounds());
int numEmittedPhotons = map.numEmit();
if (numEmittedPhotons <= 0 || histogram[histogram.length - 1] <= 0) {
UI.printError(Module.LIGHT, "Photon mapping enabled, but no %s photons to emit", type);
return false;
}
UI.taskStart("Tracing " + type + " photons", 0, numEmittedPhotons);
Thread[] photonThreads = new Thread[scene.getThreads()];
final float scale = 1.0f / numEmittedPhotons;
int delta = numEmittedPhotons / photonThreads.length;
photonCounter = 0;
Timer photonTimer = new Timer();
photonTimer.start();
for (int i = 0; i < photonThreads.length; i++) {
final int threadID = i;
final int start = threadID * delta;
final int end = (threadID == (photonThreads.length - 1)) ? numEmittedPhotons : (threadID + 1) * delta;
photonThreads[i] = new Thread(new Runnable() {
public void run() {
IntersectionState istate = new IntersectionState();
for (int i = start; i < end; i++) {
synchronized (LightServer.this) {
UI.taskUpdate(photonCounter);
photonCounter++;
if (UI.taskCanceled()) {
return;
}
}
int qmcI = i + seed;
double rand = QMC.halton(0, qmcI) * histogram[histogram.length - 1];
int j = 0;
while (rand >= histogram[j] && j < histogram.length) {
j++;
}
// make sure we didn't pick a zero-probability light
if (j == histogram.length) {
continue;
}
double randX1 = (j == 0) ? rand / histogram[0] : (rand - histogram[j]) / (histogram[j] - histogram[j - 1]);
double randY1 = QMC.halton(1, qmcI);
double randX2 = QMC.halton(2, qmcI);
double randY2 = QMC.halton(3, qmcI);
Point3 pt = new Point3();
Vector3 dir = new Vector3();
Color power = new Color();
lights[j].getPhoton(randX1, randY1, randX2, randY2, pt, dir, power);
power.mul(scale);
Ray r = new Ray(pt, dir);
scene.trace(r, istate);
if (istate.hit()) {
shadePhoton(ShadingState.createPhotonState(r, istate, qmcI, map, LightServer.this), power);
}
}
}
});
photonThreads[i].setPriority(scene.getThreadPriority());
photonThreads[i].start();
}
for (int i = 0; i < photonThreads.length; i++) {
try {
photonThreads[i].join();
} catch (InterruptedException e) {
UI.printError(Module.LIGHT, "Photon thread %d of %d was interrupted", i + 1, photonThreads.length);
return false;
}
}
if (UI.taskCanceled()) {
// shut down task cleanly
UI.taskStop();
return false;
}
photonTimer.end();
UI.taskStop();
UI.printInfo(Module.LIGHT, "Tracing time for %s photons: %s", type, photonTimer.toString());
map.init();
return true;
}
use of org.sunflow.math.Point3 in project joons-renderer by joonhyublee.
the class Plane method prepareShadingState.
@Override
public void prepareShadingState(ShadingState state) {
state.init();
state.getRay().getPoint(state.getPoint());
Instance parent = state.getInstance();
Vector3 worldNormal = state.transformNormalObjectToWorld(normal);
state.getNormal().set(worldNormal);
state.getGeoNormal().set(worldNormal);
state.setShader(parent.getShader(0));
state.setModifier(parent.getModifier(0));
Point3 p = state.transformWorldToObject(state.getPoint());
float hu, hv;
switch(k) {
case 0:
{
hu = p.y;
hv = p.z;
break;
}
case 1:
{
hu = p.z;
hv = p.x;
break;
}
case 2:
{
hu = p.x;
hv = p.y;
break;
}
default:
hu = hv = 0;
}
state.getUV().x = hu * bnu + hv * bnv + bnd;
state.getUV().y = hu * cnu + hv * cnv + cnd;
state.setBasis(OrthoNormalBasis.makeFromW(normal));
}
use of org.sunflow.math.Point3 in project joons-renderer by joonhyublee.
the class RealtimeBenchmark method createGeometry.
private void createGeometry() {
// light source
parameter("source", new Point3(-15.5945f, -30.0581f, 45.967f));
parameter("dir", new Vector3(15.5945f, 30.0581f, -45.967f));
parameter("radius", 60.0f);
parameter("radiance", null, 3, 3, 3);
light("light", "directional");
// gi-engine
parameter("gi.engine", "fake");
parameter("gi.fake.sky", null, 0.25f, 0.25f, 0.25f);
parameter("gi.fake.ground", null, 0.01f, 0.01f, 0.5f);
parameter("gi.fake.up", new Vector3(0, 0, 1));
options(DEFAULT_OPTIONS);
// shaders
parameter("diffuse", null, 0.5f, 0.5f, 0.5f);
shader("default", "diffuse");
parameter("diffuse", null, 0.5f, 0.5f, 0.5f);
parameter("shiny", 0.2f);
shader("refl", "shiny_diffuse");
// objects
// teapot
parameter("subdivs", 10);
geometry("teapot", "teapot");
parameter("shaders", "default");
Matrix4 m = Matrix4.IDENTITY;
m = Matrix4.scale(0.075f).multiply(m);
m = Matrix4.rotateZ((float) Math.toRadians(-45f)).multiply(m);
m = Matrix4.translation(-7, 0, 0).multiply(m);
parameter(TRANSFORM, m);
instance("teapot.instance", "teapot");
// gumbo
parameter("subdivs", 10);
geometry("gumbo", "gumbo");
m = Matrix4.IDENTITY;
m = Matrix4.scale(0.5f).multiply(m);
m = Matrix4.rotateZ((float) Math.toRadians(25f)).multiply(m);
m = Matrix4.translation(3, -7, 0).multiply(m);
parameter("shaders", "default");
parameter(TRANSFORM, m);
instance("gumbo.instance", "gumbo");
// ground plane
parameter("center", new Point3(0, 0, 0));
parameter("normal", new Vector3(0, 0, 1));
geometry("ground", "plane");
parameter("shaders", "refl");
instance("ground.instance", "ground");
}
use of org.sunflow.math.Point3 in project joons-renderer by joonhyublee.
the class JoonsRenderer method buildLight.
private boolean buildLight(JRFiller temp, int i) {
// light mesh
if (temp.np == 3 || temp.np == 4) {
api.parameter("radiance", null, new float[] { temp.p[0], temp.p[1], temp.p[2] });
if (temp.np == 4)
api.parameter("samples", (int) temp.p[3]);
api.parameter("points", "point", "vertex", temp.verticesToArray());
api.parameter("triangles", temp.triangleIndicesToArray());
api.light("Shader_" + i, "triangle_mesh");
} else {
PApplet.println(FILLER_LIGHT_ERROR);
return false;
}
// light spheres
ArrayList<Float> spheres = temp.getSpheres();
int noOfSpheres = (int) spheres.size() / 4;
for (int j = 0; j < noOfSpheres; j++) {
float x = spheres.get(j * 4);
float y = spheres.get(j * 4 + 1);
float z = spheres.get(j * 4 + 2);
float r = spheres.get(j * 4 + 3);
if (temp.np == 3 || temp.np == 4) {
api.parameter("radiance", null, new float[] { temp.p[0], temp.p[1], temp.p[2] });
api.parameter("center", new Point3(x, y, z));
api.parameter("radius", r);
if (temp.np == 4)
api.parameter("samples", (int) temp.p[3]);
api.light("SphereLight_" + i + "_" + j, "sphere");
} else {
return false;
}
}
return true;
}
use of org.sunflow.math.Point3 in project joons-renderer by joonhyublee.
the class SCParser method parseLightBlock.
private void parseLightBlock(SunflowAPIInterface api) throws ParserException, IOException, ColorSpecificationException {
p.checkNextToken("{");
p.checkNextToken(TYPE);
if (p.peekNextToken("mesh")) {
UI.printWarning(Module.API, "Deprecated light type: mesh");
p.checkNextToken(NAME);
String name = p.getNextToken();
UI.printInfo(Module.API, "Reading light mesh: %s ...", name);
p.checkNextToken(EMIT);
api.parameter(RADIANCE, null, parseColor().getRGB());
int samples = numLightSamples;
if (p.peekNextToken(SAMPLES)) {
samples = p.getNextInt();
} else {
UI.printWarning(Module.API, "Samples keyword not found - defaulting to %d", samples);
}
api.parameter(SAMPLES, samples);
int numVertices = p.getNextInt();
int numTriangles = p.getNextInt();
float[] points = new float[3 * numVertices];
int[] triangles = new int[3 * numTriangles];
for (int i = 0; i < numVertices; i++) {
p.checkNextToken("v");
points[3 * i + 0] = p.getNextFloat();
points[3 * i + 1] = p.getNextFloat();
points[3 * i + 2] = p.getNextFloat();
// ignored
p.getNextFloat();
p.getNextFloat();
p.getNextFloat();
p.getNextFloat();
p.getNextFloat();
}
for (int i = 0; i < numTriangles; i++) {
p.checkNextToken("t");
triangles[3 * i + 0] = p.getNextInt();
triangles[3 * i + 1] = p.getNextInt();
triangles[3 * i + 2] = p.getNextInt();
}
api.parameter(POINTS, POINT, VERTEX, points);
api.parameter(TRIANGLES, triangles);
api.light(name, TRIANGLE_MESH);
} else if (p.peekNextToken(POINT)) {
UI.printInfo(Module.API, "Reading point light ...");
Color pow;
if (p.peekNextToken(COLOR)) {
pow = parseColor();
p.checkNextToken(POWER);
float po = p.getNextFloat();
pow.mul(po);
} else {
UI.printWarning(Module.API, "Deprecated color specification - please use color and power instead");
p.checkNextToken(POWER);
pow = parseColor();
}
p.checkNextToken("p");
api.parameter(CENTER, parsePoint());
api.parameter(POWER, null, pow.getRGB());
api.light(generateUniqueName("pointlight"), POINT);
} else if (p.peekNextToken("spherical")) {
UI.printInfo(Module.API, "Reading spherical light ...");
p.checkNextToken(COLOR);
Color pow = parseColor();
p.checkNextToken(RADIANCE);
pow.mul(p.getNextFloat());
api.parameter(RADIANCE, null, pow.getRGB());
p.checkNextToken(CENTER);
api.parameter(CENTER, parsePoint());
p.checkNextToken(RADIUS);
api.parameter(RADIUS, p.getNextFloat());
p.checkNextToken(SAMPLES);
api.parameter(SAMPLES, p.getNextInt());
api.light(generateUniqueName("spherelight"), "sphere");
} else if (p.peekNextToken("directional")) {
UI.printInfo(Module.API, "Reading directional light ...");
p.checkNextToken("source");
Point3 s = parsePoint();
api.parameter("source", s);
p.checkNextToken("target");
Point3 t = parsePoint();
api.parameter("dir", Point3.sub(t, s, new Vector3()));
p.checkNextToken(RADIUS);
api.parameter(RADIUS, p.getNextFloat());
p.checkNextToken(EMIT);
Color e = parseColor();
if (p.peekNextToken("intensity")) {
float i = p.getNextFloat();
e.mul(i);
} else {
UI.printWarning(Module.API, "Deprecated color specification - please use emit and intensity instead");
}
api.parameter(RADIANCE, null, e.getRGB());
api.light(generateUniqueName("dirlight"), "directional");
} else if (p.peekNextToken("ibl")) {
UI.printInfo(Module.API, "Reading image based light ...");
p.checkNextToken("image");
api.parameter(TEXTURE, p.getNextToken());
p.checkNextToken(CENTER);
api.parameter(CENTER, parseVector());
p.checkNextToken("up");
api.parameter("up", parseVector());
p.checkNextToken("lock");
api.parameter("fixed", p.getNextBoolean());
int samples = numLightSamples;
if (p.peekNextToken(SAMPLES)) {
samples = p.getNextInt();
} else {
UI.printWarning(Module.API, "Samples keyword not found - defaulting to %d", samples);
}
api.parameter(SAMPLES, samples);
if (p.peekNextToken("lowsamples")) {
api.parameter("lowsamples", p.getNextInt());
} else {
api.parameter("lowsamples", samples);
}
api.light(generateUniqueName("ibl"), "ibl");
} else if (p.peekNextToken("meshlight")) {
p.checkNextToken(NAME);
String name = p.getNextToken();
UI.printInfo(Module.API, "Reading meshlight: %s ...", name);
p.checkNextToken(EMIT);
Color e = parseColor();
if (p.peekNextToken(RADIANCE)) {
float r = p.getNextFloat();
e.mul(r);
} else {
UI.printWarning(Module.API, "Deprecated color specification - please use emit and radiance instead");
}
api.parameter(RADIANCE, null, e.getRGB());
int samples = numLightSamples;
if (p.peekNextToken(SAMPLES)) {
samples = p.getNextInt();
} else {
UI.printWarning(Module.API, "Samples keyword not found - defaulting to %d", samples);
}
api.parameter(SAMPLES, samples);
// parse vertices
p.checkNextToken(POINTS);
int np = p.getNextInt();
api.parameter(POINTS, POINT, VERTEX, parseFloatArray(np * 3));
// parse triangle indices
p.checkNextToken(TRIANGLES);
int nt = p.getNextInt();
api.parameter(TRIANGLES, parseIntArray(nt * 3));
api.light(name, TRIANGLE_MESH);
} else if (p.peekNextToken("sunsky")) {
p.checkNextToken("up");
api.parameter("up", parseVector());
p.checkNextToken("east");
api.parameter("east", parseVector());
p.checkNextToken("sundir");
api.parameter("sundir", parseVector());
p.checkNextToken("turbidity");
api.parameter("turbidity", p.getNextFloat());
if (p.peekNextToken(SAMPLES)) {
api.parameter(SAMPLES, p.getNextInt());
}
if (p.peekNextToken("ground.extendsky")) {
api.parameter("ground.extendsky", p.getNextBoolean());
} else if (p.peekNextToken("ground.color")) {
api.parameter("ground.color", null, parseColor().getRGB());
}
api.light(generateUniqueName("sunsky"), "sunsky");
} else if (p.peekNextToken("cornellbox")) {
UI.printInfo(Module.API, "Reading cornell box ...");
p.checkNextToken("corner0");
api.parameter("corner0", parsePoint());
p.checkNextToken("corner1");
api.parameter("corner1", parsePoint());
p.checkNextToken("left");
api.parameter("leftColor", null, parseColor().getRGB());
p.checkNextToken("right");
api.parameter("rightColor", null, parseColor().getRGB());
p.checkNextToken("top");
api.parameter("topColor", null, parseColor().getRGB());
p.checkNextToken("bottom");
api.parameter("bottomColor", null, parseColor().getRGB());
p.checkNextToken("back");
api.parameter("backColor", null, parseColor().getRGB());
p.checkNextToken(EMIT);
api.parameter(RADIANCE, null, parseColor().getRGB());
if (p.peekNextToken(SAMPLES)) {
api.parameter(SAMPLES, p.getNextInt());
}
api.light(generateUniqueName("cornellbox"), "cornell_box");
} else {
UI.printWarning(Module.API, "Unrecognized object type: %s", p.getNextToken());
}
p.checkNextToken("}");
}
Aggregations