本日は昨日に引き続きShader枠です。
昨日はUnityのワールド座標基準で出現エフェクトを行うシェーダーを作成しました。
今回はさらに発展させ、あるオブジェクトを中心に3次元的にエフェクトが行われる表現を行います。
〇Unity上の別のオブジェクトの位置情報をシェーダーに反映する
Unity上の位置情報をShaderで取得して反映するにはプロパティブロックでVector型の変数として宣言し、C#スクリプト側から参照する必要があります。
これをシェーダーであらわすと次のようになります。
Properties { _userPos("Traget",vector) = (0,0,0,0) } Pass{ _}userPosを使ってあれこれ ・・・ }
C#側は次のようになります。
public void hoge(){ this.material.setVector("_userPos", this.transform.position)l }
Pass内のHLSL文でfloat4 _usePosを宣言することでシェーダー内の処理に組み込むことができるようになります。
〇Unity座標空間で座標を中心とした球表現
今回はある座標を中心に3次元の球状にエフェクトをかけていきます。
Unity上の座標自体は前述のとおり取得を行えるためこの座標を中心とした旧表現を行います。
これはDistanceメソッドを使用していきます。
Distance(A,B)のように記述することでAとBの距離を返します。
これをDistace(Unityの座標空間,Unityの特定の座標)のように記述することでUnityの特定の座標を中心とした球状領域を取得できます。
また、以下のように空間に対してパラメータをかけ合わせることで領域半径をカスタマイズすることができます。
Distace(Unityの座標空間*任意のパラメータ,Unityの特定の座標)
このようにして求めた球を先日まで同様にsmoothstep関数を使用してグラデーションをかけていきます。
smoothstep(0.1,0.8, distance(i.worldPos* _Power, _userPos))
これによってUnity上の座標を中心に0.1~0.8(パラメータなしのデフォルトでm)の距離の間でグラデーションがかかります。
これまでの変更によってシェーダーが完成しました。
フラグメントシェーダーの処理は以下のようになります。
fixed4 frag(v2f i) : SV_Target { float2 Hex; float2 HexUV; float HexPos; float2 HexIndex; Hexagon(i.uv, _Scale, HexIndex, HexPos, HexUV, Hex); fixed4 col = tex2D(_MainTex, i.uv); float StepHex = 1- step(float3(Hex,Hex.x), smoothstep(0.1,0.8, distance(i.worldPos* _Power, _userPos))); col *= StepHex; float3 emission = _EmissionColor.rgb*smoothstep( 0.1, 0.8,distance(i.worldPos* _Power, _userPos)); emission *= 1-Hex.x; col.rgb += emission; return col; }
〇シェーダー全文
Shader "Unlit/HexShader(WorldCircle)" { Properties { _MainTex ("Texture", 2D) = "white" {} _Scale("Scale" ,float) = 0 _Power("Power",float) = 0 _userPos("Traget",vector) = (0,0,0,0) [HDR]_EmissionColor("Emission" ,color) = (1,1,1,1) } SubShader { Tags { "RenderType"="Opaque" } LOD 100 AlphaToMask On Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag // make fog work #pragma multi_compile_fog #include "UnityCG.cginc" #include "Hex.hlsl" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; float3 worldPos: TEXCOORD1; }; sampler2D _MainTex; float4 _MainTex_ST; float _Scale; float _Power; float4 _EmissionColor; float3 _userPos; v2f vert(appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz; //worldPos o.uv = TRANSFORM_TEX(v.uv, _MainTex); return o; } fixed4 frag(v2f i) : SV_Target { float2 Hex; float2 HexUV; float HexPos; float2 HexIndex; Hexagon(i.uv, _Scale, HexIndex, HexPos, HexUV, Hex); fixed4 col = tex2D(_MainTex, i.uv); float StepHex = 1- step(float3(Hex,Hex.x), smoothstep(0.1,0.8, distance(i.worldPos* _Power, _userPos))); col *= StepHex; float3 emission = _EmissionColor.rgb*smoothstep( 0.1, 0.8,distance(i.worldPos* _Power, _userPos)); emission *= 1-Hex.x; col.rgb += emission; return col; } ENDCG } } }