MENU閉じる

HEXA BLOG

プログラム

HEXA BLOGプログラム2023.4.6

2022新人ブログデビュー!⑲

はじめまして!
2022年に東京オフィスに入社した、新人プログラマーのアスターです。
もう4月になりましたね。すっかり春になったと思います。

1年前のこの頃から、UE4を勉強し始めましたが、自分が新しいエディタやツールの描画周りに関する勉強をする際、レイマーチングを一度試してみることで様々なエディタの仕様や習わしを理解していくことが一種のルーティンになっています。

そこで今回は、実際に入社後に勉強として行った「UE4でレイマーチングをする方法」について紹介します。
具体的には、レイマーチングで球体を描画してみようと思います。

——————————————————————————————

◆前置き -レイマーチングについて-
そもそもレイマーチングは、レイトレーシングの一種です。
レイトレーシングについては、同じく新人ブログのこちらでも紹介されていますので、興味のある方はご覧ください。

レイマーチングとは、カメラから光線(レイ)を飛ばし、スフィアトレーシングという手法でレイを進め、そのレイがオブジェクトと衝突したら、そのオブジェクトを描画するといったレンダリング方法です。
また、スフィアトレーシングとは、レイの先端から最も近いオブジェクトとの最短距離を算出し、その距離分だけレイを進めて最終的なレイを形成していくトレーシング方法です。

スフィアトレーシングの例図
スフィアトレーシングの例

レイマーチング自体がポリゴンに依存しない描画方法であることから、雲などの3次元データを描画する際に使用されることがあります。

また、レイマーチングでは距離関数というものを用いてオブジェクトの形を定義します。
距離関数とは、そのオブジェクトとの最短距離を返す関数のことです。
今回は、この距離関数を使用して、レイとオブジェクトとの距離が一定値以下になった時に描画するという条件で描画を行います。

——————————————————————————————

◆実装
では、実際にマテリアルノードを使用して作成していきましょう。

1.Customノード作成
まず初めに、レイマーチングを描画するためのCustomノードを用意します。
作成したCustomノードの入力変数には、以下の四つを用意しておきます。

CustomノードのInputs

それぞれの意味合いは以下の通りです。
rayOrigin → レイを飛ばす原点
rayDirection → レイを飛ばす方向
sphereColor → 描画する球体の色
scale → 描画する球体の大きさ

 

2.コード入力
次に、CustomノードのCodeに以下のコードを貼り付けます。
内容としては、球体の形をコードで定義し、それを実際に描画しています。
詳しいコードの説明に関しては、本記事の後半で解説しているため、ここでは割愛します。

 

3.ノード連結
そして、各Customノードの入力値に、それぞれ以下の値を設定します。

rayOrigin: float3(0, 0, -仮想カメラの位置)
rayDirection: float(uv – float2(0.5, 0.5), fov)
sphereColor: 表示する球体の色
scale: 表示する球体の大きさ

レイの光線方向を決めるrayDirectionに使用するuvは、0.5ズラしておくことでピッタリとオブジェクトの中央を中心として描画することが出来ます。
今回、自分は下図のようにしてみました。

レイマーチングのマテリアルノード

 

4.完成!

作成したマテリアルをPlaneに張り付けたところ、3Dの球体が描画されました!

完成図

 

——————————————————————————————

◆コード解説
ここからは、記載したコードについて解説します。
気になるという方は、ご覧ください。

 

1.冒頭のfor文
まず、最初のfor文は、最大99回スフィアトレーシングしていることを示しています。

スフィアトレーシングは、ひたすらレイを前に進めることでした。

スフィアトレーシングの例図

スフィアトレーシングの例

ですので、for文を用いてレイを繰り返し前に進めています。
今回はMAX99回までにしていますが、この値を変えることも出来ます。
しかし、値を大きくしすぎるとPCに物凄い負荷がかかってしまうため、値の変更には注意が必要です。

 

2.座標計算
次の処理では、レイの先端の座標を取得しています。

一般的なベクトル計算です。図にすると分かりやすいかと思います。
まず、各点を次のような意味合いとして図を書きます。

