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