Slide 1

Slide 1 text

Low level APIs
 using three.js Presented by Akihiro Oyamada (@yomotsu) Jul 6, 2015

Slide 2

Slide 2 text

Frontend Engineer at PixelGrid, Inc. @yomotsu recent works • http://yomotsu.github.io/walkthrough/ • http://yomotsu.github.io/xmas2014/ Akihiro Oyamada

Slide 3

Slide 3 text

three.js makes WebGL easier

Slide 4

Slide 4 text

• Too lengthy initialization of WebGL • Shaders in GLSL • Math: Linear algebra, physics, etc and others. *USFEVDFT

Slide 5

Slide 5 text

You may think that’s all?

Slide 6

Slide 6 text

You can also use
 low level APIs,
 like pure WebGL.

Slide 7

Slide 7 text

THREE.BufferGeometry
 for attributes

Slide 8

Slide 8 text

THREE.ShaderMaterial and
 THREE.RawShaderMaterial
 for uniforms
 and shaders in GLSL

Slide 9

Slide 9 text

sorry for a CHEAP figure, ive been having a cold…

Slide 10

Slide 10 text

var width = window.innerWidth; var height = window.innerHeight; var clock = new THREE.Clock(); var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera( 60, width / height, .1, 100 ); camera.position.set( 0, 0, 2 ); var renderer = new THREE.WebGLRenderer(); renderer.setSize( width, height ); document.body.appendChild( renderer.domElement ); ! ! var indices = new Uint16Array( [ 0, 1, 2, 3, 4, 5 ] ); ! var vertices = new Float32Array( [ -1, -1, 0, 1, -1, 0, -1, 1, 0, !

Slide 11

Slide 11 text

! ! var indices = new Uint16Array( [ 0, 1, 2, 3, 4, 5 ] ); ! var vertices = new Float32Array( [ -1, -1, 0, 1, -1, 0, -1, 1, 0, ! -1, 1, 0, 1, -1, 0, 1, 1, 0 ] ); ! var uvs = new Float32Array( [ 0, 1, 1, 1, 0, 0, ! 0, 0,

Slide 12

Slide 12 text

! ! var indexBuffer = new THREE.BufferAttribute( indices, 1 ); var vertexBuffer = new THREE.BufferAttribute( vertices, 3 ); var uvBuffer = new THREE.BufferAttribute( uvs, 2 ); ! ! var geometry = new THREE.BufferGeometry(); geometry.addAttribute( 'index', indexBuffer ); geometry.addAttribute( 'position', vertexBuffer ); geometry.addAttribute( 'uv', uvBuffer ); ! ! // // You don't need to put following uniforms. // modelMatrix is automatically linked to `mesh.matrixWorld` // viewMatrix is automatically linked to `camera.matrixWorldInverse` // projectionMatrix is automatically linked to `camera.projectionMatrix` // var uniforms = { // modelMatrix : { type: 'm4', value: new THREE.Matrix4() }, // viewMatrix : { type: 'm4', value: new THREE.Matrix4() }, // projectionMatrix : { type: 'm4', value: new THREE.Matrix4() },

Slide 13

Slide 13 text

! // // You don't need to put following uniforms. // modelMatrix is automatically linked to `mesh.matrixWorld` // viewMatrix is automatically linked to `camera.matrixWorldInverse` // projectionMatrix is automatically linked to `camera.projectionMatrix` // var uniforms = { // modelMatrix : { type: 'm4', value: new THREE.Matrix4() }, // viewMatrix : { type: 'm4', value: new THREE.Matrix4() }, // projectionMatrix : { type: 'm4', value: new THREE.Matrix4() }, diffuse : { type: "t", value: THREE.ImageUtils.loadTexture( 'uv.png' ) } }; ! var vertexShader = [ ! 'attribute vec3 position;', 'attribute vec2 uv;', ! 'uniform mat4 projectionMatrix;', 'uniform mat4 viewMatrix;', 'uniform mat4 modelMatrix;', !

Slide 14

Slide 14 text

! var vertexShader = [ ! 'attribute vec3 position;', 'attribute vec2 uv;', ! 'uniform mat4 projectionMatrix;', 'uniform mat4 viewMatrix;', 'uniform mat4 modelMatrix;', ! 'varying vec2 vUv;', ! 'void main() {', ! ' gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4( position, 1.0 );', ' vUv = uv;', ! '}' ! ].join( "\n" ); ! !

Slide 15

Slide 15 text

! ! var fragmentShader = [ ! 'precision mediump float;', ! 'uniform sampler2D diffuse;', ! 'varying vec2 vUv;', ! 'void main() {', ! 'vec4 diffuseColor = texture2D( diffuse, vUv );', 'gl_FragColor = diffuseColor;', // 'gl_FragColor = vec4( 1 );', ! '}', ! ].join( "\n" ); ! ! var material = new THREE.RawShaderMaterial( { vertexShader : vertexShader, fragmentShader : fragmentShader,

Slide 16

Slide 16 text

! ! var material = new THREE.RawShaderMaterial( { vertexShader : vertexShader, fragmentShader : fragmentShader, attributes : { // if you put custom attributes except // positions, indices, normals, colors and UVs // you need to declare those like // // vertexOpacity: { type: 'f', value: [] } }, uniforms : uniforms, defines : {} } ); ! var mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); ! ! ( function animate () { ! requestAnimationFrame( animate ); !

Slide 17

Slide 17 text

! var mesh = new THREE.Mesh( geometry, material ); scene.add( mesh ); ! ! ( function animate () { ! requestAnimationFrame( animate ); ! var theta = clock.getElapsedTime(); mesh.rotation.set( 0, theta, 0 ); ! renderer.render( scene, camera ); ! } )();

Slide 18

Slide 18 text

18

Slide 19

Slide 19 text

No content

Slide 20

Slide 20 text

A gas-ish fluid object in a MMO game

Slide 21

Slide 21 text

21 https://github.com/yomotsu/VolumetricFire Fire in three.js using
 THREE.BufferGeometry and THREE.RawShaderMaterial

Slide 22

Slide 22 text

Extended build-in shades

Slide 23

Slide 23 text

No content

Slide 24

Slide 24 text

In a MMO game what I play… Similar to THREE.MeshPhongMaterial, but edge of the model is different. It seems, normal directions make it…

Slide 25

Slide 25 text

25 https://github.com/mrdoob/three.js/blob/master/src/renderers/shaders/ShaderLib.js

Slide 26

Slide 26 text

You can use THREE.ShaderChank
 in your custom shader

Slide 27

Slide 27 text

var uniforms = THREE.UniformsUtils.merge( [ ! THREE.UniformsLib[ "common" ], THREE.UniformsLib[ "bump" ], THREE.UniformsLib[ "normalmap" ], THREE.UniformsLib[ "fog" ], THREE.UniformsLib[ "lights" ], THREE.UniformsLib[ "shadowmap" ], ! { "emissive" : { type: "c", value: new THREE.Color( 0x000000 ) }, "specular" : { type: "c", value: new THREE.Color( 0x111111 ) }, "shininess": { type: "f", value: 30 }, "wrapRGB" : { type: "v3", value: new THREE.Vector3( 1, 1, 1 ) } }, ! { // ADDED UNIFROMS The same as actual code of
 build-in PhongMaterial

Slide 28

Slide 28 text

"shininess": { type: "f", value: 30 }, "wrapRGB" : { type: "v3", value: new THREE.Vector3( 1, 1, 1 ) } }, ! { // ADDED UNIFROMS glowColor : { type: "c", value: new THREE.Color( 0x84ccff ) }, viewVector: { type: "v3", value: new THREE.Vector3() }, viewMatrixInverse : { type: 'm4', value: new THREE.Matrix4() } }, ! ] ); ! var vertexShader = [ ! "#define PHONG", ! "varying vec3 vViewPosition;", ! "#ifndef FLAT_SHADED", The same as actual code of
 build-in PhongMaterial

Slide 29

Slide 29 text

! var vertexShader = [ ! "#define PHONG", ! "varying vec3 vViewPosition;", ! "#ifndef FLAT_SHADED", ! " varying vec3 vNormal;", ! "#endif", ! THREE.ShaderChunk[ "common" ], THREE.ShaderChunk[ "map_pars_vertex" ], THREE.ShaderChunk[ "lightmap_pars_vertex" ], THREE.ShaderChunk[ "envmap_pars_vertex" ], THREE.ShaderChunk[ "lights_phong_pars_vertex" ], THREE.ShaderChunk[ "color_pars_vertex" ], THREE.ShaderChunk[ "morphtarget_pars_vertex" ], The same as actual code of
 build-in PhongMaterial

Slide 30

Slide 30 text

THREE.ShaderChunk[ "skinning_pars_vertex" ], THREE.ShaderChunk[ "shadowmap_pars_vertex" ], THREE.ShaderChunk[ "logdepthbuf_pars_vertex" ], ! ! 'uniform mat4 viewMatrixInverse;', //ADDED 'uniform vec3 viewVector;', //ADDED 'varying float vIntensity;', //ADDED ! "void main() {", ! THREE.ShaderChunk[ "map_vertex" ], THREE.ShaderChunk[ "lightmap_vertex" ], THREE.ShaderChunk[ "color_vertex" ], ! THREE.ShaderChunk[ "morphnormal_vertex" ], THREE.ShaderChunk[ "skinbase_vertex" ], THREE.ShaderChunk[ "skinnormal_vertex" ], THREE.ShaderChunk[ "defaultnormal_vertex" ], ! The same as actual code of
 build-in PhongMaterial

Slide 31

Slide 31 text

! ! var fragmentShader = [ ! "#define PHONG", ! "uniform vec3 diffuse;", "uniform vec3 emissive;", "uniform vec3 specular;", "uniform float shininess;", "uniform float opacity;", ! "uniform vec3 glowColor;", //ADDED 'varying float vIntensity;', //ADDED ! THREE.ShaderChunk[ "common" ], THREE.ShaderChunk[ "color_pars_fragment" ], THREE.ShaderChunk[ "map_pars_fragment" ], THREE.ShaderChunk[ "alphamap_pars_fragment" ], THREE.ShaderChunk[ "lightmap_pars_fragment" ], The same as actual code of
 build-in PhongMaterial

Slide 32

Slide 32 text

this should be pre-multiplied to allow for bright highlights on very transparent objects // 'gl_FragColor = vec4( outgoingLight, diffuseColor.a );', // REMOVED ! 'vec3 glow = glowColor * vIntensity;', 'gl_FragColor = vec4(', // 'glow,', 'outgoingLight + glow,', 'diffuseColor.a', ');', ! "}" ! ].join( "\n" ); ! ! ! var material = new THREE.ShaderMaterial( { vertexShader : vertexShader,

Slide 33

Slide 33 text

! ! var material = new THREE.ShaderMaterial( { vertexShader : vertexShader, fragmentShader: fragmentShader, attributes: {}, uniforms: uniforms, defines: {}, ! fog: true, lights: true, // side: THREE.FrontSide, // blending: THREE.AdditiveBlending, skinning: true, transparent: true, // depthWrite: false // wireframe: true } ); ! material.uniforms.map = { type: 't', value: texture }

Slide 34

Slide 34 text

// side: THREE.FrontSide, // blending: THREE.AdditiveBlending, skinning: true, transparent: true, // depthWrite: false // wireframe: true } ); ! material.uniforms.map = { type: 't', value: texture } material.defines.USE_MAP = '';

Slide 35

Slide 35 text

build in shader custom shader

Slide 36

Slide 36 text

Conclusion

Slide 37

Slide 37 text

Three.js is not only high level APIs,
 but also it provides low level APIs

Slide 38

Slide 38 text

• THREE.BufferAttribute • THREE.BufferGeometry • THREE.ShaderMaterial • THREE.RawShaderMaterial "WBJMBCMFGFBUVSFTJOUISFFKT

Slide 39

Slide 39 text

Three.js is a
 flexible and extensible library

Slide 40

Slide 40 text

gl.finish(); @yomotsu