Point3 p = x.getPosition();
Medium medium = x.getAmbientMedium();
Color n1 = medium.refractiveIndex(p, lambda);
Color k1 = medium.extinctionIndex(p, lambda);
Color n2 = refractiveIndex.sample(lambda);
Vector3 normal = x.getShadingNormal();
boolean fromSide = x.getNormal().dot(v) < 0.0;
Color R = MaterialUtil.reflectance(v, n1, k1, n2, null, normal);
Color T = cm.getWhite(lambda).minus(R);
double r = ColorUtil.getMeanChannelValue(R);
if (RandomUtil.bernoulli(r, rj)) {
Vector3 out = Optics.reflect(v, normal);
boolean toSide = x.getNormal().dot(out) >= 0.0;
if (fromSide == toSide) {
return ScatteredRay.specular(new Ray3(p, out), R.divide(r), r);
}
} else {
if (false && disperse) {
// for (int i = 0, channels = cm.getNumChannels(); i < channels; i++) {
// Complex eta1 = new Complex(n1.getValue(i), k1.getValue(i));
// Complex eta2 = new Complex(n2.getValue(i));
// Vector3 out = Optics.refract(v, eta1, eta2, normal);
// boolean toSide = x.getNormal().dot(out) >= 0.0;
//
// if (fromSide != toSide) {
// recorder.add(ScatteredRay.transmitSpecular(new Ray3(p, out), T.disperse(i), 1.0));
// }
// }
} else { // !disperse
double n1avg = ColorUtil.getMeanChannelValue(n1);
double k1avg = ColorUtil.getMeanChannelValue(k1);
double n2avg = ColorUtil.getMeanChannelValue(n2);
Complex eta1 = new Complex(n1avg, k1avg);
Complex eta2 = new Complex(n2avg);
Vector3 out = Optics.refract(v, eta1, eta2, normal);
boolean toSide = x.getNormal().dot(out) >= 0.0;
if (fromSide != toSide) {
return ScatteredRay.transmitSpecular(new Ray3(p, out), T.divide(1 - r), 1 - r);
}