Rustでレイトレしてみる
Rustの入門ができたので、習作としてレイトレーサを作りたい
できるかわからないけど......。
リポジトリはこちら。なんとなくpublicで作ってます
今の段階ではVectorの実装を進めている
見よう見まねでUnitテストも組んでみてたり
座標系は、Unityに慣れているのでY-Upの左手座標系にしようかなと思っている
Vectorの実装に必要な機能
- コンストラクタとファクトリ
- 加算減算の演算子のオーバーロード
- 内積外積
- 正規化
必要な構造体を書き出してみる
Vector、Ray、Hit、Interaction、Sphere、Image、だろうか?
ベクターの実装OK!
所有権の問題を全く考えていなかったので、
所有権の移動が発生していて困った
最初に関数の引数を全部参照にしたけど、
結局add/sub演算子が解決できなかったので、Copyトレイトを実装した
rayの実装Done
newとtメソッドを実装した
Rustの書き方わからない~~~
SphereにIntersectableクレイトを実装して、
intersectメソッドでOption<Hit>を返すって感じか......?
今日、このようなご指摘をいただいた。
最初は何のことだかわからなかったんだけど、よく調べてみると
Rustってそもそも文字列を結合するときの+演算子で
なぜか2項目からは参照渡してたりするなぁとおもったら、
加算したら所有権が移動する、というのが当たり前らしい
確かに……代入したら所有権移動するしな、、、
Sphereの実装もたぶんdone
hit構造体の実装もdone
シンプルな実装
残るのは
- Intersectableトレイト
- Scene構造体
- Light構造体
- Image構造体
- Material列挙体
かな
SphereとSceneをにIntersectトレイトを実装したい感じがする
とりまlight実装してimage出力して、ランバート拡散で実装で来たら
intersectとかsphereとか色々にMaterialを実装していく
lightどうしようかな、簡単なシーンだったら太陽光にしたいし
コーネルボックスだったらPointLightにしたい
どっちも作るか......
球とレイ(半直線)の交差判定の方程式
SphereにIntersectトレイトが実装できたら
- Cameraを実装する
- Sceneを実装する前にIntersectのテストがしたいので、それっぽい処理を書く
- Imageを実装する
- 交差判定の結果とか法線を表示してみる
これが直近のタスクになりそう
directional lightおよびSphereのIntersectトレイトを実装した
一応これらのテストカヴァレッジは100%になってるけどいかに
Cameraの実装めんどくさそうだなぁとなっている
いったんIntersectのテストをするのは平行投影でもいいかなって感じ
directional lightの方向ベクトルを正規化するように仕様変更
画像出力について調べていた
RustのCrateにImageというものがあって、それを使うといい感じっぽい
ここのドキュメントに良さげにまとまっている
RgbImageというものがあるけど、これってImageBufferのタイプエイリアスなんだな
ImageBuffer系を追っていれば、普通の画像保存とかはできそう
imageに必要な機能を整理したい
- 画素を格納できる
- pngで書き出しができる
- 画素数を取得できる
これくらい?
Imageの実装及びImageのテストを書いた
mainで処理を書いて、法線ベクトルを出力できた
これでintersectがあるていどうまくいってることが分かったな
カメラの実装を考えていた
カメラに必要な情報とカメラがするべきことって何なのかなぁと
カメラにレンダリングの命令を出すのは適切ではない気がしている
レンダラに対してレンダリングの命令を出すのが適切かな
ここで言うカメラとは透視投影をするカメラのことで
- 位置と回転(方向?)
- アスペクト比
- fov
- (クリッピング範囲)
などの情報が必要で、
カメラからは像に対するUV座標を入力したときに
それにまつわるレイを取得できるメソッドが欲しいかなって思った
それがあればシーンとの交差判定ができる
あと必要なのはシーンオブジェクトって感じだろうか
シーンオブジェクトはオブジェクトとかライトとかカメラみたいなものをまとめておく役割で
シーンに対してIntersectionトレイトを実装することで、
シーンに含まれる球オブジェクトで一番近いものへの交差判定を返すことができる
シーンの役割ってなんだろう
オブジェクトをまとめるのはいいんだけど、シーンの外部から交差判定命令を出すためには
カメラが必要なのではないだろうか
ということはシーンにはカメラオブジェクトは含めない方がよい?
レンダラのレンダリング命令に対してシーンとカメラを渡すという実装
Three.jsとかそういう感じじゃなかったっけ
透視投影カメラの実装メモ
アイデアとして、uv座標が渡されたときに、
そもそもuvって[-1,1]なんだから、カメラの画角もアスペクト比を考慮してそれに合わせればいいじゃん?
というもので、別にカメラの画角って今回は例の方向ベクトルなだけなのでどこでもいいんだけど
とりあえずxは[-a,a]、yは[-1,1]にしようってなった
補足すると、今回カメラの実装に手間取りたくないので
カメラは原点からz方向を向くカメラで使用固定しちゃってよくない?というもの
カメラを実装してみた結果、思いのほかいい感じになった
カメラのテストが一発でオールグリーンかつカバレッジ100%だったので褒めて(誰が
シーンを作ろう
シーンを作れば複数のオブジェクトをまとめて扱うことができる
光源は今のところ単一でいいか、DirectionalLightしか作ってないし
シーンに必要な機能とデータ
- オブジェクト(今回はSphere)のリスト
- 光源情報
- intersectトレイトの実装
レンダラに関しては、
- シーン
- カメラ
- イメージ
のデータを渡してrender()メソッドを実行する形がいいのかしら
あと色々なレンダリングができるように
rendererトレイトでも作ろうかしら
以下のママでも法線のレンダリングはできているわけだし
地味にvec使うの初めてなのでヒェってなってる
シーン構造体の動作確認done
良い感じ
画角の端に行けば行くほどすごい湾曲して映るようになってしまったけど、これってそういうもんなんだっけな......
レンダラとか作らずに、とりあえずレイトレやっちゃおうと思って
最後ごりっと実装したらできた
久しぶりだなこの感じ
materialを導入して、Diffuseに色を付けてみた
なんとかスぺキュラの実装も完了した
ひと先ず完成でいいかなぁ