Я пишу трассировщик лучей в java, и я пытаюсь реализовать преломление, но меня смущает информация, которую я нахожу на эту тему. Если у меня есть 3D-вектор для входящего луча света, нормальная поверхность, заданная как 3D-вектор, и показатели преломления двух сред, какие операции мне нужно применить, чтобы получить вектор проходящего луча?Как найти преломляющий вектор от входящего вектора и поверхности нормальный
ответ
V_incedence быть нормализованным входящим вектором. Пусть n1
и n2
являются показателями преломления двух поверхностей. Вы хотите рассчитать V_refraction. Пусть n - нормализованный нормальный вектор.
V_refraction = r*V_incedence + (rc - sqrt(1-r^2(1-c^2)))n
where r = n1/n2 and c = -n dot V_incedence.
Спасибо за ответ. В первой строке это означает добавление вектора V_incedence.multiply (r) с вектором n.multiply (rc - sqrt (1-r^2 (1-c^2)))? – user2320239
Да, точно. –
Я реализовал это в моем луче Java трассера гляньте https://github.com/bradforj287/brads-java-raytracer
private static double clamp(final double val, final double min, final double max) {
return Math.max(min, Math.min(max, val));
}
private Vector3d getRefractionVector(final Vector3d I, final Vector3d N, final double ior) {
double cosi = clamp(-1, 1, I.dot(N));
double etai = 1, etat = ior;
Vector3d n = N;
if (cosi < 0) {
cosi = -cosi;
} else {
double temp = etai;
etai = etat;
etat = temp;
n = N.multiply(-1);
}
double eta = etai/etat;
double k = 1 - (eta * eta) * (1 - (cosi * cosi));
if (k <= 0) {
return Vector3d.ZERO;
} else {
return I.multiply(eta).add(n.multiply(((eta * cosi) - Math.sqrt(k))));
}
}
http://en.wikipedia.org/wiki/Snell%27s_law#Vector_form –