点O : 位置ベクトルの原点
点A : レイの原点
点B : レイの先端

座標計算図
ベクトル図

この時、レイの先端である点Bの位置ベクトルは

OB = OA + AB

で求めることが出来ます。
これをコードにした場合、rayOriginはレイの原点、rayDirectionはレイの進行ベクトルを示していることから

OA : rayOrigin
AB : rayDirection * dist
OB : pos

と置き換えることが出来るので、上で示したベクトル式より

pos = rayOrigin + rayDirection * dist

という式が完成するというわけです。

 

3.オブジェクトとの最短距離を取得
次の処理では、レイの先端座標から球体までの最短距離を取得しています。


例で挙げたGIFでいうと、下図の黒線部分の処理ですね。

最短距離計算模式図

 

SDF構造体の中で定義した距離関数Sphereを用いて、球体との最短距離を取得します。
この距離が、レイを前に進める距離になるわけですね。

 

4.色塗り
次の行では、球体との距離が一定値以下になった場合、レイが物体に衝突したとみなし、キャンバスに色を塗ってfor文から抜けます。
影についてはDiffuseライティングを行っています。オブジェクトの法線と光との内積を用いたシンプルなライティング方法です。


ただ、このオブジェクトの法線を取得する関数GetNormalの記述がちょっと特殊ですね。
ここでは、レイがオブジェクトとぶつかった点を入力値として、そこからその点での法線を算出しています。
具体的には、XYZそれぞれ少しズラした座標を用意し、それを距離関数に渡し、その返り値で勾配を取っています。

数学的には、法線は関数を微分することで求めることが出来ますが、コンピューターの世界では離散数学が成り立つため、微分は微小空間の引き算で求めることが出来ます。

微分の例図
微分の例

ですので、GetNormalにおいても、引き算から法線を求めているという訳です。
このあたりの話は、微積分あたりの数学の知識が必要になりますね。

また、どうしてこのようなことをしているのかというと、オブジェクトの定義を距離関数で行っているため、法線も自力で計算するしかないからです。

 

5.レイを進める
次の処理では、レイを距離関数から取得した距離だけ前に進めています。

ここで初めて、光線(レイ)が前に進む(マーチングする)訳です。
その後は、for文の頭に戻って、同様の処理を繰り返します。

 

6.描画
最後のreturnで、for文処理で得た色を返して描画しています。

 

——————————————————————————————

◆終わりに
UE4のCustomノードを使って、レイマーチングで球体を描画してみました。
他の様々な距離関数をコード内のSDF構造体に定義することで、色々な形のオブジェクトを描画することが出来ます。

他のレイマーチング図形

他のレイマーチング図形2

気になった方は是非挑戦してみてください!

また、記事を書く上で参考にした もしくは レイマーチングをしていく上で非常に参考になるサイトのリンクを幾つか下に貼っておきます。
レイマーチングを始めてみたいという方は、この辺りから見てみると良いと思います。

以上になります!
それでは皆さんも良いShaderライフを!!!👋

 

——————————————————————————————

◆参考

Ray marching :
https://en.wikipedia.org/wiki/Ray_marching

distance functions :
https://iquilezles.org/articles/distfunctions/

魔法使いになりたい人のためのシェーダーライブコーディング入門 :
https://qiita.com/kaneta1992/items/21149c78159bd27e0860

[GLSL] レイマーチング入門 vol.1 :
https://qiita.com/edo_m18/items/034665d42c562da88cb6

【GLSL】【シェーダー】文系で数学なんもわからんエンジニアだって、シェーダー完全に理解したい!!〜レイマーチング入門編①〜 :
https://www.wwwmaplesyrup-cs6.work/entry/2019/07/08/171333

【Shadertoy】レイマーチング基礎 :
https://logicalbeat.jp/blog/6237/

法線の算出と簡単なライティング :
https://wgld.org/d/glsl/g010.html

RECRUIT

大阪・東京共にスタッフを募集しています。
特にキャリア採用のプログラマー・アーティストに興味がある方は下のボタンをクリックしてください

RECRUIT SITE