Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
WebGL2入門
Search
Rintarooo
November 11, 2023
Programming
0
67
WebGL2入門
Rintarooo
November 11, 2023
Tweet
Share
Other Decks in Programming
See All in Programming
AI時代の『改訂新版 良いコード/悪いコードで学ぶ設計入門』 / ai-good-code-bad-code
minodriven
23
9.1k
A full stack side project webapp all in Kotlin (KotlinConf 2025)
dankim
0
140
Startups on Rails in Past, Present and Future–Irina Nazarova, RailsConf 2025
irinanazarova
0
210
Deep Dive into ~/.claude/projects
hiragram
14
12k
AI駆動のマルチエージェントによる業務フロー自動化の設計と実践
h_okkah
0
220
High-Level Programming Languages in AI Era -Human Thought and Mind-
hayat01sh1da
PRO
0
840
初学者でも今すぐできる、Claude Codeの生産性を10倍上げるTips
s4yuba
16
12k
PipeCDのプラグイン化で目指すところ
warashi
1
290
PHPでWebSocketサーバーを実装しよう2025
kubotak
0
310
VS Code Update for GitHub Copilot
74th
2
670
イベントストーミング図からコードへの変換手順 / Procedure for Converting Event Storming Diagrams to Code
nrslib
2
1k
dbt民主化とLLMによる開発ブースト ~ AI Readyな分析サイクルを目指して ~
yoshyum
3
1.1k
Featured
See All Featured
Adopting Sorbet at Scale
ufuk
77
9.5k
What's in a price? How to price your products and services
michaelherold
246
12k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
108
19k
What’s in a name? Adding method to the madness
productmarketing
PRO
23
3.5k
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
53
2.9k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
507
140k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
667
120k
Intergalactic Javascript Robots from Outer Space
tanoku
271
27k
Six Lessons from altMBA
skipperchong
28
3.9k
Balancing Empowerment & Direction
lara
1
440
How to Ace a Technical Interview
jacobian
278
23k
Become a Pro
speakerdeck
PRO
29
5.4k
Transcript
WebGL2 Tutorial 1 @Rintarooo 2023/11/11
コンテンツ Contents • WebGLとは • Hands-on⓪ • Hands-on① • シェーダーとは
• Hands-on② • レンダリングパイプライン • Hands-on③ • VBO, IBO and VAO • Hands-on (optional) 2
参考 オライリー・ジャパン 「初めてのWebGL2」 & ネットに落ちてる技術系ブログ・講義スライド 3 GPU並列図形処理入門 コンピュータ グラフィックス
WebGLとは 4
WebGLとは • Javascriptで呼び出せる(Webブラウザ上で動く)グラフィックスAPI。 • 呼び出す上で、ライブラリのインストールやプラグインは不要。 5
WebGLとは グラフィックスAPIとは? 6 • Javascriptで呼び出せる(Webブラウザ上で動く)グラフィックスAPI。 • 呼び出す上で、ライブラリのインストールやプラグインは不要。
まかせろ〜! WebGLとは • Javascriptで呼び出せる(Webブラウザ上で動く)グラフィックスAPI。 • 呼び出す上で、ライブラリのインストールやプラグインは不要。 Javascript グラフィックスAPIとは? こんな感じの絵を 描いてくれ〜!
7 WebGL
WebGLとは • Javascriptで呼び出せる(Webブラウザ上で動く)グラフィックスAPI。 • 呼び出す上で、ライブラリのインストールやプラグインは不要。 グラフィックスAPIとは? 8 • WebGLはライブラリではなく, 「みんな〜!こういう風に実装しようね!」という、仕様書※のようなもの。
• 実際に実装されるAPIの内部処理は、Intel, NVIDIA, AMDなどの CPUやGPUの開発会社(ベンダー)に委ねられる。(差はほぼ無いらしい) 参考:OpenGLは普通のライブラリとは違う グラフィックスの基礎 ※仕様を策定している非営利団体:Khronos Group
WebGLの位置付け 図引用:WebGLのなりたち 9 (OpenGLの派生。 ES=組み込み スマホで動かせるように。 ) (OpenGL ESの派生。 ブラウザ上で動かせるように。
) 2016年に、WebGLからWebGL2へ移行。 ネット記事に両方の情報が混在。
WebGLの位置付け (Appleが開 発元) 抽象度 (下に行くほどローレベル) PyOpenGL • WebGLは、ローレベル※なAPI • 抽象度の高いライブラリやCG系のソ
フトは、描画する際に、 内部的にローレベルのAPIを呼び出 すこともある (Direct3D) (Microsoftが 開発元) 参考:WebGLのなりたち ライブラリ グラフィックスAPI CG系のソフト 10 抽象化 派生 派生 DirectX 12 ※ローレベル =ハードウェア側に近い。 結果として、コードの記述量が多くなる。
Three.jsでもこんなの作れる Three.jsのサンプル例 → https://threejs.org/examples/#webgl_animation_keyframes 11
なぜWebGLを学ぶ? • より抽象度の高い便利なCGソフトやライブラリを勉強する時、 ◦ WebGLのような、ローレベルAPIに触れておくことで、 内部処理の知識を流用して、安易に扱えれるようになる◎ • 一方、WebGLではなく、 ◦ Vulkanだと、
▪ ローレベル過ぎて、学習コストがあまりにも高過ぎる。 ◦ OpenGLだと、 ▪ WebGLと比べて、環境作るハードル高め (GLFW, GLADなどのライブラリ要る)。 ▪ Apple、独自のMetalなどのAPIへの移行を推奨 参考:OpenGLを勉強する必要はあるのか 12
Hands-on⓪ Canvasを作ろう 13
まかせろ〜! Canvasとは • WebGLが描画した絵を表示する領域 Javascript こんな感じの絵を 描いてくれ〜! 14 WebGL
描いたぞ! Canvasとは • WebGLが描画した絵を表示する領域 Javascript WebGLが 描いた絵 15 WebGL
Canvasとは • WebGLが描画した絵を表示する領域を、用意してあげる Javascript WebGLが 描いた絵 どこに絵を 表示しよう??? 16 WebGL
描いたぞ!
Canvasとは • WebGLが描画した絵を表示する領域(=Canvas)を、用意してあげる Javascript WebGLが 描いた絵 Canvasってとこに表 示するか〜 17 WebGL
描いたぞ!
Hands-on⓪ : Canvasを作ってみる $ git clone https://github.com/Rintarooo/WebGL2-tutorial 18 1. ターミナルからリポジトリをクローン
Hands-on⓪ : Canvasを作ってみる 19 3. `src/sample0_hello_world_canvas/index.html`を右クリックして、 Live Serverで開く $ code
WebGL2-tutorial/ 2. codeコマンドで、VSCodeで開く (VSCodeユーザ向け) VSCodeの拡張機能であるLive Server
Hands-on⓪ : Canvasを作ってみる 20 2. VSCode以外のユーザーは、Pythonの標準のhttpパッケージの serverモジュール使って、ローカルサーバーを起動 $ python3 -m
http.server 3000 参考:簡単なローカルサーバーの立て方 (非VSCodeユーザ向け※ ) $ cd WebGL2-tutorial/src/sample0_hello_world_canvas 3. 指定したポート番号(この例だと、3000)に、ブラウザから `http://localhost:3000`にアクセス ※Macのopenコマンドは、後にモジュールをimportしたjsを使う時 にエラーになるので非推奨
Hands-on⓪ : Canvasを作ってみる 21 こういうのが、ブラウザ上で表示出来ると成功。
Canvasとは(厳密には) • WebGLが描画した絵を表示する領域を、用意してあげる Javascript Canvasってとこに表 示するか〜 22 厳密には、javascript内で Canvasを作っているのではなく、 html・css内で宣言・定義したCanvasに、
javascriptからアクセスしている。
まだWebGL出てきてない、、 23
Hands-on① Hello World! WebGL 24
Hands-on① : Hello World! WebGL 25 (VSCodeユーザ向け) 1個目のサンプル`src/sample1_hello_world_webgl/index.html` を右クリックして、Live Serverで開く
Hello World! WebGLの中身 26 1. (L6) html側で定義したcanvasのidを指定して、どのcanvasに描画するか決める 2. (L9) GLコンテキストと呼ばれる、描画命令を司るオブジェクトを作成。
この時に、引数に”webgl”ではなく、”webgl2”を指定。 3. (L23) 色を指定して、canvasをクリアする src/sample1_hello_world_webgl/hello_webgl.jsの解説 ID : webgl-canvas-id
Hello World! WebGLの中身 27 1. (L6) html側で定義したcanvasのidを指定して、どのcanvasに描画するか決める 2. (L9) GLコンテキストと呼ばれる、描画命令を司るオブジェクトを作成。
この時に、引数に”webgl”ではなく、”webgl2”を指定。 3. (L23) 色を指定して、canvasをクリアする src/sample1_hello_world_webgl/hello_webgl.jsの解説 GLコンテキスト
Hello World! WebGLの中身 28 1. (L6) html側で定義したcanvasのidを指定して、どのcanvasに描画するか決める 2. (L9) GLコンテキストと呼ばれる、描画命令を司るオブジェクトを作成。
この時に、引数に”webgl”ではなく、”webgl2”を指定。 3. (L20)(L23) 色を指定して、canvasをクリアする src/sample1_hello_world_webgl/hello_webgl.jsの解説
Hands-on① : 背景色を変更してみよう 29 canvasの背景色の色を、好きな色に変更しよう!
Hands-on①のヒント 30 rgba=(0.7, 0.7, 0.7, 1,0)で、canvasの色を塗り潰す。aは透明度。 (rgbの値は、0.0f~1.0fまでのfloatで指定。 描画される時に255倍されてuint8になる) ヒント:`src/sample1_hello_world_webgl/hello_webgl.js`のL23を修正 図引用:https://viewpoint-nk.github.io/blog/webgl/webgl-hello-world.html
Hands-on① : 背景色を変更してみよう 31 解答
シェーダーとは 32
2Dの正方形を描こう 33 サンプル2の実行結果(`src/sample2_2d_square/index.html`)
2Dの正方形を描こう 34 サンプル2のソースコード(src/sample2_2d_square/)を例に、解説!
シェーダーとは 35 図引用:https://fmiranda.me/courses/cs425-slides/04-webgl.pdf シーン(3D) (オブジェクト、マテリアル、カメラ、光源) 絵(2D) (レンダリング画像) レンダリ ング シェーダー
=実際に絵を描くとこを担当
シェーダーとは • シェーダーとは =GPU使って絵を描く人 • シェーダーにどのようにデータを渡すか? 36 シェーダー Javascript こんな感じの絵を
描いてくれ〜!
シェーダー2人いる! • シェーダー実はもう一人いる! 37 Javascript こんな感じの絵を 描いてくれ〜! シェーダー
2つのシェーダー 38 頂点シェーダー (=図形の頂点のみを描く人) フラグメントシェーダー (=ピクセルの色を塗る人) (0.3, 0.3) (-0.3, -0.3)
(0.3, -0.3) (-0.3, 0.3)
頂点シェーダー 39 頂点シェーダー (=図形の頂点のみを描く人) フラグメントシェーダー (=ピクセルの色を塗る人) (0.3, 0.3) (-0.3, -0.3)
(0.3, -0.3) (-0.3, 0.3)
頂点シェーダー 40 in:シェーダーの入力変数を表す修飾子。 out:シェーダーの出力変数を表す修飾子。 • 頂点シェーダーの2Dベクトル(vec2)の入力変数:`aVertexPosition`を宣言。 2Dの図形の頂点の座標を代入する。(例:[[0.3,0.3],[-0.3,0.3],...]) • `gl_Position`:出力変数。描画される頂点の座標(予約語なので、宣言しない) •
ベクトルが4D(vec4)なのは、3Dの同次座標系(n+1次元)のため。 (0.3, 0.3) (-0.3, -0.3) (0.3, -0.3) (-0.3, 0.3) src/sample2_2d_square/shaders/vertex-shader-glsl.js
頂点シェーダー 41 • シェーダー部分は、GLSL(GL Shading Language)と呼ばれる 特有のシェーダー言語で書かれる。 ◦ GLSLの文法≠javascriptの文法 •
WebGL2で使われるシェーディング言語はGLSL。一方、厳密には、WebGL2 はOpenGLではなくOpenGL ES3.0の仕様に基づくので、GLSLのサブセット であるESSLと呼ぶのが正しいらしい。 (0.3, 0.3) (-0.3, -0.3) (0.3, -0.3) (-0.3, 0.3) src/sample2_2d_square/shaders/vertex-shader-glsl.js
フラグメント シェーダー 42 頂点シェーダー (=図形の頂点のみを描く人) フラグメントシェーダー (=ピクセルの色を塗る人) (0.3, 0.3) (-0.3,
-0.3) (0.3, -0.3) (-0.3, 0.3)
フラグメント シェーダー 43 FlagColorという変数名の出力変数を宣言。 今回は、rgba=(0.5, 1, 1, 1)の固定色で、ピクセルの色を塗り潰す。 (rgbの値は、0.0f~1.0fまでのfloatで指定。 描画される時に255倍されてuint8になる)
src/sample2_2d_square/shaders/fragment-shader-glsl.js
2つのシェーダー 44 頂点シェーダー (=図形の頂点のみを描く人) フラグメントシェーダー (=ピクセルの色を塗る人) (0.3, 0.3) (-0.3, -0.3)
(0.3, -0.3) (-0.3, 0.3)
Hands-on② 2Dの正方形をいじろう 45
Hands-on② - 1:正方形の色を好きな色に変更してみよう! 46 src/sample2_2d_square/を修正して、 正方形の色を好きな色に変更してみよう!
Hands-on② - 1のヒント 47 頂点シェーダー (=図形の頂点のみを描く人) フラグメントシェーダー (=ピクセルの色を塗る人) (0.3, 0.3)
(-0.3, -0.3) (0.3, -0.3) (-0.3, 0.3) ピクセルの色を決めてたのは、、
Hands-on② - 1のヒント 48 ピクセルの色を決めてたのは、、 フラグメントシェーダー src/sample2_2d_square/shaders/fragment-shader-glsl.js
Hands-on② - 1:正方形の色を好きに変更してみよう! 49 解答 rgbの値を変更
レンダリング パイプライン 50
描画までの流れ 51 1. ウェブページが読み込まれて、main.jsのmain関数が実行される (以下、main関数内) 2. シェーダーのコンパイル 3. シェーダーのリンク 4.
バッファの初期化 5. ドローコール main関数内
描画までの流れ 52 1. ウェブページが読み込まれて、main.jsのmain関数が実行される (以下、main関数内) 2. シェーダーのコンパイル(shaderオブジェクトの作成) 3. シェーダーのリンク(programオブジェクトの作成) 4.
バッファの初期化(bufferオブジェクトの作成) 5. ドローコール(描画命令) main関数内
描画までの流れ 53 1. ウェブページが読み込まれて、main.jsのmain関数が実行される (以下、main関数内) 2. シェーダーのコンパイル(shaderオブジェクトの作成) 3. シェーダーのリンク(programオブジェクトの作成) 4.
バッファの初期化(bufferオブジェクトの作成) 5. ドローコール main関数内
描画までの流れ 54 1. ウェブページが読み込まれて、main.jsのmain関数が実行される (以下、main関数内) 2. シェーダーのコンパイル(shaderオブジェクトの作成) 3. シェーダーのリンク(programオブジェクトの作成) 4.
バッファの初期化(bufferオブジェクトの作成) 5. ドローコール main関数内
シェーダーのコンパイル・リンクを行う関数を呼び出す 1. main.jsで、自作モジュール`init-shader.js`の 自作関数`initShaderProgram`をimport 2. main関数内で呼び出す 55
1. (L34)まずは、shaderオブジェクト (=シェーダーのスクリプトを読み込む用のオブジェクト)を作成。 2. (L37)次に、shaderオブジェクトにシェーダーのスクリプト(source)を読み込ませる。 3. (L40)shaderオブジェクトをコンパイル。 shaderオブジェクトの作成(コンパイル) 56 コンパイル中...
描画までの流れ 57 1. ウェブページが読み込まれて、main.jsのmain関数が実行される (以下、main関数内) 2. シェーダーのコンパイル(shaderオブジェクトの作成) 3. シェーダーのリンク(programオブジェクトの作成) 4.
バッファの初期化(bufferオブジェクトの作成) 5. ドローコール main関数内
描画までの流れ 58 1. ウェブページが読み込まれて、main.jsのmain関数が実行される (以下、main関数内) 2. シェーダーのコンパイル(shaderオブジェクトの作成) 3. シェーダーのリンク(programオブジェクトの作成) 4.
バッファの初期化(bufferオブジェクトの作成) 5. ドローコール main関数内
programオブジェクトの作成(リンク)① 59 1. (L9) programオブジェクト (=2つの両方のシェーダーの情報を保持する用のオブジェクト)を作成 2. (L12)作成したprogramオブジェクトに、 先程コンパイルした2つのシェーダー(shaderオブジェクト)を紐付ける。 program
オブジェクト
program オブジェクト 3. (L16) programオブジェクトを使って、2つのシェーダーのスクリプトをリンク。 4. (L25)programオブジェクトを、GLコンテキストに紐付ける。 (=使うことを教えてあげる) programオブジェクトの作成(リンク)② 60
リンク
描画までの流れ 61 1. ウェブページが読み込まれて、main.jsのmain関数が実行される (以下、main関数内) 2. シェーダーのコンパイル(shaderオブジェクトの作成) 3. シェーダーのリンク(programオブジェクトの作成) 4.
バッファの初期化(bufferオブジェクトの作成) 5. ドローコール main関数内
描画までの流れ 62 1. ウェブページが読み込まれて、main.jsのmain関数が実行される (以下、main関数内) 2. シェーダーのコンパイル(shaderオブジェクトの作成) 3. シェーダーのリンク(programオブジェクトの作成) 4.
バッファの初期化(bufferオブジェクトの作成) 5. ドローコール main関数内
バッファとは? • バッファとは? ◦ 広く一般的には、一時的に使われるメモリを指す。 • 一方、WebGLでは、 シェーダーが読み取るためのGPU上のメモリを指す。 63 バッファに格納された
頂点のデータを 使うぞ〜! 頂点シェーダー pos[0] =0.3 pos[1] =0.3 pos[2] =-0.3 バッファ
1. main.jsで、自作モジュール`init-buffer.js`の自作関数`initBuffers`をimport 2. main関数内で呼び出す バッファの初期化を行う関数を呼び出す 64
1. (L51)空のバッファを作成(=GPU上のメモリ確保) 2. 作成したバッファに対して、 gl.ARRAY_BUFFERをバインド(=バッファの種類を、割り当てる) 3. 作成した空のバッファに、 頂点のデータ(例:positions=[0.3,0.3,...])を入れて、 バッファを埋める(=CPU側からGPU上のメモリに、データを転送して格納) バッファの初期化①
65 メモリ確保! (中身はまだない)
1. 空のバッファを作成(=GPU上のメモリ確保) 2. (L52)作成したバッファに対して、 gl.ARRAY_BUFFERをバインド(=バッファの種類を、割り当てる) 3. 作成した空のバッファに、 頂点のデータ(例:positions=[0.3,0.3,...])を入れて、 バッファを埋める(=CPU側からGPU上のメモリに、データを転送して格納) バッファの初期化②
66 このバッファは、頂点データだよ! シェーダー側で読み取っていいよ! バインド済み • gl.ARRAY_BUFFER =頂点データ(座標、色、法線など) • gl.ELEMENT_ARRAY_BUFFER =頂点の順番を表すデータ バッファの種類は2種類。
バッファの初期化③ • 頂点のデータの配列をCPU側で宣言(L46)。 67 pos[0] =0.3 pos[1] =0.3 pos[2] =-0.3
今回、GPU側に転送したい頂点のデータ。 変数宣言時には、VRAM上(CPU側)にある。 正方形の頂点の2D座標
1. 空のバッファを作成(=GPU上のメモリ確保) 2. 作成したバッファに対して、 gl.ARRAY_BUFFERをバインド(=バッファの種類を、割り当てる) 3. (L53)作成した空のバッファに、 頂点のデータ(例:positions=[0.3,0.3,...])を流し込んで、 バッファを埋める(=CPU側からGPU上のメモリに、データを転送して格納) バッファの初期化④
68 pos[0] =0.3 pos[1] =0.3 pos[2] =-0.3 pos[0] =0.3 pos[1] =0.3 pos[2] =-0.3 バインド済み
1. (L51)空のバッファを作成(=GPU上のメモリ確保) 2. (L52)作成したバッファに対して、 gl.ARRAY_BUFFERをバインド(=バッファの種類を、割り当てる) 3. (L53)作成した空のバッファに、 頂点のデータ(例:positions=[0.3,0.3,...])を流し込んで、 バッファを埋める(=CPU側からGPU上のメモリに、データを転送して格納) バッファの初期化
69 pos[0] =0.3 pos[1] =0.3 pos[2] =-0.3 pos[0] =0.3 pos[1] =0.3 pos[2] =-0.3 バインド済み
描画までの流れ 70 1. ウェブページが読み込まれて、main.jsのmain関数が実行される (以下、main関数内) 2. シェーダーのコンパイル(shaderオブジェクトの作成) 3. シェーダーのリンク(programオブジェクトの作成) 4.
バッファの初期化(bufferオブジェクトの作成) 5. ドローコール main関数内
描画までの流れ 71 1. ウェブページが読み込まれて、main.jsのmain関数が実行される (以下、main関数内) 2. シェーダーのコンパイル(shaderオブジェクトの作成) 3. シェーダーのリンク(programオブジェクトの作成) 4.
バッファの初期化(bufferオブジェクトの作成) 5. ドローコール(描画命令) main関数内
ドローコールを行う関数を呼び出す 1. main.jsで、自作モジュール`draw-scene.js`の 自作関数`drawScene`をimport 2. main関数内で呼び出す 72
バッファの初期化完了! 73 pos[0] =0.3 pos[1] =0.3 pos[2] =-0.3 頂点データが格納された GPU上のバッファ
バインド済み
頂点シェーダーはバッファに格納された値を使いたい 74 頂点シェーダー フラグメント シェーダー (0.3, 0.3) (-0.3, -0.3) (0.3,
-0.3) (-0.3, 0.3) pos[0] =0.3 pos[1] =0.3 pos[2] =-0.3 バインド済み 頂点データが格納された GPU上のバッファ 頂点のデータ 使いたい〜!
頂点シェーダーはバッファに格納された値を使いたい 75 頂点シェーダー 頂点のデータ 使いたい〜! pos[0] =0.3 pos[1] =0.3 pos[2]
=-0.3 バインド済み 頂点データが格納された GPU上のバッファ
Attributeとは 76 頂点シェーダー 頂点のデータ 使いたい〜! pos[0] =0.3 pos[1] =0.3 pos[2]
=-0.3 バインド済み 頂点データが格納された GPU上のバッファ Attribute =頂点シェーダーの入力変数のこと 参考:WebGL2で、頂点シェーダー内での変数宣言の際の修飾子が、 attributeからinに変更。
Attributeのポインタでバッファを指し示す 77 頂点シェーダー 頂点のデータ 使いたい〜! pos[0] =0.3 pos[1] =0.3 pos[2]
=-0.3 バインド済み 頂点データが格納された GPU上のバッファ ポインタ Attribute =頂点シェーダーの入力変数のこと
Attributeのポインタでバッファを指し示す 78 頂点シェーダー pos[0] =0.3 pos[1] =0.3 pos[2] =-0.3 バインド済み
頂点データ Attribute ポインタ バッファをAttributeのポインタで指し、頂点シェーダーに分かるように、バッファに 格納されたデータの説明をしてあげる どんな頂点の データなの〜? draw-scene.js(L10)
Attributeの有効化 79 頂点シェーダー pos[0] =0.3 pos[1] =0.3 pos[2] =-0.3 バインド済み
頂点データ Attribute ポインタ じゃあ使うね〜! Attributeを有効化 draw-scene.js(L11)
ビューポート変換とは 80 図引用:https://tokoik.github.io/gg/ggnote01.pdf ビューボリュームからはみ出たとこは描画しない (-1,-1,-1) (1,1,1) (0,0,0) ビューボリューム (クリッピング空間) draw-scene.js(L5)
ビューポート変換とは 81 gl.canvas.width gl.canvas.height (0, 0) ビューポート ビューボリューム内でシェーダーで描いた図形が、 ビューポート変換後、ビューポートがcanvasに表示される ビューポート変換
参考:WebGLとcanvasのサイズ (gl.canvas.width,gl.canvas.height) (-1,-1,-1) (1,1,1) (0,0,0) ビューボリューム (クリッピング空間) draw-scene.js(L5)
ビューポート変換による歪みを解消 82 ビューポート(canvas)のアスペクト比に 合わせて、頂点の座標を修正することで、 ビューポート変換の際の、図形の歪みを解消。 (長方形ではなく、正方形として表示される) 図引用 :https://mitani.cs.tsukuba.ac.jp/lecture/old2015/cg/03/03_slides.pdf init-buffer.js(L39)
ドローコール ドローコール(Draw call)=描画命令。 これでcanvas(描画領域)に描画される `gl.drawArrays()`の第一引数は、primitiveの種類。 今回の例では、`gl.TRIANGLE_STRIP`を指定。 =最初の3つの頂点が最初の三角形を形成し、その後は、 前の2つの頂点を再利用して、新たな1つの頂点が新しい三角形を形成。 83 図引用
:https://fmiranda.me/courses/cs425-slides/04-webgl.pdf draw-scene.js(L17)
Hands-on③ 三角形を描画してみよう 84
Hands-on② - 2:正方形→三角形を描画してみよう! 85 五角形や好きな図形でも!
Hands-on② - 2のヒント • 頂点の座標データ • ドローコール 86 今回、転送する頂点のデータ (正方形の2D座標)
Hands-on② - 2のヒント • 頂点の座標データ • ドローコール ◦ プリミティブのタイプ ◦
頂点の個数 87
Hands-on② - 2:正方形→三角形を描画してみよう! 88 • 頂点の座標データ • ドローコール ◦ プリミティブのタイプ
◦ 頂点の個数 解答
VBO, IBO and VAO 89
• バッファの種類3つ • VBO、IBO、VAO ◦ VBOとは? ▪ Vertex Buffer Object(頂点バッファオブジェクト)
◦ IBOとは? ▪ Index Buffer Object(インデックスバッファオブジェクト) ◦ VAOとは? ▪ Vertex Array Object 90 バッファの種類
VBO • VBOとは? ◦ Vertex Buffer Object(頂点バッファオブジェクト) • 頂点の座標、色、法線などの頂点のデータを表すバッファの名称。 91
(0.3, 0.3) (-0.3, -0.3) (0.3, -0.3) (-0.3, 0.3) (0.3, 0.3) (-0.3, -0.3) (0.3, -0.3) (-0.3, 0.3) (0.3, 0.3) (-0.3, -0.3) (0.3, -0.3) (-0.3, 0.3) 頂点の座標 VBO1つ 頂点の座標+色 VBO2つ 頂点の座標+色+法線 VBO3つ
IBO • IBOとは? ◦ Index Buffer Object(インデックスバッファオブジェクト) ◦ 頂点のインデックスの配列(描画の順番を表す。) •
同じ頂点データを使い回す時に有効。 92 • バインドするときにのバッファの種類を gl.ARRAY_BUFFERではなく、 gl.ELEMENT_ARRAY_BUFFER • ドローコールの際に、 gl.drawArrays()ではなく、gl.drawElements()
IBO使って、2Dの正方形を描こう 93 サンプル3の実行結果(`src/sample3_2d_square_ibo/index.html`)
VBO • VBOとは? ◦ Vertex Buffer Object(頂点バッファオブジェクト) • 頂点の座標、色、法線などの頂点のデータを表すバッファの名称。 94
(0.3, 0.3) (-0.3, -0.3) (0.3, -0.3) (-0.3, 0.3) (0.3, 0.3) (-0.3, -0.3) (0.3, -0.3) (-0.3, 0.3) (0.3, 0.3) (-0.3, -0.3) (0.3, -0.3) (-0.3, 0.3) 頂点の座標 VBO1つ 頂点の座標+色 VBO2つ 頂点の座標+色+法線 VBO3つ
複数のVBO • 頂点の座標+色+法線の場合、VBO3つ • VBO1つ1つバインドしたり、管理めんどくさい。一つに集約出来ないか...? 95 (0.3, 0.3) (-0.3, -0.3)
(0.3, -0.3) (-0.3, 0.3) 頂点の座標+色+法線 VBO3つ VBO (座標) VBO (色) VBO (法線)
VAO • 複数のVBOを、1つのVAOにまとめる。 • VAOは、attribute(頂点シェーダーの入力変数)のポインタを持ってる (ドローコールの際に、VAOをバインドするだけでOK) 96 VAO VBO (座標)
VBO (色) VBO (法線) ポインタ
VAOで、複数のVBOまとめる src/sample5_2d_square_vao_color 頂点の座標+色を、頂点シェーダーに入力。 97
Hands-on(optional) 3Dの立方体を描こう 98
3Dの立方体を描こう src/sample6_3d_cube 99
軌道(周回、Orbiting)カメラ src/sample11_3d_cube_orbit_cam_phongLight マウスのxy座標を読み取って、原点を中心にカメラが回転 100 図引用 :https://www.amazon.co.jp/GPU%E4%B8%A6%E5%88%97%E5%9B%B3% E5%BD%A2%E5%87%A6%E7%90%86%E5%85%A5%E9%96%80-CUDA% E3%83%BBOpenGL%E3%81%AE%E5%B0%8E%E5%85%A5%E3%81%A8 %E6%B4%BB%E7%94%A8-Software-Design-plus/dp/477416304X
複数の立方体の描画 src/sample12_3d_cube_orbit_cam_phong_pointLight_multipleCubes 立方体の数や落下・回転の速度を変えてみよう! 101
行列ライブラリ:glMatrix 102 図引用 :https://mitani.cs.tsukuba.ac.jp/lecture/old2015/cg/03/03_slides.pdf