$30 off During Our Annual Pro Sale. View Details »

Low level APIs using three.js

yomotsu
June 06, 2015

Low level APIs using three.js

my talk at Tokyo WebGL Meetup #2
http://tokyowebglmeetup.github.io/2/

yomotsu

June 06, 2015
Tweet

More Decks by yomotsu

Other Decks in Programming

Transcript

  1. Low level APIs

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

    View Slide

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

    View Slide

  3. three.js makes
    WebGL easier

    View Slide

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

    View Slide

  5. You may think
    that’s all?

    View Slide

  6. You can also use

    low level APIs,

    like pure WebGL.

    View Slide

  7. THREE.BufferGeometry

    for attributes

    View Slide

  8. THREE.ShaderMaterial and

    THREE.RawShaderMaterial

    for uniforms

    and shaders in GLSL

    View Slide

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

    View Slide

  10. 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,
    !

    View Slide

  11. !
    !
    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,

    View Slide

  12. !
    !
    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() },

    View Slide

  13. !
    //
    // 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;',
    !

    View Slide

  14. !
    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" );
    !
    !

    View Slide

  15. !
    !
    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,

    View Slide

  16. !
    !
    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 );
    !

    View Slide

  17. !
    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 );
    !
    } )();

    View Slide

  18. 18

    View Slide

  19. View Slide

  20. A gas-ish fluid object
    in a MMO game

    View Slide

  21. 21
    https://github.com/yomotsu/VolumetricFire
    Fire in three.js using

    THREE.BufferGeometry and
    THREE.RawShaderMaterial

    View Slide

  22. Extended build-in shades

    View Slide

  23. View Slide

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

    View Slide

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

    View Slide

  26. You can use
    THREE.ShaderChank

    in your custom shader

    View Slide

  27. 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

    View Slide

  28. "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

    View Slide

  29. !
    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

    View Slide

  30. 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

    View Slide

  31. !
    !
    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

    View Slide

  32. 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,

    View Slide

  33. !
    !
    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 }

    View Slide

  34. // 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 = '';

    View Slide

  35. build in shader custom shader

    View Slide

  36. Conclusion

    View Slide

  37. Three.js is not only high level APIs,

    but also it provides low level APIs

    View Slide

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

    View Slide

  39. Three.js is a

    flexible and extensible library

    View Slide

  40. gl.finish();
    @yomotsu

    View Slide