use of org.sunflow.core.LightSample in project joons-renderer by joonhyublee.
the class DirectionalSpotlight method getSamples.
public void getSamples(ShadingState state) {
if (Vector3.dot(dir, state.getGeoNormal()) < 0 && Vector3.dot(dir, state.getNormal()) < 0) {
// project point onto source plane
float x = state.getPoint().x - src.x;
float y = state.getPoint().y - src.y;
float z = state.getPoint().z - src.z;
float t = ((x * dir.x) + (y * dir.y) + (z * dir.z));
if (t >= 0.0) {
x -= (t * dir.x);
y -= (t * dir.y);
z -= (t * dir.z);
if (((x * x) + (y * y) + (z * z)) <= r2) {
Point3 p = new Point3();
p.x = src.x + x;
p.y = src.y + y;
p.z = src.z + z;
LightSample dest = new LightSample();
dest.setShadowRay(new Ray(state.getPoint(), p));
dest.setRadiance(radiance, radiance);
dest.traceShadow(state);
state.addSample(dest);
}
}
}
}
use of org.sunflow.core.LightSample 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.core.LightSample in project joons-renderer by joonhyublee.
the class Hair method getRadiance.
@Override
public Color getRadiance(ShadingState state) {
// don't use these - gather lights for sphere of directions
// gather lights
state.initLightSamples();
state.initCausticSamples();
Vector3 v = state.getRay().getDirection();
v.negate();
Vector3 h = new Vector3();
Vector3 t = state.getBasis().transform(new Vector3(0, 1, 0));
Color diff = Color.black();
Color spec = Color.black();
for (LightSample ls : state) {
Vector3 l = ls.getShadowRay().getDirection();
float dotTL = Vector3.dot(t, l);
float sinTL = (float) Math.sqrt(1 - dotTL * dotTL);
// float dotVL = Vector3.dot(v, l);
diff.madd(sinTL, ls.getDiffuseRadiance());
Vector3.add(v, l, h);
h.normalize();
float dotTH = Vector3.dot(t, h);
float sinTH = (float) Math.sqrt(1 - dotTH * dotTH);
float s = (float) Math.pow(sinTH, 10.0f);
spec.madd(s, ls.getSpecularRadiance());
}
Color c = Color.add(diff, spec, new Color());
// transparency
return Color.blend(c, state.traceTransparency(), state.getV(), new Color());
}
use of org.sunflow.core.LightSample in project joons-renderer by joonhyublee.
the class ImageBasedLight method getSamples.
public void getSamples(ShadingState state) {
if (samples == null) {
int n = state.getDiffuseDepth() > 0 ? 1 : numSamples;
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 dir = getDirection(su, sv);
basis.transform(dir);
if (Vector3.dot(dir, state.getGeoNormal()) > 0) {
LightSample dest = new LightSample();
dest.setShadowRay(new Ray(state.getPoint(), dir));
dest.getShadowRay().setMax(Float.MAX_VALUE);
Color radiance = texture.getPixel(su, sv);
dest.setRadiance(radiance, radiance);
dest.getDiffuseRadiance().mul(invP);
dest.getSpecularRadiance().mul(invP);
dest.traceShadow(state);
state.addSample(dest);
}
}
} else {
if (state.getDiffuseDepth() > 0) {
for (int i = 0; i < numLowSamples; i++) {
if (Vector3.dot(lowSamples[i], state.getGeoNormal()) > 0 && Vector3.dot(lowSamples[i], state.getNormal()) > 0) {
LightSample dest = new LightSample();
dest.setShadowRay(new Ray(state.getPoint(), lowSamples[i]));
dest.getShadowRay().setMax(Float.MAX_VALUE);
dest.setRadiance(lowColors[i], lowColors[i]);
dest.traceShadow(state);
state.addSample(dest);
}
}
} else {
for (int i = 0; i < numSamples; i++) {
if (Vector3.dot(samples[i], state.getGeoNormal()) > 0 && Vector3.dot(samples[i], state.getNormal()) > 0) {
LightSample dest = new LightSample();
dest.setShadowRay(new Ray(state.getPoint(), samples[i]));
dest.getShadowRay().setMax(Float.MAX_VALUE);
dest.setRadiance(colors[i], colors[i]);
dest.traceShadow(state);
state.addSample(dest);
}
}
}
}
}
use of org.sunflow.core.LightSample in project joons-renderer by joonhyublee.
the class AnisotropicWardShader method getRadiance.
public Color getRadiance(ShadingState state) {
// make sure we are on the right side of the material
state.faceforward();
OrthoNormalBasis onb = state.getBasis();
// direct lighting and caustics
state.initLightSamples();
state.initCausticSamples();
Color lr = Color.black();
// compute specular contribution
if (state.includeSpecular()) {
Vector3 in = state.getRay().getDirection().negate(new Vector3());
for (LightSample sample : state) {
float cosNL = sample.dot(state.getNormal());
float fr = brdf(in, sample.getShadowRay().getDirection(), onb);
lr.madd(cosNL * fr, sample.getSpecularRadiance());
}
// indirect lighting - specular
if (numRays > 0) {
int n = state.getDepth() == 0 ? numRays : 1;
for (int i = 0; i < n; i++) {
// specular indirect lighting
double r1 = state.getRandom(i, 0, n);
double r2 = state.getRandom(i, 1, n);
float alphaRatio = alphaY / alphaX;
float phi = 0;
if (r1 < 0.25) {
double val = 4 * r1;
phi = (float) Math.atan(alphaRatio * Math.tan(Math.PI / 2 * val));
} else if (r1 < 0.5) {
double val = 1 - 4 * (0.5 - r1);
phi = (float) Math.atan(alphaRatio * Math.tan(Math.PI / 2 * val));
phi = (float) Math.PI - phi;
} else if (r1 < 0.75) {
double val = 4 * (r1 - 0.5);
phi = (float) Math.atan(alphaRatio * Math.tan(Math.PI / 2 * val));
phi += Math.PI;
} else {
double val = 1 - 4 * (1 - r1);
phi = (float) Math.atan(alphaRatio * Math.tan(Math.PI / 2 * val));
phi = 2 * (float) Math.PI - phi;
}
float cosPhi = (float) Math.cos(phi);
float sinPhi = (float) Math.sin(phi);
float denom = (cosPhi * cosPhi) / (alphaX * alphaX) + (sinPhi * sinPhi) / (alphaY * alphaY);
float theta = (float) Math.atan(Math.sqrt(-Math.log(1 - r2) / denom));
float sinTheta = (float) Math.sin(theta);
float cosTheta = (float) Math.cos(theta);
Vector3 h = new Vector3();
h.x = sinTheta * cosPhi;
h.y = sinTheta * sinPhi;
h.z = cosTheta;
onb.transform(h);
Vector3 o = new Vector3();
float ih = Vector3.dot(h, in);
o.x = 2 * ih * h.x - in.x;
o.y = 2 * ih * h.y - in.y;
o.z = 2 * ih * h.z - in.z;
float no = onb.untransformZ(o);
float ni = onb.untransformZ(in);
float w = ih * cosTheta * cosTheta * cosTheta * (float) Math.sqrt(Math.abs(no / ni));
Ray r = new Ray(state.getPoint(), o);
lr.madd(w / n, state.traceGlossy(r, i));
}
}
lr.mul(rhoS);
}
// add diffuse contribution
lr.add(state.diffuse(getDiffuse(state)));
return lr;
}
Aggregations