我有一个可用的光线追踪器(使用 gl-matrix 在 Node 中编写) 它与球体配合得很好,但现在我添加通用矩阵变换(平移、旋转、缩放)以支持其他对象类型。
每个对象有两个变换矩阵,一个是世界到对象的逆矩阵,称为
trans
,另一个是 transFwd
,使用 fromRotationTranslationScale 设置
// Here pos is center of sphere and r is radius
mat4.fromRotationTranslationScale(this.transFwd, rotation, [pos[0], pos[1], pos[2]], [r, r, r]);
mat4.invert(this.trans, this.transFwd);
我使用
trans
变换将所有光线变换到对象空间,计算关于原点的光线与对象交集(t 的值),球体半径为 1。
挑战是在计算t之后,使用我的交集和法线。当我在变换中添加任何类型的旋转时,它们都会变形
// ray has already been transformed to object space
// getPoint simply returns ray.pos + t * ray.dir
let intersect: vec4 = ray.getPoint(t);
let normal: vec4 = vec4.sub(vec4.create(), i, [0, 0, 0, 1]);
vec4.normalize(n, n);
// move intersect back to world space
vec4.transformMat4(intersect, intersect, this.transFwd);
为对象使用变换矩阵时处理法线的正确方法是什么?之后我尝试转换回世界空间,我尝试在将交叉点移回后计算法线,但没有任何效果!
我已经成功解决了这个问题。我走在正确的道路上,只是我没有改变我的法线和反射光线,所以它看起来仍然很奇怪。光线追踪的困难之处在于您唯一可以做的测试是通过“目视检查”
这是我在对象空间中的球体的工作交集代码的摘要
// Intersection in object space
let intersect: vec4 = ray.getPoint(t);
// Normal is pointing from center of sphere (0,0,0) to intersect (i)
// Divide by sphere radius
vec4.div(normal, intersect, [radius, radius, radius, 1]);
n[3] = 0;
// Move i back to world space
vec4.transformMat4(intersect, intersect, transFwd);
// Reflected ray about the normal, & move to world
let reflect: vec4 = ray.reflect(normal);
vec4.transformMat4(reflect, r, transFwd);
vec4.normalize(reflect, reflect);
// Move normal into world & normalize
vec4.transformMat4(normal, normal, transFwd);
vec4.normalize(normal, normal);