Closed51

Rustでレイトレしてみる

にー兄さんにー兄さん

Rustの入門ができたので、習作としてレイトレーサを作りたい
できるかわからないけど......。

にー兄さんにー兄さん

今の段階ではVectorの実装を進めている
見よう見まねでUnitテストも組んでみてたり

にー兄さんにー兄さん

座標系は、Unityに慣れているのでY-Upの左手座標系にしようかなと思っている

にー兄さんにー兄さん

Vectorの実装に必要な機能

  • コンストラクタとファクトリ
  • 加算減算の演算子のオーバーロード
  • 内積外積
  • 正規化
にー兄さんにー兄さん

所有権の問題を全く考えていなかったので、
所有権の移動が発生していて困った

最初に関数の引数を全部参照にしたけど、
結局add/sub演算子が解決できなかったので、Copyトレイトを実装した

にー兄さんにー兄さん

SphereにIntersectableクレイトを実装して、
intersectメソッドでOption<Hit>を返すって感じか......?

にー兄さんにー兄さん

今日、このようなご指摘をいただいた。

最初は何のことだかわからなかったんだけど、よく調べてみると
Rustってそもそも文字列を結合するときの+演算子で
なぜか2項目からは参照渡してたりするなぁとおもったら、
加算したら所有権が移動する、というのが当たり前らしい
確かに……代入したら所有権移動するしな、、、

にー兄さんにー兄さん

ちょっとCopyトレイトの実装消してみるか......
右引数を参照にすればいいのかな

にー兄さんにー兄さん

こちらの実装が良さそうな気がしてきた
まず加算の問題点としては、所有権がmoveすることで
それを何とかする手段としてCopyを実装するのは悪手ということだった

であれば、参照を引数に取る演算子にすればいいじゃん、という解決策
ちょっと直観的ではないから混乱しないか怖いけど、
Rustの特性を保持したまま安全に加算を実行できそう

https://scrapbox.io/nwtgck/Rustの演算子のオーバーロードで借用してmoveさせないようにする方法_-_std::ops::AddとかMulとか

にー兄さんにー兄さん

SphereとSceneをにIntersectトレイトを実装したい感じがする
とりまlight実装してimage出力して、ランバート拡散で実装で来たら
intersectとかsphereとか色々にMaterialを実装していく

にー兄さんにー兄さん

lightどうしようかな、簡単なシーンだったら太陽光にしたいし
コーネルボックスだったらPointLightにしたい
どっちも作るか......

にー兄さんにー兄さん

SphereにIntersectトレイトが実装できたら

  1. Cameraを実装する
  2. Sceneを実装する前にIntersectのテストがしたいので、それっぽい処理を書く
  3. Imageを実装する
  4. 交差判定の結果とか法線を表示してみる

これが直近のタスクになりそう

にー兄さんにー兄さん

directional lightおよびSphereのIntersectトレイトを実装した
一応これらのテストカヴァレッジは100%になってるけどいかに

にー兄さんにー兄さん

Cameraの実装めんどくさそうだなぁとなっている
いったんIntersectのテストをするのは平行投影でもいいかなって感じ

にー兄さんにー兄さん

画像の保存ができるようになった
なんかIntelliJ Ultimateだと補完が効かなくなっちゃたりしたけど、なんとか解決できるようにした

にー兄さんにー兄さん

imageに必要な機能を整理したい

  • 画素を格納できる
  • pngで書き出しができる
  • 画素数を取得できる

これくらい?

にー兄さんにー兄さん

mainで処理を書いて、法線ベクトルを出力できた
これでintersectがあるていどうまくいってることが分かったな

にー兄さんにー兄さん

カメラの実装を考えていた
カメラに必要な情報とカメラがするべきことって何なのかなぁと
カメラにレンダリングの命令を出すのは適切ではない気がしている
レンダラに対してレンダリングの命令を出すのが適切かな

ここで言うカメラとは透視投影をするカメラのことで

  • 位置と回転(方向?)
  • アスペクト比
  • fov
  • (クリッピング範囲)

などの情報が必要で、

カメラからは像に対するUV座標を入力したときに
それにまつわるレイを取得できるメソッドが欲しいかなって思った

それがあればシーンとの交差判定ができる

にー兄さんにー兄さん

あと必要なのはシーンオブジェクトって感じだろうか
シーンオブジェクトはオブジェクトとかライトとかカメラみたいなものをまとめておく役割で
シーンに対してIntersectionトレイトを実装することで、
シーンに含まれる球オブジェクトで一番近いものへの交差判定を返すことができる

にー兄さんにー兄さん

シーンの役割ってなんだろう
オブジェクトをまとめるのはいいんだけど、シーンの外部から交差判定命令を出すためには
カメラが必要なのではないだろうか
ということはシーンにはカメラオブジェクトは含めない方がよい?

レンダラのレンダリング命令に対してシーンとカメラを渡すという実装
Three.jsとかそういう感じじゃなかったっけ

にー兄さんにー兄さん

透視投影カメラの実装メモ
アイデアとして、uv座標が渡されたときに、
そもそもuvって[-1,1]なんだから、カメラの画角もアスペクト比を考慮してそれに合わせればいいじゃん?
というもので、別にカメラの画角って今回は例の方向ベクトルなだけなのでどこでもいいんだけど
とりあえずxは[-a,a]、yは[-1,1]にしようってなった

にー兄さんにー兄さん

補足すると、今回カメラの実装に手間取りたくないので
カメラは原点からz方向を向くカメラで使用固定しちゃってよくない?というもの

にー兄さんにー兄さん

カメラのテストが一発でオールグリーンかつカバレッジ100%だったので褒めて(誰が

にー兄さんにー兄さん

シーンを作ろう
シーンを作れば複数のオブジェクトをまとめて扱うことができる
光源は今のところ単一でいいか、DirectionalLightしか作ってないし

にー兄さんにー兄さん

シーンに必要な機能とデータ

  • オブジェクト(今回はSphere)のリスト
  • 光源情報
  • intersectトレイトの実装
にー兄さんにー兄さん

レンダラに関しては、

  • シーン
  • カメラ
  • イメージ

のデータを渡してrender()メソッドを実行する形がいいのかしら

あと色々なレンダリングができるように
rendererトレイトでも作ろうかしら
以下のママでも法線のレンダリングはできているわけだし

にー兄さんにー兄さん

画角の端に行けば行くほどすごい湾曲して映るようになってしまったけど、これってそういうもんなんだっけな......

にー兄さんにー兄さん

レンダラとか作らずに、とりあえずレイトレやっちゃおうと思って
最後ごりっと実装したらできた
久しぶりだなこの感じ

このスクラップは2021/10/17にクローズされました