2017年7月21日

Unity スプライトに影をつける ~その3~


前回作ったCutoutシェーダーにSprite Rendererの色情報を加えます…


※このページの内容の動作確認にはUnity5.6を使用しています。
前回は、Cutoutのシェーダーを作成し、裏側にも自然な影がつくよう無理くり変更を加えたのですが、Sprite RendererのColorのことをすっかり忘れていたので少しだけ追記。

どうやらSprite Rendererで設定したColorの値は頂点カラーとして設定されるようなので、以前の投稿でやったのと同じ方法でシェーダーを頂点カラーに対応させれば色が反映されるようになります。

  1. Shader "Custom/Cutout Double-sided" {
  2. Properties {
  3.   _Cutoff ("Cutoff", Range(0,1)) = 0.5
  4.   _Color ("Color", Color) = (1,1,1,1)
  5.   _MainTex ("Albedo (RGB)", 2D) = "white" {}
  6.   _Glossiness ("Smoothness", Range(0,1)) = 0.5
  7.   _Metallic ("Metallic", Range(0,1)) = 0.0
  8. }
  9. SubShader {
  10.   Tags { "Queue"="AlphaTest" "RenderType"="TransparentCutout" }
  11.   LOD 200
  12.   
  13.   Cull Off
  14.   
  15.   CGPROGRAM
  16.   #pragma surface surf Standard alphatest:_Cutoff addshadow fullforwardshadows vertex:vert
  17.   #pragma target 3.0
  18.   
  19.   sampler2D _MainTex;
  20.     
  21.   struct Input {
  22.    float2 uv_MainTex;
  23.    fixed4 vertexColor;
  24.   };
  25.  
  26.   void vert (inout appdata_full v, out Input o) {
  27.    UNITY_INITIALIZE_OUTPUT(Input, o);
  28.    o.vertexColor = v.color; // 頂点カラーを取得
  29.   }
  30.   
  31.   half _Glossiness;
  32.   half _Metallic;
  33.   fixed4 _Color;
  34.  
  35.   void surf (Input IN, inout SurfaceOutputStandard o) {
  36.    fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
  37.    o.Albedo = c.rgb * IN.vertexColor.rgb; // 頂点カラーを適用
  38.    o.Metallic = _Metallic;
  39.    o.Smoothness = _Glossiness;
  40.    o.Alpha = c.a;
  41.   }
  42.   ENDCG
  43.   
  44.   Cull Front
  45.   
  46.   CGPROGRAM
  47.  
  48.   #pragma surface surf Standard alphatest:_Cutoff fullforwardshadows vertex:vert
  49.   #pragma target 3.0
  50.  
  51.   sampler2D _MainTex;
  52.   
  53.   struct Input {
  54.    float2 uv_MainTex;
  55.    fixed4 vertexColor;
  56.   };
  57.   
  58.   void vert (inout appdata_full v, out Input o) {
  59.    UNITY_INITIALIZE_OUTPUT(Input, o);
  60.    o.vertexColor = v.color; // 頂点カラーを取得
  61.    v.normal.xyz = v.normal * -1;
  62.   }
  63.  
  64.   half _Glossiness;
  65.   half _Metallic;
  66.   fixed4 _Color;
  67.  
  68.   void surf (Input IN, inout SurfaceOutputStandard o) {
  69.    fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
  70.    o.Albedo = c.rgb * IN.vertexColor.rgb; // 頂点カラーを適用
  71.    o.Metallic = _Metallic;
  72.    o.Smoothness = _Glossiness;
  73.    o.Alpha = c.a;
  74.   }
  75.   ENDCG
  76. }
  77. FallBack "Diffuse"
  78. }

頂点カラーのうち使用するのはRGBだけで、アルファは反映されないようにしています。

頂点カラーで色付け

どうしてもアルファを反映させて透過させたい!という場合は

Blend SrcAlpha OneMinusSrcAlpha

のようにブレンドを指定したうえで

o.Alpha = c.a * IN.vertexColor.a;

surf関数でアルファに頂点カラーの情報を渡せばOK。

Blendで透過処理 なんか変

ただこれだと透け方がおかしいので

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

のように、タグのQueueをAlphaTestからTransparentに変更して描画順を変えます。

Transparentを指定

これで自然な見た目で透過するようになりました。ただし、Transparentを指定すると基本的に他のオブジェクトから受ける影は描画されなくなってしまいます。つまり今までやってきたことが水の泡です。あちゃー!

あと、アルファ値がプロパティの_Cutoffより小さくなってしまうとalphatest:_Cutoffのおかげで無残にも完全な透明になってしまうので気を付けましょう。

てなわけで、スプライト用のシェーダーについてはとりあえずこのへんで。サーフェスシェーダーはかなり楽で便利ですが、もうちょっと痒い所に手が届くような突っ込んだ処理をやりたければやはりフラグメントシェーダーを使うべきかもしれませんね。 また勉強しよ…。

0 件のコメント:

コメントを投稿