2D Raytracer 算法 [英] Algorithm for 2D Raytracer

查看:35
本文介绍了2D Raytracer 算法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

我的问题是,我不知道从哪里开始这整件事.

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

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

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

完成的版本应该看起来像这样:

解决方案

恐怕您提议的那种光线追踪应用程序比使用真正的 3D 光线追踪器更容易误导.

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

我会尝试选择更原生的 2D 光线跟踪用法,例如:

  1. 光学模拟

    这用于模拟镜头和反射镜光学.这张图片来自我的一个古老的 2D 光线追踪模拟:

    1. 存储你的世界

      你有一个多段线 + 衍射指数形式的镜头和镜子也作为多段线.你有世界衍射指数

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

      仅投射重要的或全部投射.使用Snell定律模拟光学

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

    1. 首先将地板和天花板/天空绘制为 2 个半屏(屏幕除以地平线)
    2. 那么你就有了你的迷宫/世界的二维地图(右)

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

    3. 在屏幕上为每个射线命中绘制适当的列(垂直线)

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

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

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

    这里是动画 GIF 示例:

    如果您有兴趣查看此相关 QA:

I want to do a programmatical RayTracer in Java for demo purpose while giving a presentation about Ray Tracing in general (also mentioning 3D, this 2D model should only be for easier understanding, and to train my general Java knowledge).

My problem is, that i dont know where to start this whole thing.

The first thing i would try is to use vectors to trace every pixel on the screen from a given coordinate (eg. the position of my mouse cursor). Then I would calculate if the vector intersects with a polygon and then i would stop the vector there and draw it only to this specific point.

Maybe i could even draw some shadows by calculating the normal and reflect the vector in the other direction with a lower intensity.

So would it be a good idea to draw a vector from A = {everypixelonthescreen} to a specific Point P and calculate the intersections?

The finished version should look somewhat like this:

解决方案

I am afraid that the kind of ray trace app you are proposing is a bit more misleading than to use a real 3D ray-tracer.

  • 2D ray tracers are used a bit differently
  • and this may confuse your audience a lot

I would try to chose a more native 2D ray-trace usage like:

  1. Optic simulation

    This is used to simulate lens and mirrors optics. This image is from one of my ancient 2D ray-trace simulations:

    1. Store your world

      You’ve got a lens in the form of polylines + diffraction index and mirrors also as polylines. You have the world diffraction index

    2. cast R,G,B rays from source of light

      Cast important ones only or all of them. Use Snell's law to simulate optics

    As you can see the chromatic error is visible (each color has its own wavelength so the diffraction index is different). You can also use MultiBand rendering.

    I used this to tune custom optic systems. If you add drag & drop capability you’ve got Optic Lab.

  2. Wolfenstein demo

    This pseudo 3D game used a 2D ray casting engine. See Wiki: Wolfenstein_3D_engine. This image was taken from this link:

    1. first draw the floor and ceiling/sky as 2 half screens (screen divided by horizon)
    2. then you’ve got a 2D map of your maze/world (right)

      So cast rays from your current position in all visible directions (similar to your image but usually a 60 degree view is used). Rays must be done with subpixel (cell) precision. Where your ray hit the wall (on map) obtain the subpixel (cell) position. It indicates which part of wall texture is hit

    3. draw the appropriate column (vertical line) on the screen for each ray hit

      The size and scale of it is determinated by the distance from the ray origin. The fish eye correction is applied — if my memory serves it was done by using only perpendicular distance (multiply distance by cos(ray_angle - player_angle)).

    Here’s an example of what I busted out for fun just now:

    It was done in C++ with pure GDI (using the bitmap scan line only), no other 3th party libs at all. It uses a single texture, diffuse + ambient lighting, 2D raycasting. Has 2 bitmaps (screen, texture-atlas) and a single 2D map. The code is less then 9 KByte including rems. It is controlled by keyboard only (mouse is used to edit the maze in the map subwindow).

    Here animated GIF example:

    If you're interested see this related QA:

这篇关于2D Raytracer 算法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