Login
Community
DARK THEME

What is raytracing/raymarching/raycasting

So, with my raymarcher in progress, my list-based raycaster in progress, my raytracer, and my raycasted terrain engine I have * officially * created one of each. But I thought I would just quickly explain the differences between these three types of 3d renderers (to my understanding, there is a lot of gray area between the definitions and this is just what I understand). I also thought I would quickly explain how each one works.

What is raytracing/raymarching/raycasting?

Raytracing, raymarching and raycasting are all different ways to render objects in a 3d space. Despite losing on speed to rasterizers or poly-filling, they have the advantage of being able to do accurate lighting, reflections, shadows, etc. that rasterizers and poly-filling can't as effeciently or as accurately.

Each one of these processes will get a normalised ray direction from a 2d position on the screen, and use a camera position as well to determine if the ray vector will intersect with an object. Just as a quick example, the ray vector would be decided by this.

getrayvector=function(x,y) // 2d xy coords on the screen
  // Ray vector is normalised vector between 2d xy coords and FOV
  dist=sqrt(x^2+y^2+FOV^2) // FOV is the field of view
  dirx=x/dist
  diry=y/dist
  dirz=FOV/dist

Please note that the ray direction can be rotated to a camera x and y direction by using simple rotation scripts:

rotate=function(x,y,rot) // Rotates points x,y using 2d rotation
  rotx=cosd(rot)*x-sind(rot)*y // cos'd' because I prefer to work in degrees
  roty=sind(rot)*x+cosd(rot)*y
end

rotateray=function()
  rotate(dirz,diry) // yrotation
  dirz=rotx
  diry=roty
  rotate(dirz,dirx) // xrotation, use already rotated z coordinate.
  dirz=rotx
  dirx=roty
end

What is raytracing?

Raytracing uses math to immediately calculate intersections with objects from a ray vector and position. It has the disadvantage of being the hardest of the three techniques, but is the fastest of the three techniques by far. Basically, it uses math to immediately intersect with an object.

That sounds very hard to do, but it is simpler than it seems; a very basic method to calculate intersection with a plane is below:

plane=function(ypos)
  dist=abs(camy-ypos) // Distance to y plane
  dist=dist/raydiry // Distance the ray will take to hit plane
  dist=-dist // Switch to negative, because a negative ray direction results in an intersection with a plane below camy and vice versa
  if dist>0 then // Without this, it would just calculate intersection with a plane above and below the camera
    intersected=1
    intersectx=raydirx*dist // XYZ positions, where the ray hits the plane
    intersecty=raydiry*dist
    intersectz=raydirz*dist
  end
end

See? Easier then it sounds :). However, finding intersections with non-primitive objects is much harder then it is in a raymarcher or raycaster.

What is raymarching?

Raymarching marches towards an object instead of immediately calculating intersections by using object distance functions. Basically, it will calculate the nearest distance to every object and then move that many steps forward, because it is the only 'safe' distance - the only distance you know you can move without going inside an object. It will repeat this until the nearest distance to an object is below a certain number, eg. 0.1, because then the ray is basically inside an object.

It has the disadvantage of being slower than a raytracer (and faster than a raycaster) but gives large advantages in simplicity, object manipulation, and making different objects. It is also much more efficient at rendering 3d fractals such as a mandelbulb. Raymarching is much easier than raytracing, for example, it can calculate the surface normal at any point by using object distance functions and can find intersections with objects a lot easier. See below for a few examples:

calculatenormal=function(x) // final intersected position of ray
  nearestdist(x+0.1) // Function to find nearest distance from any point
  normalx=dist
  nearestdist(x-0.1)
  normalx=normalx-dist
  // Please note I only calculate normalx in this example.
end

planedist=function(y) // distance to plane
  dist=camy-y
end

What is raycasting?

Raycasting (too my understanding) refers to anything that moves a 'fixed' step distance and then calculates intersections. For example, it might move forward 1 distance in the ray direction until it calculates that the ray is inside an object. Raycasting is often used to project 2d maps onto a 3d screen, and has a variant called list-based raycasting where instead of moving a fixed step distance you move to the nearest edge of a grid until calculating an intersection.

Raycasting is the simplest of the three methods, but the slowest by far. It doesn't really have much advantage over raymarching other than that, except it being much easier to raycast procedurally generated planes. You can use raymarcher distance estimations to calculate intersections as well, by checking if the distance is below 0. However, in raycasting you cannot use the same method as raycasting to calculate distance estimations, meaning you have to use the same method as raytracing.

See below for a few examples:

plane=function(y)
  if rayy<y then // rayy is the y position of the ray
    intersected=1
  end
end

plane=function(y)
  planedist(y,rayy) // Distance to plane using same formula from raymarcher
  if dist<0 then
    intersected=1 // This works for every distance estimation
  end
end

Summary

Basically, you can think of raytracing as using math to jump straight to an object, raymarching as 'marching to an object by using distance estimations', and raycasting as moving one step at a time.

Raytracing is the fastest but hardest of the three, while raycasting is the slowest and easiest, and raymarching has the advantage of being able to efficiently render 3d fractals and calculate a surface normal.

And that's the end! Hope this helps :) Also, sorry for not really providing examples. I aim to give articles/tutorials about these in the future so that's why :)

I would love to introduce more people to raytracing or raymarching as well, so let me know if you have any questions or would like some more in-depth examples :).

Still looking at you, tinkersmith ;). And in response to yoru response, I have no idea what I'm doing either :)

Great post, thanks!

No, thank you :)! It was a pleasure to write this - especially if it helped you out.

And believe it or not, I don't mind writing articles such as this especially since, as I said, I would love to introduce more people to raytracing or raymarching!

Thanks for this article @this_trace_is_taken ... lol

Need some coffee, some paper and a pen (I need to visualise things on paper to 'get' it) and then I'll tinker my way through it.

So it always depends on the situation what is best.

Thanks for taking the time to write this all down ... will result in some tinkering

Great! If you need any extra info let me know :), @this_tinkerer_is_taken ... lol.

Also, just a quick tip, lighting can be done by taking the dot product of the surface normal and the light vector - and then multiplying the RGB by that. The surface normal is the 'normalised direction' of the surface, and the light vector is just the normalised vector between the light source and the point of intersection.

Shadows are done by tracing a ray between the light source and point of intersection - bascically just tracing in the direction of the normalised light vector from the point of intersection - and seeing if an object is between the point and light source.

Awesome! I'm looking forward to many other tutorials (and hopefully a one on 3d platforming :P)

Thanks! I'll see what I can do :)

Post a reply

Progress

Status

Preview
Cancel
Post
Validate your e-mail address to participate in the community