t3d.js (ThingJS 3D Engine)

repository·dev·Indexed 42 days ago

https://github.com/uinosoft/t3d.js

A lightweight, web-first, and extendable 3D rendering library designed for high-performance web3D workflows. Version 0.5.4 provides a three.js-inspired API with modern optimizations like clustered lighting, customizable rendering callbacks, and support for glTF extensions such as KHR_materials_sheen and KHR_texture_transform.

Tokens
9.7K
Snippets
15
Records
46
Agent score
52%

What's inside t3d

  1. t3d Extensions and Tools

    dev

    The t3d ecosystem includes several specialized extensions and developer tools:

    Extensions

    • t3d-effect-composer: Post Effects extension.
    • t3d-particle: Particle system implementation.
    • t3d-pano: Panorama extension.
    • t3d-3dtiles: 3dtile support.
    • t3d-dynamic-sky: Dynamic sky addon.
    • t3d-gaussian-splatting: 3D Gaussian Splatting implementation.

    Tools

    • t3d-model-viewer: A model viewer built with t3d and t3d-effect-composer.
    • t3d-particle-editor: An editor for the t3d-particle system.
    • t3d-ibl-baker: A tool to bake Image Based Lighting (IBL) maps.
  2. Verify tangent vector generation with Normal-Tangent Test

    dev

    The NormalTangentTest model is a diagnostic tool used to verify if a rendering engine correctly calculates and handles tangent vectors at runtime. Unlike models that provide pre-computed tangent vectors, this model relies on the engine to generate them.

    How to use this test

    1. Environment Setup: Use an environment map with a clear horizon line. This makes it easy to detect if reflections are level or distorted.
    2. Successful Result: In a correct implementation, reflections of the horizon line should appear level across both real geometry and normal-mapped surfaces.
    3. Failure Detection (Top-down view): When viewing off-axis (e.g., top-down), the illusion of normal-mapping breaks. You should be able to clearly distinguish between real geometry and normal-mapped quads.
    4. Failure Detection (Back-side view): For concave geometry (like mirror-bowls), the sky should be visible below the ground in reflections.

    If you need to test the rendering of supplied tangent vectors instead of runtime generation, use the NormalTangentMirrorTest model.

  3. Draco decoder file variations

    dev

    The Draco library provides two main variations of decoder files depending on your requirements:

    1. Default: Latest stable builds tracking the Draco master branch.
    2. glTF: Builds specifically targeted by the glTF mesh compression extension.

    Each variation includes:

    • draco_decoder.js: An Emscripten-compiled decoder compatible with any modern browser.
    • draco_decoder.wasm: A WebAssembly decoder for newer browsers and devices.
    • draco_wasm_wrapper.js: A JavaScript wrapper for the WASM decoder.
  4. Use the KHR_texture_transform extension in glTF models

    dev

    The t3d.js engine supports the KHR_texture_transform glTF extension, which allows for manipulating how textures are mapped onto geometry using three primary parameters: Offsets, Rotation, and Scale.

    When using models that implement this extension, the engine applies these transformations to the UV coordinates of the mesh. This is useful for tiling textures, rotating patterns, or shifting texture positions without modifying the underlying geometry or the texture file itself.

  5. Understand the GlamVelvetSofa glTF model extensions

    dev

    The GlamVelvetSofa model is a high-fidelity glTF asset designed to demonstrate advanced material rendering for e-commerce. It utilizes several glTF extensions to achieve realistic velvet textures:

    • KHR_materials_variants: Enables switching between five fabric color options (Black, Champagne, Gray, Navy, Pale Pink).
    • KHR_materials_sheen: Simulates how velvet microfibers interact with light at glancing angles.
    • KHR_materials_specular: Used to colorize reflections on dielectric surfaces (like velvet or silk), which traditional PBR metal-roughness models struggle to replicate.
    • KHR_lights_punctual: Provides a directional key light (Intensity: 3) to enhance the sheen response, as sheen effects are more visible under punctual lights than image-based lighting (IBL) alone.
    • KHR_texture_transform: Allows for independent scaling of textures, such as repeating the normal map for fabric detail while keeping the ambient occlusion map at a different scale.
  6. Understand texture transform parameters: Offset, Rotation, and Scale

    dev

    The KHR_texture_transform extension provides three ways to manipulate texture mapping:

    1. Offsets: Shifts the texture coordinates. For example, applying an offset of (0.5, 0.5) to UV coordinates of (0.0, 0.0) will shift the texture position.
    2. Rotation: Rotates the texture around a pivot point. Rotation is typically defined in radians (e.g., 0.392699 radians is approximately 22.5 degrees).
    3. Scale: Resizes the texture mapping. A scale of 1.5 will make the texture appear larger/tiled differently relative to the UV space.

    These parameters can be used individually or combined simultaneously to achieve complex texture effects.

  7. Quick Start: Create a rotating PBR cube

    dev

    This example demonstrates the basic lifecycle of a t3d application: initializing a WebGL2 renderer, creating a scene with a PBR mesh, adding lights and a camera, and running an animation loop.

    Key steps in the loop:

    1. Update mesh rotation.
    2. Call scene.updateMatrix().
    3. Call scene.updateRenderStates(camera).
    4. Call scene.updateRenderQueue(camera).
    5. Call renderer.renderScene(scene, camera, screenRenderTarget).
    // Initialize renderer with WebGL2
    const width = window.innerWidth || 2;
    const height = window.innerHeight || 2;
    
    const canvas = document.createElement('canvas');
    canvas.width = width;
    canvas.height = height;
    document.body.appendChild(canvas);
    
    // Create WebGL2 context and renderer
    const gl = canvas.getContext('webgl2', {
      antialias: true,
      alpha: false
    });
    const renderer = new t3d.WebGLRenderer(gl);
    const screenRenderTarget = new t3d.ScreenRenderTarget(canvas);
    screenRenderTarget.setColorClearValue(0.1, 0.1, 0.1, 1);
    
    // Create scene
    const scene = new t3d.Scene();
    
    // Create mesh with PBR material
    const geometry = new t3d.BoxGeometry(8, 8, 8);
    const material = new t3d.PBRMaterial();
    const mesh = new t3d.Mesh(geometry, material);
    scene.add(mesh);
    
    // Add lighting
    const ambientLight = new t3d.AmbientLight(0xffffff);
    scene.add(ambientLight);
    
    const directionalLight = new t3d.DirectionalLight(0xffffff);
    directionalLight.position.set(-5, 5, 5);
    directionalLight.lookAt(new t3d.Vector3(), new t3d.Vector3(0, 1, 0));
    scene.add(directionalLight);
    
    // Set up camera
    const camera = new t3d.Camera();
    camera.position.set(0, 10, 30);
    camera.lookAt(new t3d.Vector3(0, 0, 0), new t3d.Vector3(0, 1, 0));
    camera.setPerspective(45 / 180 * Math.PI, width / height, 1, 1000);
    scene.add(camera);
    
    // Animation loop
    function loop(count) {
      requestAnimationFrame(loop);
    
      // Rotate cube
      mesh.euler.y = count / 1000 * .5;
    
      scene.updateMatrix();
      scene.updateRenderStates(camera);
      scene.updateRenderQueue(camera);
    
      renderer.renderScene(scene, camera, screenRenderTarget);
    }
    requestAnimationFrame(loop);
  8. Install the t3d engine

    dev

    You can install t3d using npm, or include it directly in your HTML via script tags or CDNs.

    Using npm

    Install the package to your project:

    npm install t3d --save

    Then import the library or specific classes:

    import * as t3d from 't3d';
    // or
    import { Scene, Renderer } from 't3d';

    Using CDN

    Use the following URLs for direct browser usage:

    • Unpkg: https://unpkg.com/t3d@latest/build/t3d.min.js or https://unpkg.com/t3d@latest/build/t3d.module.js
    • jsDelivr: https://cdn.jsdelivr.net/npm/t3d@latest/build/t3d.min.js or https://cdn.jsdelivr.net/npm/t3d@latest/build/t3d.module.min.js
  9. Configure KTX2Loader with Basis Universal transcoders

    dev

    To load .basis or .ktx2 textures using KTX2Loader, you must provide the path to the Basis Universal transcoder files. The transcoder requires two specific files to be present in the directory: basis_transcoder.js (the JavaScript wrapper) and basis_transcoder.wasm (the WebAssembly binary).

    Use setTranscoderPath() to point the loader to the folder containing these files before calling detectSupport() and load().

    const ktx2Loader = new KTX2Loader();
    // Point to the directory containing basis_transcoder.js and basis_transcoder.wasm
    ktx2Loader.setTranscoderPath( 'examples/jsm/libs/basis/' );
    
    // Detect GPU support for compressed formats
    ktx2Loader.detectSupport( renderer );
    
    // Load the texture
    ktx2Loader.load( 'diffuse.ktx2', function ( texture ) {
    	const material = new THREE.MeshStandardMaterial( { map: texture } );
    }, function () {
    	console.log( 'onProgress' );
    }, function ( e ) {
    	console.error( e );
    } );
  10. Configure DRACOLoader with Draco decoders

    dev

    To use Draco 3D data compression for meshes and point clouds, you must provide a path to the decoder files and optionally configure the decoder type. The decoders are provided as draco_decoder.js (Emscripten-compiled) and draco_decoder.wasm (WebAssembly).

    Use setDecoderPath to point to the directory containing these files and setDecoderConfig if you need to manually override the automatic detection of WASM support.

    const dracoLoader = new DRACOLoader();
    dracoLoader.setDecoderPath('path/to/decoders/');
    dracoLoader.setDecoderConfig({type: 'js'}); // (Optional) Override detection of WASM support.
  11. Use the Query API for GPU queries

    dev

    The Query API allows you to perform GPU-side queries (like occlusion or timer queries).

    Query Types

    Use the QUERY_TYPE constant to specify the type of query:

    • ANY_SAMPLES_PASSED: 7000
    • ANY_SAMPLES_PASSED_CONSERVATIVE: 7001
    • TIME_ELAPSED: 7002

    Workflow

    1. Create a new Query instance.
    2. Use WebGLRenderer.beginQuery(query, target) to start the query.
    3. Perform your rendering commands.
    4. Use WebGLRenderer.endQuery(query) to finish the query.
    5. Check WebGLRenderer.isQueryResultAvailable(query) before calling WebGLRenderer.getQueryResult(query) to avoid blocking the CPU.

    Note: The Query class is an EventDispatcher and can be disposed of via .dispose().

    import { Query, QUERY_TYPE } |
      from 't3d';
    
    const query = new Query();
    renderer.beginQuery(query, QUERY_TYPE.TIME_ELAPSED);
    // ... rendering commands ...
    renderer.endQuery(query);
    
    // Later in the loop...
    if (renderer.isQueryResultAvailable(query)) {
      const result = renderer.getQueryResult(query);
      console.log('Elapsed time:', result);
    }
    query.dispose();