しゅみぷろ

プログラミングとか

法線に影響される液垂れの表現

はじめに

液垂れ表現についてです。 最近Switchばっかやってて全然更新してなかったので久しぶりにネタ消化。

液垂れの基本的な部分は過去記事で。

esprog.hatenablog.com

esprog.hatenablog.com

今回は法線マップに影響させる部分について軽くメモしていきます。

f:id:es_program:20170401115307g:plain:w600

f:id:es_program:20170401135622g:plain:w600

法線に応じて流れやすさを変える

Shaderに法線マップを入力として取らせ、接空間上で法線と液体の付着量から、力の働いている方向にどの程度流れるかをそれっぽく計算してやります。

float3 normal = normalize(UnpackNormal(tex2D(_NormalMap, i.uv)).xyz);

で法線マップの法線を取ってきて

float VITIATE_Z = pow(normal.b, 2) - normal.y * 0.2;
float VITIATE_X = 0.1 * rand(float3(i.uv.xy, i.uv.x + i.uv.y)) * (1 + normal.b * 30);

どのくらい縦、横の液体を考慮するかの係数(VATATE_ZとVITATE_X)を計算します。 式自体に特に深い意味はなく、それっぽく流れてくれるよう、法線が上向きなら流れにくく・・・とかやってるだけです。

この係数を使って液体マップの周囲(液体が垂れてくると予想される場所)をサンプリングし、付着量を出します。

float2 shiftZ = float2(_FlowDirection.x * _MainTex_TexelSize.x, _FlowDirection.y * _MainTex_TexelSize.y) * _ScaleFactor * _Viscosity * VITIATE_Z;
float2 shiftX = float2(_MainTex_TexelSize.x * _FlowDirection.y, _MainTex_TexelSize.y * _FlowDirection.x) * _ScaleFactor * _Viscosity * VITIATE_X;
float2 shiftx = -shiftX;

float4 texZ = tex2D(_MainTex, clamp(i.uv.xy + shiftZ, 0, 1));
float4 texx = tex2D(_MainTex, clamp(i.uv.xy + shiftx + shiftZ, 0, 1));
float4 texX = tex2D(_MainTex, clamp(i.uv.xy + shiftX + shiftZ, 0, 1));

float amountUp = (texZ.a + texx.a + texX.a) * 0.3333;

この付着量が粘性係数を上回る場合は液垂れ計算が行われ、下回る場合は変化なしということになります。

最後に

Texture basedなので、勿論uv依存です。 使用用途として考えているのは壁等のシンプルなオブジェクトへの液体の付着表現(血の表現、Splatoonのようなインク表現)なので、uvが複雑になるモデルには不向きです。

今はまだ試作段階なので、係数のパラメーター化や色の減法混色なども実装していこうと思います。