こんにちわ。Pocolです。
今日は,タイルシェーディングについての実装メモを書くことにします。
レイトレ合宿8に参加してきました!
こんにちわ。Pocolです。
先週,レイトレ合宿8に参加してきました!
今年の開催地は沖縄ということで,台風11号が迫る中参加してきました。
台風が来ているせいで,まず現地に行くのが通常よりも難度が高いw。
金曜日到着の前泊組は問題なかったそうなのですが,自分は土曜日到着組だったので,
羽田空港から出発する便が,条件付き飛行になってました。
空港でも,「機長が着陸が難しいと判断した場合は羽田空港に引き返す恐れがありますので,予めご注意ください。」とアナウンスされている状況。
台風だからだと思うのですが,乗客も非常に少なかったです。でも,こんな中でも乗る人意外といるんだなと思ってびっくりしました。
しかし,タクシー載るころには豪雨状態。
さらに風も強くなってきたので,傘だと風でひっくり返ってしまってダメですね。
レインコートも持って行ったのですが,山用のやつだったので,夏だと暑いですし,上下セパレートしているので装着も面倒で結局着ずじまいでした。
ポンチョみたいな簡単に着れるやつを今後常備しておこうと思います。
さて、今年のレイトレ合宿の宿はVilla VALISOAで,これが滅茶苦茶良かったです。
詳細はWebページ見て欲しいのですが,写真詐欺も無く本当にこのままで,非常に綺麗でした。水着を持っていけばジャグジーやプールも入れます。
バスとトイレ・洗面所が隣同士なので,誰かが風呂に入っている最中はトイレを利用できなくなるというのが唯一の不便なところでした。2階にもバス・トイレ・洗面所があるので,そちらを利用することで回避も可能です。
ちなみに1階はガラス張りで外が見えます。ブラインドもついているので,下げた方がいいです(浴室隣の部屋から見えてしまいます)。
朝食等は2階にキッチンがついているので,各自で作るという感じのスタイルだそうです。食器等も一式揃っています。
2階から見える景色も非常に良かったです。台風が来ていなければ素晴らしい景色だったんだろうなと想像されます。
また,沖縄に行く機会があれば,再度利用したいなと思いました。
宿の話はこれぐらいにして…
今年はセミナーが非常に多く充実していました。
- ishiyamaさんの光線のなりたち
- yumcyawizさんのIntroduction to volume rendering
- Kinakomoti2357さんのPathtracingにおけるCausticsレンダリング
- 8picozさんのRustとGPU
- ykozwさんのAll about golden ratio
- うしおさんのNeural Radiance Fields to Implementation
…などなど。
ちなみに自分は,キャラクターレンダリングについてお話させて頂きましたが,大した内容ではないので一般公開する予定はありません。もうちょい話せるネタが溜まったら,どこかのイベントで話せるときが来るといいなーって思っています。
飛行機に乗っている時間にあったセミナーについては聴くことが出来なかったので,Zinさん,うしおさん,Shockerさんの生のプレゼンを見れなかったのが非常に悔やまれます。あとで資料をじっくりみたいと思います。
今回,セミナーで収穫があったのは,きなこ餅さん,PathtracingにおけるCausticsレンダリングについての資料で,Manifold Next Event Estimationの説明があったことです。これ論文見てもよーわからんなーって思っていたのですが,非常にわかりやすい説明で,そういうことだったのか!と納得できました。これで一気に論文が読みやすくなりました。
昼飯は車で少しいったあたりにある タコライスcafe きじむなぁ恩納村店 でタコライスを頂きました。

