NinaLabo

個人ゲーム開発者の技術メモ

【Unity】3Dモデルにシェーダーでアウトラインをつける(失敗編)

キャラクターと背景の色が同系色だと見にくいので、白猫プロジェクトみたいに3Dキャラクターの周りを線で囲みたいと思い、やりかたを調べてみました。

f:id:ninagreen:20160711233741p:plain

トゥーンシェーダー

最初に行き着いたのが、トゥーンシェーダー。

Unity 付属のシェーダーにアウトラインを付けるトゥーンシェーダー(Basic Outline)があるので、試してみました。

1. Assets > Import Package > Effects を実行

2. キャラクター の Material に Toon > Basic Outline を適用

f:id:ninagreen:20160712002454p:plain

 

実行した結果(左がBEFORE、右がAFTER)がこちら

f:id:ninagreen:20160711233741p:plain => f:id:ninagreen:20160712001843p:plain f:id:ninagreen:20160712001850p:plain

髪の毛が全部1色で塗りつぶされちゃってるし、アウトラインもブツブツしてて綺麗に出てない!ソウジャナイヨー!

ステンシルバッファ

次に試したのが、ステンシルバッファを使ったアウトライン表現。

 自分でシェーダーを書かなくてはいけないらしい(シェーダー書いたことない)。とりあえずは、新規に作成した適当なシェーダーを適用してみます...

  • 任意の場所で、右クリック > Create > Shader > Standard Surface Shader(ファイル名は、ここでは CharacterShader にしました)
  • キャラクターの Material の Shader で Custom > CharacterShader を選択

結果はこちら(左がBEFORE、右がAFTER)

f:id:ninagreen:20160711233741p:plain => f:id:ninagreen:20160718103839p:plain

とりあえず、新規シェーダーを適用するところまでは試せましたが...ん?なんか暗くない?ん?気のせいじゃないですよね? 

もともとキャラクターは Mobile/Diffuse のシェーダーを適用してたのに、別のシェーダーに置き換わったので見た目が変わってしまったんですね、きっと。ということは、Mobile/Diffuse のコードをベースにアウトラインの修正を加えればいいのかな。

てっとり早くシェーダーのコードだけ欲しかったので、Unity内蔵シェーダーのソースコードをのせてくれている、この記事はありがたいです。

www32.atwiki.jp

 Mobile/Diffuse のソースコードを、先ほど新規作成したシェーダーにコピペしたら、とりあえず元に戻りました。そこから、悪戦苦闘すること数時間... こんな感じのシェーダーを書いて試したところ...

Shader "Custom/CharacterShader" {
    Properties {
        _MainTex ("Base (RGB)"2D) = "white" {}
        _Outline ("Outline Length"Range(0.010.0)) = 0.1
        _OutlineColor ("Outline Color"Color) = (1111.0)
    }
    SubShader {
        Tags { "RenderType"="Opaque" }
        LOD 150

        Stencil {
            Ref 128
            Comp always
            Pass replace
        }

        CGPROGRAM
        #pragma surface surf Lambert noforwardadd

        sampler2D _MainTex;

        struct Input {
            float2 uv_MainTex;
        };

        void surf (Input IN, inout SurfaceOutput o) {
            fixed4 c = tex2D(_MainTex, IN.uv_MainTex);
            o.Albedo = c.rgb;
            o.Alpha = c.a;
        }
        ENDCG

        Pass {

            Stencil {
                Ref 128
                Comp NotEqual
            }
            
            Cull Off
            ZWrite Off

            Blend SrcAlpha OneMinusSrcAlpha 
        
            CGPROGRAM
            
            #pragma vertex vert
            #pragma fragment frag
            
            float _Outline;
            float4 _OutlineColor;
            
            struct appdata {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
            };
            
            struct v2f {
                float4 pos : SV_POSITION;
            };
            
            v2f vert(appdata v) {
                v2f o;
                
                float4 vert = v.vertex;
                vert.xyz += v.normal * _Outline;
                o.pos = mul(UNITY_MATRIX_MVP, vert);

                return o;
            }

            half4 frag(v2f i) : COLOR {
                return _OutlineColor;
            }    
            
            ENDCG
        }
    }
    FallBack "Diffuse"
} 

結果はこちら(左がBEFORE、右がAFTER)

f:id:ninagreen:20160711233741p:plain => f:id:ninagreen:20160718124937p:plainf:id:ninagreen:20160718124943p:plain

斜めはわりとキャラを囲めてるのに、正面向いた時に横の部分のアウトラインが消えてる... うううううう、なんでやー。誰か助けてください(涙

長くなったので一旦ここまでで... 成功したら、記事の続き書きます... 

参考記事 

tips.hecomi.com 

wgld.org 

tsubakit1.hateblo.jp 

qiita.com