26
32

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Unity】被写界深度を色収差を使って表現してみる

Last updated at Posted at 2019-04-18

#はじめに
スパイダーバースがバチボコ面白かったので、そこで使われていた演出の1つを再現してみました。(スパイダーバースの演出についてはこちら参照)
V/Fシェーダを使います。

#できたもの
キャプチャ.PNG

自作シェーダ+Post Processing Stackの被写界深度で良い感じの画がつくれた。
Post Processing Stackについてはこちらを参照。

#方針

  • カメラから頂点までの距離を出す
  • 距離によって色収差のズレの大きさを変える
  • 1Pass目で頂点全体の法線を少しずらして赤で塗りつぶす
  • 2Pass目で頂点全体の法線を少しずらして緑で塗りつぶす
  • 3Pass目でメインテクスチャのR値とG値を少しずらす

#コード

Shader "Custom/Hisyakaisindo"
{
	Properties
	{
		_Color("Color", Color) = (0,0,0,0)
		_MainTex("MainTexture", 2D) = "white" {}
	    _Opacity("Opacity", Range(0.0, 1.0)) = 1.0
        _Offset_R("Offset_R", Range(1.0, 10.0)) = 5.0
		_Offset_B("Offset_B", Range(1.0, 10.0)) = 3.0
		_DepthOffset("DepthOfset", Range(-100, 0)) = 0.0

	}
		SubShader
		{
			ZWrite Off
			Blend SrcAlpha OneMinusSrcAlpha

			Tags
			{
				"RenderType" = "Transparent"
				"Queue" = "Transparent"
			}
		

//1パス目
		Pass
		{
			Cull Front
			CGPROGRAM
		#pragma target 3.0
		#pragma vertex vert
		#pragma fragment frag

		#include "UnityCG.cginc"

			struct appdata
		{
			float4 vertex : POSITION;
			float2 uv : TEXCOORD0;
			float3 normal : NORMAL;
		};

		sampler2D _CameraDepthTexture;

		struct v2f
		{
			float4 vertex : SV_POSITION;
			float2 uv : TEXCOORD0;
			float3 screenPos : TEXCOORD1;
			float3 normal : NORMAL;
		};

		sampler2D _MainTex;
		float4 _MainTex_ST;
		float _Opacity;
		float _Offset_R;
		float _DepthOffset;


		v2f vert(appdata v)
		{
			v2f o;
			//アウトライン
			v.vertex += float4(v.normal* 0.001f, 0);
			o.vertex = UnityObjectToClipPos(v.vertex);
			o.uv = TRANSFORM_TEX(v.uv, _MainTex);

			//スクリーン座標(xy)
			o.screenPos = ComputeScreenPos(o.vertex);
			//カメラから見た距離(z)を求める
			COMPUTE_EYEDEPTH(o.screenPos.z);

			//色収差
			float DepthofWriting = o.screenPos.z + _DepthOffset;
			o.vertex.x += pow(DepthofWriting,2) * 0.0001f * _Offset_R;

			return o;
		}

		fixed4 _Color;


		fixed4 frag(v2f i) : SV_Target
		{
		float partZ = i.screenPos.z;
		return float4(1,0,0, _Opacity);
	}
			ENDCG
			}
			


//2パス目
		Pass
		{
					Cull Front

			CGPROGRAM
		#pragma target 3.0
		#pragma vertex vert
		#pragma fragment frag

		#include "UnityCG.cginc"

			struct appdata
		{
			float4 vertex : POSITION;
			float2 uv : TEXCOORD0;
			float3 normal : NORMAL;
		};

		sampler2D _CameraDepthTexture;

		struct v2f
		{
			float4 vertex : SV_POSITION;
			float2 uv : TEXCOORD0;
			float3 screenPos : TEXCOORD1;
			float3 normal : NORMAL;
		};

		sampler2D _MainTex;
		float4 _MainTex_ST;
		float _Offset_B;
		float _Opacity;
		float _DepthOffset;


		v2f vert(appdata v)
		{
			v2f o;
			v.vertex += float4(v.normal* 0.001f, 0);
			o.vertex = UnityObjectToClipPos(v.vertex);
			o.uv = TRANSFORM_TEX(v.uv, _MainTex);

			//スクリーン座標(xy)
			o.screenPos = ComputeScreenPos(o.vertex);
			//カメラから見た距離(z)を求める
			COMPUTE_EYEDEPTH(o.screenPos.z);

			//色収差
			float DepthofWriting = o.screenPos.z + _DepthOffset;
			o.vertex.x -= pow(DepthofWriting,2) * 0.0001f*_Offset_B;

			return o;
		}

		fixed4 _Color;


		fixed4 frag(v2f i) : SV_Target
		{
		float partZ = i.screenPos.z;
		return float4(0,1,0, _Opacity);
	}
			ENDCG
			}



//3パス目
			Pass
		{
			CGPROGRAM
#pragma target 3.0
#pragma vertex vert
#pragma fragment frag

#include "UnityCG.cginc"

				struct appdata
			{
				float4 vertex : POSITION;
				float2 uv : TEXCOORD0;
			};


			struct v2f
			{
				float4 vertex : SV_POSITION;
				float2 uv : TEXCOORD0;
				float3 screenPos : TEXCOORD1;
			};

			sampler2D _MainTex;
			float4 _MainTex_ST;
			float _Offset_R;
			float _Offset_B;
			float _DepthOffset;


			v2f vert(appdata v)
			{
				v2f o;
				o.vertex = UnityObjectToClipPos(v.vertex);
				o.uv = TRANSFORM_TEX(v.uv, _MainTex);

				//スクリーン座標(xy)
				o.screenPos = ComputeScreenPos(o.vertex);
				//カメラから見た距離(z)を求める
				COMPUTE_EYEDEPTH(o.screenPos.z);

				return o;
			}

			fixed4 _Color;


			fixed4 frag(v2f i) : SV_Target
			{
			//色収差
			float DepthofWriting = i.screenPos.z + _DepthOffset;
			float R_Offset = pow(DepthofWriting,2) * 0.0001f * _Offset_R;
			float B_Offset = pow(DepthofWriting, 2) * 0.0001f * _Offset_B;
			float4 col = tex2D(_MainTex, i.uv);
			col.r = tex2D(_MainTex, i.uv + float2(R_Offset*0.1f,0));
			col.b = tex2D(_MainTex, i.uv - float2(B_Offset*0.1f,0));
			return col;
			}
	ENDCG
	}
		}
}

(ポストエフェクトの方が楽だったのでは...?)

#参考

26
32
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
26
32

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?