use of org.sunflow.core.Ray in project joons-renderer by joonhyublee.
the class ShinyDiffuseShader method getRadiance.
public Color getRadiance(ShadingState state) {
// make sure we are on the right side of the material
state.faceforward();
// direct lighting
state.initLightSamples();
state.initCausticSamples();
Color d = getDiffuse(state);
Color lr = state.diffuse(d);
if (!state.includeSpecular()) {
return lr;
}
float cos = state.getCosND();
float dn = 2 * cos;
Vector3 refDir = new Vector3();
refDir.x = (dn * state.getNormal().x) + state.getRay().getDirection().x;
refDir.y = (dn * state.getNormal().y) + state.getRay().getDirection().y;
refDir.z = (dn * state.getNormal().z) + state.getRay().getDirection().z;
Ray refRay = new Ray(state.getPoint(), refDir);
// compute Fresnel term
cos = 1 - cos;
float cos2 = cos * cos;
float cos5 = cos2 * cos2 * cos;
Color ret = Color.white();
Color r = d.copy().mul(refl);
ret.sub(r);
ret.mul(cos5);
ret.add(r);
return lr.add(ret.mul(state.traceReflection(refRay, 0)));
}
use of org.sunflow.core.Ray in project joons-renderer by joonhyublee.
the class CornellBox method scatterPhoton.
@Override
public void scatterPhoton(ShadingState state, Color power) {
int side = state.getPrimitiveID();
Color kd = null;
switch(side) {
case 0:
kd = left;
break;
case 1:
kd = right;
break;
case 3:
kd = back;
break;
case 4:
kd = bottom;
break;
case 5:
float lx = state.getPoint().x;
float ly = state.getPoint().y;
if (lx >= lxmin && lx < lxmax && ly >= lymin && ly < lymax && state.getRay().dz > 0) {
return;
}
kd = top;
break;
default:
assert false;
}
// make sure we are on the right side of the material
if (Vector3.dot(state.getNormal(), state.getRay().getDirection()) > 0) {
state.getNormal().negate();
state.getGeoNormal().negate();
}
state.storePhoton(state.getRay().getDirection(), power, kd);
double avg = kd.getAverage();
double rnd = state.getRandom(0, 0, 1);
if (rnd < avg) {
// photon is scattered
power.mul(kd).mul(1 / (float) avg);
OrthoNormalBasis onb = OrthoNormalBasis.makeFromW(state.getNormal());
double u = 2 * Math.PI * rnd / avg;
double v = state.getRandom(0, 1, 1);
float s = (float) Math.sqrt(v);
float s1 = (float) Math.sqrt(1.0 - v);
Vector3 w = new Vector3((float) Math.cos(u) * s, (float) Math.sin(u) * s, s1);
w = onb.transform(w, new Vector3());
state.traceDiffusePhoton(new Ray(state.getPoint(), w), power);
}
}
use of org.sunflow.core.Ray in project joons-renderer by joonhyublee.
the class CornellBox method getSamples.
@Override
public void getSamples(ShadingState state) {
if (lightBounds.contains(state.getPoint()) && state.getPoint().z < maxZ) {
int n = state.getDiffuseDepth() > 0 ? 1 : samples;
float a = area / n;
for (int i = 0; i < n; i++) {
// random offset on unit square
double randX = state.getRandom(i, 0, n);
double randY = state.getRandom(i, 1, n);
Point3 p = new Point3();
p.x = (float) (lxmin * (1 - randX) + lxmax * randX);
p.y = (float) (lymin * (1 - randY) + lymax * randY);
p.z = maxZ - 0.001f;
LightSample dest = new LightSample();
// prepare shadow ray to sampled point
dest.setShadowRay(new Ray(state.getPoint(), p));
// check that the direction of the sample is the same as the
// normal
float cosNx = dest.dot(state.getNormal());
if (cosNx <= 0) {
return;
}
// light source facing point ?
// (need to check with light source's normal)
float cosNy = dest.getShadowRay().dz;
if (cosNy > 0) {
// compute geometric attenuation and probability scale
// factor
float r = dest.getShadowRay().getMax();
float g = cosNy / (r * r);
float scale = g * a;
// set final sample radiance
dest.setRadiance(radiance, radiance);
dest.getDiffuseRadiance().mul(scale);
dest.getSpecularRadiance().mul(scale);
dest.traceShadow(state);
state.addSample(dest);
}
}
}
}
use of org.sunflow.core.Ray in project joons-renderer by joonhyublee.
the class UberShader method scatterPhoton.
public void scatterPhoton(ShadingState state, Color power) {
Color diffuse, specular;
// make sure we are on the right side of the material
state.faceforward();
diffuse = getDiffuse(state);
specular = getSpecular(state);
state.storePhoton(state.getRay().getDirection(), power, diffuse);
float d = diffuse.getAverage();
float r = specular.getAverage();
double rnd = state.getRandom(0, 0, 1);
if (rnd < d) {
// photon is scattered
power.mul(diffuse).mul(1.0f / d);
OrthoNormalBasis onb = state.getBasis();
double u = 2 * Math.PI * rnd / d;
double v = state.getRandom(0, 1, 1);
float s = (float) Math.sqrt(v);
float s1 = (float) Math.sqrt(1.0 - v);
Vector3 w = new Vector3((float) Math.cos(u) * s, (float) Math.sin(u) * s, s1);
w = onb.transform(w, new Vector3());
state.traceDiffusePhoton(new Ray(state.getPoint(), w), power);
} else if (rnd < d + r) {
if (glossyness == 0) {
float cos = -Vector3.dot(state.getNormal(), state.getRay().getDirection());
power.mul(diffuse).mul(1.0f / d);
// photon is reflected
float dn = 2 * cos;
Vector3 dir = new Vector3();
dir.x = (dn * state.getNormal().x) + state.getRay().getDirection().x;
dir.y = (dn * state.getNormal().y) + state.getRay().getDirection().y;
dir.z = (dn * state.getNormal().z) + state.getRay().getDirection().z;
state.traceReflectionPhoton(new Ray(state.getPoint(), dir), power);
} else {
float dn = 2.0f * state.getCosND();
// reflected direction
Vector3 refDir = new Vector3();
refDir.x = (dn * state.getNormal().x) + state.getRay().dx;
refDir.y = (dn * state.getNormal().y) + state.getRay().dy;
refDir.z = (dn * state.getNormal().z) + state.getRay().dz;
power.mul(spec).mul(1.0f / r);
OrthoNormalBasis onb = state.getBasis();
double u = 2 * Math.PI * (rnd - r) / r;
double v = state.getRandom(0, 1, 1);
float s = (float) Math.pow(v, 1 / ((1.0f / glossyness) + 1));
float s1 = (float) Math.sqrt(1 - s * s);
Vector3 w = new Vector3((float) Math.cos(u) * s1, (float) Math.sin(u) * s1, s);
w = onb.transform(w, new Vector3());
state.traceReflectionPhoton(new Ray(state.getPoint(), w), power);
}
}
}
use of org.sunflow.core.Ray in project joons-renderer by joonhyublee.
the class GlassShader method scatterPhoton.
public void scatterPhoton(ShadingState state, Color power) {
Color refr = Color.mul(1 - f0, color);
Color refl = Color.mul(f0, color);
float avgR = refl.getAverage();
float avgT = refr.getAverage();
double rnd = state.getRandom(0, 0, 1);
if (rnd < avgR) {
state.faceforward();
// don't reflect internally
if (state.isBehind()) {
return;
}
// photon is reflected
float cos = state.getCosND();
power.mul(refl).mul(1.0f / avgR);
float dn = 2 * cos;
Vector3 dir = new Vector3();
dir.x = (dn * state.getNormal().x) + state.getRay().getDirection().x;
dir.y = (dn * state.getNormal().y) + state.getRay().getDirection().y;
dir.z = (dn * state.getNormal().z) + state.getRay().getDirection().z;
state.traceReflectionPhoton(new Ray(state.getPoint(), dir), power);
} else if (rnd < avgR + avgT) {
state.faceforward();
// photon is refracted
float cos = state.getCosND();
float neta = state.isBehind() ? eta : 1.0f / eta;
power.mul(refr).mul(1.0f / avgT);
float wK = -neta;
float arg = 1 - (neta * neta * (1 - (cos * cos)));
Vector3 dir = new Vector3();
if (state.isBehind() && absorptionDistance > 0) {
// this ray is inside the object and leaving it
// compute attenuation that occured along the ray
power.mul(Color.mul(-state.getRay().getMax() / absorptionDistance, absorptionColor.copy().opposite()).exp());
}
if (arg < 0) {
// TIR
float dn = 2 * cos;
dir.x = (dn * state.getNormal().x) + state.getRay().getDirection().x;
dir.y = (dn * state.getNormal().y) + state.getRay().getDirection().y;
dir.z = (dn * state.getNormal().z) + state.getRay().getDirection().z;
state.traceReflectionPhoton(new Ray(state.getPoint(), dir), power);
} else {
float nK = (neta * cos) - (float) Math.sqrt(arg);
dir.x = (-wK * state.getRay().dx) + (nK * state.getNormal().x);
dir.y = (-wK * state.getRay().dy) + (nK * state.getNormal().y);
dir.z = (-wK * state.getRay().dz) + (nK * state.getNormal().z);
state.traceRefractionPhoton(new Ray(state.getPoint(), dir), power);
}
}
}
Aggregations