Unityで自作ポストエフェクトを試してみた。
上記のサイトを参考にしてUnityで初めてシェーダーを触ってみました。
UnityのシェーダーはShaderLabと言って、頭の部分にシェーダーに値を渡すための記述を書き、下の方にCgかHLSLでシェーダーを書くみたいです。
一応GLSLでも書けるみたいですけど、ターゲットがMac OS XかOpenGL ESをサポートしたモバイルデバイスかLinuxの時だけにしとき、っと公式サイトに書いてます。
今回は、作っているゲームで風が吹いている方向を分かるようにしたかったので、そんな感じのものを作りました。単純にテクスチャを流しているだけです。
githubにサンプルをプロジェクトごと上げてます。
github.com
※一時、プロジェクトにコミットし忘れてました。ごめんなさい。
githubにコードありますが、こっちにも載せておきます。
using UnityEngine; public class WindImageEffect : CustomImageEffect { [SerializeField] [Range(0, 360)] private float rotation; [SerializeField] private float translateSpeed = 2.0f; [SerializeField] [Range(0, 2.0f)] private float density = 0.4f; [SerializeField] private Color windColor = Color.white; private float translate = 0.0f; public override string ShaderName { get { return "Hidden/WindImageEffectShader"; } } void Update() { translate += translateSpeed * Time.deltaTime; } protected override void UpdateMaterial() { float rad = Mathf.Deg2Rad * rotation; //shader側に値を渡す Material.SetFloat( "_translate", translate ); Material.SetFloat( "_density", density ); Material.SetColor( "_windColor", windColor ); Material.SetFloat( "_rotCos", Mathf.Cos( rad ) ); Material.SetFloat( "_rotSin", Mathf.Sin( rad ) ); } }
Shader "Hidden/WindImageEffectShader" { Properties { _MainTex ("Texture", 2D) = "white" {} _WindTex ("Wind Texture", 2D) = "white" {} _translate ("Translate", Float) = 0 _density ("Density", Float) = 0 _windColor ("Wind Color", COLOR) = (1,1,1,1) _rotCos ("RotCos", Float) = 0 _rotSin ("RotSin", Float) = 0 } SubShader { // No culling or depth Cull Off ZWrite Off ZTest Always Fog { Mode Off } Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float2 uv_wind : TEXCOORD1; float4 vertex : SV_POSITION; }; Float _rotCos; Float _rotSin; Float _translate; v2f vert (appdata v) { v2f o; o.vertex = mul(UNITY_MATRIX_MVP, v.vertex); o.uv = v.uv; o.uv_wind = v.uv; o.uv_wind.y *= _ScreenParams.y / _ScreenParams.x;//アスペクト比の分補正 o.uv_wind = float2( _rotCos * o.uv_wind.x - _rotSin * o.uv_wind.y, _rotSin * o.uv_wind.x + _rotCos * o.uv_wind.y );//回転行列を掛ける o.uv_wind.x += _translate;//移動 return o; } sampler2D _MainTex; sampler2D _WindTex; Float _density; fixed4 _windColor; fixed4 frag (v2f i) : SV_Target { fixed4 col = tex2D(_MainTex, i.uv); fixed4 wind = tex2D(_WindTex, i.uv_wind); float ratio = _density * wind.r; return lerp( col, _windColor, ratio ); } ENDCG } } }
あとUnityではポストエフェクトの類をImage Effectと呼んでいるようです。ポストにやるとは限らないからかな。