昼飯を食べ後は,デノイズ部門と本戦です。
まず,今年新設されたデノイズ部門でしたが,人によって異なる特徴を持つデノイズ結果が出ており,非常に興味深くそこが面白かったです。自分は余力が無かったため,エントリーしなかったのですが,次回開催するときもデノイズ部門があるようであれば,エントリーしてみたいなと思っています。
デノイズ部門参加者はみんな機械学習系が来るだろうと構えていたみたいですが,意外とみんな普通に書いていたみたいです。
決勝はykozwさんとholeさんとyumcyawizさんの戦いでした。
ちなみに,holeさんとyumcyawizさんは,ベース手法としてNL-Means (Non Local Means)フィルタを使用していて,接戦でした。
ykozwさんの手法は,明るさなどが他の二人と比べていてリファレンスに近い明るさが出ているなど,優れている部分もあり決勝は投票が非常に難しかったです。
今回のデノイズ部門はみんな投票悩んでいる感じで,会場にいて全体見るとこっちがよさげなんだけども,部分的にみるとなぁとか,自分も同じ感じで悩んだりしていて,その雰囲気も面白かったです。
今年の本戦ですが,色々な作品があって面白かったです。
意外とみんなカットとか変えないだろうなと予想していたのですが,やはりレンダリング野郎の集いなので,色々と凝っていてレベルが高かったです。
自分は今年は,GPUレンダラー作ったことが無かったので,とりあえず動くものを作れれば順位とか気にしないという,スタンスでレンダラー書きました。
テクスチャアニメーションとかリアルタイムっぽいのを使う人はいないだろうと予想したので,特徴としてテクスチャスクロールするだけのテクスチャアニメーションを入れました。本当は綺麗なコースティクスを出したいなぁと思ったのですが,提出2日前に全然バグの原因がわからず,そのまま提出したのであんまりレイトレ感が無いので,次回はちゃんとレイトレ感がある作品を提出したいなぁと思います。
あと,提出間際にシーンを変更したりとか色々とやっていた関係で,もとのIBL画像がバグって表示されるという残念な結果になるのを全然確認できていなかったので,このあたりもきちんとデバッグしておこうと思います。
とりあえず,GPUレンダラーのベースがある程度できたので,バグを取り除いて来年も使えるレンダラーに育てていきたいなと思っています。
Shcokerさんとかうしおさんとかの作品見ていると新しい技術取り入れていていいなぁーって思いました。新しい技術は積極的に取り入れていきたいです。
今年ビビったのが,holeさんの作品で見ると分かるのですが,ノイズが無いです。これが一番,驚きがありました。しかも書いたのが提出日当日とかって化物じみていてすげぇなぁっていう感想しかないです。

