算法四 May 作者

Algorithm for 2D Raytracer

我想在 Java 中做一个程序化的 RayTracer 用于演示目的,同时给出关于光线追踪的一般介绍(也提到 3D,这个 2D 模型应该只是为了更容易理解,并且训练我的一般 Java 知识)。

我的问题是,我不知道从哪里开始。

我要尝试的第一件事是使用向量从给定坐标(例如鼠标光标的位置)追踪屏幕上的每个像素。然后我会计算矢量是否与多边形相交,然后我会在那里停止矢量并仅将其绘制到这个特定点。

也许我什至可以通过计算法线来绘制一些阴影,并以较低的强度在另一个方向反射矢量。

那么从 A = {everypixelonthescreen} 到特定的 Point P 绘制一个向量并计算交点是个好主意吗?

完成后的版本应该是这样的:

据我了解,这个问题的处理方式会有所不同。给定某个位置(鼠标的当前位置或类似的东西),将从那里在某个给定角度的范围内跟踪环境(例如 90 度,在您的图片中看起来像 360 度)。在所需的角度分辨率中,来自初始位置的光线与上述多边形相交。渲染最近的交点。这种方法应该渲染距离给定位置 'visible' 的点。

恐怕您提出的那种光线追踪应用程序比使用真正的 3D 更具误导性 ray-tracer。

  • 2D 光线追踪器的使用方式略有不同
  • 这可能会让您的听众感到困惑

我会尝试选择更原生的 2D ray-trace 用法,例如:

  1. 光学仿真

    这用于模拟镜头和反射镜光学。此图像来自我的一个古老的 2D ray-trace 模拟:

    1. 储存你的世界

      你有一个折线+衍射指数形式的镜头和折线形式的镜子。你有世界绕射指数

    2. 从光源投射 R、G、B 光线

      仅投射重要的或全部投射。使用斯涅尔定律模拟光学

    如您所见,色差是可见的(每种颜色都有自己的波长,因此衍射指数不同)。您也可以使用 MultiBand rendering.

    我用它来调整自定义光学系统。如果您添加 drag & drop 功能,您将获得 Optic Lab

  2. 德军总部演示

    这款伪 3D 游戏使用了 2D 光线投射引擎。参见 Wiki: Wolfenstein_3D_engine。此图片取自 link:

    1. 先把地板和ceiling/sky画成2个半屏(屏幕除以horizon)
    2. 那么你就有了你的 maze/world 的二维地图(右)

      因此从您当前位置向所有可见方向投射光线(类似于您的图像,但通常使用 60 度视图)。光线必须以亚像素(单元)精度完成。在您的光线击中墙壁(在地图上)的位置获得子像素(单元格)位置。它表示被击中的墙体纹理

    3. 在屏幕上为每条光线绘制适当的列(垂直线)

      它的大小和比例由到光线原点的距离决定。应用了鱼眼校正——如果我没记错的话,它是通过仅使用垂直距离(将距离乘以 cos(ray_angle - player_angle))完成的。

    这是我刚才为了好玩而搞砸的一个例子:

    它是在 C++ 中使用纯 GDI(仅使用位图扫描线)完成的,根本没有其他第 3 方库。它使用单一纹理、漫反射+环境照明、2D 光线投射。有 2 个位图(屏幕,texture-atlas)和一个 2D 地图。代码小于 9 KB,包括 rems。它仅由键盘控制(鼠标用于在地图子窗口中编辑迷宫)。

    这里是动画GIF例子:

    如果您有兴趣,请参阅此相关 QA: