【WebGL / GLSL】デザイナーにモテるためのWebGL入門（概念編）

# TBS火曜ドラマ「わたし、定時で帰ります」第4話より
カワイイデザイナー: 「メインの花火、WebGLですよね！？よく実装したなって。」
冴えないエンジニア: 「え、まあ。。」
視聴者ぼく: 「！！！」

デザイナー: 「こんなのできるエンジニアと組めたらなって、ずっと憧れてたんで♡」
エンジニア: 「...」
視聴者ぼく: 「！！！！！！」
 
WebGLを勉強すれば何かいいことがありそうだと閃いてしまったので、
全力で勉強しようと思います。

ちなみにドラマ設定同様、自分も広告制作会社のエンジニアです。
そのためクライアントワークにWebGLを使用することを目標としています。

# すべては```canvas```からはじまる。
私は[Awwwards - Website Awards - Best Web Design Trends](https://www.awwwards.com/)を見るのが大好きです。
ここでsite of the DAYを受賞しているような派手めな演出のサイト。
そのソースを覗くと、必ず以下のようなコードに出会います。

```html
<canvas id="canvas"></canvas>
```

いや、せっかくコード参考にしようと思ったのになんやねん！！
```canvas```タグの中に何か要素とかあればまだ何かヒントになるのによ！！
なんもねえじゃねえか！

でも学んでわかりました。
これは**Canvas API**というもの。
[Canvas API - Web API | MDN](https://developer.mozilla.org/ja/docs/Web/API/Canvas_API)から引用すると、

> Canvas API は JavaScript と HTML の <canvas> 要素によってグラフィックを描く方法を提供します。

というものらしい。
なるほどつまりhtmlの```canvas```とは、
文字通り何も描かれていない真っ白なキャンバスなのであって、
その上にJavaScriptという筆でお絵かきをするということなのだ。

そして、MDNのサイトにはさらに衝撃的な文言が続いていた。

> Canvas API は全体的に 2D グラフィックを対象としています。 WebGL API は、こちらも <canvas> 要素を使用して、ハードウェアで高速化された 2D および 3D グラフィックを描きます。

え？「WebGL ＝ 3D表現」じゃないの？
2DでもWebGLって使うんだ！！
っていうか**WebGLの正式名称って「WebGL API」**なんだ。。

まとめると。

### まとめ
- WebGL（正式名称 : WebGL API）は、**canvas要素に2Dもしくは3Dグラフィックを描くJavaScriptのAPI**である！
- だから、**3D表現すなわちWebGL、と言うわけではない！**WebGL APIが2D表現を描くときもある。

## **GPU**について知ろう。
制作会社のエンジニアとして、
気になるのはブラウザ対応。
なるほど、IE11含め、一般的なモダンブラウザは大丈夫そう。
でもMDNに気になる記述が。

> ブラウザーだけでなく、GPU も機能をサポートしていなければなりません。

GPUってなんだ？？調べてみよう。

...

GPUとはGraphics Processing Unitの略で、デバイスの中に入っている画像処理専門の装置。
（よく聞く似たような単語であるCPUは、Central Processing Unitの略。こいつは司令塔みたいな装置。）

一発で理解できる動画を見つけました。

[Mythbusters Demo GPU versus CPU](https://www.youtube.com/watch?v=-P28LKWTzrI) 　※youtubeが開きます。

[![Image from Gyazo](https://i.gyazo.com/41c87d999f77756937d08c609b4974bb.png)](https://gyazo.com/41c87d999f77756937d08c609b4974bb)

画像は上記youtube動画の一場面です。
左がcanvas、右がGPUを模しているようです。
動画をご覧いただくとわかるのですが、
右の一個一個の管みたいなものからペンキが発射され、
一瞬でcanvasに絵が描かれます。

イメージはわかりました。
とにかく「グラフィックを描くために、PCに入ってるすごいやつ」
と覚えておくことにします。

「グラフィックを描く」といえば、まさにWebGL APIの役割でした。
なるほど、WebGL APIで```canvas```にグラフィックが描かれるためには、
それ相応の強いGPUが必要になるということなのですね。

強いGPUじゃないとWebGLを動かせない、ということ！

そういえば、[これがGPUの力！three.jsによる“リアルタイム”なレイトレーシング 〜宝石編〜](これがGPUの力！three.jsによる“リアルタイム”なレイトレーシング 〜宝石編〜)
みたいな記事を見たことがあります。
「GPUで暖をとる」という表現があったのですが、
GPUがWebGL動かしているから、あんまり頑張りすぎるとPCが熱くなってしまうわけですね。
早くmacを熱くさせたいものです。


# 色々なGPU。ひとつの仕様、**OpenGL**。

[![Image from Gyazo](https://i.gyazo.com/f082d072f80434e04fd808e87206f73c.png)](https://gyazo.com/f082d072f80434e04fd808e87206f73c)

WebGLを勉強していくと、よく聞く単語「OpenGL」。
GLGLうるさいな、と思いますが、ここでしっかり理解しておきます。

前章の通り、各々のPCにあるGPUが、ブラウザでWebGLを動かしている、と。
しかし、世の中にはWindows・macなどさまざまなOSがあります。
それによってGPUのタイプもさまざま。

そうなると、統一したグラフィック描画仕様が必要になる。（らしい）
**統一された仕様のことをOpenGL**という。
あれか、W3Cみたいなものなのですね。

と、ここまではいいのですが調べていくと不安な記事が。

[次世代仕様のWebGPUとは？　次期macOSでのOpenGL非推奨化はWebGLに影響をもたらすのか - ICS MEDIA](https://ics.media/entry/18412/)

タイトル通り、「macOSはこれからOpenGLを非推奨化しまーーーす」とのこと。
え？じゃあどうすればいいの？？
と思ったが、ブラウザ上ではWebGLは普通に動くようなので、深入りせず安心して勉強することにします。
プログラムするのはOpenGLじゃなくてJavaScriptだしね！

# モニターって2次元なのになんで3次元が表示されてるの？？
話は変わって。
WebGLで3Dのグラフィックを描く場合を考えます。
我々が見ているPC画面。これは間違いなく2次元空間です。
では、どうやって3次元空間を2次元へ変換するのか？？

3次元から2次元への変換、これを**座標変換**といいます。
はっきり言って全くわかりませんが割り切って続けます。

そして、**WebGLにはこの「座標変換」をすることができない！**
いや、そんな難しそうなの、できるやつ少ないやろ。

## 座標変換をしてくれる助っ人、**GLSL**

そこで助っ人登場。
座標変換をしてくれるひとを、**シェーダー**と呼ぶ！

シェーダーは2種類。

- **頂点シェーダー（vertex shader）** 〜 座標（点）を描く
- **フラグメントシェーダー（fragment shader）** 〜 色を描く

これはなんとなく直感的にわかるような気がしなくもない。
例えば立方体があるとして、
それを表現するために必要な情報は**座標（x座標,y座標,z座標）**と**色**の二つだ。

そして、シェーダーを書くための言語が**GLSL**。
CやC++のような言語らしい。
どっちもやったことがない。。大学でちゃんと勉強すればよかったな。。

# ```canvas```に素敵なグラフィックを描く流れ
これまでの流れをまとめるとこうなる。

1. **GLSL（シェーダー）**にて、頂点の位置（座標）や色の情報を書く。
2. JavaScriptの**WebGL API**が、GLSLをコンパイルし情報を受け取る。
3. WebGL APIが、```canvas```にグラフィックを描く。

日本語で書くと3行で終わってしまうが、
プログラムで書くとそこそこの量になりそう。

## こんな手順毎回踏むの！？大丈夫。ライブラリがある。

次回から具体的にGLSLやJavaScriptを書いてみようと思うが、
そのまま素直に上記1〜3の流れをプログラムで書くと難解かつ膨大になる。

例えば、フラグメントシェーダーで色を指定するためには、
「0」「1」で表現しなければならないし、
頂点シェーダーで立方体の座標を表現するためには、
行列式（数学C！！）みたいな複雑な式を書かなければならない。

上記をより簡単に扱うためのライブラリが[three.js](https://threejs.org/)だ。
2Dであれば、[PixiJS](https://www.pixijs.com/)になる。
例えば

```javascript
new THREE.CubeGeometry(10, 10, 10)
```
と書けば簡単に立方体が出るし、
色の扱いも#000000みたいなおなじみな方法でいい。

何も知らない自分は「WebGL ＝ three.js」と考えていたが、
必ずしもそうではない。
**「WebGL APIをより簡単に扱うためのライブラリがthree.js」**と言うのが正しい。

# まとめ
ここまで記事を書いてみて気づいた。
Hello Worldにすら到達していない...！

とりあえず概念は理解できたので、
次回はコードを書いていきたいと思います。

初学ゆえ、記事中に間違いなどあればご教示いただけると幸いです。

# 参考文献
- [WebGL 開発支援サイト wgld.org](https://wgld.org/)
    - 学習の指針・モチベーションになりました。
- [OpenGLに入門する前に知っておきたかったこと - かみのメモ](https://kamino.hatenablog.com/entry/opengl-prior-knowledge)
    - OpenGLについて、一番わかりやすかったです。
- [説明できますか？CPUとGPUの違い | Aidemy Blog](https://blog.aidemy.net/entry/2017/10/29/005803)
    - 件の動画はこちらで見つけました。GPUの理解ができました。
- [WebGLのシェーダーとGLSL](https://webglfundamentals.org/webgl/lessons/ja/webgl-shaders-and-glsl.html)
    - GLSLからcanvasに描かれるまで、どういう流れなのか？をコードとして俯瞰できるページでした。

# 絶賛WebGL勉強中！！続編は以下
[【WebGL / GLSL】ド文系だけど、行列とかラスタライズとか頑張って理解する](https://qiita.com/yukiTTT/items/2cfa5612b6fcbc96da91)