Slide 1

Slide 1 text

レイマーチング入門


Slide 2

Slide 2 text

目次
 ラスタライズ
 グラフィックスパイプライン
 GLSL
 レイトレーシング
 レイマーチング
 マーチングループ
 距離関数


Slide 3

Slide 3 text

3Dレンダリングの手法
 大きく分けて
 ● ラスタライズ
 ● レイトレーシング
 の2つ
 レイマーチングはレイトレーシングの1種


Slide 4

Slide 4 text

ラスタライズの流れ (グラフィックスパイプライン)
 1. 入力
 2. 頂点パイプライン
 各頂点の位置や色を計算、投影面に投影
 3. ラスタライズ
 頂点の集合をピクセルの集合に変換
 4. ピクセルパイプライン
 各ピクセルの色を計算
 5. 出力


Slide 5

Slide 5 text

入力
 ポリゴン、テクスチャ、マッピング、法線など


Slide 6

Slide 6 text

頂点パイプライン
 透視投影 - Wikipedia


Slide 7

Slide 7 text

ラスタライズ
 頂点の持つパラメーターをピクセルごとに線形補間


Slide 8

Slide 8 text

ピクセルパイプライン
 ピクセルの位置と線形補間されたパラメータからピクセルの色などを決定


Slide 9

Slide 9 text

グラフィックスパイプラインの処理対象は膨大
 最大で数千万個の頂点を数百万個のピクセルに描画する
 これらの処理を並列実行するのがGPU


Slide 10

Slide 10 text

GPU (Graphics Processing Unit)
 グラフィックスパイプラインを処理することに特化したプロセッサ
 性能を抑えたコアを大量に搭載して並列実行


Slide 11

Slide 11 text

OpenGL (Open Graphics Library)
 グラフィックスパイプラインに入力を行うためのAPI
 Unix, Linux, Windows, Mac, Android, iPhoneで使える
 ただしAppleはOpenGLを非推奨に (f**k)
 かつてはDirect3D (WindowsのグラフィックスAPI) に後れを取っていたが、
 現在では遜色なく使える


Slide 12

Slide 12 text

シェーダー
 グラフィックスパイプラインの一部を担うプログラム
 頂点シェーダー
 頂点パイプラインの一部
 座標変換・頂点ごとの陰影処理などを担う
 フラグメントシェーダー
 ピクセルパイプラインの一部
 ピクセルの色付け・ピクセルごとの陰影処理などを担う


Slide 13

Slide 13 text

GLSL (OpenGL Shader Language)
 OpenGLに含まれる、シェーダーを記述するためのプログラミング言語
 C言語をベースとした高級言語
 行列演算・ベクトル演算向けの機能が豊富


Slide 14

Slide 14 text

GLSLだけで描画する
 raymarching.pdeを実行
 mandelbrot.glslが内部で実行される
 ここでGLSLのキホンをがんばって話す


Slide 15

Slide 15 text

ラスタライズの欠点
 陰影表現には優れているが、光の反射・屈折などの光学現象の再現が難しい
 環境マッピング・シャドウマッピングなどで擬似的に再現
 描画負荷が頂点数に依存するので複雑な図形の描画が重い


Slide 16

Slide 16 text

レイトレーシング
 視点に入る光を逆にたどって、その先にある物体を描画する
 この光線を「レイ」と呼ぶ
 光の反射や屈折を再現できるので、リアルな描画ができる


Slide 17

Slide 17 text

レイトレーシングの欠点
 描画負荷が非常に高い
 数百万の光線を飛ばして物体との当たり判定や反射・屈折の処理を行う
 反射回数を増やすとさらに光線が増える
 物体の形状ごとに当たり判定が必要
 球や直方体などのプリミティブなら容易だが複雑な形状は苦手
 


Slide 18

Slide 18 text

レイマーチング
 距離関数という関数で物体の形状を定義
 レイと物体の交点を解析的でなく数値的に求める
 距離関数で定義できるなら複雑な形状も表現できる


Slide 19

Slide 19 text

数値的にレイを進める
 進む距離が短いと物体に
 当たるまで時間がかかる


Slide 20

Slide 20 text

数値的にレイを進める
 進む距離が長いと物体を
 貫通するかもしれない


Slide 21

Slide 21 text

数値的にレイを進める
 
 
 
 このあたりは一気にレイを進めたい
 ↓
 ↑
 このあたりは少しずつレイを進めたい


Slide 22

Slide 22 text

数値的にレイを進める
 一番近い物体の、一番近い点までの
 距離進めば無駄がないし貫通しない


Slide 23

Slide 23 text

数値的にレイを進める
 「物体の一番近い点までの距離」が
 分かれば「一番近い物体」も
 自動的に分かる


Slide 24

Slide 24 text

距離関数
 物体Objの距離関数 distObj(pos) とは、点posからObjまでの最短距離である


Slide 25

Slide 25 text

レイマーチング
 レイを距離関数の長さだけ進めることを繰り返し (マーチング・ループ) 、
 距離関数が十分0に近づいたら
 レイが物体に当たったとみなす


Slide 26

Slide 26 text

球の距離関数
 中心(0, 0, 0), 半径rの球Sphereの距離関数distSphere(pos)は
 distSphere(pos) = length(pos) - r
 で表される


Slide 27

Slide 27 text

球の距離関数
 dist(pos) = length(pos) - r


Slide 28

Slide 28 text

直方体の距離関数
 中心 (0, 0, 0), 3辺の長さが 2 * b の直方体の距離関数distBox(pos)は
 distBox(pos) = length(max(abs(pos) - b, 0))
 で表される


Slide 29

Slide 29 text

直方体の距離関数
 dist(pos) = length(max(abs(pos) - b, 0))


Slide 30

Slide 30 text

和集合
 distObj1(pos) で表される立体 Obj1 と
 distObj2(pos) で表される立体 Obj2 の
 和集合 Obj1 ∪ Obj2 は
 Obj1 ∪ Obj2 = min(distObj1, distObj2)
 で表される


Slide 31

Slide 31 text

積集合
 distObj1(pos) で表される立体 Obj1 と
 distObj2(pos) で表される立体 Obj2 の
 積集合 Obj1 ∩ Obj2 は
 Obj1 ∪ Obj2 = max(distObj1, distObj2)
 で表される
 


Slide 32

Slide 32 text

差集合
 distObj1(pos) で表される立体 Obj1 から
 distObj2(pos) で表される立体 Obj2 を
 除いた差集合 Obj1 - Obj2 は
 Obj1 - Obj2 = max(distObj1, -distObj2)
 で表される
 


Slide 33

Slide 33 text

差集合の仕組み


Slide 34

Slide 34 text

複製
 distObj(pos)で表されるObjを間隔periodで
 無限に繰り返す距離関数は
 distObj(pos’)
 pos’ := mod(pos, period) - period/2


Slide 35

Slide 35 text

回転
 distObj(pos)で表されるObjをnのまわりにθ回転させた距離関数は
 distObj(Rn(θ) × pos)
 
 
 ロドリゲスの回転公式 - Wikipedia


Slide 36

Slide 36 text

シェーディング
 Obj上の点posにおけるObjの法線nは
 n = ∇distObj(pos)
 で表される


Slide 37

Slide 37 text

メンガーのスポンジを作ってみよう


Slide 38

Slide 38 text

References
 wgld.org | GLSL
 https://wgld.org/d/glsl/
 Inigo Quilez | distance functions
 http://iquilezles.org/www/articles/distfunctions/distfunctions.htm