光线跟踪矢量

Ray tracing vectors

本文关键字:光线跟踪      更新时间:2023-10-16

所以前几天我决定写一个光线跟踪器,但我被卡住了,因为我忘记了所有的矢量数学。我有一个点在屏幕后面(眼睛/相机,400300,-1000),然后是屏幕上的一个点(一个平面,从0,0,0到800600,0),我只是通过使用我正在寻找的当前像素的x和y值(使用SFML进行渲染,所以它有点像267409,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(如果需要大幅更改,则调整屏幕)

函数中的参数"ray",

bool SphereCheck(Ray& ray, Sphere& sphere, float& t)
{
    ...
}

应该已经包含方向信息,并且使用此方向需要检查光线是否与球体相交。(传入的"射线"参数是相机点和发送射线的像素之间的矢量。)

因此,局部"dist"变量似乎已过时。

我可以看到的一件事是,当您创建射线时,您没有使用屏幕中每个像素的中心作为构建方向向量的点。您不希望仅使用网格上的(x,y)坐标来构建这些向量。

我看过你的示例代码,计算结果确实不正确。这就是你想要的。

http://www.csee.umbc.edu/~olano/435f02/ray-sphere.html(我在大学里学过这门课,这家伙知道他的东西)

本质上,这意味着你有一条光线,它有一个原点和方向。你有一个有一个点和一个半径的球体。使用射线方程并将其插入球体方程中,然后求解t。t是射线原点和球体曲面上的交点之间的距离。我不认为你的代码能做到这一点。

所以我知道光线的起点是眼睛的位置,但方向是什么?

相机由向量frontupright(彼此垂直并归一化)和"位置"(眼睛位置)定义。

您还有视口(像素)的widthheight、垂直视场(vfov)和水平视场(hfov)(以度或弧度为单位)。

还有像素的2D xy坐标。X轴(2D)指向右侧,Y轴(二维)指向下方。

对于平面屏幕,射线可以这样计算:

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度),您可能希望使屏幕平面为球形,并使用不同的公式。

你将如何转换

矩阵。