瓶に入った、粘性の高い液体をUnityで表現してみます。RPGの回復系液体ドリンク・・・・とはちょっと違いますね。笑
今回はいちからUnityでシェーダを書くのではなく、ShaderToyで紹介されているシェーダを利用して液体を作ってみました。
ShaderToyを利用する
ShaderToyにあるシェーダはOpenGLで使われるGLSLというシェーダ言語で書かれています。一方UnityはHLSLと呼ばれる言語を使っているため、少し変換作業が必要になります。
といっても機械的に置き換えていくだけなので、簡単簡単!液体を表現するのに使ったプログラムはこちらで紹介されているものです。
https://www.shadertoy.com/view/Xts3WH
なんと、この液体のシェーダは次の4行だけで作られています。なんというか、、、神業ですね。このGLSLで書かれたシェーダをUnity用に書き換えていきましょう。
void mainImage( out vec4 c, in vec2 w ) { vec2 p = w/iResolution.xy, a = p*5.; a.y -= iGlobalTime; vec2 f = fract(a); a -= f; f = f*f*(3.-2.*f); vec4 r = fract(sin(vec4(a.x + a.y*1e3) + vec4(0, 1, 1e3, 1001)) * 1e5)*30./p.y; c.rgb = p.y + vec3(1,.5,.2) * clamp(mix(mix(r.x, r.y, f.x), mix(r.z, r.w, f.x), f.y)-30., -.2, 1.); }
Unityで液体を入れるボトルとマテリアルを作る
まずはプロジェクトを作って、液体を入れるボトルになる円柱を配置しておきます。また、シェーダにはUnlitシェーダを使うので、プロジェクトビューから右クリックで「Create」→「Shader」→「Unlit Shader」を選択して下さい。(Unlitはunlightingの略、だと思っています)
作成したシェーダに対応するマテリアルを作成します。ファイルを選択した状態で、右クリックして「Create」→「Material」を選択します。作られたマテリアルは円柱にアタッチしておきます。
UnityにShaderToyの液体シェーダを移植する
では、いま作成した液体のシェーダにShaderToyの液体シェーダを移植しましょう。移植する場所はフラグメントシェーダ内(fragメソッド)です。まずは機械的に修正できる点から見ていきましょう。
- fract → frac
- vec → half
- mix → lerp
Unityでは小数点以下を計算するfract関数は無いので、frac関数に変換します。また、ベクトル型もUnityでは使えないので、half型に置き換えます。GLSLのmix関数はUnityのlerp関数に変更します。
また、ShaderToyでは引数にスクリーン座標が渡されてくるため、正規座標系に直すために画面解像度(iResolution)で割り算していますが、UnityではテクスチャのUV座標が使えるのでそちらを使います。
修正後の液体シェーダは次のとおりです。
fixed4 frag (v2f i) : SV_Target { half2 p = i.uv.xy; half2 a = p*4.; a.y -= _Time.w*0.5; half2 f = frac(a); a -= f; f = f*f*(3.-2.*f); half4 r = frac(sin((a.x + a.y*1e3) + half4(0, 1, 1e3, 1001)) * 1e5)*30./p.y; return half4(p.y+half3(1,.5,.2) * clamp(lerp(lerp(r.x, r.y, f.x), lerp(r.z, r.w, f.x), f.y)-30., -.2, 1.),1); }
実行結果
液体シェーダを保存したら実行してみましょう。次のように液体が湧き上がってくる感じになると思います。あとは瓶の蓋とかガラス瓶とかを作って、Unityでマテリアルを設定するとそれっぽくなります。