rn.log

備忘録など

【シェーダーグラフメモ その55】ボロノイを利用した、水中コースティクス表現

 

はじめに

ShaderGraphで水中コースティクス表現を作る方法を紹介します。

f:id:r-ngtm:20201114181653g:plain

コースティクス表現

 

f:id:r-ngtm:20201114214023g:plain

ライトの向きを変えた時のコースティクス




水中コースティクスが発生する仕組み

まず最初に、水中コースティクスの発生原理を簡単に紹介します。

 

水の外からやってきた光が水底にぶつかると、そこにコースティクスが生まれます。

f:id:r-ngtm:20201114184302p:plain

光が水底にぶつかった位置にコースティクスが発生する

 

光が水面のどこを通ったかが分かればコースティクスを描画できますが、

光がどこを通ってきたかは未知の情報です。

 

コースティクスの描画方法 (Backward Ray Tracing)

今回はBackward Ray Tracingと呼ばれる手法でコースティクスを描画したいと思います。

描画したい水底の各点から、光とは逆方向にRayを飛ばします。

f:id:r-ngtm:20201114183835p:plain

逆方向にRayを飛ばす

 

Rayが水面にぶつかる位置をコースティクスのテクスチャ座標として利用して、

コースティクスを描画します。

f:id:r-ngtm:20201114200151p:plain

Rayを水面へ向けて飛ばし、ぶつかった点の色を使う

※水へ入射する光はスネルの法則などを利用して屈折させるのが正しいですが、

今回そこは重要ではないので処理を省きます。

 

水面のコースティクス座標の計算

今回は計算を簡単にするため、水面は平面として扱います。

 

Rayが進む距離dの計算

初めに、水底にある点から出たRayが水面にぶつかるまでの距離dを計算します。

距離dは、高低差h、Rayの向きL から算出できます。

Rayの向きLは、射し込む光と真逆にします。

f:id:r-ngtm:20201114185530p:plain

Rayが進む距離を求める

 

 

Rayが水面にぶつかる座標Cの計算

距離dやRay向きLなどを利用して、水面コースティクス座標Cを計算します。

f:id:r-ngtm:20201114185806p:plain

水面のコースティクスの座標を求める。

 

点CのXZ座標をUV座標として利用することで、水底に投影されたコースティクスが描画されます。

f:id:r-ngtm:20201114193744p:plain

水面コースティクスの点の色を水底のコースティクスとして利用する

f:id:r-ngtm:20201114200151p:plain

Rayを水面へ向けて飛ばし、ぶつかった点の色を使う

以上でコースティクスの実装方法の解説は終わりです。

 

 

ShaderGraphによる実装

次に、ShaderGraphで水中コースティクスを実装します。

ShaderGraph全体は以下のようになります。

f:id:r-ngtm:20201114205806p:plain

ShaderGraph全体


Rayが進む距離の計算

左下の箇所では、Rayが進む距離dを計算しています。

f:id:r-ngtm:20201114210049p:plain

Rayが進む距離dの計算処理

f:id:r-ngtm:20201114185530p:plain

Rayが進む距離を求める

 

 

水面コースティクスの位置の計算

その右上では水面のコースティクスの座標を計算しています。

f:id:r-ngtm:20201114210442p:plain

水面のコースティクスの位置(Rayが当たる位置)の計算

f:id:r-ngtm:20201114185806p:plain

水面のコースティクスの座標を求める。

 

ボロノイの描画

求めた点Cのxz座標をUVとして、ボロノイを描画します。(Voronoiノード)

f:id:r-ngtm:20201114210811p:plain

 

これにより、水底に投影されるボロノイが取得できます。

f:id:r-ngtm:20201114200151p:plain

Rayを水面へ向けて飛ばし、ぶつかった点の色を使う

最後に、Lerpを使ってボロノイに色を付けます。

f:id:r-ngtm:20201114211311p:plain

色をつける

以上でシェーダーグラフの実装は完了です。

 

 

シェーダーパラメータ

プロパティ名 説明
Light (_Light)
光の向きベクトル
WaterLevel
水面の高さ(Y座標)
CausticsScale
コースティクスの大きさ調整用パラメータ
WaterColor
コースティクス無しの水の色
LightColor
光の色(コースティクスの色)
LightIntensity
光の強度(コースティクスの強度)
VoronoiPower
ボロノイの鋭さ(Powerノードの指数部分に使用する数値

 

f:id:r-ngtm:20201114211554p:plain

ShaderGraphパラメータ

 

シェーダー内の光の向き(Light)の同期

シーンに配置されたライトの向きをシェーダーのLightと同期させるロジックをC#スクリプトで書きます。

 

コースティクスを描画するMeshRenderが付いたGameObjectへ、以下のコンポーネントをアタッチします。

using UnityEngine;

public class MaterialSyncLight : MonoBehaviour
{
// シェーダープロパティ _Light にアクセスするためのShaderID
private readonly int shaderId_Light = Shader.PropertyToID("_Light");

[SerializeField] private Light targetLight = null;
private Material _material = null;

void Start()
{
var meshRenderer = GetComponent<MeshRenderer>();
if (meshRenderer != null)
{
_material = meshRenderer.material;
}
}

void Update()
{
if (_material != null)
{
_material.SetVector(shaderId_Light, targetLight.transform.forward);
}
}
}

f:id:r-ngtm:20201114213420p:plain

コンポーネント設定

Material Sync LightコンポーネントTarget Lightには、シーン内のライト(DirectionalLight)を持たせておきます。 

f:id:r-ngtm:20201114221302p:plain

シーン内のライト


ゲームを再生すると、ライトの向きとコースティクスが同期します。

f:id:r-ngtm:20201114214023g:plain

ライトの向きを変えた時の、コースティクスの振る舞い

 

 

参考リンク

コースティクスの描画は下記リンクを参考にしました(英語)

developer.download.nvidia.com