
WebAssembly Raytracer - omn1
https://sniklaus.com/blog/raytracer
======
jandem
The JS version is slow in Firefox because of a silly perf cliff, I filed a bug
[0]. A quick fix for that improves the JS version from ~400 ms to ~180 ms for
me locally. ~140 ms if I disable the Nightly-only GC poisoning.

edit: the JS code is a bit buggy: it does |if (Math.abs(dblDiscriminant) <
0.01)| in the |intersection| function, but dblDiscriminant is a var set in the
next loop! Math.abs(undefined) is something we can easily optimize in the JIT,
but really the JS code is broken. Folding this in our JIT [1] improves this to
< 130 ms for me.

Please let us know if you run into JS perf problems, these bugs are usually
easy to fix.

[0]
[https://bugzilla.mozilla.org/show_bug.cgi?id=1425687](https://bugzilla.mozilla.org/show_bug.cgi?id=1425687)

[1] [https://pastebin.com/CzfP5vQj](https://pastebin.com/CzfP5vQj)

~~~
sniklaus
Thank you for your evaluation! It should have been _dblDenominator_ instead of
_dblDiscriminant_ and I fixed it accordingly. However, this change does not
seem to significantly affect performance.

------
IvanK_net
I made a Path-tracer (photorealistic algorithm) in pure JS four years ago:
[http://renderer.ivank.net/](http://renderer.ivank.net/)

It rendered this image:
[http://renderer.ivank.net/balls.jpg](http://renderer.ivank.net/balls.jpg) :)

I also made the "full" 3D game:
[http://powerstones.ivank.net/](http://powerstones.ivank.net/) (uses a GLSL
shader).

~~~
blarg1
The 3D game doesn't work for me, when I hit play all I get is a white screen
with light pink/teal/yellow coloured pixels/blocks flickering at the top of
the screen. I'm on an intel integrated graphics.

~~~
khedoros1
Worked fine for me in Windows 10, FF57, using Intel integrated graphics.
Things were noisy-looking, and I'm not sure of that's just part of the game
aesthetic, or what.

~~~
simooooo
It's how Ray traced images look until you give then long enough to smooth out.

------
Sharlin
Firefox really benefits from WebASM: the time per frame is ~90ms on my machine
whereas the JS version is close to 400ms or so.

On the other hand, on Chrome the WebASM performance is ~100ms and JS is just a
tiny bit slower at around 120ms!

~~~
WhitneyLand
But would adding antialiasing kill the performance? It’s a small thing, but
it’s kind of like a movie where you can totally suspend disbelief and one bad
actor or effect jolts you out it.

~~~
Sharlin
Well, sure, but so would rendering at a more reasonable resolution, or a more
realistic scene than five spheres on a plane. And it's not like 10fps is a
useful frame rate in the first place. But it's the relative, not absolute,
performance figures that are interesting here.

~~~
bartread
> And it's not like 10fps is a useful frame rate in the first place.

How times have changed. I remember running flight sims back in the 16-bit era
(Amiga 500, for example) when 10fps would have been considered pretty good,
especially if there was a lot going on.

But yes, I think nowadays you're right: 60fps or bust. And this is really why
ray-tracing isn't used that much in games - it's just so computationally
expensive.

------
Francute
On my desktop:

Firefox: JavaScript ~372ms, asm ~121ms, WebAssembly ~91ms, Shader ~0.1ms

Chrome: JavaScript ~115ms, asm ~150ms, WebAssembly ~105ms, Shader ~0.1ms

Edge: JavaScript ~3340ms , asm ~(230-240)ms, WebAssembly ~(160-180)ms, Shader:
Broken

IE11: Broken.

Interesting values.....

~~~
peterdn
Doesn't work for me at all in Edge (v41.16299.15.0). Are you on an Insider
Preview?

------
bufferoverflow
Shader is broken on both android chrome and ff.

These work fine:

[https://www.shadertoy.com/view/4tyXDR](https://www.shadertoy.com/view/4tyXDR)

[https://www.shadertoy.com/view/4sXGDs](https://www.shadertoy.com/view/4sXGDs)

[https://www.shadertoy.com/view/4dsGRn](https://www.shadertoy.com/view/4dsGRn)

[https://www.shadertoy.com/view/4lB3D1](https://www.shadertoy.com/view/4lB3D1)

~~~
Macha
Might depend on your device, the shader mode worked fine on my nvidia shield,
but is broken on my nexus 5x.

~~~
sniklaus
I unfortunately had a bug in my code that I just fixed. It should work now,
unless you encounter the bug that has been discussed here:
[https://github.com/mrdoob/three.js/issues/9716](https://github.com/mrdoob/three.js/issues/9716)

------
zurn
Interesting that there is a 1000x speed difference (0.1 vs 100 ms, in Chrome)
between the shader and the JS/WebASM versions even with just Intel integrated
graphics.

~~~
Klathmon
Even after working with them for a while, GPUs still feel like cheating. They
are just so goddamn good at what they do.

That kind of speed up isn't just a fluke here, it's pretty normal when your
work aligns with what a GPU does best.

~~~
roywiggins
They're really fast even if you're sort of abusing them. Using fragment
shaders to render entire scenes ("two triangle" style) probably wasn't what
GPUs were built to do but the technique is awfully effective.

I mean:
[https://www.shadertoy.com/view/Mt2yzK](https://www.shadertoy.com/view/Mt2yzK)

------
TekMol
Is there a resource to learn WebAssembly?

I don't mean how to use a tool chain to compile higher level languages to
WASM. I mean how to write the linear assembly bytecode as seen here on
Wikipedia:

[https://en.wikipedia.org/wiki/WebAssembly#Representation](https://en.wikipedia.org/wiki/WebAssembly#Representation)

~~~
steveklabnik
I went straight to the spec personally; it’s quite readable and shorter than I
expected.

~~~
TekMol
Where is it?

~~~
kodablah
[http://webassembly.org](http://webassembly.org)

------
k__
the shader version is the fastest, but looks like modern art on my smartphone.

Like someone scribbled the colors over the circles instead of filling them.

~~~
jsheard
This is probably the culprit: [https://github.com/sniklaus/experiment-
raytracer/blob/master...](https://github.com/sniklaus/experiment-
raytracer/blob/master/shader.js#L11)

It declares that floats should only be medium precision by default, but those
precision specifiers are only followed on mobile platforms.

Desktop WebGL implementations just promote everything to high precision so
that kind of bug is invisible until you test on mobile.

~~~
sniklaus
Thank you for pointing it out, I fixed it by now. :)

~~~
simooooo
Fixed for me. Nice work

------
z3t4
When WASM only give's a 10% increase in performance, is it really worth it ?
While at the same time using "hardware" shaders gives 1000% increase in
performance. If the goal of WASM is not performance, what is the reasoning
behind it ? That you would be able to compile any!? program to be run in the
browser !?

~~~
akmittal
This might not be best way measure wasm performance. WebAssembly can be 2-5x
fater than JavaScript.

Not to forget wasm is in very early stage, once we get threading
support([https://github.com/WebAssembly/threads](https://github.com/WebAssembly/threads))
we can get much better results.

------
igravious
Wow, Chrome is able to run the Shader on my Intel integrated graphics on
Wayland in Ubuntu 17.10

Colo(u)r me impressed.

I'm getting 0.1 versus 125 for WebAsm versus ASM.js/JS of ~210 – kind of crazy
that Chrome can run plain JS as fast as ASM.js (or is it?)

Firefox (57) can't run Shader unless there's some under the hood option I have
to turn on …

~~~
clouddrover
I'm using Firefox 58 beta on macOS with Intel graphics and the Shader version
works for me. Maybe WebGL is disabled in your set up. Some drivers and driver
versions are blocklisted to avoid instability:

[https://developer.mozilla.org/en-
US/docs/Mozilla/QA/Graphics...](https://developer.mozilla.org/en-
US/docs/Mozilla/QA/Graphics_Blocklisting)

The graphics section in about:support might tell you your WebGL status.

------
radarsat1
A little beside the point, but I _love_ the real-time distribution
visualisation with the boxplot.

~~~
sniklaus
Thank you for your kind words. I borrowed the idea from a previous project in
which curious students could evaluate the computational performance of their
various implementation using a similar plot:
[https://github.com/sniklaus/teaching-
minichess](https://github.com/sniklaus/teaching-minichess)

------
based2
a raytracer in JS: ~407.3 ms and in WASM: ~87.4 ms and in GLSL: ~0.17 ms

[https://www.reddit.com/r/programming/comments/7k4v5t/a_raytr...](https://www.reddit.com/r/programming/comments/7k4v5t/a_raytracer_in_js_4073_ms_and_in_wasm_874_ms_and/)

~~~
sniklaus
This is where I answered most of the questions. I didn't even see that someone
posted it here as well. Thanks!

------
singularity2001
I had no idea ray tracers can be written with such concise and clean code. the
results are amazing too. lesson learnt: JavaScript is extremely fast on
chrome, 6 times slower than WASM in Firefox and GPU shaders are still faster
by a factor of 1000!!

~~~
sniklaus
If you give up having clean code, you can even fit a raytracer on a business
card:
[http://fabiensanglard.net/rayTracing_back_of_business_card/](http://fabiensanglard.net/rayTracing_back_of_business_card/)

------
kowdermeister
Hmmm:

JavaScript 106.8

asm.js 140.0

WebAssembly 88.4

Shader 0.1

Just a Dell 13 inspiron laptop with latest Chrome 63.

~~~
vanderZwan
Seeing the same with Chromium on my Linux machine. In Firefox the JS version
is really slow, as you would expect.

It's kind of hard to judge this without having a decent enough look at the
code, or how it is being benchmarked. For example, asm.js requires quite a bit
of set-up to intialise; if it's restarted from scratch every loop for
benchmarking purposes that would mess up the timing.

