所以我前几天决定写一个光线追踪器,但是因为忘记了所有的矢量数学而陷入困境。 我在屏幕后面有一个点(眼睛/摄像头,400,300,-1000),然后是屏幕上的一个点(一个平面,从0,0,0到800,600,0),我刚刚得到使用我正在寻找的当前像素的x和y值(使用SFML进行渲染,所以它类似于267,409,0)
问题是,我不知道如何正确地投射光线。我正在使用它来测试球体交集(C ++):
bool SphereCheck(Ray& ray, Sphere& sphere, float& t)
{ //operator * between 2 vec3s is a dot product
Vec3 dist = ray.start - sphere.pos; //both vec3s
float B = -1 * (ray.dir * dist);
float D = B*B - dist * dist + sphere.radius * sphere.radius; //radius is float
if(D < 0.0f)
return false;
float t0 = B - sqrtf(D);
float t1 = B + sqrtf(D);
bool ret = false;
if((t0 > 0.1f) && (t0 < t))
{
t = t0;
ret = true;
}
if((t1 > 0.1f) && (t1 < t))
{
t = t1;
ret = true;
}
return ret;
}
所以我知道光线的起点是眼睛的位置,但方向是什么?
或者,如果失败了,有没有更好的方法呢?我听说有些人使用光线开始为(x,y,-1000),方向为(0,0,1),但我不知道它是如何工作的。
另一方面,您将如何进行转换?我假设要改变摄像机角度你只需调整摄像机的x和y(或者如果你需要进行剧烈的改变就可以调整屏幕)
答案 0 :(得分:1)
函数中的参数“ray”,
bool SphereCheck(Ray& ray, Sphere& sphere, float& t)
{
...
}
应该已经包含方向信息,您需要检查光线是否与球体相交。 (传入的“ray”参数是摄像机点和光线发送像素之间的向量。)
因此,本地“dist”变量似乎已过时。
答案 1 :(得分:0)
我可以看到的一件事是,当你创建光线时,你并没有使用屏幕中每个像素的中心作为构建方向向量的点。您不希望仅使用网格上的(x,y)坐标来构建这些向量。
我查看了您的示例代码,但计算确实不正确。这就是你想要的。
http://www.csee.umbc.edu/~olano/435f02/ray-sphere.html(我在大学读过这门课程,这家伙知道他的东西)
基本上它意味着你有这条射线,它有一个起源和方向。你有一个带有点和半径的球体。您使用射线方程并将其插入球体方程并求解t。 t是射线原点与球体表面上的交叉点之间的距离。我不认为你的代码会这样做。
答案 2 :(得分:0)
所以我知道光线的起点是眼睛的位置,但方向是什么?
您的相机由矢量front
,up
和right
(彼此垂直且标准化)和“位置”(眼睛位置)定义。
您还有width
和height
视口(像素),垂直视野(vfov
)和水平视野(hfov
),以度或弧度为单位。
还有像素的2D x
和y
坐标。 X轴(2D)指向右侧,Y轴(2D)指向下方。
对于平面光线,可以这样计算:
startVector = eyePos;
endVector = startVector
+ front
+ right * tan(hfov/2) * (((x + 0.5)/width)*2.0 - 1.0)
+ up * tan(vfov/2) * (1.0 - ((y + 0.5f)/height)*2.0);
rayStart = startVector;
rayDir = normalize(endVector - startVector);
假设屏幕平面。对于极端视角(fov> = 180度),您可能希望使屏幕平面呈球形,并使用不同的公式。
你将如何进行转型
矩阵