Raycasting engine rendering creating slight distortion increasing towards edges of screen

前端 未结 2 1479
心在旅途
心在旅途 2020-12-30 17:13

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 t

2条回答
  •  灰色年华
    2020-12-30 18:16

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

    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:

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

    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 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.

提交回复
热议问题