今年の結果見ると,次回のレイトレ合宿の本戦はどんなハイレベルな戦いになるのか予想が全くつきませんね。
次回も非常に楽しみです!
こうした楽しいイベントに参加できるもの,きちんと運営してくださる方があってのことなので,非常に有難いです。いつも本当にありがとうございます!
もし,レイトレ合宿の次回開催に参加したい人はTwitterで自作レンダラーの画像をいっぱいアップロードしておくと良いかもしれません。
レイトレ合宿楽しいぞ!! 君もレンダラーを書いてみないか?
以上です。
レイトレ日記 2022/07/27
今日は,ノートPCでの起動チェックを行いました。
で,早速DirectX周りでハマりました。
まず,当たり前ですがSwapChainの解像度がサポートされているものしか対応しないので,デスクトップと同じ解像度を指定したら,SwapChainが作成できなくて起動できないという問題にあたりました。
結局,画像出力用のレンダーターゲットを1つ用意して,そちらは高解像度にしてリードバックして,CPUからPNGに書き出し。SwapChainの方は,縮小して表示することにしました。
次のハマりポイントですが,EnumOutputs()がエラーを返すというのでハマりました。どうやらIDXGIAdapterの中には,EnumOutputs()の0番が失敗するものがいるようです。で,それを採用するように軽く実装したら,今度はAdapterが変わってDXRのチェックに通らないみたいなことが発生しました。結局,EnumOutputs()用にAdapterは別のものにするという対応で,ようやくサポート解像度がとれるようになりました。本当,こういうところがDirectXは面倒くさくて嫌いです。
コードは下記のような感じになりました。
// DXGIアダプター生成.
{
RefPtr<IDXGIAdapter1> pAdapter;
for(auto adapterId=0;
DXGI_ERROR_NOT_FOUND != m_pFactory->EnumAdapterByGpuPreference(adapterId, DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE, IID_PPV_ARGS(pAdapter.GetAddress()));
adapterId++)
{
DXGI_ADAPTER_DESC1 desc;
auto hr = pAdapter->GetDesc1(&desc);
if (FAILED(hr))
{ continue; }
hr = D3D12CreateDevice(pAdapter.GetPtr(), D3D_FEATURE_LEVEL_11_0, __uuidof(ID3D12Device), nullptr);
if (SUCCEEDED(hr))
{
if (m_pAdapter.GetPtr() == nullptr)
{
m_pAdapter = pAdapter.GetPtr();
m_pAdapter->AddRef();
}
RefPtr<IDXGIOutput> pOutput;
hr = pAdapter->EnumOutputs(0, pOutput.GetAddress());
if (FAILED(hr))
{ continue; }
hr = pOutput->QueryInterface(IID_PPV_ARGS(m_pOutput.GetAddress()));
if (SUCCEEDED(hr))
{ break; }
}
}
}
これで,一応ノートPCでプログラムが起動するようになりました。
今週末が,レギュレーションテストなので,明日はテスト用のアセット生成などをして本番と同じフローになるように大枠だけは整えたいなと思っています。
レイトレ日記 2022/07/08
今日は実装用のメモをとっておこうと思います。
自分さえわかればいいので,詳しい説明は省略します。
レイトレ日記 2022/07/05
ここ、最近無気力感で何もやる気が起きないのですが,今日は頑張ってプログラムちろっと書きました。
土日で,再帰的にレイを飛ばすようにしたんですが,プログラムがバグっていて全部同じ色になってしまっていたので修正しました。マテリアルはまだ正式対応していないので,単色です。
まだ、マテリアル周りの実装をどうするか迷っています。
テスト実装で読み込んでいるモデルのロード処理がクソ重いということも分かったので,そろそろ本番用に最適化したやつに切り替えないとヤバそうです。
これから実装をバリバリ進められるように,シェーダのホットリロードにも対応しました。
残りの課題としては,
- シーンデータの作成方法(ツールとかどうするか?)
- トーンマップの実装
- 本番シーンの選定
- ライトの実装
などが,残っているので早い所これらは決めてしまいたいです。
残り57日!!
レイトレ日記 2022/06/16
今日は,シーン読み込みを実装することに。
毎回どうしようか悩んで,結局間に合わず同じものを使いまわすという過ちを繰り返してきたので,今回はちゃんとやることにした。
理想的にはバイナリ読み込んで,バイナリキャストして,そのまま使える形になるやつが欲しい!
…と思ったら既にありました。
FlatBuffers!!
https://github.com/google/flatbuffers
これよ。これ!欲しかったやつ。
早速試すと,かなり簡単にバイナリフォーマットを定義できる。
最初はstructとtableの違いが判らなかったが,プリミティブ型じゃないものを配列に取る場合はtableにしないとエラーになるので,自前定義のやつを配列で使いたい場合はtableにすればいいみたい。
結構便利なので,メッシュやらテクスチャやらの定義も書きまくる。
struct Vector2
{
x:float;
y:float;
}
struct Vector3
{
x:float;
y:float;
z:float;
}
struct Vector4
{
x:float;
y:float;
z:float;
w:float;
}
struct Matrix3x4
{
row0:Vector4;
row1:Vector4;
row2:Vector4;
}
struct ResVertex
{
Position:Vector3;
Normal:Vector3;
Tangent:Vector3;
TexCoord:Vector2;
}
table SubResource
{
Width:uint;
Height:uint;
MipIndex:uint;
Pitch:uint;
SlicePitch:uint;
Pixels:[byte];
}
table ResTexture
{
Dimension:uint;
Width:uint;
Height:uint;
Depth:uint;
Format:uint;
MipLevels:uint;
SurfaceCount:uint;
Option:uint;
Resources:[SubResource];
}
struct ResMaterial
{
BaseColor:uint;
Normal:uint;
Orm:uint;
Emissive:uint;
}
table ResMesh
{
MateiralId:uint;
VertexCount:uint;
IndexCount:uint;
Vertices:[ResVertex];
Indices:[uint];
}
struct ResInstance
{
MeshIndex:uint;
Transform:Matrix3x4;
}
table ResScene
{
MeshCount:uint;
InstanceCount:uint;
TextureCount:uint;
MaterialCount:uint;
IblTexture:ResTexture;
Meshes:[ResMesh];
Instances:[ResInstance];
Textures:[ResTexture];
Materials:[ResMaterial];
}
root_type ResScene;
お作法的には,スネークケースで書かないと警告が出る。…が,そんな他人のルールなんて知ったこっちゃない。仕事じゃないんで。
自分さえよければいい。それが趣味プログラムの醍醐味!
ランタイム側はファイルを読み込んで,バイナリを
auto resScene = GetResScene(m_pBinary);
と引数で渡してやれば,データにアクセスできるようになる。すごく簡単!
ランタイムの読み込み側は実装したので,あとはシーンエディットと書き出しさえ実装すれば,パストレの実装に集中できそう。
シーンエディタ作るのめんどいなぁ。どうしよ?
残り75日!
レイトレ日記 2022/06/12
今日は,目標だった交差判定するところまでを実装した。
DXRでレイとヒットしたところが,赤くなる。
あとは,使うかわからんが,デノイズ処理用にアルベドと法線のデータも毎フレーム作成するようにした,デバッグビューで表示できるようにもしておいた。
あとは,マテリアルのデータや頂点データ等がちゃんとレイヒット時に取れるようになれば,パストレが組めそう。
で,そのためにはシーンデータの管理周りを整備しなくちゃなということで,実装に着手。シェーダ側は既に実装済み。
色々と進めると,作ったModelMgrクラスが根本的にダメなことがわかったので修正した。
HLSL側にでっかいVertexBufferとIndexBufferを渡して使う仕組みだったんだが,UINT32_MAX以上の数扱えないことに今更気が付いたという感じ。
結局,VertexBufferとIndexBufferは各メッシュごとに小分けに作ることにした。
HLSLはDynamicResourceで直接ResourceDescriptorHeapから頂点バッファとインデックスバッファを参照するように変更。
このために,DescriptorIndexを渡す必要があるので,
struct Instance
{
uint32_t VertexBufferId;
uint32_t IndexBufferId;
uint32_t MaterialId;
};
という構造体を作って,これをバッファ化することに。このバッファにはInstanceID()を使ってアクセスする。
無理やりInstanceIdにマテリアルIDとジオメトリIDをパッキングする方法をやめたので,マテリアル数も少し多く扱えるようになった。
DynamicResource様様ですね。大分実装が楽になった。
結構めんどっちい実装なので,アドベントカレンダーのときに,ざっくりどんなつくりは説明しようかなって思っています。
残り79日!
レイトレ日記 2022/06/07
おとといは、会社の提出物関係で残業してしまったので,作業できず。
昨日は,マテリアルエディタのバグを修正した。
結局,定数バッファが設定されていなかったというしょぼバグ。
設計して,そのあとずっと実装を忘れていたんだろうな…。
あとはスキニング用の処理も中途半端な状態になっていて,ボーン行列が設定されない関係で計算がおかしくなっていたので,いったんスキニング処理をしないようにして対処。
時間が出来た時の楽しみとしてスキニング処理周りは残しておくことにする。
これで,スタティックメッシュについては問題なくマテリアルも表示できるようになったので,今夜はエクスポーターを書いて,いよいよレイトレ用のメッシュバイナリとマテリアルバイナリを作ることにする。
週末からはようやくレイトレできそうな予感。
残り84日!
















