Upgrade to Pro — share decks privately, control downloads, hide ads and more …

WebGL Libs for
 WebApp Frameworks

yomotsu
September 24, 2017

WebGL Libs for
 WebApp Frameworks

yomotsu

September 24, 2017
Tweet

More Decks by yomotsu

Other Decks in Programming

Transcript

  1. webpack three.js pixi.js etc React Vue.js Angular etc three.js logo:

    https://github.com/mrdoob/three.js/issues/2789
  2. Tips for development with frameworks + WebGL libs: 1. Import

    three.js plugins in webpack. 2. Handle Canvas and Renderer as a WebApp view. 3. Remove Canvas and GL context appropriately. 4. Assets compressing. Agenda
  3. import * as THREE from 'three'; THREE.OrbitControls = require( 'imports-loader?THREE!

    exports-loader?THREE.OrbitControls!../node_modules/ three/examples/js/controls/OrbitControls.js' ); // snip const controls = new THREE.OrbitControls( camera );
  4. import * as THREE from 'three'; THREE.OrbitControls = require( 'imports-loader?THREE!

    exports-loader?THREE.OrbitControls!../node_modules/ three/examples/js/controls/OrbitControls.js' ); // snip const controls = new THREE.OrbitControls( camera );
  5. import * as THREE from 'three'; THREE.OrbitControls = require( 'imports-loader?THREE!

    exports-loader?THREE.OrbitControls!../node_modules/ three/examples/js/controls/OrbitControls.js' ); // snip const controls = new THREE.OrbitControls( camera );
  6. import * as THREE from 'three'; THREE.OrbitControls = require( 'imports-loader?THREE!

    exports-loader?THREE.OrbitControls!../node_modules/ three/examples/js/controls/OrbitControls.js' ); // snip const controls = new THREE.OrbitControls( camera );
  7. import * as THREE from 'three'; THREE.OrbitControls = require( 'imports-loader?THREE!

    exports-loader?THREE.OrbitControls!../node_modules/ three/examples/js/controls/OrbitControls.js' ); // snip const controls = new THREE.OrbitControls( camera );
  8. import * as THREE from 'three'; THREE.OrbitControls = require( 'imports-loader?THREE!

    exports-loader?THREE.OrbitControls!../node_modules/ three/examples/js/controls/OrbitControls.js' ); // snip const controls = new THREE.OrbitControls( camera );
  9. import * as THREE from 'three'; THREE.OrbitControls = require( 'imports-loader?THREE!

    exports-loader?THREE.OrbitControls!../node_modules/ three/examples/js/controls/OrbitControls.js' ); // snip const controls = new THREE.OrbitControls( camera );
  10. <template> <canvas></canvas> </template> <script> import * as THREE from 'three';

    export default { name: 'view-3d', data () { return { width: 200, height: 200 mount a canvas element
  11. } }, mounted() { const width = this.width; const height

    = this.height; const loader = new THREE.JSONLoader(); // (snip) this.renderer = new THREE.WebGLRenderer( { canvas: this.$el, // <-- bind to mouted canvas antialias: true, stencil: false } );
  12. return {} }, mounted() { this.renderer = new PIXI.WebGLRenderer( {

    width: 300, height: 300, view: this.$el, antialias: true, transparent: false, backgroundColor: 0xcccccc } );
  13. tick() { if ( ! this.running ) return; requestAnimationFrame( ()

    => this.tick() ); this.mesh.rotation.y += 0.03; this.renderer.render( this.scene, this.camera ); } Your render loop
  14. beforeDestroy() { this.running = false; while ( this.scene.children.length > 0

    ) { const object = this.scene.children[ this.scene.children.length - 1 ]; deepDispose( object ); this.scene.remove( object ); } this.renderer.dispose(); this.renderer.forceContextLoss(); this.renderer.context = undefined; this.renderer.domElement = undefined; // until next garbage collection this.$el.width = 1; this.$el.height = 1; }, Dispose all objects
  15. beforeDestroy() { this.running = false; while ( this.scene.children.length > 0

    ) { const object = this.scene.children[ this.scene.children.length - 1 ]; deepDispose( object ); this.scene.remove( object ); } this.renderer.dispose(); this.renderer.forceContextLoss(); this.renderer.context = undefined; this.renderer.domElement = undefined; // until next garbage collection this.$el.width = 1; this.$el.height = 1; }, Children of scene consist of • Meshes • Lights • Object3d
  16. function deepDispose( object3D ) { object3D.traverse( object3D => dispose( object3D

    ) ); } function dispose ( object3D ) { if ( !! object3D.geometry ) { object3D.geometry.dispose(); object3D.geometry = undefined; } if ( !! object3D.material && object3D.material instanceof Array ) { object3D.material.forEach( material => disposeMaterial( material ) );
  17. function deepDispose( object3D ) { object3D.traverse( object3D => dispose( object3D

    ) ); } function dispose ( object3D ) { if ( !! object3D.geometry ) { object3D.geometry.dispose(); object3D.geometry = undefined; } if ( !! object3D.material && object3D.material instanceof Array ) { object3D.material.forEach( material => disposeMaterial( material ) );
  18. function dispose ( object3D ) { if ( !! object3D.geometry

    ) { object3D.geometry.dispose(); object3D.geometry = undefined; } if ( !! object3D.material && object3D.material instanceof Array ) { object3D.material.forEach( material => disposeMaterial( material ) ); } else if ( !! object3D.material ) { disposeMaterial( material ); }
  19. function disposeMaterial( material ) { if ( !! material.map )

    { material.map.dispose(); material.map = undefined; } // do that for normalMap, specularMap and bumpMap too material.dispose(); material = undefined; }
  20. Before unmount: • Stop render loop. • Dispose all geoms,

    materials and textures recursively. • Release renderer and context. • Resize canvas to 1px * 1px.
  21. tick() { if ( ! this.running ) return; requestAnimationFrame( ()

    => this.tick() );
 this.movieClip.rotation += 0.03; this.renderer.render( this.stage ); }
  22. beforeDestroy() { this.running = false; const destroyChildren = true; this.stage.destroy(

    destroyChildren ); this.renderer.destroy(); this.renderer.view = undefined; // until next garbage collection this.$el.width = 1; this.$el.height = 1; },
  23. Before unmount: • Stop render loop. • Destroy the stage

    with deep option. • Release renderer and context. • Resize canvas to 1px * 1px.
  24. FYI: May not necessary to remove the canvas. It may

    cause flickering. Consider to just hide it.
  25. const DRACO_PATH = './libs/'; const DRACO_TYPE = !! window.WebAssembly ?

    'wasm' : 'js'; const dracoLoader = new THREE.DRACOLoader( DRACO_PATH, { type: DRACO_TYPE } ); dracoLoader.load( './model/rameses.drc', ( geometry ) => { const material = new THREE.MeshStandardMaterial( { map: texture } ); const mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); } );
  26. const DRACO_PATH = './libs/'; const DRACO_TYPE = !! window.WebAssembly ?

    'wasm' : 'js'; const dracoLoader = new THREE.DRACOLoader( DRACO_PATH, { type: DRACO_TYPE } ); dracoLoader.load( './model/rameses.drc', ( geometry ) => { const material = new THREE.MeshStandardMaterial( { map: texture } ); const mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); The decoder will be loaded from external file.
 You need set the path to it.
  27. const DRACO_PATH = './libs/'; const DRACO_TYPE = !! window.WebAssembly ?

    'wasm' : 'js'; const dracoLoader = new THREE.DRACOLoader( DRACO_PATH, { type: DRACO_TYPE } ); dracoLoader.load( './model/rameses.drc', ( geometry ) => { const material = new THREE.MeshStandardMaterial( { map: texture } ); const mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); The recorder is available in both Wasm and JS. Use preferred version.
  28. const DRACO_PATH = './libs/'; const DRACO_TYPE = !! window.WebAssembly ?

    'wasm' : 'js'; const dracoLoader = new THREE.DRACOLoader( DRACO_PATH, { type: DRACO_TYPE } ); dracoLoader.load( './model/rameses.drc', ( geometry ) => { const material = new THREE.MeshStandardMaterial( { map: texture } ); const mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); Make a loader instance for three.js
  29. const DRACO_PATH = './libs/'; const DRACO_TYPE = !! window.WebAssembly ?

    'wasm' : 'js'; const dracoLoader = new THREE.DRACOLoader( DRACO_PATH, { type: DRACO_TYPE } ); dracoLoader.load( './model/rameses.drc', ( geometry ) => { const material = new THREE.MeshStandardMaterial( { map: texture } ); const mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); } ); Load a drc file
  30. const DRACO_PATH = './libs/'; const DRACO_TYPE = !! window.WebAssembly ?

    'wasm' : 'js'; const dracoLoader = new THREE.DRACOLoader( DRACO_PATH, { type: DRACO_TYPE } ); dracoLoader.load( './model/rameses.drc', ( geometry ) => { const material = new THREE.MeshStandardMaterial( { map: texture } ); const mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); } );
  31. three.js / pixi.js and others can be
 a part of

    WebApp! Not only for artistic projects. Conclusion