NHacker Next
  • new
  • past
  • show
  • ask
  • show
  • jobs
  • submit
Show HN: 3D Raycasting Engine in JavaScript (ahuth.github.io)
gh123man 1445 days ago [-]
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/

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 1445 days ago [-]
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/) and made the field-of-view and movement speed a "mechanic".

GonzaloQuero 1444 days ago [-]
I just finished your game, and it was really, really good! I love trippy, timey-wimey experiences!
mysterydip 1445 days ago [-]
There are ways to fake an amount of up and down looking without too much work, rise of the triad used an approach. the larger the angle the more apparent the fakery, but it works well for "small freedom". I love raycasting engines and yours is a nice addition!

https://permadi.com/1996/05/ray-casting-tutorial-16/#LOOKING...

sharkbot 1445 days ago [-]
I appreciated your earlier comment that talked about how you used signed distance functions to make the virtual joystick slightly expand. I used that as inspiration for some terrain generation in a very basic game I’m making to learn the ECS design pattern. So far, it’s working really well!

Thanks again!

ahuth 1445 days ago [-]
This is awesome. Nice job!
gh123man 1445 days ago [-]
Thanks! It means a lot! Since a few people have expressed interested, I decided to open source the early prototype code that has a simple implementation of portal casting. https://github.com/gh123man/Raycaster
tomxor 1445 days ago [-]
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 1445 days ago [-]
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 1445 days ago [-]
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!

adamredwoods 1445 days ago [-]
I applaud the misuse of React!

We've seen a lot of raycasters, so one made with React and hooks isn't a bad thing.

Interesting code of using useRef with your state, and then useEffect to update it every render. A simple/better Redux?

xendke 1445 days ago [-]
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 1445 days ago [-]
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 1444 days ago [-]
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

tombert 1445 days ago [-]
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 1445 days ago [-]
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 1445 days ago [-]
Yeah, I wouldn't expect them to already know the way to do it, more of a "walk-them-through-it" question.
akdas 1445 days ago [-]
Great demo.

A couple of years ago, I wrote a Javascript implementation myself: 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

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 1445 days ago [-]
What was performance like js-raycast vs emcc-raycast?
akdas 1444 days ago [-]
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 1445 days ago [-]
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

dormando 1445 days ago [-]
These are fun!

Shameless: 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 1445 days ago [-]
Also this -> https://keithclark.co.uk/labs/css-fps/ - 3D using CSS :)
btzll 1445 days ago [-]
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 1445 days ago [-]
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 1445 days ago [-]
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 1445 days ago [-]
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 1445 days ago [-]
That’s a good idea. I’ll do that
high_byte 1444 days ago [-]
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 1445 days ago [-]
Doesn't work with the arrow keys :(
alyssaxuu 1445 days ago [-]
Oh wow, this is quite impressive.
tantalor 1445 days ago [-]
Looks more like 2d?
MrK93 1445 days ago [-]
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 1445 days ago [-]
Perspective does not require 3d.

You can have perspective in flatland.

ahuth 1445 days ago [-]
You're right, this is definitely not really 3d. It's more of a trick to give the illusion of perspective to a 2d scene.

Made for some nice games in the early 90s, though!

vokep 1445 days ago [-]
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.
1445 days ago [-]
CommieDetector 1445 days ago [-]
Disgusting. Javascript is from the devil
Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact
Rendered at 20:23:54 GMT+0000 (Coordinated Universal Time) with Vercel.