光线投射引擎渲染产生轻微的扭曲,朝向屏幕边缘逐渐增加

2023-11-25

我正在为 HTML5 画布开发一个基本的光线投射引擎,该引擎在 Wolfenstein 3D 和 Doom 等游戏中使用,作为学习练习/爱好项目。我已经到了使用纹理映射在画布上渲染墙壁的地步,经过相当多的努力使相交测试功能正确后,效果非常好。

我正在纠正“鱼缸”/“鱼眼”失真效果(由于与屏幕中心的角度增加而导致到交叉点的距离增加),但边缘仍然有非常轻微但明显的弯曲失真屏幕的。如下图所示(我画了红色的直线,让效果更明显):

example of distortion

谁能解释一下这种扭曲的根源是什么?这不是一个大问题,但我一直无法找出原因,所以我显然错过了一些东西,我相信一定有人知道答案。我已经广泛搜索了这个问题,网上没有太多信息,但我确实在论坛帖子中找到了以下片段:

“使用恒定角度增量而不是水平投影引起的扭曲完全是另一回事 - 这是横向拉伸/聚束效果,尽管通常它只是一个几乎不明显的效果(对于合理的 FOV,尽管事实上您可以定义 999999 度的 FOV)应该敲响警钟),除了一开始就做对之外,根本没有任何合理的方法来补偿……使用固定增量的角度是错误的,这就是全部。”

这听起来可能指的是我正在经历的相同失真,但除了表明固定角度增量是问题的根源之外,它没有提供太多帮助或见解(这是一种弯曲的失真,朝着屏幕边缘增加) ,这似乎与这表明的内容相符)。我用来纠正扭曲的函数是:

function m_CorrectRayLengthDistortion( dist, angleFromCentre ){

    return dist * Math.cos( MOD_Maths.degToRad( angleFromCentre ) );
}

MOD_Maths 是一个实用模块(在本例中用于将角度从度数转换为弧度,以便余弦函数可以使用它)。

非常感谢任何有关此问题的帮助,如果有人回答这个问题,鉴于网上明显缺乏有关该主题的信息,它有望为将来遇到该问题的任何人提供指南。

谢谢 :)


我很久以前就正确解决了这个问题,但直到现在才抽出时间来更新答案。我删除了之前不正确的答案(它给出了几乎正确的结果,但通过间接方法,由于我对问题的根本原因缺乏了解)。

正如 Sam 在之前的评论中提到的,问题的根本原因是,如果您想实现等距列(这对于渲染结果看起来不失真是必要的),固定角度增量实际上是不正确的。这个在论坛帖子里提到过here,但是尽管我发现了这一点,但直到很久以后我才完全理解为什么会出现这种情况,或者如何解决这个问题。

为了在屏幕上实现等距的列,按理说,每条光线必须从视点出发并穿过沿投影表面等距分布的像素,这意味着随着光线远离投影面的中心像素,在屏幕上,与观看方向的角度增加的增量逐渐变小。下图说明了这一点(抱歉,这不完全是一件艺术品):

diagram

对于较小的视场,问题不是很明显,但随着视场的增加,问题变得更加严重(在我的图中,视场相当大,可以清楚地说明问题)。为了正确计算光线角度增量,必须使用以下过程:

Where:

ang = ray angle from the look direction, whose ray passes through the central x coordinate of the screen;
opp = opposite side (equivalent to the distance of the screen X coordinate through which the ray passes from the screen X coordinate of the central pixel);
adj = adjacent side (equivalent to the distance from the point of view to the projection surface, which will be predetermined in code somewhere);

我们可以使用以下公式(为了清楚起见,包括推导):

tan( ang ) = opp / adj
ang = atan( opp / adj )
ang = atan( ( pixel x coord - half screen width ) / dist to projection surface )

我的引擎中的 Javascript 代码示例:

for( var x = 0; x < canvasSizeX; x++ ){

    var xAng = _atan( ( x - canvasSizeHalfX ) / m_DistToProjSurf );
    xRayAngles.push( xAng );
}

由于在线提供的有关光线投射引擎的信息有些稀缺,而且由于任何主要教程都没有明确涵盖这个特定问题,我想用正确的内容更新这篇文章信息以防其他人遇到与我相同的问题并且不明白原因。希望这会对某人有所帮助。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

光线投射引擎渲染产生轻微的扭曲,朝向屏幕边缘逐渐增加 的相关文章

  • 尝试使用掩码裁剪位图会抛出 IllegalArgumentException:

    我正在使用以下代码 public void cropSelection Bitmap bitmap annotationBitmap copy annotationBitmap getConfig true Canvas canvas ne
  • 反转二进制网络

    如何反转二元方程 以便找到哪些输入将产生给定的输出 Example Inputs i0 through i8 Outputs o0 through o8 Operators XOR AND 二元方程 1 i0 1 i1 0 i2 1 i3
  • 小数除以小数并得到零

    为什么当我这样做时 select CAST 1 AS DECIMAL 38 28 CAST 1625625 AS DECIMAL 38 28 我得到 0 吗 但是当我得到 0 时 select CAST 1 AS DECIMAL 20 10
  • 如何在画布中旋转图表同时保持数字垂直?

    我正在尝试围绕其中心旋转画布中的图表 同时保持字母直立 我正在尝试使用 ctx rotate 但它使用画布的左侧作为中心来旋转整个图表 以下链接提供了视觉效果 我希望它看起来像绿色 而不是红色 就像我的代码当前所做的那样 视觉解释 http
  • 是否可以像 html 视频元素一样将流作为源添加到 html canvas 元素?

    根据MDN The HTMLMediaElement https developer mozilla org en US docs Web API HTMLMediaElement界面添加到HTMLElement属性 支持基本媒体相关功能所
  • 在 C# 中存储矩阵值的快速且有用的方法

    我需要用 C 为 3D 引擎创建一个 4x4 矩阵类 我见过一些其他引擎将矩阵值存储在单个浮点成员变量 字段中 如下所示 float m11 m12 m13 m14 float m21 m22 m23 m24 float m31 m32 m
  • SVG 在 Firefox 中渲染得很糟糕

    我正在制作带有滑动轮播的信息图表 li 我认为 尽管 FF 中 SVG 的错误已得到解决 但 SVG 在 Firefox 中显示为像素化 有人能看到这个问题的解决办法吗 URL http weaver wp weavertest com r
  • 如何在 html 5 画布上旋转单个对象?

    我试图弄清楚如何在 html 5 画布上旋转单个对象 例如 http screencast com t NTQ5M2E3Mzct http screencast com t NTQ5M2E3Mzct 我希望每一张卡都能以不同的角度旋转 到目
  • onScale 和 Canvas - 缩放图像后如何调整原点?

    我有一个非常简单的测试应用程序 带有自定义组件MyView java https github com afarber android newbie blob master TestScroll src de afarber testscr
  • 数学 - 映射数字

    如何将 a 和 b 之间的数字线性映射到 c 和 d 之间 也就是说 我希望 2 到 6 之间的数字映射到 10 到 20 之间的数字 但我需要广义的情况 我的脑子炸了 如果您的数字 X 位于 A 和 B 之间 并且您希望 Y 位于 C 和
  • 如何在 Mac 的任何 webkit 中隐藏父圆角的画布内容?

    我有一个父母div带有圆角 其中包含canvas div div
  • 获取 byte[]

    我有一个 html 画布 如下所示 output is a base64string of image data var oldImage new Image oldImage onload function var resizeRatio
  • IE9-11 检测变换样式:preserve-3d

    我为一个项目制作了一个 3d 类型的菜单 自然 IE 会引起问题 因为 IE10 即使 3d 变换工作 也不支持变换样式 preserve 3d 我尝试了解决方法 通过对 3d 菜单容器的每个子元素应用变换 但至少可以说 动画看起来很糟糕
  • 计算两点之间的最短路线

    过去几周我一直在开发一款多人 HTML5 游戏 使用nodejs and websockets 我已经被这个问题困扰了一段时间 想象一下 我用数组实现了这个平铺地图 如下所示 1 or 棕色瓷砖 路上有障碍物 玩家无法通过 0 or 绿色瓷
  • C++ 中求幂的函数是什么?

    如何计算一个数的幂 2 1 2 2 2 3 etc cmath 库中的 pow 更多信息here http en cppreference com w cpp numeric math pow 别忘了放 include
  • 在 JavaScript 函数中加载图像

    我有获取图像像素颜色的功能 function getImage imgsrc var img img src imgsrc var imageMap new Object img load function var canvas
  • 将文本大小调整为矩形 在 Canvas HTML5 中调整大小

    我是 Canvas 新手 我正在创建一个网站 以在调整矩形大小时增加文本 我尝试了很多 但没有任何效果 实际上 我希望如果我仅按其宽度调整矩形大小 向左拉伸 向右拉伸 则仅应增加文本宽度而不是字体大小 我已经完成了字体大小 但发现增加孤立文
  • 如何在画布上所有其他内容后面绘制图像? [复制]

    这个问题在这里已经有答案了 我有一块画布 我想用drawImage在画布上当前内容后面绘制图像 由于画布上已经有内容 我正在使用字面上的画布来创建包含图像的画布 因此我无法真正先绘制图像 所以我无法使用drawImage在我呈现其余内容之前
  • CGPoint 标量乘法 Swift

    我正在 SpriteKit 中构建一个平台游戏 并将为我的实体实现更新功能 以便它们根据重力和速度移动 但是 我需要使添加的速度量与增量时间成比例 以防止帧速率影响我的实体的移动方式 因此我将导入 GLKit 以便我可以使用标量函数 但是
  • WPF画布性能-children.add调用多次

    我在长画布上绘制了很多线条 想想条形图 并对其性能进行了相当好的调整 使用低级几何类并冻结它们等 这极大地提高了性能 但仍然需要几秒钟将几千个项目加载到画布中 我对应用程序进行了性能分析 看起来每次调用都花费了很大一部分时间canvas c

