光线跟踪向量

时间:2012-01-16 13:23:27

标签: c++ vector-graphics raytracing

所以我前几天决定写一个光线追踪器,但是因为忘记了所有的矢量数学而陷入困境。 我在屏幕后面有一个点(眼睛/摄像头,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(或者如果你需要进行剧烈的改变就可以调整屏幕)

3 个答案:

答案 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)

  

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

您的相机由矢量frontupright(彼此垂直且标准化)和“位置”(眼睛位置)定义。

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

还有像素的2D xy坐标。 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度),您可能希望使屏幕平面呈球形,并使用不同的公式。

  

你将如何进行转型

矩阵