GLSL Sphere——射线相交几何求解
GLSL Sphere - ray intersection geometric solution
我正在尝试在 GLSL 中实现球面射线相交,包括几何和解析解。我在解决 geom 问题时遇到了问题,它应该与我 return true or false:
的方式有关
bool hitSphere(Ray ray, Sphere sphere, float t_min, float t_max, out float t_out) {
// Geometric solution
float R2 = sphere.radius * sphere.radius;
vec3 L = sphere.position - ray.origin;
float tca = dot(L, normalize(ray.direction));
// if(tca < 0) return false;
float D2 = dot(L, L) - tca * tca;
if(D2 > R2) return false;
float thc = sqrt(R2 - D2);
float t0 = tca - thc;
float t1 = tca + thc;
if(t0 < t_max && t0 > t_min) {
t_out = t0;
return true;
}
if(t1 < t_max && t1 > t_min) {
t_out = t1;
return true;
}
return false;
}
我认为问题在于我如何处理 none 的 t0 和 t1,一个或两个交集案例。
编辑:有效的分析版本:
vec3 oc = ray.origin - sphere.position;
float a = dot(ray.direction, ray.direction);
float b = dot(oc, ray.direction);
float c = dot(oc, oc) - sphere.radius * sphere.radius;
float discriminant = b * b - a * c;
if (discriminant > 0.0f) {
if(b > 0)
t_out = (-b + sqrt(discriminant)) / a;
else
t_out = (-b - sqrt(discriminant)) / a;
if(t_out < t_max && t_out > t_min) {
return true;
}
}
return false;
问题是由 t_out
引起的。该算法必须以这种方式计算 t_out
,即 X
是射线与球体表面的交点,因为:
X = ray.origin + ray.direction * t_out;
在工作算法中t_out
取决于ray.direction
的长度。 t_out
变小,如果向量的大小 ray.direction
更大。
在不起作用的算法中,ray.direction
被归一化。
float tca = dot(L, normalize(ray.direction));
因此,t_out
是针对光线方向长度 1 计算的。实际上,您计算的是 t_out'
,其中 t_out' = t_out * length(ray.direction)
.
将t0
分别t1
除以ray.direction
的长度:
bool hitSphere_2(Ray ray, Sphere sphere, float t_min, float t_max, out float t_out)
{
float R2 = sphere.radius * sphere.radius;
vec3 L = sphere.position - ray.origin;
float tca = dot(L, normalize(ray.direction));
// if(tca < 0) return false;
float D2 = dot(L, L) - tca * tca;
if(D2 > R2) return false;
float thc = sqrt(R2 - D2);
float t0 = tca - thc;
float t1 = tca + thc;
if (t0 < t_max && t0 > t_min) {
t_out = t0 / length(ray.direction); // <---
return true;
}
if (t1 < t_max && t1 > t_min) {
t_out = t1 / length(ray.direction); // <---
return true;
}
return false;
}
我正在尝试在 GLSL 中实现球面射线相交,包括几何和解析解。我在解决 geom 问题时遇到了问题,它应该与我 return true or false:
的方式有关bool hitSphere(Ray ray, Sphere sphere, float t_min, float t_max, out float t_out) {
// Geometric solution
float R2 = sphere.radius * sphere.radius;
vec3 L = sphere.position - ray.origin;
float tca = dot(L, normalize(ray.direction));
// if(tca < 0) return false;
float D2 = dot(L, L) - tca * tca;
if(D2 > R2) return false;
float thc = sqrt(R2 - D2);
float t0 = tca - thc;
float t1 = tca + thc;
if(t0 < t_max && t0 > t_min) {
t_out = t0;
return true;
}
if(t1 < t_max && t1 > t_min) {
t_out = t1;
return true;
}
return false;
}
我认为问题在于我如何处理 none 的 t0 和 t1,一个或两个交集案例。
编辑:有效的分析版本:
vec3 oc = ray.origin - sphere.position;
float a = dot(ray.direction, ray.direction);
float b = dot(oc, ray.direction);
float c = dot(oc, oc) - sphere.radius * sphere.radius;
float discriminant = b * b - a * c;
if (discriminant > 0.0f) {
if(b > 0)
t_out = (-b + sqrt(discriminant)) / a;
else
t_out = (-b - sqrt(discriminant)) / a;
if(t_out < t_max && t_out > t_min) {
return true;
}
}
return false;
问题是由 t_out
引起的。该算法必须以这种方式计算 t_out
,即 X
是射线与球体表面的交点,因为:
X = ray.origin + ray.direction * t_out;
在工作算法中t_out
取决于ray.direction
的长度。 t_out
变小,如果向量的大小 ray.direction
更大。
在不起作用的算法中,ray.direction
被归一化。
float tca = dot(L, normalize(ray.direction));
因此,t_out
是针对光线方向长度 1 计算的。实际上,您计算的是 t_out'
,其中 t_out' = t_out * length(ray.direction)
.
将t0
分别t1
除以ray.direction
的长度:
bool hitSphere_2(Ray ray, Sphere sphere, float t_min, float t_max, out float t_out)
{
float R2 = sphere.radius * sphere.radius;
vec3 L = sphere.position - ray.origin;
float tca = dot(L, normalize(ray.direction));
// if(tca < 0) return false;
float D2 = dot(L, L) - tca * tca;
if(D2 > R2) return false;
float thc = sqrt(R2 - D2);
float t0 = tca - thc;
float t1 = tca + thc;
if (t0 < t_max && t0 > t_min) {
t_out = t0 / length(ray.direction); // <---
return true;
}
if (t1 < t_max && t1 > t_min) {
t_out = t1 / length(ray.direction); // <---
return true;
}
return false;
}