WebGL / WebVR
for FrontEnd Engineer

3c557c6103a4addc52f7b76ffd0a0f27?s=47 yomotsu
February 25, 2017

WebGL / WebVR
for FrontEnd Engineer

3c557c6103a4addc52f7b76ffd0a0f27?s=128

yomotsu

February 25, 2017
Tweet

Transcript

  1. WebGL / WebVR
 for FrontEnd Engineer Presented by Akihiro Oyamada

    (@yomotsu) Feb 25, 2017
  2. Frontend Engineer at PixelGrid, Inc. Akihiro Oyamada @yomotsu

  3. I don’t talk about WebVR much… Disclaimer...

  4. None
  5. http://yomotsu.net/blog/assets/2016-12-25-xmas/ http://www.welcometofillory.com/ https://plus360degrees.com/uxcars/ http://www.playkeepout.com/

  6. Almost native app looks!
 Cuz it works on top of

    native graphic APIs
  7. None
  8. Sounds difficult? There are libraries!

  9. None
  10. Pros • Strong and large community • Docs and examples

    • JS friendly easy APIs • Low level WebGL access Cons • Doesn't follow semver,
 Breaking changes sometime • Tricky garbage collection
  11. None
  12. None
  13. None
  14. var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera(

    60, width / height, 1, 1000 ); camera.position.set( 0, 0, 5 ); var renderer = new THREE.WebGLRenderer(); renderer.setSize( width, height ); document.body.appendChild( renderer.domElement ); var light = new THREE.HemisphereLight( 0x443333, 0x332222, 2 ); scene.add( light ); var geometry = new THREE.SphereGeometry( 2, 2, 2 ); var material = new THREE.MeshPhongMaterial( { color: 0xff0000 } ); var mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); renderer.render( scene, camera );
  15. let’s move onto the main topics for today

  16. • Avoid unnecessary rendering • Reduce drawcalls • Avoid frequent

    texture uploading • Consider to use GPU • Compress 3D assets
  17. Avoid unnecessary rendering

  18. Continuously re-rendering Better

  19. demo 19 http://localhost:8000/1_re-rendering/bad.html http://localhost:8000/1_re-rendering/better.html

  20. ( function anim () { requestAnimationFrame( anim ); renderer.render( scene,

    camera ); } )(); Re-rendering may unnecessary
  21. window.addEventListener( 'resize', function () { const width = window.innerWidth; const

    height = window.innerHeight; camera.aspect = width / height; camera.updateProjectionMatrix(); renderer.setSize( width, height );
 renderer.render( scene, camera ); // <- don't do this! } ); Re-rendering may unnecessary
  22. ( function anim () { requestAnimationFrame( anim ); if (

    !myApp.needsUpdate ) { return; } renderer.render( scene, camera ); } )(); Pass re-rendering if unnecessary
  23. var prevPosition = new THREE.Vector3(); var checkCameraPosition = function ()

    { if ( !approximatelyEqual( camera.position, prevPosition ) ) { myApp.needsUpdate = true; } prevPosition.copy( camera.position ); }; Checking “needsUpdate”
  24. window.addEventListener( 'resize', function () { const width = window.innerWidth; const

    height = window.innerHeight; camera.aspect = width / height; camera.updateProjectionMatrix(); renderer.setSize( width, height );
 myApp.needsUpdate = true; // for next rAF } ); Checking “needsUpdate”
  25. Reduce drawcalls

  26. Continuously repainting Better 8 drawcalls 1 drawcall

  27. demo 27 http://localhost:8000/2_texture-atlas/1_house1.html http://localhost:8000/2_texture-atlas/2_house2.html

  28. .FSHFNBUFSJBMT

  29. 3 drawcalls for 3 objects 1 drawcall 3 objects

  30. demo 30 http://localhost:8000/2_texture-atlas/3_house-multi1.html http://localhost:8000/2_texture-atlas/4_house-multi2.html http://localhost:8000/2_texture-atlas/5_house-multi3.html

  31. var houseGeometry = ...; var houseGeometry2 = ...;
 houseGeometry2.applyMatrix( new

    THREE.Matrix4().makeTranslation( -10, 0, 0 ) ); houseGeometry.merge( houseGeometry2 ); Merge geometries
  32. Avoid frequent
 texture uploading

  33. None
  34. demo 34 http://localhost:8000/3_spriteAnim/bad.html http://localhost:8000/3_spriteAnim/better.html

  35. None
  36. None
  37. $16BOE(16
 BSFQIZTJDBMMZTFQBSBUFE

  38. ( function anim () { var elapsed = clock.getElapsedTime(); requestAnimationFrame(

    anim ); texture.image = images[ frame ]; texture.needsUpdate = true; renderer.render( scene, camera ); frame = ( elapsed * 20 % images.length ) | 0; } )(); Bad: Replacing image
  39. ( function anim () { var elapsed = clock.getElapsedTime(); requestAnimationFrame(

    anim ); texture.offset.set( frame % frameCol / frameCol, ( frameRow - 1 ) / frameRow - ( ( frame / frameCol ) | 0 ) / frameRow ); renderer.render( scene, camera ); frame = ( elapsed * 20 % frameLength ) | 0; } )(); Better: Use UV offset
  40. None
  41. var rtt = new THREE.WebGLRenderTarget( 512, 512,
 { minFilter: THREE.LinearFilter,

    magFilter: THREE.NearestFilter, format: THREE.RGBFormat } ); renderer.render( sceneRTT, cameraRTT, rtt, true ); RTT
  42. GPU may be utilised

  43. None
  44. demo 44 http://localhost:8000/4_particle/bad.html http://localhost:8000/4_particle/better.html

  45. requestAnimationFrame( anim ); for ( var i = 0, l

    = particleLength; i < l; i ++ ) { if ( geometry.attributes.position.array[ i * 3 + 1 ] > - boxHeight * 0.5 ) { geometry.attributes.position.array[ i * 3 + 1 ] -= delta; } else { geometry.attributes.position.array[ i * 3 + 1 ] = boxHeight * 0.5; } }; geometry.attributes.position.needsUpdate = true; Calc in CPU
  46. uniform float time; uniform float height; uniform float scale; void

    main () { vec3 pos = vec3( position.x, position.y - time * 1.0, position.z ); pos.y = mod( pos.y, height ) - ( height * 0.5 ); vec4 mvPosition = modelViewMatrix * vec4( pos, 1.0 ); gl_Position = projectionMatrix * mvPosition; gl_PointSize = 1.0; } Calc in GPU (Shader)
  47. Compress 3D assets

  48. 3D Model file consists of mostly numbers

  49. 3D scanned(ish) Model file

  50. http://localhost:8000/5_compress/bad.html

  51. None
  52. Save 70% of size!

  53. None
  54. zip is an
 archive format

  55. Multiple files
 in one zip file

  56. • Contains multi files • Compressed One file • Arrows

    you to make
 a progressive bar • UnZip JS libs are
 available on GitHub
  57. None
  58. None
  59. https://opensource.googleblog.com/2017/01/introducing-draco-compression-for-3d.html As of Jan 13, 2017

  60. • Compressing lib for 3D assets • Developed by Google

    • Decompressor is available in JS
 (but 800kb emscripten) Might be still early…?
  61. Conclusion

  62. WebGL is… • Click, then it will open • No

    installing, but loading • Devices/Browsers are unspecified
  63. • Write your code efficiently • CPU and GPU are

    separated • Compress 3D assets Conclusion
  64. WebVR?

  65. https://www.youtube.com/watch?v=cBvCS78ZC1c

  66. https://w3c.github.io/webvr/

  67. Navigator.getVRDisplays() params and states

  68. Navigator.getVRDisplays() params and states •d[ i ].VREyeParameters •FOV •offset (eye

    transition) •d[ i ].getPose() •position •orientation (quaternion) and etc…
  69. WebVR is a small API!

  70. None
  71. None
  72. One more thing

  73. None
  74. ... mounted () { const scene = this.getScene(); scene.add( this.mesh

    ); }, beforeDestroy () { const scene = this.getScene(); // optional // this.mesh.material.map.dispose(); // this.mesh.geometry.dispose(); // this.mesh.material.dispose(); scene.remove( this.mesh ); },
  75. WebGL can be used
 with WebApp frameworks!

  76. 
 for FrontEnd Engineer Presented by Akihiro Oyamada (@yomotsu) Feb

    25, 2017 WebGL / WebVR

  77. three.js
 for FrontEnd Engineer Presented by Akihiro Oyamada (@yomotsu) Feb

    25, 2017
  78. gl.finish(); @yomotsu

  79. Ξϯέʔτʹ
 ͝ڠྗ͍ͩ͘͞ http://bit.ly/2meQNnL gl.finish(); @yomotsu