Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Webのグラフィックス2016 WebGL事例

2,044 views

Published on

HTML5 Conference 2016で話したスライドです

Published in: Engineering
  • Be the first to comment

  • Be the first to like this

Webのグラフィックス2016 WebGL事例

  1. 1. Webのグラフィックス2016 前編1:WebGL事例 1
  2. 2. 事例 2 パフォーマンス WebGL2 Web VR アンケート 「〇〇についてもっと詳しく知りたい」 ↓ WebGLのイベント考えます
  3. 3. WebGLを実務で 使ったことがある? 3
  4. 4. WebGLのイメージ これまで ✤3Dコンテンツ ✤大規模コンテンツ ✤難しい ✤重い 4
  5. 5. WebGLのイメージ これから ✤2Dの表現でもOK ✤ちょっとした表現でも使える ✤簡単に書くことも出来る ✤工夫次第で軽く 5
  6. 6. 表現やコンテンツの幅を 広げる選択肢の一つ 6
  7. 7. 事例1 ちょっとした3D表現 ドラゴンプロジェクト:武器防具下部 http://colopl.co.jp/dragonproject/weapon/#guard 7
  8. 8. 導入の経緯 ✤デザイン提案 ✤動きのあるコンテンツで ✤いろんな装備のバリエーションを Three.jsならいけるかも! 8 見せたい ✤開発時間に余裕なし
  9. 9. 手順 9
  10. 10. 手順 ✤WebGL(Three.js)を使う準備 9
  11. 11. 手順 ✤WebGL(Three.js)を使う準備 ✤テクスチャにする画像を読み込む 9
  12. 12. 手順 ✤WebGL(Three.js)を使う準備 ✤テクスチャにする画像を読み込む ✤空間に六角柱を準備 9
  13. 13. 手順 ✤WebGL(Three.js)を使う準備 ✤テクスチャにする画像を読み込む ✤空間に六角柱を準備 ✤テクスチャを貼る 9
  14. 14. 手順 ✤WebGL(Three.js)を使う準備 ✤テクスチャにする画像を読み込む ✤空間に六角柱を準備 ✤テクスチャを貼る ✤回す 9
  15. 15. var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 1000 ); camera.position.z = 30; ! var renderer = new THREE.WebGLRenderer( { antialias: true, alpha: true } ); renderer.setClearColor( 0x000000, 0 ); renderer.setSize( window.innerWidth, window.innerHeight ); ! var textureLoader = new THREE.TextureLoader(); textureLoader.load( 'texture_image2.png', function (texture) { var geometry = new THREE.CylinderGeometry( 14, 14, 20, 6, 1, true ); var material = new THREE.MeshBasicMaterial( { side : THREE.DoubleSide, transparent : true, map : texture, //alphaTest : 0.3, } ); ! var cylinder = new THREE.Mesh( geometry, material ); cylinder.rotation.y = Math.PI / 6; scene.add( cylinder ); ! document.body.appendChild( renderer.domElement ); ! var render = function (time) { requestAnimationFrame( render ); TWEEN.update(); renderer.render( scene, camera ); }; ! var flipTimer = setInterval(function(){ var angle = cylinder.rotation.y + Math.PI / 3; var tween = new TWEEN.Tween(cylinder.rotation).to({y:angle}, 400).easing(TWEEN.Easing.Exponential.InOut).start(); }, 3600); ! render(); }); 10
  16. 16. var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 1000 ); camera.position.z = 30; ! var renderer = new THREE.WebGLRenderer( { antialias: true, alpha: true } ); renderer.setClearColor( 0x000000, 0 ); renderer.setSize( window.innerWidth, window.innerHeight ); ! var textureLoader = new THREE.TextureLoader(); textureLoader.load( 'texture_image2.png', function (texture) { var geometry = new THREE.CylinderGeometry( 14, 14, 20, 6, 1, true ); var material = new THREE.MeshBasicMaterial( { side : THREE.DoubleSide, transparent : true, map : texture, //alphaTest : 0.3, } ); ! var cylinder = new THREE.Mesh( geometry, material ); cylinder.rotation.y = Math.PI / 6; scene.add( cylinder ); ! document.body.appendChild( renderer.domElement ); ! var render = function (time) { requestAnimationFrame( render ); TWEEN.update(); renderer.render( scene, camera ); }; ! var flipTimer = setInterval(function(){ var angle = cylinder.rotation.y + Math.PI / 3; var tween = new TWEEN.Tween(cylinder.rotation).to({y:angle}, 400).easing(TWEEN.Easing.Exponential.InOut).start(); }, 3600); ! render(); }); 10
  17. 17. var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 1000 ); camera.position.z = 30; ! var renderer = new THREE.WebGLRenderer( { antialias: true, alpha: true } ); renderer.setClearColor( 0x000000, 0 ); renderer.setSize( window.innerWidth, window.innerHeight ); ! var textureLoader = new THREE.TextureLoader(); textureLoader.load( 'texture_image2.png', function (texture) { var geometry = new THREE.CylinderGeometry( 14, 14, 20, 6, 1, true ); var material = new THREE.MeshBasicMaterial( { side : THREE.DoubleSide, transparent : true, map : texture, //alphaTest : 0.3, } ); ! var cylinder = new THREE.Mesh( geometry, material ); cylinder.rotation.y = Math.PI / 6; scene.add( cylinder ); ! document.body.appendChild( renderer.domElement ); ! var render = function (time) { requestAnimationFrame( render ); TWEEN.update(); renderer.render( scene, camera ); }; ! var flipTimer = setInterval(function(){ var angle = cylinder.rotation.y + Math.PI / 3; var tween = new TWEEN.Tween(cylinder.rotation).to({y:angle}, 400).easing(TWEEN.Easing.Exponential.InOut).start(); }, 3600); ! render(); }); 10
  18. 18. var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 1000 ); camera.position.z = 30; ! var renderer = new THREE.WebGLRenderer( { antialias: true, alpha: true } ); renderer.setClearColor( 0x000000, 0 ); renderer.setSize( window.innerWidth, window.innerHeight ); ! var textureLoader = new THREE.TextureLoader(); textureLoader.load( 'texture_image2.png', function (texture) { var geometry = new THREE.CylinderGeometry( 14, 14, 20, 6, 1, true ); var material = new THREE.MeshBasicMaterial( { side : THREE.DoubleSide, transparent : true, map : texture, //alphaTest : 0.3, } ); ! var cylinder = new THREE.Mesh( geometry, material ); cylinder.rotation.y = Math.PI / 6; scene.add( cylinder ); ! document.body.appendChild( renderer.domElement ); ! var render = function (time) { requestAnimationFrame( render ); TWEEN.update(); renderer.render( scene, camera ); }; ! var flipTimer = setInterval(function(){ var angle = cylinder.rotation.y + Math.PI / 3; var tween = new TWEEN.Tween(cylinder.rotation).to({y:angle}, 400).easing(TWEEN.Easing.Exponential.InOut).start(); }, 3600); ! render(); }); 10
  19. 19. var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 1000 ); camera.position.z = 30; ! var renderer = new THREE.WebGLRenderer( { antialias: true, alpha: true } ); renderer.setClearColor( 0x000000, 0 ); renderer.setSize( window.innerWidth, window.innerHeight ); ! var textureLoader = new THREE.TextureLoader(); textureLoader.load( 'texture_image2.png', function (texture) { var geometry = new THREE.CylinderGeometry( 14, 14, 20, 6, 1, true ); var material = new THREE.MeshBasicMaterial( { side : THREE.DoubleSide, transparent : true, map : texture, //alphaTest : 0.3, } ); ! var cylinder = new THREE.Mesh( geometry, material ); cylinder.rotation.y = Math.PI / 6; scene.add( cylinder ); ! document.body.appendChild( renderer.domElement ); ! var render = function (time) { requestAnimationFrame( render ); TWEEN.update(); renderer.render( scene, camera ); }; ! var flipTimer = setInterval(function(){ var angle = cylinder.rotation.y + Math.PI / 3; var tween = new TWEEN.Tween(cylinder.rotation).to({y:angle}, 400).easing(TWEEN.Easing.Exponential.InOut).start(); }, 3600); ! render(); }); 10
  20. 20. var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 1000 ); camera.position.z = 30; ! var renderer = new THREE.WebGLRenderer( { antialias: true, alpha: true } ); renderer.setClearColor( 0x000000, 0 ); renderer.setSize( window.innerWidth, window.innerHeight ); ! var textureLoader = new THREE.TextureLoader(); textureLoader.load( 'texture_image2.png', function (texture) { var geometry = new THREE.CylinderGeometry( 14, 14, 20, 6, 1, true ); var material = new THREE.MeshBasicMaterial( { side : THREE.DoubleSide, transparent : true, map : texture, //alphaTest : 0.3, } ); ! var cylinder = new THREE.Mesh( geometry, material ); cylinder.rotation.y = Math.PI / 6; scene.add( cylinder ); ! document.body.appendChild( renderer.domElement ); ! var render = function (time) { requestAnimationFrame( render ); TWEEN.update(); renderer.render( scene, camera ); }; ! var flipTimer = setInterval(function(){ var angle = cylinder.rotation.y + Math.PI / 3; var tween = new TWEEN.Tween(cylinder.rotation).to({y:angle}, 400).easing(TWEEN.Easing.Exponential.InOut).start(); }, 3600); ! render(); }); 10
  21. 21. ちょっとはまった (ざっくり説明します) ✤WebGLは描画順に上書きルール ✤透明なピクセルも上書きしてしまう ✤materialにalphaTest:0.3,追加 ■alphaTest:数値(0~1.0) 数値以下のalphaのピクセルを 描画しなくする設定 11 透明ピクセルの描画に注意
  22. 22. ポイント ✤結構簡単:30分くらい ✤意外と軽い 小規模なものから始めると 徐々に覚えていける。 12 ハマり版 https://dl.dropboxusercontent.com/u/2732304/html5conf/ex/ex01_1.html ハマり解決版 https://dl.dropboxusercontent.com/u/2732304/html5conf/ex/ex01_2.html
  23. 23. 事例2 パーティクルでの演出 ドラゴンプロジェクト:トップ http://colopl.co.jp/dragonproject/ 白猫プロジェクト:2周年サイト http://colopl.co.jp/shironekoproject/2nd_anniversary/sp/ 13
  24. 24. 導入の経緯:ドラプロ ✤デザイン提案 ✤すこし複雑な動き ✤加算を使いたい ✤開発時間に余裕あり ✤なくても良いけどあるとより良い Three.js+GLSLで やってみよう! 14
  25. 25. 手順:簡易版 15
  26. 26. 手順:簡易版 ✤WebGL(Three.js)を使う準備 15
  27. 27. 手順:簡易版 ✤WebGL(Three.js)を使う準備 ✤テクスチャにする画像を読み込む 15
  28. 28. 手順:簡易版 ✤WebGL(Three.js)を使う準備 ✤テクスチャにする画像を読み込む ✤空間にランダム頂点を準備 15
  29. 29. 手順:簡易版 ✤WebGL(Three.js)を使う準備 ✤テクスチャにする画像を読み込む ✤空間にランダム頂点を準備 ✤頂点にテクスチャを貼る(加算設定) 15
  30. 30. 手順:簡易版 ✤WebGL(Three.js)を使う準備 ✤テクスチャにする画像を読み込む ✤空間にランダム頂点を準備 ✤頂点にテクスチャを貼る(加算設定) ✤動かす 15
  31. 31. var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 1000 ); camera.position.z = 100; ! var renderer = new THREE.WebGLRenderer( { antialias: true, alpha: true } ); renderer.setSize( window.innerWidth, window.innerHeight ); ! var textureLoader = new THREE.TextureLoader(); textureLoader.load( 'particle.png', function (texture) { var geometry = new THREE.Geometry(); for (var i = 0; i < count/2; i++) { var v1 = new THREE.Vector3(getRandomNum(), getRandomNum(), getRandomNum()); var v2 = new THREE.Vector3(v1.x, v1.y - 100.0, v1.z); geometry.vertices.push(v1); geometry.vertices.push(v2); } var material = new THREE.PointsMaterial( { map : texture, size : 3, blending : THREE.AdditiveBlending, transparent : true, depthTest : false, //color : 0XFF5B00, } ); ! var particles = new THREE.Points( geometry, material ); scene.add( particles ); ! document.body.appendChild( renderer.domElement ); ! var render = function (time) { requestAnimationFrame( render ); var yPos = particles.position.y; particles.position.y = (yPos > 100) ? 0 : yPos + 0.2; renderer.render( scene, camera ); }; ! render(); }); 16
  32. 32. var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 1000 ); camera.position.z = 100; ! var renderer = new THREE.WebGLRenderer( { antialias: true, alpha: true } ); renderer.setSize( window.innerWidth, window.innerHeight ); ! var textureLoader = new THREE.TextureLoader(); textureLoader.load( 'particle.png', function (texture) { var geometry = new THREE.Geometry(); for (var i = 0; i < count/2; i++) { var v1 = new THREE.Vector3(getRandomNum(), getRandomNum(), getRandomNum()); var v2 = new THREE.Vector3(v1.x, v1.y - 100.0, v1.z); geometry.vertices.push(v1); geometry.vertices.push(v2); } var material = new THREE.PointsMaterial( { map : texture, size : 3, blending : THREE.AdditiveBlending, transparent : true, depthTest : false, //color : 0XFF5B00, } ); ! var particles = new THREE.Points( geometry, material ); scene.add( particles ); ! document.body.appendChild( renderer.domElement ); ! var render = function (time) { requestAnimationFrame( render ); var yPos = particles.position.y; particles.position.y = (yPos > 100) ? 0 : yPos + 0.2; renderer.render( scene, camera ); }; ! render(); }); 16
  33. 33. var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 1000 ); camera.position.z = 100; ! var renderer = new THREE.WebGLRenderer( { antialias: true, alpha: true } ); renderer.setSize( window.innerWidth, window.innerHeight ); ! var textureLoader = new THREE.TextureLoader(); textureLoader.load( 'particle.png', function (texture) { var geometry = new THREE.Geometry(); for (var i = 0; i < count/2; i++) { var v1 = new THREE.Vector3(getRandomNum(), getRandomNum(), getRandomNum()); var v2 = new THREE.Vector3(v1.x, v1.y - 100.0, v1.z); geometry.vertices.push(v1); geometry.vertices.push(v2); } var material = new THREE.PointsMaterial( { map : texture, size : 3, blending : THREE.AdditiveBlending, transparent : true, depthTest : false, //color : 0XFF5B00, } ); ! var particles = new THREE.Points( geometry, material ); scene.add( particles ); ! document.body.appendChild( renderer.domElement ); ! var render = function (time) { requestAnimationFrame( render ); var yPos = particles.position.y; particles.position.y = (yPos > 100) ? 0 : yPos + 0.2; renderer.render( scene, camera ); }; ! render(); }); 16
  34. 34. var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 1000 ); camera.position.z = 100; ! var renderer = new THREE.WebGLRenderer( { antialias: true, alpha: true } ); renderer.setSize( window.innerWidth, window.innerHeight ); ! var textureLoader = new THREE.TextureLoader(); textureLoader.load( 'particle.png', function (texture) { var geometry = new THREE.Geometry(); for (var i = 0; i < count/2; i++) { var v1 = new THREE.Vector3(getRandomNum(), getRandomNum(), getRandomNum()); var v2 = new THREE.Vector3(v1.x, v1.y - 100.0, v1.z); geometry.vertices.push(v1); geometry.vertices.push(v2); } var material = new THREE.PointsMaterial( { map : texture, size : 3, blending : THREE.AdditiveBlending, transparent : true, depthTest : false, //color : 0XFF5B00, } ); ! var particles = new THREE.Points( geometry, material ); scene.add( particles ); ! document.body.appendChild( renderer.domElement ); ! var render = function (time) { requestAnimationFrame( render ); var yPos = particles.position.y; particles.position.y = (yPos > 100) ? 0 : yPos + 0.2; renderer.render( scene, camera ); }; ! render(); }); 16
  35. 35. var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 1000 ); camera.position.z = 100; ! var renderer = new THREE.WebGLRenderer( { antialias: true, alpha: true } ); renderer.setSize( window.innerWidth, window.innerHeight ); ! var textureLoader = new THREE.TextureLoader(); textureLoader.load( 'particle.png', function (texture) { var geometry = new THREE.Geometry(); for (var i = 0; i < count/2; i++) { var v1 = new THREE.Vector3(getRandomNum(), getRandomNum(), getRandomNum()); var v2 = new THREE.Vector3(v1.x, v1.y - 100.0, v1.z); geometry.vertices.push(v1); geometry.vertices.push(v2); } var material = new THREE.PointsMaterial( { map : texture, size : 3, blending : THREE.AdditiveBlending, transparent : true, depthTest : false, //color : 0XFF5B00, } ); ! var particles = new THREE.Points( geometry, material ); scene.add( particles ); ! document.body.appendChild( renderer.domElement ); ! var render = function (time) { requestAnimationFrame( render ); var yPos = particles.position.y; particles.position.y = (yPos > 100) ? 0 : yPos + 0.2; renderer.render( scene, camera ); }; ! render(); }); 16
  36. 36. var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 1000 ); camera.position.z = 100; ! var renderer = new THREE.WebGLRenderer( { antialias: true, alpha: true } ); renderer.setSize( window.innerWidth, window.innerHeight ); ! var textureLoader = new THREE.TextureLoader(); textureLoader.load( 'particle.png', function (texture) { var geometry = new THREE.Geometry(); for (var i = 0; i < count/2; i++) { var v1 = new THREE.Vector3(getRandomNum(), getRandomNum(), getRandomNum()); var v2 = new THREE.Vector3(v1.x, v1.y - 100.0, v1.z); geometry.vertices.push(v1); geometry.vertices.push(v2); } var material = new THREE.PointsMaterial( { map : texture, size : 3, blending : THREE.AdditiveBlending, transparent : true, depthTest : false, //color : 0XFF5B00, } ); ! var particles = new THREE.Points( geometry, material ); scene.add( particles ); ! document.body.appendChild( renderer.domElement ); ! var render = function (time) { requestAnimationFrame( render ); var yPos = particles.position.y; particles.position.y = (yPos > 100) ? 0 : yPos + 0.2; renderer.render( scene, camera ); }; ! render(); }); 16
  37. 37. ポイント ✤加算はブレンドモードの設定のみ ✤y軸 - で降る + で湧く、Z軸 + で
 ✤シェーダーを使えばもっと複雑に ✤描画範囲に注意 17 向かってくる - で過ぎていく パーティクル簡易版 https://dl.dropboxusercontent.com/u/2732304/html5conf/ex/ex02.html
  38. 38. まとめ ✤ 始めるなら、ちいさなコンテンツから ✤ いきなり全てを理解はできない ✤ WebGL、そんなに難しくない(奥は深いけど ✤ WebGLを選択肢の一つとして加えてみよう 18 WebGLをつかってみましょう
  39. 39. WebGL事例サイト ✤WebGL総本山
 https://webgl.souhonzan.org/ ✤ThreejsのGoogle+
 https://plus.google.com/+ThreejsOrg 19 Join webgl-jp on Slack https://arcane-depths-9129.herokuapp.com/
  40. 40. ありがとうございました 20

×