Update
This commit is contained in:
parent
124b9d1e7c
commit
3f374a4713
85 changed files with 2281 additions and 2272 deletions
|
@ -63,7 +63,7 @@ The core element to implement is the code for casting rays, i.e. given the squar
|
|||
|
||||
**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 than the wall sides off the center, so it would by perspective laws look bigger). For non-distorted rendering we have to compute a distance that's perpendicular to the camera projection plane -- we can see the camera plane as a "canvas" onto which we project the scene (it's actually the flat computer screen that determines that we shall use such a flat projection plane), in 2D "top-down view" it is a line segment (unlike in 3D where it really is a plane, a rectangle) 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:
|
||||
|
||||
```
|
||||
```
|
||||
I-_
|
||||
/ '-X
|
||||
/ r.'/|
|
||||
|
@ -73,7 +73,7 @@ The core element to implement is the code for casting rays, i.e. given the squar
|
|||
/' | / |
|
||||
V-._-A/-----B
|
||||
'J
|
||||
|
||||
|
||||
```
|
||||
|
||||
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).
|
||||
|
@ -206,7 +206,7 @@ int castRay(int rayX, int rayY, int rayDx, int rayDy, int *dir)
|
|||
|
||||
// get the perpend dist. to camera plane:
|
||||
return (px > py) ? ((px * U) / rayDx) : ((py * U) / rayDy);
|
||||
|
||||
|
||||
// the following would give the fish eye effect instead
|
||||
// return sqrt(px * px + py * py);
|
||||
}
|
||||
|
@ -291,4 +291,4 @@ How to make this more advanced? Here are some hints and tips:
|
|||
- **different level geometry**: In theory the level doesn't have to be a square grid but some kind of another representation, or we may keep it a square grid but allow placement of additional shapes in it such as cylinders etc. Here you simply have to figure out how to trace the rays so as to find the first thing it hits.
|
||||
- **adding [billboards](billboard.md) (sprites)**: TODO
|
||||
- **reflections**: We can make our 2D raycaster a 2D [raytracer](raytracing.md), i.e. when we cast a camera ray and it hits a reflective wall (a mirror), we cast another, secondary reflected ray and trace it to see which wall it hits, i.e. which wall will get reflected in the reflective wall.
|
||||
- **partly transparent walls**: We can make some walls partially transparent, both with [alpha blending](alpha.md) or textures with transparent pixels. In both cases we'll have to look not just for the first hit of the ray, but also for the next.
|
||||
- **partly transparent walls**: We can make some walls partially transparent, both with [alpha blending](alpha.md) or textures with transparent pixels. In both cases we'll have to look not just for the first hit of the ray, but also for the next.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue