Published on Sunday, October 1, 2023
My recent adventures into shaders lead me to think about What would raymarching look like in minecraft?. Despite not finding any visually interesting idea to explore, I thought about raymarching as a replacement of raycasts.
Here are my conclusions.
The results are compared to the vanilla raycasting algorithm. This raymarching varient has been built answering to the following constraints:
This repository includes vanilla raycasting and a raymarching implementation. Benchmark folder includes stacked function calls to test them in game.
The raymarching function has 2 parameters:
.max_distance
which is the maximum range of the ray in 100th of a block.max_step
which is the maximum number of iterations of the raymarching algorithm. This permits to stop the raymarch if it is really close to an entity and avoid to do a lot of iterations.Raymarching is a technique normaly used in computer graphics to render 3D scenes. Where a raycast is testing multiple points on a ray with a constant interval, raymarching is testing points on a ray with a variable interval. In other words, it takes the distance between the current point and the nearest object and use it as the step of the next iteration. This permits to have a better precision and a faster execution time.
Raymarching is in computer graphics, a really efficient method. Tho, in MCFunction, computing a square root is really slow and could have made this raymarching implementation slower than the vanilla raycasting.
Clearly, the day we obtain a better way to compute maths and especially complex functions, raymarching will be the best method to use in MCFunction.
Even if its best case is faster than raycasting, there is few limitations:
On the other side, there is advantages:
The tests have been done on a 1.20.2 environment. 9 new players are spawned using /player
command from carpet mod, fully simulating player loading.
In the world, there is an additianal entity summoned by the datapack and tagged to not be selectable by the raymarching function during its execution. Thus, there is a total of 11 entities in the world.
The simulation distance is set to 12 chunks.
The different constants are set to:
.max_distance
= 5000 <=> 50 blocks.max_step
= 50The raycast has only one figure case (as there is no hit detection activated) so is tested consistently.
The raymarch can be summarized to these 2 different cases:
The functions used in command blocks are:
execute as Neylz run function raym:benchmark/raycast/50
execute as Neylz run function raym:benchmark/raymarch/50
The 3 tests are executed in a row.
π Profiling file
Best Case π Profiling file
Worst Case π Profiling file
Note: Minecraft profiling (using F3+L) takes a lot of performances. The MSPT is increased by ~30%. So the results you can find in ./benchmarks/
are scaled up compared to the one presented in the screenshots above.
So, raymarching is a good method to use if you want to detect entities at a really long range. But if you want to detect entities at a short range, raycasting is better. The final performances of raymarch will become better and better, the longer the distance is.
Also, the raymarch doesn't permits to test the presence of blocks (which the raycast does poorly because of its step size). So if you want to detect blocks, raycasting would be better (except if you are computing and detecting through which block the ray is supposed to go through in order to avoid missing a block because a a too large step and then test block per block).
About the "best" and "worst" cases of the raymarching. This isn't the real worst & best cases. The best case would be a map with no entity on it or only entities which would be selected by the raymarch. The worst case is pottentially infinite. It would be a map with a lot of entities concentrated near the ray but not touching it. The raymarch would then do a lot of iterations and would be really slow.
These two best & worst cases i suggest are only an idea of what you can obtain in a realistic case.
As a conclusion, I would say that raymarching is a really good method to use in MCFunction. It is way faster than raycasting in the best case and is able to detect entities at a really long range.
Tho, raycasting is still better in some cases.
Thats why this raymarching implementation is only a new tool and it is now up to you to choose which method is the best for your project.
Raymarching will be better than raycasting in the cases where: