Update
This commit is contained in:
parent
01be9b8af5
commit
c856794e38
4 changed files with 54 additions and 13 deletions
|
@ -56,23 +56,21 @@ The classic version of 2D raycasting -- as seen in the early 90s games -- only r
|
|||
|
||||
The core element to implement is the code for casting rays, i.e. given the square plan of the environment (e.g. game level), in which each square is either empty or a wall (which can possibly be of different types, to allow e.g. different textures), we want to write a function that for any ray (defined by its start position and direction) returns the information about the first wall it hits. This information most importantly includes the distance of the hit, but can also include additional things such as the type of the wall, texturing coordinate or its direction (so that we can [shade](shading.md) differently facing walls with different brightness for better realism). The environment is normally represented as a 2 dimensional [array](array.md), but instead of explicit data we can also use e.g. a function that [procedurally](procgen.md) generates infinite levels (i.e. we have a function that for given square coordinates computes what kind of square it is). As for the algorithm for tracing the ray in the grid we may actually use some kind of line [rasterization](rasterization.md) algorithm, e.g. the **[DDA](dda.md) algorithm** (tracing a line through a grid is analogous to drawing a line in a pixel grid). This can all be implemented with [fixed point](fixed_point.md), i.e. integer only! No need for [floating point](float.md).
|
||||
|
||||
**Note on distance calculation and distortion**: When computing the distance of ray hit from the camera, we usually DO NOT want to use the [Euclidean](euclidean.md) distance of that point from the camera position (as is tempting) -- that would create a so called fish eye effect, i.e. looking straight into a perpendicular wall would make the wall looked warped/bowled (as the part of the wall in the middle of the screen is actually closer to the camera position so it would, by perspective, look bigger). For non-distorted rendering we have to compute the perpendicular distance of the hit point from the camera plane -- we can see the camera plane as a "canvas" onto which we project the scene, in 2D it is a line (unlike in 3D where it really is a plane) in front of the camera at a constant distance (usually conveniently chosen to be 1) from the camera position whose direction is perpendicular to the direction the camera is facing. The good news is that with a little trick this distance can be computed even more efficiently than Euclidean distance, as we don't need to compute a square root! Instead we can utilize the similarity of triangles. Consider the following situation:
|
||||
**Note on distance calculation and distortion**: When computing the distance of ray hit from the camera, we usually DO NOT want to use the [Euclidean](euclidean.md) distance of that point from the camera position (as is tempting) -- that would create a so called fish eye effect, i.e. looking straight into a perpendicular wall would make the wall look warped/bowled (as the part of the wall in the middle of the screen is actually closer to the camera position so it would, by perspective, look bigger). For non-distorted rendering we have to compute a distance that's perpendicular to the camera plane -- we can see the camera plane as a "canvas" onto which we project the scene, in 2D it is a line (unlike in 3D where it really is a plane) at a certain distance from the camera (usually conveniently chosen to be e.g. 1) whose direction is perpendicular to the direction the camera is facing. The good news is that with a little trick this distance can be computed even more efficiently than Euclidean distance, as we don't need to compute a square root! Instead we can utilize the similarity of triangles. Consider the following situation:
|
||||
|
||||
```
|
||||
d
|
||||
/ .x
|
||||
I-_
|
||||
/ '-X
|
||||
/ r.'/|
|
||||
'-._ / ,' / |
|
||||
P '-c_.' / |
|
||||
/,'|-.e |
|
||||
/' | |
|
||||
V----a------b
|
||||
|
||||
p '-C_.' / |
|
||||
1/,'|-./ |
|
||||
/' | / |
|
||||
V-._-A/-----B
|
||||
'J
|
||||
|
||||
```
|
||||
|
||||
In the above *V* is the position of the camera (viewer) which is facing towards the point *d*, *P* is the camera plane perpendicular to *Vd* at the distance 1 from *V*. Ray *r* is cast from the camera and hits the point *x*. The length of the line *r* is the Euclidean distance, however we want to find out the distance *ex = cd*, which is perpendicular to *P*. There are two similar triangles: *Vca* and *Vdb*; from this it follows that *1 / Va = (1 + cd) / Vb*, from which we derive that *cd = Vb / Va - 1*. This can be used to calculate the perpendicular distance just from the ratio of the distances along principal axes (i.e. along axis X or Y). However watch out for the case when *Va = Vb = 0* to not divide by zero! In such case use the other principal axis (Y).
|
||||
|
||||
{ I hope the above is correct lol. ~drummyfish}
|
||||
In the above *V* is the position of the camera (viewer) which is facing towards the point *I*, *p* is the camera plane perpendicular to *VI* at the distance 1 from *V*. Ray *r* is cast from the camera and hits the point *X*. The length of the line *r* is the Euclidean distance, however we want to find out the distance *JX = VI*, which is perpendicular to *p*. There are two similar triangles: *VCA* and *VIB*; from this it follows that *1 / VA = VI / VB*, from which we derive that *JX = VB / VA*. We can therefore calculate the perpendicular distance just from the ratio of the distances along one principal axis (X or Y). However watch out for the case when *VA = VB = 0* to not divide by zero! In such case use the other principal axis (Y).
|
||||
|
||||
TODO: code
|
Loading…
Add table
Add a link
Reference in a new issue