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

WebGL:
The graphics API
for web developers

yomotsu
June 18, 2015

WebGL:
The graphics API
for web developers

my slide at GREE Tech Talk #08 : WebGL http://techtalk.labs.gree.jp/08/

yomotsu

June 18, 2015
Tweet

More Decks by yomotsu

Other Decks in Programming

Transcript

  1. • A Web Standerd • A JavaScript feature • Great

    performance • Programable Shaders in GLSL
  2. vec3(-1, -1, 0) vec3( 1, -1, 0) vec3(-1, 1, 0)

    vec3(-1, 1, 0) vec3( 1, -1, 0) vec3( 1, 1, 0) ... 1 0 0 0 1 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 ✕ position matrix
  3. for ( var i = 0, l = position.length; i

    < l; i ++ ) { ! matrix.multiplyVector( position[ i ] ); ! }
  4. • Tech definitions • Verbose initialization of WebGL • Shaders

    in GLSL • Math: Linear algebra, physics, etc… :PVTUJMMIBWFUPMFBSO
  5. <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>=^.^=</title> </head> <body> <script

    src="./lib/three.min.js"></script> <script> var width = window.innerWidth, height = window.innerHeight; ! var scene = new THREE.Scene(); ! var camera = new THREE.PerspectiveCamera( 40, width / height, 1, 1000 ); camera.position.set( 0, 0, 3 ); ! var renderer = new THREE.WebGLRenderer(); renderer.setSize( width, height ); document.body.appendChild( renderer.domElement ); !
  6. <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>=^.^=</title> </head> <body> <script

    src="./lib/three.min.js"></script> <script> var width = window.innerWidth, height = window.innerHeight; ! var scene = new THREE.Scene(); ! var camera = new THREE.PerspectiveCamera( 40, width / height, 1, 1000 ); camera.position.set( 0, 0, 3 ); ! var renderer = new THREE.WebGLRenderer(); renderer.setSize( width, height ); document.body.appendChild( renderer.domElement ); ! load pixi.js
  7. <script> var width = window.innerWidth, height = window.innerHeight; ! var

    scene = new THREE.Scene(); ! var camera = new THREE.PerspectiveCamera( 40, width / height, 1, 1000 ); camera.position.set( 0, 0, 3 ); ! var renderer = new THREE.WebGLRenderer(); renderer.setSize( width, height ); document.body.appendChild( renderer.domElement ); ! var directionalLight = new THREE.DirectionalLight( 0xffffff ); directionalLight.position.set( 0, 1, 1 ).normalize(); scene.add( directionalLight ); ! var box = new THREE.Mesh( new THREE.BoxGeometry( 1, 1, 1 ), new THREE.MeshPhongMaterial( { color: 0xff0000 } ) ); make a scene
  8. <script> var width = window.innerWidth, height = window.innerHeight; ! var

    scene = new THREE.Scene(); ! var camera = new THREE.PerspectiveCamera( 40, width / height, 1, 1000 ); camera.position.set( 0, 0, 3 ); ! var renderer = new THREE.WebGLRenderer(); renderer.setSize( width, height ); document.body.appendChild( renderer.domElement ); ! var directionalLight = new THREE.DirectionalLight( 0xffffff ); directionalLight.position.set( 0, 1, 1 ).normalize(); scene.add( directionalLight ); ! var box = new THREE.Mesh( new THREE.BoxGeometry( 1, 1, 1 ), new THREE.MeshPhongMaterial( { color: 0xff0000 } ) ); make a camera
  9. var scene = new THREE.Scene(); ! var camera = new

    THREE.PerspectiveCamera( 40, width / height, 1, 1000 ); camera.position.set( 0, 0, 3 ); ! var renderer = new THREE.WebGLRenderer(); renderer.setSize( width, height ); document.body.appendChild( renderer.domElement ); ! var directionalLight = new THREE.DirectionalLight( 0xffffff ); directionalLight.position.set( 0, 1, 1 ).normalize(); scene.add( directionalLight ); ! var box = new THREE.Mesh( new THREE.BoxGeometry( 1, 1, 1 ), new THREE.MeshPhongMaterial( { color: 0xff0000 } ) ); scene.add( box ); ! ( function renderLoop () { ! make a renderer
  10. ! var renderer = new THREE.WebGLRenderer(); renderer.setSize( width, height );

    document.body.appendChild( renderer.domElement ); ! var directionalLight = new THREE.DirectionalLight( 0xffffff ); directionalLight.position.set( 0, 1, 1 ).normalize(); scene.add( directionalLight ); ! var box = new THREE.Mesh( new THREE.BoxGeometry( 1, 1, 1 ), new THREE.MeshPhongMaterial( { color: 0xff0000 } ) ); scene.add( box ); ! ( function renderLoop () { ! requestAnimationFrame( renderLoop ); box.rotation.y += 0.01; renderer.render( scene, camera ); ! make a light
  11. var directionalLight = new THREE.DirectionalLight( 0xffffff ); directionalLight.position.set( 0, 1,

    1 ).normalize(); scene.add( directionalLight ); ! var box = new THREE.Mesh( new THREE.BoxGeometry( 1, 1, 1 ), new THREE.MeshPhongMaterial( { color: 0xff0000 } ) ); scene.add( box ); ! ( function renderLoop () { ! requestAnimationFrame( renderLoop ); box.rotation.y += 0.01; renderer.render( scene, camera ); ! } )(); </script> ! </body> </html> make an 3d object
  12. scene.add( directionalLight ); ! var box = new THREE.Mesh( new

    THREE.BoxGeometry( 1, 1, 1 ), new THREE.MeshPhongMaterial( { color: 0xff0000 } ) ); scene.add( box ); ! ( function renderLoop () { ! requestAnimationFrame( renderLoop ); box.rotation.y += 0.01; renderer.render( scene, camera ); ! } )(); </script> ! </body> </html> render it
  13. • 3D model import • Animations • Math functions (

    such as vector and matrix ) • Build-in Shaders • Post processing effects and more!
  14. <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>=^.^=</title> <style> body{margin: 0;}

    canvas{display: block;} </style> </head> <body> ! <script src="pixi.min.js"></script> ! <script> ! var renderer = new PIXI.autoDetectRenderer( 600, 400, { backgroundColor : 0xCCCCCC } ); document.body.appendChild( renderer.view ); !
  15. <style> body{margin: 0;} canvas{display: block;} </style> </head> <body> ! <script

    src="pixi.min.js"></script> ! <script> ! var renderer = new PIXI.autoDetectRenderer( 600, 400, { backgroundColor : 0xCCCCCC } ); document.body.appendChild( renderer.view ); ! var stage = new PIXI.Container(); ! var monster = new PIXI.Sprite.fromImage( 'monster.png' ); monster.position.set( 100, 50 ); stage.addChild( monster ); load pixi.js
  16. <script src="pixi.min.js"></script> ! <script> ! var renderer = new PIXI.autoDetectRenderer(

    600, 400, { backgroundColor : 0xCCCCCC } ); document.body.appendChild( renderer.view ); ! var stage = new PIXI.Container(); ! var monster = new PIXI.Sprite.fromImage( 'monster.png' ); monster.position.set( 100, 50 ); stage.addChild( monster ); ! var animate = ( function animate() { ! requestAnimationFrame( animate ); renderer.render( stage ); ! } )(); make a renderer
  17. backgroundColor : 0xCCCCCC } ); document.body.appendChild( renderer.view ); ! var

    stage = new PIXI.Container(); ! var monster = new PIXI.Sprite.fromImage( 'monster.png' ); monster.position.set( 100, 50 ); stage.addChild( monster ); ! var animate = ( function animate() { ! requestAnimationFrame( animate ); renderer.render( stage ); ! } )(); ! </script> ! </body> </html> make a container as a stage
  18. backgroundColor : 0xCCCCCC } ); document.body.appendChild( renderer.view ); ! var

    stage = new PIXI.Container(); ! var monster = new PIXI.Sprite.fromImage( 'monster.png' ); monster.position.set( 100, 50 ); stage.addChild( monster ); ! var animate = ( function animate() { ! requestAnimationFrame( animate ); renderer.render( stage ); ! } )(); ! </script> ! </body> </html> make a display object
  19. var stage = new PIXI.Container(); ! var monster = new

    PIXI.Sprite.fromImage( 'monster.png' ); monster.position.set( 100, 50 ); stage.addChild( monster ); ! var animate = ( function animate() { ! requestAnimationFrame( animate ); renderer.render( stage ); ! } )(); ! </script> ! </body> </html> render it
  20. • Sprite and spine animations • Mouse and touch events

    • Pixel manipulation with WebGL • Custom shaders and more
  21. • Stage has been deprecated, now container • Name spaces

    has been changed • EventListener has been supported • Color matrix has been changed to 5x4 from 4x4 and many changes %JGGFSFODFTCFUXFFO7BOE7
  22. <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>=^.^=</title> <style> body{margin: 0;}

    canvas{display: block;} </style> </head> <body> ! <canvas id="canvas" width="512" height="512"></canvas> ! ! <script src="twgl-full.js"></script> <script> ! var canvas = document.getElementById( 'canvas' ); canvas.width = window.innerWidth; canvas.height = window.innerHeight;
  23. </head> <body> ! <canvas id="canvas" width="512" height="512"></canvas> ! ! <script

    src="twgl-full.js"></script> <script> ! var canvas = document.getElementById( 'canvas' ); canvas.width = window.innerWidth; canvas.height = window.innerHeight; ! var gl = twgl.getWebGLContext( canvas ); ! var vs = [ 'attribute vec3 position;', 'attribute vec2 texcoord;', 'uniform mat4 projectionMatrix;', 'uniform mat4 viewMatrix;', prepare a canvas
  24. </head> <body> ! <canvas id="canvas" width="512" height="512"></canvas> ! ! <script

    src="twgl-full.js"></script> <script> ! var canvas = document.getElementById( 'canvas' ); canvas.width = window.innerWidth; canvas.height = window.innerHeight; ! var gl = twgl.getWebGLContext( canvas ); ! var vs = [ 'attribute vec3 position;', 'attribute vec2 texcoord;', 'uniform mat4 projectionMatrix;', 'uniform mat4 viewMatrix;', load twgl.js
  25. ! <script src="twgl-full.js"></script> <script> ! var canvas = document.getElementById( 'canvas'

    ); canvas.width = window.innerWidth; canvas.height = window.innerHeight; ! var gl = twgl.getWebGLContext( canvas ); ! var vs = [ 'attribute vec3 position;', 'attribute vec2 texcoord;', 'uniform mat4 projectionMatrix;', 'uniform mat4 viewMatrix;', 'uniform mat4 modelMatrix;', 'varying vec2 vUv;', 'void main () {', get gl context
  26. ! var vs = [ 'attribute vec3 position;', 'attribute vec2

    texcoord;', 'uniform mat4 projectionMatrix;', 'uniform mat4 viewMatrix;', 'uniform mat4 modelMatrix;', 'varying vec2 vUv;', 'void main () {', 'gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(position, 1.0 );', 'vUv = texcoord;', ! '}' ].join( '\n' ); ! var fs = [ prepare VS source
  27. ].join( '\n' ); ! var fs = [ 'precision mediump

    float;', ! 'uniform sampler2D diffuse;', ! 'varying vec2 vUv;', ! 'void main () {', ! 'vec4 diffuseColor = texture2D( diffuse, vUv );', 'gl_FragColor = diffuseColor;', // 'gl_FragColor = vec4( 0, 0, 0, 1 );', ! '}' ].join( '\n' ); ! var programInfo = twgl.createProgramInfo( gl, [ vs, fs ] ); ! var arrays = { position: { prepare FS source
  28. ! '}' ].join( '\n' ); ! var programInfo = twgl.createProgramInfo(

    gl, [ vs, fs ] ); ! var arrays = { position: { numComponents: 3, data: [ -1, -1, 0, 1, -1, 0, -1, 1, 0, ! -1, 1, 0, 1, -1, 0, 1, 1, 0 ] }, indices: { numComponents: 3, data: [ compile those and
 create a program
  29. ! var arrays = { position: { numComponents: 3, data:

    [ -1, -1, 0, 1, -1, 0, -1, 1, 0, ! -1, 1, 0, 1, -1, 0, 1, 1, 0 ] }, indices: { numComponents: 3, data: [ 0, 1, 2, 3, 4, 5 ] }, prepare attributes
  30. }, indices: { numComponents: 3, data: [ 0, 1, 2,

    3, 4, 5 ] }, texcoord: { numComponents: 2, data: [ 0, 1, 1, 1, 0, 0, ! 0, 0, 1, 1, 1, 0 ] } }; !
  31. }; ! var bufferInfo = twgl.createBufferInfoFromArrays( gl, arrays ); !

    ! var projectionMatrix = twgl.m4.perspective( 30 * Math.PI / 180, gl.canvas.clientWidth / gl.canvas.clientHeight, 1, 1000 ); var viewMatrix = twgl.m4.translate( twgl.m4.identity(), [ 0, 0 ,-5 ] ); var modelMatrix = twgl.m4.rotationY( 1 ); ! ! var tex = twgl.createTexture( gl, { min: gl.NEAREST, mag: gl.NEAREST, src: './uv.png' }, function () {} ); ! make a buffer
  32. ! var projectionMatrix = twgl.m4.perspective( 30 * Math.PI / 180,

    gl.canvas.clientWidth / gl.canvas.clientHeight, 1, 1000 ); var viewMatrix = twgl.m4.translate( twgl.m4.identity(), [ 0, 0 ,-5 ] ); var modelMatrix = twgl.m4.rotationY( 1 ); ! ! var tex = twgl.createTexture( gl, { min: gl.NEAREST, mag: gl.NEAREST, src: './uv.png' }, function () {} ); ! var uniforms = { projectionMatrix: projectionMatrix, viewMatrix : viewMatrix, modelMatrix : modelMatrix, prepare unifroms
  33. }, function () {} ); ! var uniforms = {

    projectionMatrix: projectionMatrix, viewMatrix : viewMatrix, modelMatrix : modelMatrix, diffuse : tex }; ! var render = function ( time ) { ! twgl.resizeCanvasToDisplaySize( gl.canvas ); gl.viewport( 0, 0, gl.canvas.width, gl.canvas.height ); uniforms.modelMatrix = twgl.m4.rotationY( time * 0.001 ); ! gl.useProgram( programInfo.program ); twgl.setBuffersAndAttributes( gl, programInfo, bufferInfo ); twgl.setUniforms( programInfo, uniforms ); gl.drawElements( gl.TRIANGLES, bufferInfo.numElements, gl.UNSIGNED_SHORT, 0 ); !
  34. ! var render = function ( time ) { !

    twgl.resizeCanvasToDisplaySize( gl.canvas ); gl.viewport( 0, 0, gl.canvas.width, gl.canvas.height ); uniforms.modelMatrix = twgl.m4.rotationY( time * 0.001 ); ! gl.useProgram( programInfo.program ); twgl.setBuffersAndAttributes( gl, programInfo, bufferInfo ); twgl.setUniforms( programInfo, uniforms ); gl.drawElements( gl.TRIANGLES, bufferInfo.numElements, gl.UNSIGNED_SHORT, 0 ); ! requestAnimationFrame( render ); ! }; ! render( 0 ); ! </script> ! render it!
  35. • WebUI for 3D contents
 Still not exist a lot

    • Multiple devices
 High-End Gaming PC, Laptop, Mobile and others • Internet Connection 8IBUXFOFFEUPUIJOLBCPVU
  36. • Number of polygons
 esp. file size • Texture size

    • Resolution • Number of Draw-calls 8IBUXFOFFEUPDBSFBCPVU
  37. Like 3DS, PSP, PSVita FYI: Playable characters in FINAL FANTASY

    TYPE-0 consist of
 about 1000 tris and 76KB textures http://hexadrive.jp/lab/case/1573/
  38. d = navigator.
 getVRDevices() •d[ i ].VRDevice (Type of the

    device) •d[ i ].VREyeParameters •FOV •eyeTranslation •d[ i ].VRPositionState •position •velocity •orientation •angularVelocity othres...
  39. Virtuix Omni Locomotion HMD Cyberith Virtualizer OCULUS Rift SONY Morpheus

    HTC Vine • Leap Motion • PrioVR • Control VR • Sixense Stem • Razer Hydra Others
  40. Drop-in Phone
 Viewers • Different APIs
 (It will use DeviceOrientation

    API instead) • Limited performance
 (Stereo rendering on mobile device)