引用元:https://www.ioccc.org/2011/zucker/zucker.c
審査員・作者による説明:https://www.ioccc.org/2011/zucker/hint.html
動作
レイトレーサ。実行には数分かかる。
$ gcc -o zucker zucker.c -lm
$ ./zucker > image.ppm
$ convert image.ppm image.png
コマンドライン引数で文字を指定できる。
$ ./zucker "Hello!" > hello.ppm
$ convert hello.ppm hello.png
第2引数に-preview
コマンドをつけると画質を下げて速くできる。
この出力はIOCCCのサイトでロゴとして使われている。
解説
このプログラムはプログラミング初心者向けとうそぶいている。
29行しかないし、void
やswitch
やwhile
のような難しい概念は使っていないし、putchar
と一部の数学関数しか使っていないなど。
初心者はグローバル変数を使いがちなのにあわせて、ローカル変数は全く使っていないとのこと。
コード形状は、物体の表面で光が反射するときにの幾何学的構造を表現している。
丸い物体の表面に対し、Dが入射してくる光のベクトル(direction vector)、Nが法線ベクトル、Rが反射していく光のベクトル(reflection vector)を表している。
古くからあるレイトレーシングではなく、スフィアトレーシングを使っているとのこと。
交点を解析的に見つけるのではなく、近接物体との距離を考慮しながら徐々に光線をすすめる手法で、これにより複雑な形状の交点を見つけやすくなったり、環境光の遮蔽を計算できるようになったりする。
普通はループで徐々に近づけるが、このコードでは再帰によって光線をすすめるのでややこしい。
hint.textによると、コード上の難読化もいろいろ工夫されている。
グローバル変数に入っている値を違う意味で使う(たとえばX
は整数40とASCIIコード'('
の両方として使っているとのこと)ので、画像のサイズを変えるのも難しくなっている。
ベクトル演算の関数はいろいろ定義するのではなく、掛け算して足し算する関数1つを使い回すようにしている。
なるべく、論理演算よりビット演算、ビット演算より算術演算を好んで使う。
キャストをするときは、キャスト構文を使わず、キャストしたい型の変数に代入することで行う。