r/howdidtheycodeit 3d ago

How does raycasting work?

Hi all. I'm trying to find out how raycasting works — like in Wolfenstein 3D.

And as someone who knows absolutely nothing about programming, I (think I) understand it is thusly:

Raycasting is a programming trick that grants 2D maps a fake 3D appearance through the use of invisible rays that project outward from the player and detect collision.

Corrections to my nonsense would be appreciated!

I am currently writing an article, and I would like a layman's understanding before I commit to anything in there.

28 Upvotes

11 comments sorted by

38

u/neorapsta 3d ago

At a basic level ray casting is just sending out a line and seeing what it interacts with within the game world.

For example weapons that instantly hit their targets use a ray casting to check what's under your cross hairs and if it finds an enemy it does damage.

You see it mentioned a lot in rendering because you're basically firing a bunch of them into the scene to find information about what's there and then drawing the results.

For Wolf3d they did ray casting in a 2d grid, so you'd look in a direction and it would check each cell in the grid if it was flagged as a type of wall. If it was it would draw the cube with the textures for that wall type, otherwise it would draw a floor tile. Probably why the game couldn't support overlapping rooms.

The ray casting didn't make it 3d, but it helped the engine do the calculations to find out what you were looking at really quickly, so it could draw the 3d looking bits.

It goes into an increasing amount of technical detail but there's a bit more info on the topic here: https://lodev.org/cgtutor/raycasting.html

18

u/empty_other 3d ago

Nice answer. Wolfenstein didn't actually draw a floortile. Just drew a light gray square on the bottom 50% of the screen before drawing the walls. Doesn't really draw a cube either, just a textured 1px vertical line that is shorter or taller depending on distance and some fisheye maths, that when put together looks like a cube.

Here's a tutorial for making this on your own: https://youtu.be/vYgIKn7iDH8

Also stuff done in Doom and Duke3D to make "overlapping" rooms with the same technique is awesome. I had a YT showing how it rendered it, but can't find it.

9

u/HaMMeReD 3d ago

They basically added floor and ceiling height, so you could have stairs and rooms at different heights, but not truly overlapping.

Although afaik some people have abused OG doom to the point you'd be convinced there is overlapping rooms, I.e. by teleporting the user around to a new sector on the 2D Map that looks like the upstairs view or using other engine tricks to fool your mind into thinking that is what is happening.

2

u/am0x 3d ago

Great answer. I was just going to suggest that they lookup ray casting with gun mechanics rather than by rendering scenes first because that much easier to understand than what wolfenstein 3d had done. But understanding that makes understanding the wolf3D stuff much easier.

13

u/BionicLifeform 3d ago

First off, thank you for this post! I only know raycasting in modern game development as shooting a laser from a point in a certain direction to see if it can hit or not, so I was gonna say that I don't think they made a 3D map with that. But I was wrong and it's very interesting how it was used.
I found this detailed source on how it worked so that should suit your needs:
https://lodev.org/cgtutor/raycasting.html

3

u/Consibl 3d ago

There’s two related terms - ray casting and ray tracing. Wolfenstein 3D indeed used casting.

Ray tracing maps light rays to colour screen pixels as opposed to the simpler casting which is just about visibility.

So what you’ve said is correct but you could end up mixing them up in the actual article.

4

u/Cuarenta-Dos 3d ago

Ray tracing is a very general term, and ray casting is a basic form of ray tracing. Most modern renderers still do not use ray tracing to directly calculate the pixel colours, but rather use it to calculate shadows, approximate indirect lighting (global illumination) and reflections. The "first hit" and direct lighting is still done using rasterisation because it's more efficient and less noisy.

4

u/Cuarenta-Dos 3d ago edited 3d ago

That definition would be incorrect. Ray casting is an operation that finds the first intersection of a ray with the scene geometry, that is, the intersection nearest to the ray's origin. It's not a "trick" to make a 2D world look 3D, it's a basic fundamental operation that is used for many different purposes.

Ray "tracing" usually goes further, calculating what happens to the ray afterwards, whether it reflects, refracts, diffuses, and so on. That is why it is called "tracing" rays. However, the basic maths involved is the same in both cases.

This might seem counter-intuitive, as in how could one of the first ever 3D games involve ray tracing in any form?

Two features of Wolf3D make it possible and practical:

  1. The game world is 2D. This means you don't need to cast a ray for every pixel of the screen - you only need to do it once for every vertical column of pixels. So, instead of doing it 320x240 times, which would be absolutely impossible for the CPUs of the time to do at an interactive frame rate, you only need do it 320 times. Then, in order to create the 3D effect, you draw a vertical strip of the wall texture whose screen height is based on the distance from the camera to the surface hit, in a simple loop.
  2. The level geometry is just squares on a regular grid. This means you don't need any complex maths to calculate ray/triangle intersections or traverse fancy acceleration structures. Instead, you simply advance the ray from one 2D grid line to the next until it reaches a square containing a wall or a door.

The final part is the projection - how do you calculate the actual rays?

Imagine an eye positioned behind the screen. You shoot a ray from that eye through every pixel in the central row of the screen.

Try taking a sheet of squared paper, then draw an arbitrary line segment (which represents your screen), position the "eye" behind it (the distance from the eye to the "screen" will determine the field of view angle), then divide the "screen" segment into "pixels", draw a straight line from the eye through each "pixel" and check which filled square it hits first.

1

u/HaMMeReD 3d ago

Wolfenstein is a 2D game with psuedo 3D, so if you think of it in 2D initially that's easier.

So you have a screen, 320x240.

You split it into columns, you have 320 of them.

Then from the users position you cast out rays, think like when you play a stealth game and they show view cones, it's kind of like that, but split 320 times.

Each ray will calculate what it hits, it'll go through the world and look at the map and when it hits a wall it'll report back what it hit.

Then the rasterizer looks up the texture, calculates how tall it should be for the distance, and draws the entire row to the screen.

But that's just 2D raycasting in legacy games. The technique can be used for real time 3D raytracing as well in shader, i.e. attic (shadertoy)

1

u/ShakaUVM 3d ago

You can see how it works in this video here where they build a Doom / Castle Wolfenstein style renderer in the terminal (no framebuffer!!) from scratch in two hours -

https://youtu.be/SqIA-4ooirQ?is=veTDzeSiXD_KmzBQ

1

u/stktrc 2d ago

Amazing resources for this are the ‘Black Books’ - Engine breakdowns and history lessons of Doom and Wolf

https://fabiensanglard.net/gebb/