随机推荐

  • 表单验证 - 我收到标签两次

    我有一个注册表单 来自 FOSUserBundle 它位于模板中 form theme form AcmeMyBundle Form errors html twig
  • 无法在脚本中导入导入日期时间[重复]

    这个问题在这里已经有答案了 我无法从 python 脚本导入日期时间 但可以从终端命令行导入 1 import datetime 2 From datetime import datetime month datetime datetime
  • java8数组流到二维数组

    我是 Java8 的新手 无法使用流将一个数组映射到另一个二维数组 我有一个二维数组 它是一种模式 boolean pattern true true false true false true false true true 第二个数组包
  • 未知类型名称 __m256 - AVX 的英特尔内在函数无法识别?

    我正在尝试测试一些英特尔内部函数 看看它们是如何工作的 因此 我创建了一个函数来为我执行此操作 这是代码 void test intel 256 m256 res vec1 vec2 M256 MM SET PS vec1 7 0 7 0
  • Python tkinter 禁用按钮直到所有字段都被填充

    假设我在 tkinter 中有 2 个条目小部件 1 个选项菜单 下拉列表 和 1 个按钮 在用户填充所有 3 个小部件之前 如何将按钮小部件状态设置为 禁用 这就是我当前所拥有的 import Tkinter as tk root tk
  • 颤振删除应用栏上的后退按钮

    我想知道是否有人知道如何删除显示在屏幕上的后退按钮appBar当您使用 flutter 应用程序时Navigator pushNamed转到另一个页面 我不希望它出现在这个结果页面上的原因是它来自导航 我希望用户使用logout按钮 以便会
  • Spring Data Mongodb批量操作示例

    有人可以给我指点 Spring Data Mongodb DB 批量操作示例的完整示例吗 我正在尝试使用 spring data mongodb 切换到批量更新 无法找到一个好的例子 谢谢 Spring data mongodb 中的 Bu
  • Javascript - 跟踪鼠标位置

    我希望每 t 毫秒定期跟踪鼠标光标的位置 所以本质上 当页面加载时 这个跟踪器应该启动并且 比如说 每 100 毫秒 我应该获取 posX 和 posY 的新值并将其打印在表单中 我尝试了以下代码 但值没有刷新 只有 posX 和 posY
  • 了解 Xcode 中的 Instruments,测试泄漏

    我刚刚开始使用 Instruments 这是一个很好的小工具 用于测试内存分配 泄漏以及所有这些很棒的东西 但我对它的工作原理感到非常困惑 我寻找过解释如何使用它的教程 但没有教程解释如何使用它 我将尝试解释这一点 我将其设置为每当我运行
  • 无法从本地计算机连接到 Google 计算引擎上的 kafka 服务器

    我正在谷歌计算引擎上运行我的动物园管理员和卡夫卡服务器 两者都在默认端口上运行 zookeeper 在 2181 上 kafka 在 9092 上 两者都在同一个实例上运行 我也打开了这两个端口 在我的 server properties
  • 在 Maven 中配置 hibernate-jpamodelgen

    我要配置hibernate jpamodelgen进入Mavenpom xml 我试过这个
  • C++ 声明中的“&”有什么作用?

    我是一个 C 人员 我正在尝试理解一些 C 代码 我有以下函数声明 int foo const string myname cout lt lt called foo for lt lt myname lt lt endl return 0
  • Rails 4 Devise 3.1.1 Devise::RegistrationsController#new 中的 ActionController::UnknownFormat

    我正在开发一个 Rails 4 应用程序 使用 Devise 3 1 1 进行用户身份验证 当我单击 users sign up user 链接时 Rails 抛出以下异常 ActionController UnknownFormat in
  • 将发送的短信写入 content://sms/sent 表

    我正在开发一个 android 短信应用程序 我可以使用以下代码向单个联系人发送短信 sms sendTextMessage phoneNumber null message sentPI deliveredPI 现在我想向多重联系人发送短
  • Kibana 直方图 - 在单个图表上绘制多个系列

    我在 Elasticsearch 中有一个索引 其中包含一个简单对象数组 键值请参见下面的示例 这些文档有时间戳 我可以在 Kibana 中为每个键值创建单独的直方图 即一个图表用于 bytes sent 另一个图表用于 bytes rec
  • Angular 2 的 JSPM 与 WebPack

    最近我在我的 Angular 2 项目中使用了 JSPM 发现它使用起来非常简单和方便 无论是添加新模块还是创建用于生产的捆绑包 基本上就是 jspm install npm angular somepackage package json
  • 在 Web 应用程序中显示 PDF

    我已经用谷歌搜索了这个 搜索了这个 浏览了SO和其他网站 我已经尝试阅读这个问题几个小时了 但我似乎仍然找不到一个令人满意的解决方案来解决这个看似简单的问题 常见的编程问题 让我来设定一下场景 我有一个网站 Web 应用程序 允许用户搜索
  • python opencv imwrite ...找不到参数

    我正在使用 opencv 和 python 我想做一个 cv2 imwrite cv2 imwrite myimage png my im 唯一的问题是 opencv 无法识别 params 常量 cv2 imwrite myimage p
  • 使用内置“crypto”在nodejs中进行密码散列

    仅使用内置函数在 Node js 中实现密码哈希和验证的最佳方法是什么crypto模块 基本上需要什么 function passwordHash password gt passwordHash function passwordVeri
  • 光线投射引擎渲染产生轻微的扭曲,朝向屏幕边缘逐渐增加

    我正在为 HTML5 画布开发一个基本的光线投射引擎 该引擎在 Wolfenstein 3D 和 Doom 等游戏中使用 作为学习练习 爱好项目 我已经到了使用纹理映射在画布上渲染墙壁的地步 经过相当多的努力使相交测试功能正确后 效果非常好