まずは画像出力

http://www.ryanlothian.com/articles/haskell-raytracer
に倣って画像出力から。

main=do
  writeP3 "tmp.ppm" width height (rendering width height)
  where
    width=256
    height=256

writeP3::String->Int->Int->[RGB24]->IO()
writeP3 filepath width height rawdata=
  writeFile filepath
    ("P3\n"
    ++(show width)++" "++(show height)++"\n"
    ++"255\n"
    ++(unlines $ map show rawdata))

rendering::Int->Int->[RGB24]
rendering width height=[(RGB24 x y 0)|x<-[0..width-1], y<-[0..height-1]]

-- RGB24
data RGB24=RGB24
  Int -- r
  Int -- g
  Int -- b

instance Show RGB24 where
  show (RGB24 r g b)=(show r)++" "++(show g)++" "++(show b)

はじめからフル機能レンダラをトップダウンで書き始めたら破綻してしまった。
なるべくボトムアップである程度パーツを揃える方向の方がよさそう。
あと、Data宣言のフィールドラベル名が被ったらだめなことに衝撃を受けた。フィールドの順番に依存したコードは書きたくないなぁ・・・

ToDo

PPMをテキストのP3形式から、バイナリのP6形式が出せるようにする
球との交差を実装