第1回目　WebGLの概念

<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script language="JavaScript">
$(document).ready( function () {
   $("a[href^='http']:not([href*='" + location.hostname + "'])").attr('target', '_blank');
})
</script>

##講師紹介
講師：杉本　雅広さん
[wgld.org](http://wgld.org/ "webd.org") という WebGL 開発支援サイトの管理人
WebGL の普及と発展のために日夜活動中

##授業の流れ
1.WebGLとは何か？、利用状況、将来性
2.WebGLのメリット・デメリット
3.開発環境構築など

##<span style="color:#0080A0;">1. WebGLとは何か？</span>
・[GPU(Graphics Processing Unit)](http://www.gdep.jp/page/view/248)へ直接アクセスすることができる<span style="color:red;">ブラウザに組み込まれた[API](http://e-words.jp/w/API.html)</span>

・ブラウザ側の実装（ブラウザに組み込まれている）によるものなので、ブラウザによって性能や機能に差が生じる

####WebGLはOpenGLというネイティブで動作するグラフィックスAPIをブラウザから呼び出すためのパイプ役のような存在

![firest_lesson.jpg](https://qiita-image-store.s3.amazonaws.com/0/42003/f6055ba2-7630-6021-571c-2ac20792d5d7.jpeg "firest_lesson.jpg")


・javascriptからOpenGLへ直接アクセスすることはできないがWebGLが間に入ることでOpenGLを間接的に呼び出すことができる
・OpenGLはグラフィックスドライバと通信できるため、グラフィックスに関する処理を高速に行うことができる
####簡潔に表現するなら、WebGLはOpenGLを介して直接GPUを利用できるため非常に高速




##<span style="color:#0080A0;">2. ブラウザ以外の制約</span>
・各ブラウザベンダーによって実装状況が異なるので、ブラウザによっては動作しなかったり、動作しても結果が異なったりする
・OSレベルでWebGLが無効化されていたりする（※iOSは8からWebGLに対応）

####OSやブラウザが対応していても、GPUなどのハードウェアの制約により動作しないケースなどがあり、基本的にすべての環境を漏れなくカバーすることは難しいというのが現状





##<span style="color:#0080A0;">3. 各種ブラウザベンダの対応状況</span>
最新の対応状況を[確認](http://caniuse.com/#feat=webgl)
モバイル端末での[パフォーマンス](http://ics-web.jp/lab/archives/2372)




##<span style="color:#0080A0;">4. WebGLで作られたコンテンツ</span>
[3dbricks](http://www.holoduke.nl/3dbricks/)
![002.jpg](https://qiita-image-store.s3.amazonaws.com/0/42003/248b683d-a149-808f-d1f2-0537cc9cfb65.jpeg "002.jpg")


[Urban Galaxy Online](https://www.urbangalaxyonline.com/)
![003.jpg](https://qiita-image-store.s3.amazonaws.com/0/42003/5eadba3f-5c07-b5d2-2b05-04472aa507f9.jpeg "003.jpg")


[G-Star RAW | New Denim Arrivals](https://www.g-star.com/en_nl/newdenimarrivals)
![004.jpg](https://qiita-image-store.s3.amazonaws.com/0/42003/2b58843c-5f3c-bdc2-68af-9d0cdb272f1f.jpeg "004.jpg")


[FishGL](http://www.fishgl.com/)
![005.jpg](https://qiita-image-store.s3.amazonaws.com/0/42003/8d3523cd-7572-621f-7132-9031bd754f2a.jpeg "005.jpg")


[thisway.js by stravaganza](http://kile.stravaganza.org/lab/thiswayjs/)
![006.jpg](https://qiita-image-store.s3.amazonaws.com/0/42003/f7dbc4fd-574b-8e70-d518-c4ab66711e12.jpeg "006.jpg")



[WebGL Fluid Experiment](http://haxiomic.github.io/projects/webgl-fluid-and-particles/?q=UltraLow)
![007.jpg](https://qiita-image-store.s3.amazonaws.com/0/42003/a0dcbc9f-46b7-906a-73f6-e8da8a86711d.jpeg "007.jpg")




##<span style="color:#0080A0;">5. WebGLの特徴（メリット）</span>
・ブラウザで即実行できるため非常に手軽
・ユーザーにダウンロードやインストールなどの手間を掛けさせない
・非常に高速によりリッチなコンテンツを配信できる
・他の次世代Web技術と組み合わせて利用することができる

##<span style="color:#0080A0;">6. WebGLの特徴（デメリット）</span>
・意図した通りの動作をするかが環境依存
・通信するデータ量が肥大化しやすくユーザーの負担や待ち時間が増える
・学習コストが非常に高いため扱える人が少ない



##<span style="color:#0080A0;">7. WebGLの動作確認</span>
・javascriptからWebGLの命令を呼び出すには、WebGL[コンテキストオブジェクト](http://software.fujitsu.com/jp/manual/manualfiles/M070190/B1WN8771/01Z201/apgod12/apgod501.htm)を介した処理を記述
・webGLコンテキストはHTML5で利用できるようになった[\<canvas>](http://www.html5.jp/canvas/)から生成することができる
・WebGLコンテキストが生成できない場合は、そもそもWebGLを使うことができない環境


1.HTMLを用意

```html:index.html
<html>
    <body>
        <canvas id="canvas"></canvas>
    </body>
</html>
```


2.javascriptを用意

```javascript:script.js
//canvasへの参上を変数に取得する
 var c = document.getElementById('canvas');

//WebGLコンテキストをcanvasから取得する
var gl = c.getContext('webgl') || c.getContext('experimental-webgl');

//WebGLコンテキストの取得ができたかどうか
if(gl){
	console.log('supports webgl');
}else{
	console.log('webgl not supported');
}
```




##<span style="color:#0080A0;">8. WebGLプログラミングの流れ</span>

####例）javascriptでHTML内に文字を記述する場合
```javascript:script.js
var s = 'hello world!';
document.write(s);
```

変数の初期化（生成）⇒ 利用という流れになっている

####これをWebGLの場合に例える
WebGLでは生成から利用までの間に登録する作業などが追加される


####例）WebGLの場合
```javascript:script.js
var s = gl.createXXXXX(); // 専用のメソッドでオブジェクトを生成
gl.bindXXXXX(s); // 専用のメソッドでオブジェクトを登録
gl.applyXXXXX('hello world'); // 登録してあるオブジェクトにデータを適用
```

####生成　⇒　登録　⇒　利用　のスリーステップ方式

WebGL(OpenGL)がGPUと直接やり取りが可能なためWebGLでは様々なオブジェクトが登録作業を経て利用可能になる





##<span style="color:#0080A0;">9. グラフィクスパイプライン</span>
![graphics_pipeline.jpg](https://qiita-image-store.s3.amazonaws.com/0/42003/ca93e87c-b268-b280-ed06-9076c282173a.jpeg "graphics_pipeline.jpg")

###ディスプレイに映像が出るまでの流れを[グラフィックスパイプライン](http://ja.wikipedia.org/wiki/%E3%82%B0%E3%83%A9%E3%83%95%E3%82%A3%E3%83%83%E3%82%AF%E3%82%B9%E3%83%91%E3%82%A4%E3%83%97%E3%83%A9%E3%82%A4%E3%83%B3)と呼ぶ



![graphics_pipeline2.jpg](https://qiita-image-store.s3.amazonaws.com/0/42003/87cba1dd-f911-6beb-ce90-026252b34dae.jpeg "graphics_pipeline2.jpg")


###javascriptとWebGLの役目は、このグラフィックスパイプラインにデータを送ったり、どのようにデータを扱うのかを指定すること


・グラフィックスパイプラインとは、最終的にスクリーン上に何かを描き出すまでのその道のりのこと

・グラフィックスパイプラインをさらに細かく見ていくと、その中には[レンダリングパイプライン](http://ja.wikipedia.org/wiki/%E3%82%B0%E3%83%A9%E3%83%95%E3%82%A3%E3%83%83%E3%82%AF%E3%82%B9%E3%83%91%E3%82%A4%E3%83%97%E3%83%A9%E3%82%A4%E3%83%B3)と呼ばれる領域がある





##<span style="color:#0080A0;">10. レンダリングパイプライン</span>

レンダリングパイプラインの中では、WebGLから送られてきたデータを加工してディスプレイに出力するところまでを行う
※このレンダリングパイプラインの中もさらに細分化される

![rendering_pipeline.jpg](https://qiita-image-store.s3.amazonaws.com/0/42003/746801b3-2c60-ef5f-5e98-e9fbaa3cfd6a.jpeg "rendering_pipeline.jpg")

恐ろしいことにジオメトリパイプラインやフラグメントパイプラインの中身もさらに細かく分解され、いくつもの処理が詰め込まれている




##<span style="color:#0080A0;">11. レンダリングパイプラインの役割</span>

####画面上に何かを描くこと

例えば・・・
画面上に四角形を表示させていとしたら、どのようなプログラムを書けばいいのか


####HTMLとCSSの場合
---

```html:index.html
<div style="background-color: red; width: 100px; height: 100px;"></div>
```

※赤い四角形が画面上に表示される
![shikaku.jpg](https://qiita-image-store.s3.amazonaws.com/0/42003/1d1a91e1-4714-1e60-438b-465760c0a400.jpeg "shikaku.jpg")





####三次元の場合
---

```html:index.html
<div style="background-color: #ff0000; width: 100px; height: 100px; transform: matrix(-0.5, 0.5, 1.0, 0, 20, 10);"></div>
<div style="background-color: #00ff00; width: 100px; height: 100px; transform: matrix( 1.0, 0, 0.5, 0.5, 20, -40);"></div>
<div style="background-color: #0000ff; width: 70px; height: 70px; transform: matrix3d(0.707, 0.707, 0, 0, -0.707, 0.707, 0, 0, 0, 0, 1, 0, 110, -150, 0, 1);"></div>
```

![sikaku2.jpg](https://qiita-image-store.s3.amazonaws.com/0/42003/9e84c858-9829-7375-77bc-510a72352d28.jpeg "sikaku2.jpg")


###二次元に空間に三次元のものを描くのはとても複雑な計算をしなくてはならない
※移動・回転・変形・色などをどのように表現するのかを手で計算すつのは無謀

###レンダリングパイプラインは面倒で大変な変換作業を行う
プログラムからは、どのような形状のものを、どのような角度で、どんなふうに見えるようにしたいかを指定してやる。すると、レンダリングパイプラインを通るうちにデータが変換され、三次元のデータを二次元のスクリーン上に映し出してくれる





##<span style="color:#0080A0;">12. 固定機能パイプライン</span>

固定機能パイプラインはパイプラインの中の機能が固定されており、複雑なことや応用技術は利用できないが、その代わり初めから組み込まれているので簡単に利用することができる


しかし。。。
###WebGLには固定機能パイプラインは実装されていない
・OpenGLには様々な種類がありPC以外にもモバイル端末などで利用することを前提にした軽量な実装が用意されており、それがOpenGL ESと呼ばれているもの
・OpenGL ES は、軽量化の観点からいくつかの機能が削除されていて、固定機能パイプラインが含まれていない
・WebGLは、このOpenGL ESをベースにしているので、固定機能パイプラインが組み込まれていない



##<span style="color:#0080A0;">13. ジオメトリパイプライン</span>
・ジオメトリパイプラインは三次元のデータを二次元に変換することが主な役割
・二次元空間へのデータの変換を行い、最終的に画面にどのような形状のオブジェクトを描き出せばいいかを決定する


##<span style="color:#0080A0;">14. フラグメントパイプライン</span>
・フラグメントパイプラインはジオメトリパイプラインから送られてきたデータを精査して最終的に画面に出力される色を決めることが主な役割
・ジオメトリパイプラインから「ここは陰になるよ」という情報が流れてくれば、そこを暗い色にするのはフラグメントパイプラインの仕事


###映画製作に例えると
---
・プログラマであるあなたは映画監督です

・まずは javascript くんと WebGL くんのチームに、俳優たちを揃えるように指示します

・監督であるあなたは、集まった俳優たちをどのような配置にするか、どのような角度から撮影するか、どんなカメラを利用するかなどを決めます

・次にあなたは、ジオメトリくんに指示を出して、シーンを撮影させました

・三次元空間上でおのおの配置についていた俳優たちは、フィルムという二次元の世界に焼き付けられました

・フィルムを受け取ったフラグメントくんは、フィルムの色合いを調整したり、影を濃くしたり、女優さんの肌を白くしたり、監督に言われたとおりに映像を加工しました

・こうして、晴れてスクリーンに映像が映し出されました

![flagment_pipeline.jpg](https://qiita-image-store.s3.amazonaws.com/0/42003/52c57253-e2f9-cc1b-3f61-0b50c7b34015.jpeg "flagment_pipeline.jpg")

演出家、カメラマン、編集屋さん、というような役割分担！


##<span style="color:#0080A0;">15. シェーダ</span>

・ジオメトリパイプライン、フラグメントパイプラインの動作を指定するのに利用されるのがシェーダ
・固定機能パイプラインを持つプラットフォームでは必ずしもシェーダを記述する必要はないが、WebGLではシェーダの記述が必須
・シェーダはジオメトリ、フラグメントのそれぞれのステージごとに個別に記述するもので、ジオメトリパイプラインでは頂点シェーダが処理を行う
・フラグメントパイプラインでは、フラグメントシェーダが処理を担当
・WebGLには頂点シェーダとフラグメントシェーダ二種類のシェーダが実装
・本家OpenGLやDirectXには上記二種類のシェーダ以外にもジオメトリシェーダなどの種類がある
・プラットフォームごとにシェーダを記述するための専用のシェーダ記述言語が用意されていることが多い



##<span style="color:#0080A0;">16. GLSL</span>
・WebGLにおいてはOpenGL用のシェーダ記述専用言語であるGLSLを利用する
・WebGLを習得するためにはjavascriptで記述するWebGL独自の実装の他に、このGLSLをマスターする必要がある
・GLSLはC言語に近い言語仕様になっているので、比較的一般的なプログラミングの知識を流用しやすい


##<span style="color:#0080A0;">17. 3D 数学超基礎入門</span>
###頂点
---
・WebGLにおける頂点とは画面上に描かれるモデルの最小構成単位
・WebGLでは、点、線、三角形のいずれかを画面に描く
・頂点がひとつであれば点
　ふたつあれば線が描ける
　頂点がみっつあればそれを結んで三角形を表現できる

![002.jpg](https://qiita-image-store.s3.amazonaws.com/0/42003/467ba42b-9b0c-a09e-59c3-61e7a7b13319.jpeg "002.jpg")

###ポリゴン
---
・頂点をみっつ使って表現される三角形のことをポリゴン
・ポリゴンをたくさん生成すればするほど滑らかな曲線を表現することができる
・ポリゴン数(頂点数)が多いと負荷も高くなる
・ローポリゴンのほうが負荷は低くなるがディティールは甘い

![003.jpg](https://qiita-image-store.s3.amazonaws.com/0/42003/14eaf496-b58a-262d-ae3c-6c7ff0619136.jpeg "003.jpg")



###ベクトル
---
・方向と大きさを持つ量
・方向とその方向に掛かる力の大きさを表現できる単位
####ベクトル(二次元)
・二次元でのベクトルは横と縦のふたつのパラメータによって表される
・Xを横軸、Yを縦軸

![004.jpg](https://qiita-image-store.s3.amazonaws.com/0/42003/3dfc3450-0eea-49c3-6885-29abdd6fa166.jpeg "004.jpg")
・ベクトルはあくまでも方向と大きさを表すもの

![005.jpg](https://qiita-image-store.s3.amazonaws.com/0/42003/d879ec63-78cd-0190-4dd5-ef0efca80400.jpeg "005.jpg")
・矢印の始点と終点が変わってもベクトルの方向や大きさは変わっていない

![006.jpg](https://qiita-image-store.s3.amazonaws.com/0/42003/e03ef2d8-0cef-2c8b-2f53-d4237c8b547e.jpeg "006.jpg")
・この場合は方向も、大きさも、いずれも先ほどまでとは異なっている


####ベクトル(三次元)
・X、Y、に加えてZで奥行を表現するのが三次元ベクトル

#####プラス方向とマイナス方向はどういうふうに決まる？
######[左手系と右手系](http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1396778653)
---
・Zの符号をどのように扱うのかはAPIの実装によって異なる
・OpenGL系列は右手系でDirectXなどは左手系
・右手系の場合は手前がプラス奥に行くほどマイナス

###WebGLが[右手系](http://ja.wikipedia.org/wiki/%E5%8F%B3%E6%89%8B%E7%B3%BB)である



###行列
---

・行列というのは、数学で用いられる概念のひとつ
・一度にたくさんの情報を持つことができるという特性がある





とりあえず、ざっくりとした概念的なものは以上になります。