Slide 1

Slide 1 text

WebGL / WebVR
 for FrontEnd Engineer Presented by Akihiro Oyamada (@yomotsu) Feb 25, 2017

Slide 2

Slide 2 text

Frontend Engineer at PixelGrid, Inc. Akihiro Oyamada @yomotsu

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

Almost native app looks!
 Cuz it works on top of native graphic APIs

Slide 7

Slide 7 text

No content

Slide 8

Slide 8 text

Sounds difficult? There are libraries!

Slide 9

Slide 9 text

No content

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

No content

Slide 12

Slide 12 text

No content

Slide 13

Slide 13 text

No content

Slide 14

Slide 14 text

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 );

Slide 15

Slide 15 text

let’s move onto the main topics for today

Slide 16

Slide 16 text

• Avoid unnecessary rendering • Reduce drawcalls • Avoid frequent texture uploading • Consider to use GPU • Compress 3D assets

Slide 17

Slide 17 text

Avoid unnecessary rendering

Slide 18

Slide 18 text

Continuously re-rendering Better

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

( function anim () { requestAnimationFrame( anim ); renderer.render( scene, camera ); } )(); Re-rendering may unnecessary

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

( function anim () { requestAnimationFrame( anim ); if ( !myApp.needsUpdate ) { return; } renderer.render( scene, camera ); } )(); Pass re-rendering if unnecessary

Slide 23

Slide 23 text

var prevPosition = new THREE.Vector3(); var checkCameraPosition = function () { if ( !approximatelyEqual( camera.position, prevPosition ) ) { myApp.needsUpdate = true; } prevPosition.copy( camera.position ); }; Checking “needsUpdate”

Slide 24

Slide 24 text

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”

Slide 25

Slide 25 text

Reduce drawcalls

Slide 26

Slide 26 text

Continuously repainting Better 8 drawcalls 1 drawcall

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

.FSHFNBUFSJBMT

Slide 29

Slide 29 text

3 drawcalls for 3 objects 1 drawcall 3 objects

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

var houseGeometry = ...; var houseGeometry2 = ...;
 houseGeometry2.applyMatrix( new THREE.Matrix4().makeTranslation( -10, 0, 0 ) ); houseGeometry.merge( houseGeometry2 ); Merge geometries

Slide 32

Slide 32 text

Avoid frequent
 texture uploading

Slide 33

Slide 33 text

No content

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

No content

Slide 36

Slide 36 text

No content

Slide 37

Slide 37 text

$16BOE(16
 BSFQIZTJDBMMZTFQBSBUFE

Slide 38

Slide 38 text

( 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

Slide 39

Slide 39 text

( 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

Slide 40

Slide 40 text

No content

Slide 41

Slide 41 text

var rtt = new THREE.WebGLRenderTarget( 512, 512,
 { minFilter: THREE.LinearFilter, magFilter: THREE.NearestFilter, format: THREE.RGBFormat } ); renderer.render( sceneRTT, cameraRTT, rtt, true ); RTT

Slide 42

Slide 42 text

GPU may be utilised

Slide 43

Slide 43 text

No content

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

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)

Slide 47

Slide 47 text

Compress 3D assets

Slide 48

Slide 48 text

3D Model file consists of mostly numbers

Slide 49

Slide 49 text

3D scanned(ish) Model file

Slide 50

Slide 50 text

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

Slide 51

Slide 51 text

No content

Slide 52

Slide 52 text

Save 70% of size!

Slide 53

Slide 53 text

No content

Slide 54

Slide 54 text

zip is an
 archive format

Slide 55

Slide 55 text

Multiple files
 in one zip file

Slide 56

Slide 56 text

• Contains multi files • Compressed One file • Arrows you to make
 a progressive bar • UnZip JS libs are
 available on GitHub

Slide 57

Slide 57 text

No content

Slide 58

Slide 58 text

No content

Slide 59

Slide 59 text

https://opensource.googleblog.com/2017/01/introducing-draco-compression-for-3d.html As of Jan 13, 2017

Slide 60

Slide 60 text

• Compressing lib for 3D assets • Developed by Google • Decompressor is available in JS
 (but 800kb emscripten) Might be still early…?

Slide 61

Slide 61 text

Conclusion

Slide 62

Slide 62 text

WebGL is… • Click, then it will open • No installing, but loading • Devices/Browsers are unspecified

Slide 63

Slide 63 text

• Write your code efficiently • CPU and GPU are separated • Compress 3D assets Conclusion

Slide 64

Slide 64 text

WebVR?

Slide 65

Slide 65 text

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

Slide 66

Slide 66 text

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

Slide 67

Slide 67 text

Navigator.getVRDisplays() params and states

Slide 68

Slide 68 text

Navigator.getVRDisplays() params and states •d[ i ].VREyeParameters •FOV •offset (eye transition) •d[ i ].getPose() •position •orientation (quaternion) and etc…

Slide 69

Slide 69 text

WebVR is a small API!

Slide 70

Slide 70 text

No content

Slide 71

Slide 71 text

No content

Slide 72

Slide 72 text

One more thing

Slide 73

Slide 73 text

No content

Slide 74

Slide 74 text

... 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 ); },

Slide 75

Slide 75 text

WebGL can be used
 with WebApp frameworks!

Slide 76

Slide 76 text


 for FrontEnd Engineer Presented by Akihiro Oyamada (@yomotsu) Feb 25, 2017 WebGL / WebVR


Slide 77

Slide 77 text

three.js
 for FrontEnd Engineer Presented by Akihiro Oyamada (@yomotsu) Feb 25, 2017

Slide 78

Slide 78 text

gl.finish(); @yomotsu

Slide 79

Slide 79 text

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