
Show HN: 3D Raycasting Engine in JavaScript - ahuth
https://ahuth.github.io/raycast/
======
gh123man
Very cool!

I went deep down the rabbit hole with raycaster engines over the last 2 years.
While this particular rendering technique has lots of limitations (like a
fixed camera - unable to look up and down) it also has some interesting
properties. Such as the ability to create windows, mirrors, and portals very
easily by re-directing the way the rays fly.

I actually put together an entire game around this to test the limits of what
I could achieve with raycasting. If anyone is curious you can see a video of
it on my blog:
[https://blog.sb1.io/gateescape/](https://blog.sb1.io/gateescape/)

What I think would be a great project is moving the casting and drawing part
over to a compute shader. My engine is multi threaded and chunks the screen so
each thread can do some section of the work. Unfortunately I want the engine
to be cross platform, but Apple has made that rather difficult with the
requirement of Metal going forward. If anyone has seen this style of
raycasting implemented on a GPU I would be very interested!

~~~
mrspeaker
Wow, that looks cool. Portals are a great idea and seem like the would be
(relatively) easy to implement in a raycaster!

The simplicity of them makes them fun to experiment with: I used one in a
Ludum Dare game
([https://www.mrspeaker.net/dev/ld27/](https://www.mrspeaker.net/dev/ld27/))
and made the field-of-view and movement speed a "mechanic".

~~~
GonzaloQuero
I just finished your game, and it was really, really good! I love trippy,
timey-wimey experiences!

------
tomxor
Very neat. Shameless plug: Things can get extremely minimal if you make the
view frustum orthogonal and also use _raymarching_ instead, then the geometry
(SDF) is very concise to define... a lot of the math disappears and the code
gets super short... like 140 chars short:

    
    
      Spheres + Displacement
      https://www.dwitter.net/d/15947
      https://www.dwitter.net/d/15951
    
      Spheres Orbit + Fake Lighting
      https://www.dwitter.net/d/16192
    
      "Smoke" (3D perlin-esc noise)
      https://www.dwitter.net/d/16179
      https://www.dwitter.net/d/16169
    
      Snowman + Snow
      https://www.dwitter.net/d/16955
    

Not very practical for much of an engine of course, and also much slower than
casting, but it makes it dead easy to understand by removing matrix transforms
et al.

------
mrspeaker
Ha ha - very interesting use of React... I love that the columns are
components!

Though my "negative nancy" comment would be that this is the wrong tool for
the job (or at least, it could use a little renaming?) because after jumping
from Scene to App to useCastRays hook... I finally found all the actual logic
in "utils": which I'm always suspicious of ;)

Anyhoo - really cool, I'd like to see how the 2D sprites are integrated!

~~~
ahuth
Definitely a misuse of React! And for whatever reason, naming is always an
issue for me. Need a better name than "utils" for sure.

One thing that surprised me about this is how fast the browser renders 320
absolutely positioned divs that are constantly updating.

But then I thought about it some more, and realized that many websites these
days probably have way more DOM and DOM manipulation than that going on!

~~~
xendke
As a developer that uses react every day, I'm so glad it was used in this
project because I was able to look at the code and understand it quite
quickly!

~~~
ahuth
That's the reason I used React in the first place - because I'm very familiar
with it. Made it easier to focus on the concepts, not the technology.

------
0-_-0
Interesting trivia: The game Wolfenstein 3D originally used raycasting to
determine visibility. Later, id software signed a contract with Nintendo for a
SNES port, which they outsourced to a contractor while they worked on Doom.
During this time Carmack realized that the same method won't be fast enough
for Doom and started studying BSP [1] trees. Meanwhile, the contractor was
unable to do the port because of the very paltform-specific code (heavy
optimisations for the 386 and 486). So id software took time off from Doom and
went back to do the port themselves, eventually succeeeding by using BSP for
visibility and a lower resolution.

[https://en.wikipedia.org/wiki/Binary_space_partitioning](https://en.wikipedia.org/wiki/Binary_space_partitioning)

------
tombert
A couple years ago I got bored on the train, and coded a simple ray-caster in
Pico-8.

Ray-Casting is fun because it's a relatively simply algorithm to "rediscover",
and can be coded in just a few hundred lines of code... I've debated making it
a guided question to ask during interviews, though I've resisted thus far
because I'm afraid it might be a bit too much for a junior candidate, and
might be too easy for a senior candidate.

~~~
ahuth
My worry about asking it as a question is that because it's kind of esoteric,
someone could have all the tools they need to implement it, and not know it.

That's probably where your guidance comes in, though.

~~~
tombert
Yeah, I wouldn't expect them to already know the way to do it, more of a
"walk-them-through-it" question.

------
akdas
Great demo.

A couple of years ago, I wrote a Javascript implementation myself:
[https://github.com/avik-das/js-raycast](https://github.com/avik-das/js-
raycast)

And then, when asm.js (precursor to WebAssembly) became a thing, I rewrote it
in C and compiled it to asm.js: [https://github.com/avik-das/emcc-
raycast](https://github.com/avik-das/emcc-raycast)

I'd already written a ray tracer (so a fully 3D renderer) prior to that in
college, so it was fun to learn about a more limited algorithm that was better
suited to older hardware.

~~~
MuffinFlavored
What was performance like js-raycast vs emcc-raycast?

~~~
akdas
At the time I wrote those, I was actually surprised because I didn't see much
improvement using emcc-raycast. In both implementations, you can see that I'm
allocating objects/structs all over the place, so that probably brings down
the performance.

------
atum47
Nice. Not so long ago I was trying to make one without the grid layout, using
lines instead. Never got the math quite right thou. Here's the link if you
wanna take a look:

[https://github.com/victorqribeiro/myRaycast](https://github.com/victorqribeiro/myRaycast)

------
dormando
These are fun!

Shameless: [http://www.dormando.me/post/fpga-
raycaster/](http://www.dormando.me/post/fpga-raycaster/) \- I did one of these
last year with an arduino using an FPGA as a weird GPU :)

------
malkia
Also this -> [https://keithclark.co.uk/labs/css-
fps/](https://keithclark.co.uk/labs/css-fps/) \- 3D using CSS :)

------
btzll
Very cool but the WASD keys do not work on Firefox. Arrow keys work fine
though!

edit: it suddenly started working after I switched to a different tab, and
then back to the raycast's tab.

~~~
ahuth
That's weird. The WASD keys work for me in Firefox.

Do you have shortcuts bound to those keys? Maybe I need to preventDefault() on
keypresses, or something.

------
matt_eeee
Nice! A trick from Wolfenstein 3D to improve the look is to give all the
north-south walls a lighter colour, and all the east-west walls a darker
colour.

------
lukevp
Can you add virtual keys so I can play with it on my phone? I like raycasters,
written a few back in the day :)

~~~
ahuth
That’s a good idea. I’ll do that

------
high_byte
you're killing your stack with redundant recursion, here:

return findWall(map, position.add(deltaX, deltaY), deltaX, deltaY);

no reason not to loop here.

------
wdb
Doesn't work with the arrow keys :(

------
alyssaxuu
Oh wow, this is quite impressive.

------
tantalor
Looks more like 2d?

~~~
MrK93
There is perspective, so it's 3D. Unless you are talking about the fact that
your display can show only 2D images then you are technically correct since
most displays are not 3D displays.

~~~
tantalor
Perspective does not require 3d.

You can have perspective in flatland.

~~~
vokep
I think you're right, its a sort of pseudo3d. Its a 3D presentation of a 1D
(2D environment) perspective. Cut a horizontal row of pixels from the center
of the screen and you have its flatland point of view.

~~~
tmilard
[https://free-visit.net/index.php/fr/demos](https://free-
visit.net/index.php/fr/demos)

