$30 off During Our Annual Pro Sale. View Details »

IFSによるフラクタルのモデリング

がむ
September 01, 2023

 IFSによるフラクタルのモデリング

レイトレ合宿9のセミナー用スライド②です。

Googleスライド
https://docs.google.com/presentation/d/1hqR1Rf-sfX2mTVOMR09xX9OUSwxk0aAXQwDJL6aZRHs/edit#slide=id.g27a8e85b88a_0_0

がむ

September 01, 2023
Tweet

More Decks by がむ

Other Decks in Programming

Transcript

  1. IFSによる

    フラクタルのモデリング

    2023-09-01 レイトレ合宿9セミナー
    @gam0022 / Sho HOSODA

    View Slide

  2. Transcendental Cubeについて

    • Transcendental Cube

    ‣ SESSIONS2023のGLSL Graphics Compo 2位🥈

    ‣ Run on twigl classic (300 es) mode


    ● 映像: @gam0022(自分)

    ● 音楽: @sadakkey さん

    2
    YouTube


    View Slide

  3. ダイジェスト版の動画
    3

    View Slide

  4. アジェンダ
    • シェーダーだけで映像をつくる

    • IFS

    • 壁面の演出

    • SESSIONSの紹介

    • おわりに

    4

    View Slide

  5. GLSL Graphics Compoとは?

    ● GLSLのシェーダーだけで映像を作る部門

    ○ GLSL (OpenGL Shading Language)

    ○ OpenGLやWebGL用のシェーダー言語


    5

    View Slide

  6. 6
    Consts, Global Variables and Utility Functions
    定数、グローバル変数、便利な関数
    Scene Modeling
    シーンのモデリング
    Lighting ライティング
    Timeline Sequence and Camera Work
    タイムラインとカメラ制御
    Total 9270 chars

    View Slide

  7. GLSL Graphics Compoとは?

    ● ソースコードは twigl.app(Webアプリ)上で実行できる

    7

    View Slide

  8. GLSL Graphics Compoとは?

    ● 外部アセット(テクスチャや3Dモデル)は使用禁止

    ○ シェーダーでプロシージャルに生成


    8

    View Slide

  9. シェーダーだけで映像を作る技術

    • twiglは2D用のシェーダー

    ‣ シェーダーの入力

    • スクリーン上の座標 + 時間

    ‣ 通常は3D描画はできない


    • レイマーチングという手法で3Dシーンを描画

    ‣ シェーダー内で3D空間やカメラを定義

    ‣ 距離関数(数式)で3Dシーンをモデリング

    9

    View Slide

  10. レイマーチングとは?

    • レイマーチングとは

    ‣ 距離関数で表現された形状に対する交差判定の手法


    • 距離関数とは

    ‣ 任意の座標pから物体表面への最短距離を返す関数

    10
    float sdSphere(vec3 p, float r)
    {
    return length(p) - r;
    }

    View Slide

  11. レイマーチングとは?

    11
    float sdBox(vec3 p, vec3 b)
    {
    vec3 q = abs(p) - b;
    return length(max(q, 0.0)) + min(max(q.x, max(q.y, q.z)), 0.0);
    }
    https://iquilezles.org/articles/distfunctions/

    View Slide

  12. レイマーチングとは?

    • レイマーチングを可視化したアニメーション by @kanetaaaaa 

    ‣ Raymarching in Raymarching

    ‣ https://twitter.com/kanetaaaaa/status/1141307706139004934

    ‣ https://qiita.com/kaneta1992/items/21149c78159bd27e0860

    12

    View Slide

  13. レイマーチングとは?

    • レイマーチングのアルゴリズム

    ‣ 距離関数だけレイを進めるのを繰り返す(マーチング・ループ)

    • 距離関数dが0に近似できたら衝突したと判定

    ‣ abs(d) < eps

    ‣ epsは0.001 など適切に設定

    • ループ回数がNを超えたら衝突していないと判定

    ‣ Nは100〜300くらいが一般的

    13
    極めてシンプル


    View Slide

  14. 距離関数の操作 = 空間の操作

    • 直感と逆の操作になる 

    ‣ オブジェクト側ではなくて 空間の側を操作

    ‣ 空間はUVと読み替えると理解しやすい 

    ‣ https://www.shadertoy.com/view/sdySR3 


    • 2倍に拡大したい

    ‣ p *= 0.5;


    • 右に 1.0 移動したい 

    ‣ p.x -= 1.0;


    • Y軸にrだけ回転したい 

    ‣ p.xz = rot(-r) * p.xz; 

    14

    View Slide

  15. modによる繰り返し

    • pにmodを適用すると無限に繰り返しができる 

    ‣ p = mod(p, 1.0) - 0.5; 


    • なぜ

    ‣ テクスチャのWrapモードのRepeatのような感じ 

    ‣ 上の例

    • -0.5〜0.5 の範囲の座標が永遠に繰り返される 

    15

    View Slide

  16. アジェンダ
    • シェーダーだけで映像をつくる

    • IFS

    • 壁面の演出

    • SESSIONSの紹介

    • おわりに

    16

    View Slide

  17. モデリング

    シンプルなCubeをIFS(Iterated Function System)で複雑にした

    17
    Cube IFS-ed Cube

    View Slide

  18. IFS(Iterated Function System)

    自身の拡縮・回転・コピーなどによるフラクタル生成システム



    2DのIFSの例



    18
    4. Iterated function system | Download Scientific Diagram 


    View Slide

  19. IFS(Iterated Function System)

    シェーダーでIFSを実装する場合、折りたたみを使う

    19
    https://www.seibundo-shinkosha.net/book/craft/57298/


    View Slide

  20. IFS(Iterated Function System)

    折りたたみ例:万華鏡

    合わせ鏡の構造によって同じパターンを繰り返す


    20
    https://minne.com/items/28401940 
 https://ja.wikipedia.org/wiki/%E4%B8%87%E8%8F%AF%E9%8F%A1 


    View Slide

  21. IFS(Iterated Function System)

    折りたたみ例:絞り染め

    絞り染め(しぼりぞめ)は布の一部を縛るなどの方法で圧力をかけ染料が染み込まないようにすることで

    模様を作り出す模様染めの技法の一つ


    折りたたみによって、模様を転写して、同じパターンを繰り返す


    21
    https://blog.goo.ne.jp/keikonogoo14/e/c5d0aa5bc072441bf27710c22a84bd60


    View Slide

  22. IFS(Iterated Function System)

    折りたたみ例:絞り染め

    22
    https://plaza.rakuten.co.jp/notonote/diary/201912170000/


    View Slide

  23. IFS(Iterated Function System)

    ● 空間を折りたたむことで、

    同じ図形を一定の法則(幾何学的)にコピーする


    ● 面白いパターンや複雑な形状を生成できる


    23

    View Slide

  24. IFS(Iterated Function System)

    シェーダーライブコーディングのすすめ by kaneta


    24

    View Slide

  25. IFS(Iterated Function System)

    シェーダーライブコーディングのすすめ by kaneta


    25

    View Slide

  26. IFS(Iterated Function System)

    シェーダーライブコーディングのすすめ by kaneta

    26

    View Slide

  27. IFS(Iterated Function System)

    27
    for (int i = 0; i < int(_IFS_Iteration); i++) {
    p1 = abs(p1 + _IFS_Offset.xyz) - _IFS_Offset.xyz;
    rot(p1.xz, TAU * _IFS_Rot.x);
    rot(p1.zy, TAU * _IFS_Rot.y);
    rot(p1.xy, TAU * _IFS_Rot.z);
    }
    opUnion(m, sdBox(p1, _IFS_BoxBase.xyz), SOL, roughness, 0.5); // ベース部分
    opUnion(m, sdBox(p1, _IFS_BoxEmissive.xyz), SOL, roughness + boxEmi, hue); // 光る部分
    forの中で適当に空間を操作
    ● 折りたたみ(abs)
    ● 平行移動(±offset)
    ● 回転(rot)
    IFSの実装自体はこれだけで簡単

    View Slide

  28. 折りたたみによるIFSのメリット

    IFSを実現するアプローチ


    1. オブジェクトを複製して配置

    a. 一般的なアプローチ


    1. 空間の折りたたみ

    b. レイマーチングで利用できるアプローチ

    28

    View Slide

  29. MengerSponge

    29
    d = 0 (フラクタルの深度)
    n = 1(箱の個数)
    d = 1
    n = 7 + 4 + 7 = 18個の箱

    View Slide

  30. MengerSponge

    30
    d = 0 (フラクタルの深度)
    n = 1(箱の個数)
    d = 1
    n = 18
    d = 2
    n = 18^2 = 324
    d = 3
    n = 18^3 = 5832
    フラクタルの深度を増やすと、箱の数が 指数関数的に増えてしまう🤯

    View Slide

  31. 折りたたみによるIFSのメリット

    IFSを実現するアプローチ


    1. オブジェクトを複製して配置

    a. ❌フラクタルの深度が増えると指数関数的にオブジェクト数が増加

    i. メモリや負荷が非現実的になる 


    1. 空間の折りたたみ

    b. レイマーチングで利用できるアプローチ

    31

    View Slide

  32. MengerSpongeを距離関数で表現

    32
    float dMenger(float3 z0, float3 offset, float scale)
    {
    float4 z = float4(z0, 1.0);
    [loop]
    for (int n = 0; n < _MengerIteration; n++)
    {
    z = abs(z);
    if (z.x < z.y) z.xy = z.yx;
    if (z.x < z.z) z.xz = z.zx;
    if (z.y < z.z) z.yz = z.zy;
    z *= scale;
    z.xyz -= offset * (scale - 1.0);
    if (z.z < - 0.5 * offset.z * (scale - 1.0))
    z.z += offset.z * (scale - 1.0);
    }
    return (length(max(abs(z.xyz) - float3(1.0, 1.0, 1.0), 0.0)) - 0.05) / z.w;
    }
    箱の距離関数を1回だけ計算
    空間の折りたたみ
    forループ数 = 再帰深度
    再帰の深度を増やしても
    線形にしか負荷が増えない

    View Slide

  33. MengerSpongeを距離関数で表現

    33
    拡大
    d = 10
    n = 18^10 = 3.5704672e+12 = 3.5兆個の箱
    3.5兆個の箱でも、レイマーチングなら 60FPSで描画できる😎

    View Slide

  34. 折りたたみによるIFSのメリット

    IFSを実現するアプローチ


    1. オブジェクトを複製して配置

    a. ❌フラクタルの深度が増えると指数関数的にオブジェクト数が増加

    i. メモリや負荷が非現実的になる 


    1. 空間の折りたたみ

    b. レイマーチングで利用できるアプローチ

    c. 💯フラクタルの深度を増えても線形にしか負荷が増えない

    34

    View Slide

  35. IFS(Iterated Function System)

    • IFSの実装自体は簡単

    ‣ forの中で適当に空間操作するだけ


    • IFSのパラメーター調整は難しい

    ‣ 今回のIFSは6次元のパラメーター

    • 平行移動(vec3)+ 回転(vec3)

    • これは比較的少ない方なので、通常はさらに増えていく

    ‣ 6次元の広大なパラメーター空間から、良い絵が出せる住所を探す必要がある

    • 砂漠からオアシスを見つけるような作業🌴

    • 試行錯誤が必要

    35

    View Slide

  36. モデリングの試行錯誤

    Unityでパラメーター調整してからGLSLに移植

    • UnityのInspectorの方がパラメーターの調整がしやすい

    • カメラも操作しやすい

    36
    Unity GLSL(Shadertoy)

    View Slide

  37. モデリングの試行錯誤(制作初期)

    制作初期は複雑なジオメトリーだったが、最終的にはシンプルに落ち着いた

    37

    View Slide

  38. モデリングの試行錯誤(制作初期)

    38

    View Slide

  39. 情報量のバランスを考慮して最終調整

    • Mad Tracingによってライティングの情報量が多い

    • ジオメトリーの情報量は抑えた方がバランスが良さそう🤔と考えた

    ‣ 両方情報量MAXだと、GPU負荷、動画のビットレートなども厳しい…

    39

    View Slide

  40. アジェンダ
    • シェーダーだけで映像をつくる

    • IFS

    • 壁面の演出

    • SESSIONSの紹介

    • おわりに

    40

    View Slide

  41. 壁面の演出

    部屋のジオメトリーも超シンプル(装飾のない完全な直方体) 

    床や壁がシンプルにすることで反射を活かしたかった 

    壁面のEmissiveのパターンによって情報量を増やした 

    41

    View Slide

  42. // Hash without Sine by David Hoskins.
    // https://www.shadertoy.com/view/4djSRW
    float hash12(vec2 p) {
    vec3 p3 = fract(vec3(p.xyx) * .1031);
    p3 += dot(p3, p3.yzx + 33.33);
    return fract((p3.x + p3.y) * p3.z);
    }
    // uvをfloorして利用
    float emi = step(.5, hash12(floor(pos.yz) + 123.23 * floor(beat * 2.)));
    壁面の演出

    42
    ライティング計算
    (Mad Tracing)用の乱数を再利用

    View Slide

  43. 壁面の演出:警告

    43

    View Slide

  44. ダイジェスト版の動画
    44

    View Slide

  45. // 2DのIFSでマークを生成
    vec4[] param_array = vec4[](
    vec4(140., 72., 0., 0.), vec4(0., 184., 482, 0.), vec4(0., 0., 753., 0.),
    vec4(541., 156., 453., 0.), vec4(112., 0., 301., 0.),
    vec4(311., 172., 50., 0.), vec4(249., 40., 492., 0.), vec4(0.));
    vec4 param = param_array[int(mod(dice * 33.01, 8.))] / vec2(1200., 675.).xyxy;
    vec2 p1 = p - param.xy;
    for (int i = 0; i < 3; i++) {
    p1 = abs(p1 + param.xy) - param.xy;
    rot(p1, TAU * param.z);
    }
    float d = sdBox(p1, vec2(.2, .05));
    mark = saturate(smoothstep(0., .01, d));
    壁面の演出:警告

    45
    IFSのパラメーターは配列で定義
    2DのIFS
    ・折りたたみ
    ・平行移動
    ・回転
    マーク

    View Slide

  46. IFSのバリエーション

    中盤の複雑なIFSのシーンもパラメーター調整のみで実現 

    46

    View Slide

  47. IFS(Iterated Function System)

    SDF for raymarching (距離関数のスキル) by @gaziya5


    47

    View Slide

  48. IFS(Iterated Function System)

    https://gam0022.net/blog/2017/03/02/raymarching-fold/


    48

    View Slide

  49. インスピレーションを得た作品①

    Life by @setchi

    2nd place at GLSL Graphics Compo, TokyoDemoFest 2018


    [TDF2018] Life (FullHD 1080p)


    シンプルなジオメトリーがだんだん複雑になっていく

    このコンセプトを参考にした

    49

    View Slide

  50. インスピレーションを得た作品②

    delight by mercury

    1st place at Combined Intro Compo, Under Construction 2015 


    delight - mercury | 64k | 60fps 



    Global Illuminationが綺麗 

    音楽との同期が素晴らしい 

    展開も良い


    50

    View Slide

  51. インスピレーションを得た作品③

    Delayed by kaneta

    #Shader1weekCompo #S1C001 neort


    壁面のパターンが床に反射するのがカッコいいので参考にした 

    51

    View Slide

  52. インスピレーションを得た作品④

    新世紀エヴァンゲリオンの演出

    52

    View Slide

  53. アジェンダ
    • シェーダーだけで映像をつくる

    • IFS

    • 壁面の演出

    • SESSIONSの紹介

    • おわりに

    53

    View Slide

  54. SESSIONS 2023とは?

    今年の4月末にC4 LAN 2023 SPRINGの会場および配信のハイブリッドで行われた
    デモパーティーです。


    デモパーティーとはコンピューターを用いた
    プログラミングやアートに興味のある人々が日本中・世界中から一堂に会し、デ
    モ作品のコンペティション (Compo) やセミナーなどが行われるイベントです。


    パーティという名の通り、勉強会のように堅苦しい感じではなく、みんな賑やかに作品の制作過程を見せ合ったりと参加者同
    士でのコミュニケーションが盛んに行われます。


    SESSIONS in C4 LAN 2023 SPRING - Aftermovie

    https://sessions.frontl1ne.net/


    54

    View Slide

  55. SESSIONS 2023とは?

    SESSIONS当日には、全5部門のコンペティションを中心にセミナーやイベントが開かれ、
    約500名(リアル+オンライン配信)が参加しました。
    今回発表された総作品数は”52作品”と作り手の熱量の高さが伺えます。


    55

    View Slide

  56. SESSIONS 2023とは?

    KLabも協賛、KLab Tech Bookを頒布!

    56

    View Slide

  57. SESSIONS 2023とは?

    C4 LAN

    LANパーティーとは参加者が好きなゲームはハードごと持ち込んで遊ぶイベント形式。イベントによっては昼夜問わず
    ぶっ続けで開催され、C4 LANは3日間(今回は48時間)通して開催されるのが特徴のひとつ。

    57

    View Slide

  58. SESSIONS 2023とは?

    C4 LANの会場内で行われた(ツインメッセ静岡) 

    58

    View Slide

  59. SESSIONS 2023とは?

    RTA(リアルタイムアタック)とは、ゲームを最初からプレイしてクリアーするまでの実時間を競う遊びかた

    59

    View Slide

  60. SESSIONS 2023とは?

    • 共通点:決められた制約の中で「すごい!」と思わせる

    ‣ RTA Japan

    • ゲームの縛りプレイやタイムアタック

    ‣ デモパーティー

    • GLSL Graphics Compo

    • 容量制限の部門


    • シナジーがありそう

    ‣ 共同開催は良かった

    • デモシーンに興味を持ってくれる人が増えると嬉しい

    60

    View Slide

  61. SESSIONS 2023とは?

    61

    View Slide

  62. SESSIONS 2023とは?

    KLab Tech Bookをじっくり読む参加者 

    62

    View Slide

  63. デモパーティーに参加しよう!

    https://16ms.tokyodemofest.jp/


    • TDF 16ms #0

    ‣ 2023/10/22開催

    ‣ 完全オンライン

    63

    View Slide

  64. SESSIONSレポート

    • CGWORLD

    ‣ 数キロバイトのプログラムに心血を注ぎ込む! デモシーンの魅力とコンペティション受賞作を紹
    介〜SESSIONS in C4 LAN 2023 SPRING(1) 

    ‣ VR空間でのクラブイベントを成功させるポイント&初心者でもわかるレイマーチング講座〜
    SESSIONS in C4 LAN 2023 SPRING(2) 

    • C4 LAN

    ‣ 【C4 LAN】大量のゲーマーがゲーム機持参で勝手に遊ぶだけ。まあまあどうかしてるのに心地い
    い。ぬるま湯みたいな闇鍋イベントの生存戦略 | ゲーム・エンタメ最新情報のファミ通.com 

    ‣ ゲームイベントとしての認知拡大を目指し、変化を迎えた「C4 LAN 2023 SPRING」レポート | マイナ
    ビニュース

    64

    View Slide

  65. 質疑応答

    • 映像作るときってどんな映像を作るか、事前に絵コンテ的な物を作成したりもするのでしょうか? 

    ‣ 自分は映像を一人で作るような小規模チームなので絵コンテなどは作らないが、 

    規模の大きいチームなら作ることが多いと思う 

    • cpu,gpu,memory資源を節約したいときに、「この表現をしたい時はレイマーチングを使わない方が良いな」
    といった判断基準は何かありますか? 

    ‣ 基本的にはポリゴンで描画した方が計算資源を使わない 

    ‣ 再帰深度が高いフラクタルはレイマーチングの方が適している 

    ‣ 雲などのボリュームレンダリングではゲームでもレイマーチングが使われている 

    • https://www.famitsu.com/news/201808/23162812.html 

    • 誰が最初にシェーダーだけで映像を作りだしたのか? 

    ‣ 自己紹介スライドで紹介した @iquilezles さんがBreakPoint 2009で発表した 

    「Elevated」という4KB容量制限のデモがおそらく初 

    ‣ ポリゴンによる手法よりも、レイマーチングの方が短いコードで要素を詰め込める 

    ‣ 容量制限のあるデモシーンではレイマーチングがよく使われる 

    ‣ https://nlab.itmedia.co.jp/games/articles/0904/30/news026.html 

    65

    View Slide

  66. おまけ
    発表時間の都合上カットしたスライド
    66

    View Slide

  67. おまけ
    • ライティング

    • カメラワーク

    67

    View Slide

  68. おまけ
    • ライティング

    • カメラワーク

    68

    View Slide

  69. シェーディング

    69
    Global Illumination
    ・Area Light
    ・Material with a blit roughness
    Bloom + Light Beam

    View Slide

  70. ライティング

    ライティングで目指したもの⛳


    • Global Illumination

    • Bloom

    70
    GLSL Graphics Compoでは
    1Pass実装が必須
    Mad Tracingで実現できた!

    View Slide

  71. Mad Tracing

    • Mad Tracing [Virgill 2018]

    71
    End of time by Alcatraz & Altair | 1st Place at 4K Intro, Nordlicht 2018

    View Slide

  72. Mad Tracing

    ざっくり言うと…


    • Path Tracingの亜種

    • Bloomもまとめて計算できる

    72

    View Slide

  73. Path Tracing

    • Global Illuminationが可能なレンダリング手法

    • BRDFに応じて確率的に反射方向をサンプリング、光源からの影響を計算

    ‣ レイを大量に飛ばす💪(モンテカルロ法でレンダリング方程式を数値的に積分) 

    73
    An illustration of reflection from a glossy surface. | Download Scientific Diagram

    View Slide

  74. Path Tracing

    74
    https://www.youtube.com/watch?v=1Ji21iGW4nY
    レイを複数方向に
    サンプリングすることで
    ブラー(ぼかし)を実現

    View Slide

  75. Raymarching

    • レイマーチングのループ

    75
    ro1
    ro = RayOrigin
    rd1
    rd = RayDirection

    View Slide

  76. Mad Tracing

    • マーチングループ中に周囲の空間をサンプリング

    ‣ レイの周囲の光源の影響を蓄積することでBloomを実現

    76
    ro1
    ro = RayOrigin
    rd1
    rd = RayDirection
    ro2’’’
    rd2’’’
    rd2’’
    rd2’
    rd2
    ro2’’
    ro2’
    ro2

    View Slide

  77. Path Tracing vs Mad Tracing

    • Path Tracing

    ‣ 物体表面に衝突してから確率的にサンプリング

    ‣ Bloomできない


    • Mad Tracing

    ‣ 物体表面に衝突する前から確率的にサンプリング

    ‣ Bloomできる

    77

    View Slide

  78. Mad Tracing

    78
    void madtracer(vec3 ro1, vec3 rd1, float seed) {
    scol = vec3(0);
    vec2 rand = hash23(vec3(seed, iTime, iTime)) * .5;
    float t = rand.x, t2 = rand.y;
    vec4 m1, m2;
    vec3 rd2, ro2, nor2;
    for (int i = 0; i < 130; i++) {
    m1 = map(ro1 + rd1 * t, true);
    // t += m1.y == VOL ? 0.25 * abs(m1.x) + 0.0008 : 0.25 * m1.x;
    t += 0.25 * mix(abs(m1.x) + 0.0032, m1.x, m1.y);
    ro2 = ro1 + rd1 * t;
    nor2 = normal(ro2);
    rd2 = mix(reflect(rd1, nor2), hashHs(nor2, vec3(seed, i, iTime)), saturate(m1.z));
    m2 = map(ro2 + rd2 * t2, true);
    // t2 += m2.y == VOL ? 0.15 * abs(m2.x) : 0.15 * m2.x;
    t2 += 0.15 * mix(abs(m2.x), m2.x, m2.y);
    scol += .015 * (pal(m2) * max(0., m2.z - 1.) + pal(m1) * max(0., m1.z - 1.));
    // force disable unroll for WebGL 1.0
    if (t < -1.) break;
    }
    }
    mapを2回参照
    周囲の空間をサンプリング

    View Slide

  79. Mad Tracing

    79
    void madtracer(vec3 ro1, vec3 rd1, float seed) {
    scol = vec3(0);
    vec2 rand = hash23(vec3(seed, iTime, iTime)) * .5;
    float t = rand.x, t2 = rand.y;
    vec4 m1, m2;
    vec3 rd2, ro2, nor2;
    for (int i = 0; i < 130; i++) {
    m1 = map(ro1 + rd1 * t, true);
    // t += m1.y == VOL ? 0.25 * abs(m1.x) + 0.0008 : 0.25 * m1.x;
    t += 0.25 * mix(abs(m1.x) + 0.0032, m1.x, m1.y);
    ro2 = ro1 + rd1 * t;
    nor2 = normal(ro2);
    rd2 = mix(reflect(rd1, nor2), hashHs(nor2, vec3(seed, i, iTime)), saturate(m1.z));
    m2 = map(ro2 + rd2 * t2, true);
    // t2 += m2.y == VOL ? 0.15 * abs(m2.x) : 0.15 * m2.x;
    t2 += 0.15 * mix(abs(m2.x), m2.x, m2.y);
    scol += .015 * (pal(m2) * max(0., m2.z - 1.) + pal(m1) * max(0., m1.z - 1.));
    // force disable unroll for WebGL 1.0
    if (t < -1.) break;
    }
    }
    m1.x = distance
    distance < eps で break しない
    m2はPath Tracingの
    衝突後のサンプリングも兼ねている

    View Slide

  80. Mad Tracing

    80
    void madtracer(vec3 ro1, vec3 rd1, float seed) {
    scol = vec3(0);
    vec2 rand = hash23(vec3(seed, iTime, iTime)) * .5;
    float t = rand.x, t2 = rand.y;
    vec4 m1, m2;
    vec3 rd2, ro2, nor2;
    for (int i = 0; i < 130; i++) {
    m1 = map(ro1 + rd1 * t, true);
    // t += m1.y == VOL ? 0.25 * abs(m1.x) + 0.0008 : 0.25 * m1.x;
    t += 0.25 * mix(abs(m1.x) + 0.0032, m1.x, m1.y);
    ro2 = ro1 + rd1 * t;
    nor2 = normal(ro2);
    rd2 = mix(reflect(rd1, nor2), hashHs(nor2, vec3(seed, i, iTime)), saturate(m1.z));
    m2 = map(ro2 + rd2 * t2, true);
    // t2 += m2.y == VOL ? 0.15 * abs(m2.x) : 0.15 * m2.x;
    t2 += 0.15 * mix(abs(m2.x), m2.x, m2.y);
    scol += .015 * (pal(m2) * max(0., m2.z - 1.) + pal(m1) * max(0., m1.z - 1.));
    // force disable unroll for WebGL 1.0
    if (t < -1.) break;
    }
    }
    レイのステップに係数を乗算
    0.25 や 0.15
    ステップを小さくして
    Volume Rendering

    View Slide

  81. Mad Tracing

    81
    void madtracer(vec3 ro1, vec3 rd1, float seed) {
    scol = vec3(0);
    vec2 rand = hash23(vec3(seed, iTime, iTime)) * .5;
    float t = rand.x, t2 = rand.y;
    vec4 m1, m2;
    vec3 rd2, ro2, nor2;
    for (int i = 0; i < 130; i++) {
    m1 = map(ro1 + rd1 * t, true);
    // t += m1.y == VOL ? 0.25 * abs(m1.x) + 0.0008 : 0.25 * m1.x;
    t += 0.25 * mix(abs(m1.x) + 0.0032, m1.x, m1.y);
    ro2 = ro1 + rd1 * t;
    nor2 = normal(ro2);
    rd2 = mix(reflect(rd1, nor2), hashHs(nor2, vec3(seed, i, iTime)), saturate(m1.z));
    m2 = map(ro2 + rd2 * t2, true);
    // t2 += m2.y == VOL ? 0.15 * abs(m2.x) : 0.15 * m2.x;
    t2 += 0.15 * mix(abs(m2.x), m2.x, m2.y);
    scol += .015 * (pal(m2) * max(0., m2.z - 1.) + pal(m1) * max(0., m1.z - 1.));
    // force disable unroll for WebGL 1.0
    if (t < -1.) break;
    }
    }
    Volume Renderingの
    アーティファクト防止のランダム値
    Ray OriginのOffset

    View Slide

  82. Mad Tracing

    82
    void madtracer(vec3 ro1, vec3 rd1, float seed) {
    scol = vec3(0);
    vec2 rand = hash23(vec3(seed, iTime, iTime)) * .5;
    float t = rand.x, t2 = rand.y;
    vec4 m1, m2;
    vec3 rd2, ro2, nor2;
    for (int i = 0; i < 130; i++) {
    m1 = map(ro1 + rd1 * t, true);
    // t += m1.y == VOL ? 0.25 * abs(m1.x) + 0.0008 : 0.25 * m1.x;
    t += 0.25 * mix(abs(m1.x) + 0.0032, m1.x, m1.y);
    ro2 = ro1 + rd1 * t;
    nor2 = normal(ro2);
    rd2 = mix(reflect(rd1, nor2), hashHs(nor2, vec3(seed, i, iTime)), saturate(m1.z));
    m2 = map(ro2 + rd2 * t2, true);
    // t2 += m2.y == VOL ? 0.15 * abs(m2.x) : 0.15 * m2.x;
    t2 += 0.15 * mix(abs(m2.x), m2.x, m2.y);
    scol += .015 * (pal(m2) * max(0., m2.z - 1.) + pal(m1) * max(0., m1.z - 1.));
    // force disable unroll for WebGL 1.0
    if (t < -1.) break;
    }
    }
    コンパイル時間短縮のためのコード
    定数のforだとunrollされてコンパイル時
    間が伸びる
    意味のないifによるダイナミックなループ
    にして、強制的にloopにする

    View Slide

  83. Mad Tracing

    メリット

    • Global Illuminationだけでなく

    Bloomもまとめて計算できる

    • 実装が短い


    デメリット

    • 負荷が高い

    ‣ 複雑なモデリング(距離関数)と組み合わせるのは厳しい

    83

    View Slide

  84. おまけ
    • ライティング

    • カメラワーク

    84

    View Slide

  85. カメラワーク

    汎用カット:2パターンのカメラワークをランダムに選択

    • Cubeを中心に回転する軌道カメラ(乱数バリエーションあり)

    • CubeをLookAtする定点カメラ(乱数バリエーションあり)


    専用カット

    • 序盤

    • 終盤

    • 壁面に注目するカット

    85
    汎用カットを活用することで
    コードを圧縮

    View Slide

  86. カメラワーク(専用カット)

    86
    float prevEndTime = 0., t = 0.;
    #define TL(end) if (t = beat - prevEndTime, beat < (prevEndTime = end))
    // 使い方
    TL(8.) {
    ro = vec3(0, -1.36, -12.3 + t * .3);
    target = vec3(0., -2.2, 0.);
    fov = 100.;
    }
    else TL(16.) {
    ro = vec3(9.5, -1.36, -12.3 + t * .3);
    target = vec3(0., -2.2, 0.);
    fov = 100.;
    }
    else TL(20.) {
    ro = vec3(5.5, -5, -1.2);
    target = vec3(0., -8., -0.);
    fov = 100.0 + t;
    }
    // ... 続く
    ● シーケンス制御
    シンプルにifをたくさん並べているだけ
    ● TLはifのマクロ
    tは各カットのローカル時間
    ● 秒単位ではなくbeat単位
    音と同期するために
    0-8 beat
    8-16 beat
    16-20 beat
    }
    }
    }

    View Slide