jdduke / three_cpp

A port of three.js to C++
MIT License
407 stars 52 forks source link

Using three_cpp as Three.js accelerator #14

Open DVLP opened 6 years ago

DVLP commented 6 years ago

This is a cool project but how to make it really useful?

Export a renderer to Web assembly so people can still use regular three.js and this library will work as a significant performance booster.

Use case:

  1. Programmer create their scene and objects in regular three.js
  2. Programmer starts an instance of WebGlCPPRenderer instead of regular renderer -WebGlCPPRenderer creates a worker and sends scene data using SharedArrayBuffer (or transferable objects because of current Meltdown situation on each frame) -worker does all the updates, matrices multiplying, skinned mesh vertices computation and renders scene in Canvas using OffscreenCanvas

Performance boost will be synergetic because it's not only wasm and SIMD perfomance gain, but also freeing main thread by utilising OffscreenCanvas.

Programmer is unaware of how worker version works and uses Three.js just as usual but gets extreme performance boost as all heavy computations happen in workerised renderer!

makc commented 5 years ago

except threre is no heavy computations in three.js :)

DVLP commented 5 years ago

not at all... below it's just one of functions which gets calculated for every object on every frame. Then you have matrix inversion, euler to quaternion and reverse etc. There's a lot happening in three.js

multiplyMatrices: function ( a, b ) {

    var ae = a.elements;
    var be = b.elements;
    var te = this.elements;

    var a11 = ae[ 0 ], a12 = ae[ 4 ], a13 = ae[ 8 ], a14 = ae[ 12 ];
    var a21 = ae[ 1 ], a22 = ae[ 5 ], a23 = ae[ 9 ], a24 = ae[ 13 ];
    var a31 = ae[ 2 ], a32 = ae[ 6 ], a33 = ae[ 10 ], a34 = ae[ 14 ];
    var a41 = ae[ 3 ], a42 = ae[ 7 ], a43 = ae[ 11 ], a44 = ae[ 15 ];

    var b11 = be[ 0 ], b12 = be[ 4 ], b13 = be[ 8 ], b14 = be[ 12 ];
    var b21 = be[ 1 ], b22 = be[ 5 ], b23 = be[ 9 ], b24 = be[ 13 ];
    var b31 = be[ 2 ], b32 = be[ 6 ], b33 = be[ 10 ], b34 = be[ 14 ];
    var b41 = be[ 3 ], b42 = be[ 7 ], b43 = be[ 11 ], b44 = be[ 15 ];

    te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;
    te[ 4 ] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;
    te[ 8 ] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;
    te[ 12 ] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;

    te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;
    te[ 5 ] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;
    te[ 9 ] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;
    te[ 13 ] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;

    te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;
    te[ 6 ] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;
    te[ 10 ] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;
    te[ 14 ] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;

    te[ 3 ] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;
    te[ 7 ] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;
    te[ 11 ] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;
    te[ 15 ] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;

    return this;

},

Three.js does a very good job of hiding complexity and it has a nice API but 3d graphics are CPU intensive and even small, low-level optimisations impact performance in big projects. Having it in a worker would allow adding SIMD plus making use of OffscreenCanvas could bring massive performance gains so developers could focus mostly on GPU performance

makc commented 5 years ago

these computations are not heavy at all, versus actually drawing these objects, shadows, post effects or handling video textures. they will likely amount to a couple of ms in total for average scene.

DVLP commented 5 years ago

You're talking about GPU effort and that's not what I started this topic for. Using three.js in a worker wont't affect any GPU bottlenecks. When it comes to CPU there are also skinned meshes and other animations. Then there must be overhead for physics, HUD, networking, and browser-specific stuff left. For simple scenes non of it matters at all but we're talking about real multiplayer games at 60fps

davidson16807 commented 5 years ago

I've personally used Three.js vectors for heavy computation and I would be very surprised if no one else did. Drawing objects takes very little time because all it amounts to is passing data to the GPU. It's what you do with those objects that can be slow.

However, I will say this: if you are doing heavy computation with Three.js, the biggest performance gain is probably going to come from addressing data locality issues. That's something that will require you to switch to a different data structure, and that's not something Three.js will provide.