光线投射引擎渲染会导致轻微失真,并向屏幕边缘增加 [英] Raycasting engine rendering creating slight distortion increasing towards edges of screen

查看:132
本文介绍了光线投射引擎渲染会导致轻微失真,并向屏幕边缘增加的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为HTML5画布开发一个基本的光线投射引擎,作为学习练习/爱好项目,该引擎用于诸如Wolfenstein 3D和Doom之类的游戏.我已经到了要在画布上使用纹理贴图渲染墙壁的位置,经过大量的工作才能正确完成交点测试功能,该效果很好.

I'm developing a basic raycasting engine for HTML5 canvas, of the variety used in games like Wolfenstein 3D and Doom, as a learning exercise / hobby project. I've got to the point where I have walls rendering on the canvas with texture mapping, which is working pretty well after a fair bit of effort getting the intersection testing functions right.

我正在校正鱼缸"/鱼眼"变形效果(由于与屏幕中心的夹角增加而导致到相交点的距离增加),但是我仍然有非常轻微但明显的弯曲变形在屏幕的边缘.可以在下图中看到(我画了红色的直线以使效果更明显):

I am correcting for the "fishbowl" / "fisheye" distortion effect (caused by increasing distances to intersection points as the angle from the centre of the screen increases), but I still have a very slight, but noticeable, curved distortion at the edges of the screen. This can be seen in the following image (I have drawn straight red lines to make the effect more obvious):

任何人都可以阐明这种失真的根源吗?这不是一个大问题,但是我无法找出原因,因此我显然缺少了一些东西,而且我敢肯定有人必须知道答案.我已经对问题进行了广泛的搜索,并且在线上没有太多信息,但是我确实在论坛帖子中找到了以下代码段:

Can anyone shed light on what the source of this distortion is? It's not a huge issue but I haven't been able to figure out the cause, so I'm clearly missing something and I'm sure someone must know the answer. I've searched the problem pretty extensively and there isn't much information online, but I did find the following snippet in a forum post:

使用恒定角度增量而不是地平线投影而引起的翘曲完全是另一回事-这就是横向拉伸/聚束效果,尽管通常情况下,这只是勉强可以察觉的效果(对于合理的FOV,尽管您可以定义一个999999度的视场角应该会响起钟声),除了正确地开始以外,根本没有任何合理的方法可以补偿..使用固定的增量来确定角度是错误的,仅此而已."

"The warping caused by using constant angular increments instead of horizon projection is another matter entirely - thats a lateral stretching/bunching effect and although usualy its only a barely noticable effect (for reasonable FOV, although the fact that you can define a 999999 degree FOV should ring bells), there simply isnt any reasonable way at all to compensate besides doing it right to begin with.. the angles are wrong using fixed increments and thats all there is to that."

这听起来好像是在指我遇到的相同变形,但是除了暗示固定角度增量是问题的根源(它是弯曲的变形,朝着边缘增加)之外,它并没有提供太多帮助或见解.屏幕上的内容,这似乎与建议的内容相符).我用来纠正失真的函数是:

This sounds like it might be referring to the same distortion I am experiencing, but it doesn't provide much help or insight other than suggesting fixed angle increments are the source of the problem (it's a curved distortion which increases towards the edges of the screen, which seems to fit with what this suggests). The function I am using to correct the distortions is:

function m_CorrectRayLengthDistortion( dist, angleFromCentre ){

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

MOD_Maths是一个实用程序模块(在这种情况下,用于将角度从度转换为弧度,以便余弦函数可以使用它).

MOD_Maths being a utility module (used in this case to convert the angle from degrees to radians so the cosine function can use it).

在这方面的任何帮助将不胜感激,并且如果有人回答此问题,那么由于在线上尚缺乏有关该主题的信息,希望将来会给遇到此问题的任何人提供指南.

Any help on this is greatly appreciated, and if anyone answers this it will hopefully provide a guide to anyone experiencing the issue in future, given the aparrent lack of information on the subject that is available online.

谢谢:)

推荐答案

我很早以前就已经正确地解决了这个问题,但是直到现在还没有办法更新答案.我删除了之前的错误答案(由于我对问题的根本原因缺乏理解,因此答案几乎是正确的,但是采用间接方法).

I solved this problem properly quite a while ago, but haven't got round to updating the answer until now. I have removed my previous answer which was incorrect (it gave almost correct results but by an indirect method, thanks to my lack of understanding of the root cause of the problem).

正如Sam在先前的评论中提到的那样,问题的根本原因在于,如果您想获得等距的列(使渲染结果看起来不失真,则固定角度增量实际上实际上是不正确的).在论坛帖子此处中已提到了该问题,尽管我发现,直到很久以后,我才完全不明白为什么会这样,或者如何解决该问题.

As Sam mentioned in his earlier comment, the root cause of the issue is that fixed angle increments are actually not correct if you want to achieve equally-spaced columns (which are necessary for the rendered result to look undistorted). This was mentioned in a forum post here, but although I found this I didn't fully understand why this was the case, or how to remedy the problem, until much later.

要在屏幕上获得等距的列,可以理解为每条光线必须从视点传播并穿过沿投影面等距分布的像素,这意味着随着光线从投影表面向远处移动,在屏幕的中心像素处,与观看方向的夹角增加的增量逐渐变小.如下图所示(很抱歉,这不是一件艺术品):

To achieve equally spaced columns on the screen, it stands to reason that each ray must travel from the point of view and pass through a pixel which is equally spaced along the projection surface, which means that as the rays move further from the central pixel of the screen, the increment by which the angle from the look direction increases gets gradually smaller. This is illustrated by the following picture (apologies, it isn't exactly a work of art):

在较小的视场中,问题不是很明显,但是随着视场的增加,问题变得更加棘手(在我的图中,视场很大,可以清楚地说明问题).要正确计算射线角度增量,必须使用以下过程:

With small fields of view the problem is not very noticeable, but becomes more problematic as the field of view increases (in my diagram the field of view is quite large to clearly illustrate the problem). To correctly calculate the ray angle increments, the following process must be used:

位置:

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);

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

We can use the following formula (derivation included for clarity):

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

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

Javascript code example from my engine:

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

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

由于在线上提供的光线投射引擎信息的本质有点稀缺,并且由于该特定问题并未在任何主要教程中明确涵盖,因此我想更新此帖子提供正确的信息,以防其他人遇到我遇到的同样的问题,并且不理解为什么.希望这会对某人有所帮助.

Due to the somewhat scarce nature of information on raycasting engines which is available online, and also due to the fact this particular issue isn't explicitly covered in any of the main tutorials which are out there, I wanted to update this post with the correct information in case anyone else has the same problem I did and doesn't understand why. Hopefully this will help someone.

这篇关于光线投射引擎渲染会导致轻微失真,并向屏幕边缘增加的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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