Vector3 n = x.getNormal();
if (n.dot(v) > 0.0) {
return null;
}
Color d = diffuse.getColor(x, lambda);
Color s = specular.getColor(x, lambda);
double davg = ColorUtil.getMeanChannelValue(d);
double savg = ColorUtil.getMeanChannelValue(s);
double total = davg + savg;
Basis3 basis = x.getShadingBasis();
Vector3 out;
if (RandomUtil.bernoulli(davg / total, rj)) { // diffuse
do {
out = RandomUtil.diffuse(ru, rv).toCartesian(basis);
} while (n.dot(out) <= 0.0);
} else { // specular
do {
SphericalCoordinates sc = new SphericalCoordinates(
Math.atan(alpha * Math.sqrt(-Math.log(1.0 - ru))),
2.0 * Math.PI * rv);
Vector3 h = sc.toCartesian(basis);
out = Optics.reflect(v, h);
} while (n.dot(out) <= 0.0);
}
Ray3 ray = new Ray3(x.getPosition(), out);
double pdf = getScatteringPDF(x, v, out, true, lambda);
Color value = bsdf(x, v, out, lambda).divide(pdf);
return ScatteredRay.diffuse(ray, value, pdf);
}