Three.js is an open-source, lightweight, JavaScript-based 3D library for the web. It utilizes the WebGL API for back-end rasterization and adds a plethora for features on top of it.
This is still very much a work in progress. The goal is ultimately to have a fully real-time in-browser renderer comparable to the above implementation.
Highlights:
Rendering is done entirely through Three.js
Allows a Three.js scene or object group to be rendered along with the splats
Code is organized into modern ES modules
Built-in viewer is self-contained so very little code is necessary to view a scene
Splats sorted via an optimized C++ counting sort contained in a WASM module
Sorting and rendering are accelerated via custom octree
Supports .ply & .splat files as well as custom compressed .ksplat file format
Support for progressive loading & simultaneous rendering
The initial implementation of this feature was pretty standard: A depth-map for the scene was rendered to a WebGL cube texture by rendering it six times from six different perspectives - looking down the positive and negative ends of the X, Y, and Z world axes. This implementation worked well and produced a nice looking result.
The initial implementation had one problem: it required extra uniforms to send samplerCube values to the shaders whenever objects that might receive shadows are rendered (Existing shadow mapping code for spot and directional lights used 2D textures). At the time WebGL was based on OpenGL ES 2.0, and there were somewhat restrictive limits on the number of uniforms and attributes available to shaders. After discussion with the core contributors to Three.js, we decided to implement a cube-to-2D projection of the cube map by using viewport adjustments to render each face of the cube onto a single 2D texture. Creating the 2D projection was the easy part; the tricky part was converting a 3D vector that was normally used to access a samplerCube into a 2D vector designed to access a sampler2D.
General purpose particle system for Three.js. This implementation exposes typical physical and visual attributes for each particle:
Position
Velocity
Acceleration
Rotation
Rotational speed
Rotational acceleration
Color
Size
Opacity
Texture
Position
Velocity
Acceleration
Rotation
Rotational speed
Rotational acceleration
Color
Size
Opacity
Texture
An "Initializer" can be assigned to each of the attributes mentioned above in order to initialize a particle to a desired state when it is created.
An "Operator" can be assigned to each attribute to vary its value over the lifetime of the particle. The current implementation also supports the concept of a texture atlas so particle textures can be animated.
Basic trail renderer for Three.js. This library allows for the straight-forward attachment of motion trails to any 3D object.
The programmer simply has to specify the shape of the trail and its target (the target must be a Three.js Object3D instance).
The update of the trail is handled automatically by the library.
The shape of the trail is specified by supplying a list of 3D points. These points make up the local-space head of the trail.
During the update phase for the trail, a new instance of the head is created by transforming the local points into world-space using the
target Object3D instance's local-to-world transformation matrix. These points are then connected to the existing head of the trail to
extend the trail's geometry.
The trail renderer currently supports both textured and non-textured trails. Non-textured trails work well with many trail shapes in both translucent and opaque modes.
Textured trails work well with many shapes as long as the trail is opaque; if the trail is not opaque, flat shapes work best.