Unity 水の揺らぎと水面の反射っぽいポストエフェクト


前回、GLSL から移植して水の波紋と揺らぎっぽいポストエフェクトを作ってみましたが、今回は GLSL Sandbox のこれ http://glslsandbox.com/e#39055.2 を移植して、水の揺らぎと水面の反射っぽいポストエフェクトを作ってみました。

それでは、移植元のコードと、移植後のコードを比較してみます。

移植元 GLSL の main 関数

void main( void ) {
	vec2 sp = surfacePosition;//vec2(.4, .7);
	vec2 p = sp * 15.0 - vec2(20.0);
	vec2 i = p;
	float c = 0.0; // brightness; larger -> darker
	float inten = 0.025; // brightness; larger -> brighter
	float speed = 1.5; // larger -> slower
	float speed2 = 3.0; // larger -> slower
	float freq = 0.8; // ripples
	float xflow = 1.5; // flow speed in x direction
	float yflow = 0.0; // flow speed in y direction

	for (int n = 0; n < MAX_ITER; n++) {
		float t = time * (1.0 - (3.0 / (float(n) + speed)));
		i = p + vec2(cos(t - i.x * freq) + sin(t + i.y * freq) + (time * xflow), sin(t - i.y * freq) + cos(t + i.x * freq) + (time * yflow));
		c += 1.0 / length(vec2(p.x / (sin(i.x + t * speed2) / inten), p.y / (cos(i.y + t * speed2) / inten)));
	}
	
	c /= float(MAX_ITER);
	c = 1.5 - sqrt(c);
	gl_FragColor = vec4(vec3(c * c * c * c), 0.0) + vec4(0.0, 0.4, 0.55, 1.0);
}

移植後のUnity用イメージエフェクトの frag 関数

// エディタからパラメータを変更できるように Properties に変数を登録しておく
sampler2D _MainTex;
int _MaxIter;
float _Refrection;
float _Brightness;
float _Fineness;
float _Speed;
float _Speed2;
float _Power;
float _DirectionX;
float _DirectionY;
fixed4 _Color;

fixed4 frag (v2f_img i) : SV_Target
{
	float time = _Time * 30;
	
	half2 sp = i.uv; // surfacePosition は i.uv で置き換える
	half2 p = sp * _Fineness - half2(_Fineness * 1.3, _Fineness * 1.3);
	half2 _i = p;
	float c = _Refrection;
	float inten = .025 * _Brightness;
	float speed = _Speed;
	float speed2 = _Speed2;
	float freq = _Power;
	float xflow = _DirectionX;
	float yflow = _DirectionY;
	
	for (int n = 0; n < float(_MaxIter); n++) 
	{
		float t = time * (1.0 - (3.0 / (n + speed)));
		_i = p + half2(cos(t - _i.x * freq) + sin(t + _i.y * freq) + (time * xflow), sin(t - _i.y * freq) + cos(t + _i.x * freq) + (time * yflow));
		c += 1.0 / length(half2(p.x / (sin(_i.x + t * speed2) / inten), p.y / (cos(_i.y + t * speed2) / inten)));
	}

	c /= _MaxIter;
	c = 1.5 - sqrt(c);

	// _MainTex にエフェクトを適用させるために uv に変形を加えつつ波のエフェクトを tex に加算する
	// _Color プロパティを使用してエディタから色味を変更できるようにする
	half3 _col = half3(c * c * c * c, c * c * c * c, c * c * c * c) + half3(_Color.r, _Color.g, _Color.b);
	half4 tex = tex2D(_MainTex, i.uv + c * .025);
	return tex + (half4(_col, 1) * .5);
	
	// 上の三行をコメントアウトして下記を有効にすると移植元の GLSL と同じような感じになる
//	half3 _col = half3(c * c * c * c, c * c * c * c, c * c * c * c) + half3(0.0, 0.4, 0.55);
//	return half4(_col, 1);

}

今回も複雑なところはありませんが、少しだけポイントを。

vec 系の変数の型を half に置き換えていますが、この際 vec だと vec2(0.0) のように x, y が同じ値の時は省略して書きますが、half で half2(0.0) と書くとエラーが出ますのでめんどくさいけど省略せずに half2(0.0, 0.0) と書くようにします。
GLSL では surfacePosition となっているところは Cg/HLSL では i.uv でよさそうです。
あと、移植元のエフェクトを _MainTex に反映させる方法は上記コード内でコメントしている通りです。

また、いくつかの変数を Properties に登録して、下のスクリーンショットのようにUnityエディタ上でパラメータを変更できるようにしました。