TeX言語でレイトレーシングを実装する話

この記事はTeX & LaTeX Advent Calendar 2019の14日目の記事です。 13日目はmattskalaさんでした。15日目はaminophenさんです。

TL; DR

TeX言語を使って,こんな画像を生成する話.

f:id:hak7a3:20191214155849p:plain
レイトレーシング結果

はじめに

周知のとおり,TeX言語はチューリング完全プログラミング言語である.すなわち,世界にある任意のプログラムはTeX言語で記述可能である.あの文法と評価規則からは直観的ではないが,CGのレンダリングも科学技術計算もその気になればTeX言語で記述できる.

今回は,久しぶりのTeX芸人活動ということで,TeX言語でレイトレーシングしてみた.

レイトレーシングとは

レイトレーシングとは,画素ごとにカメラに入ってくる光線を逆方向に追跡してCGのレンダリングをする技法である.光線の追跡では,経路上の物体に対する反射・屈折を考慮する.本記事では,その詳細は省略する.

レイトレーシングのプログラムは比較的簡単*1である.下記の機能が実現しやすいプログラミング言語なら,その実装はそこまで難しくないと思っている.

  1. ラスタ画像の出力
  2. データ構造
  3. 浮動小数点数

これらの機能をTeX言語が有しているか検証してみよう,1に関しては過去の記事で実現可能であることを示した.2については,TeXほどアドホックにデータ構造を作成しやすい言語はないと思っている*2.3については,LaTeX3チームによりxfp.styが提供されている.なぜかすべて揃っていた.

xfp.styとは

xfp.styはThe LaTeX Teamが作成している浮動小数点数およびそれに対する演算の実装である.中身は,LaTeX3用のプログラミング言語であるexpl3のラッパーになっている.当然.expl3自体はTeX言語で実装されている.

xfp.styを導入すると,\fpeval{式}の形で浮動小数点数演算ができる.四則演算はもちろん,なぜか乱数やベクトルの加算・減算とスカラ倍がサポートされている.The LaTeX TeamはこのTeX芸を見抜いていた.

できあがったもの

実際に作ったものがこちら.

https://github.com/hak7a3/raytracing-tex

読者が検証しやすいよう,最初に挙げた画像よりも解像度を落としている.というのも,あの画像は約2日ほど計算機を占有して描画した結果なので,手元で実行するにはあまりにも重い.といっても,公開版も数時間はかかる.

なお,xfp.styがエラーを出して処理が停止してしまう場合がある.おそらくxfp.styの不具合なのだが,乱数次第で回避できるので,検証する際は数回チャレンジしてほしい.

また,画像出力の関係上400x400だと計算終了後にTeX処理系が悲鳴を上げた.

TeX言語的な話

ここから先は,TeX芸人らしくTeX言語実装のテクニックに言及する.

マクロ定義よりトークンリストレジスタが高速だった話

The TeXbookには,マクロ定義を上書きしていくよりもトークンリストレジスタでそれを実施したほうが高速であると記されている.今回のプログラム,初期は計算結果をマクロで貯めていったのだが,途中で速度が気になりトークンリストレジスタに変更した.体感でかなり早くなったので,TeX芸人は少なくともThe TeXbook Appendix Dは読むべきだと思う.

\loopすら使えなかった話

LaTeXには\loop ... \repeatで繰り返しを記述できる.通常のTeX言語プログラミングでは問題にならないのだが,今回のプログラムでは,その内部構造に起因してTeXのmain memoryを食いつぶした.ループ本体部分をマクロ定義していることが悪い可能性を鑑み,自前でCPS変換したところ処理が通った.詳しい検証はしていないが,main memory不足に悩まされたら思い出してほしい.

まとめ

TeX言語はチューリング完全なので,任意のプログラムを記述できる. その一芸として,レイトレーシングを実装した.

Merry TeX'mas(ちょっと粗すぎた……).

f:id:hak7a3:20191214163933p:plain

*1:私の出身大学では学部生の実験で採用されていた.東大CPU実験でも採用されている

*2:lisp-on-texTeX言語製LISPインタプリタ)の作成経験から