【问题标题】:Ray tracing vectors光线追踪矢量
【发布时间】:2012-01-16 13:23:27
【问题描述】:

所以前几天我决定写一个光线追踪器,但因为我忘记了所有的矢量数学而被卡住了。 我在屏幕后面有一个点(眼睛/相机,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(或屏幕,如果您需要大刀阔斧的改变)

【问题讨论】:

  • 我认为应该是这样,但我忘记了我所知道的关于向量数学的一切,所以我不太确定。
  • 基本上我想说的是,我应该如何投射光线,因为我认为我可能做错了。
  • @Chris:就像 Nocturn 说的,你将来自眼睛的光线投射到像素中。方向是通过从另一个点中减去一个点来给出的。
  • 我认为我的代码在计算交叉点时可能是错误的,有人可以检查一下吗? (在原帖中)

标签: c++ vector-graphics raytracing


【解决方案1】:

函数中的参数“ray”,

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

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

因此,本地“dist”变量似乎已过时。

【讨论】:

    【解决方案2】:

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

    我查看了您的示例代码,计算确实不正确。这就是你想要的。

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

    本质上,这意味着你拥有这条射线,它有一个起点和方向。您有一个带有点和半径的球体。您使用射线方程并将其代入球体方程并求解 t。 t 是射线原点与球体表面上的交点之间的距离。我认为您的代码不会这样做。

    【讨论】:

      【解决方案3】:

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

      您的相机由向量 frontupright(相互垂直并归一化)和“位置”(眼睛位置)定义。

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

      还有像素的二维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 度),您可能需要将屏幕平面设为球形,并使用不同的公式。

      你将如何进行转换

      矩阵。

      【讨论】:

        猜你喜欢
        • 2013-11-02
        • 2011-10-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-01-08
        • 2019-11-29
        相关资源
        最近更新 更多