如何从传入矢量和表面法线中找到折射矢量?
How to find refraction vector from incoming vector and surface normal?
我正在 java 中编写光线追踪器,并且正在尝试实现折射,但我对在该主题上找到的信息感到困惑。如果我有入射光线的 3D 矢量、作为 3D 向量给出的表面法线和两种介质的折射率,我需要应用什么操作才能获得透射光线的矢量?
设V_incedence为规范化传入向量。令 n1
和 n2
为两个表面的折射率。您要计算 V_refraction。设 n 为归一化法向量。
V_refraction = r*V_incedence + (rc - sqrt(1-Math.pow(r,2)(1-Math.pow(c,2))))n
where r = n1/n2 and c = -n dot V_incedence.
我在我的 ray java tracer 中实现了这个看看 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))));
}
}
Bram de Greve 写了一篇关于光线追踪中的反射和折射的好文章。你可以找到它 here.
他的实现(C++)是这样的:
Vector refract(const Vector& normal, const Vector& incident,
double n1, double n2)
{
const double n = n1 / n2;
const double cosI = -dot(normal, incident);
const double sinT2 = n * n * (1.0 - cosI * cosI);
if(sinT2 > 1.0) return Vector::invalid; // TIR
const double cosT = sqrt(1.0 - sinT2);
return n * incident + (n * cosI - cosT) * normal;
}
我正在 java 中编写光线追踪器,并且正在尝试实现折射,但我对在该主题上找到的信息感到困惑。如果我有入射光线的 3D 矢量、作为 3D 向量给出的表面法线和两种介质的折射率,我需要应用什么操作才能获得透射光线的矢量?
设V_incedence为规范化传入向量。令 n1
和 n2
为两个表面的折射率。您要计算 V_refraction。设 n 为归一化法向量。
V_refraction = r*V_incedence + (rc - sqrt(1-Math.pow(r,2)(1-Math.pow(c,2))))n
where r = n1/n2 and c = -n dot V_incedence.
我在我的 ray java tracer 中实现了这个看看 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))));
}
}
Bram de Greve 写了一篇关于光线追踪中的反射和折射的好文章。你可以找到它 here.
他的实现(C++)是这样的:
Vector refract(const Vector& normal, const Vector& incident,
double n1, double n2)
{
const double n = n1 / n2;
const double cosI = -dot(normal, incident);
const double sinT2 = n * n * (1.0 - cosI * cosI);
if(sinT2 > 1.0) return Vector::invalid; // TIR
const double cosT = sqrt(1.0 - sinT2);
return n * incident + (n * cosI - cosT) * normal;
}