おもちゃラボ

Unityで遊びを作ってます

Unityで始めるARKit超入門 平面をシェーダで描画する

UnityのARKitについてくる平面検出マーカーって、見やすいですけどイケてないですよね。そこで、Unityのシェーダを使って、ARKitの平面検出マーカーを少しだけかっこよくする方法を紹介します。今回は上のようなドットで書かれた平面マーカーを作ってみましょう。

f:id:nn_hokuson:20181001192028j:plain

平面描画用の水玉シェーダを作成する

 上のようなドット柄の平面検出マーカーを作るだけなら、ドット模様(水玉模様)のテクスチャを用意して貼り付ければ良い気もしますね。ただ、平面が大きくなるとテクスチャも引き伸ばされるため、あまりきれいな表示になりません。

f:id:nn_hokuson:20181001185311p:plain:w300

シェーダを使って描画することで、平面の大きさによらず一定の間隔でドットを打てるのでシェーダを使った方法をオススメします。

 

水玉シェーダを作成する

まずはシーンビューで右クリックして「Create」→「Shader」→「Standard Surface Shader」を選択してシェーダファイルを作成します。ファイル名はARPlaneShaderにしておきます。

次のプログラムを入力してください。

Shader "Custom/ARPlaneShader"
{
  properties
  {
    _Ratio("Ratio", float) = 1
  }
  SubShader {
    Blend SrcAlpha OneMinusSrcAlpha
    Pass {
      Tags { "Queue"="Transparent" "RenderType" = "Transparent" }

      CGPROGRAM
      #pragma vertex vert
      #pragma fragment frag
       #include "UnityCG.cginc"

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

      struct v2f
      {
        float4 position : SV_POSITION;
        float2 uv     : TEXCOORD0;
      };

      v2f vert (appdata input)
      {
        v2f output;
        output.position = UnityObjectToClipPos(input.vertex);
        output.uv = input.uv;
        return output;
      }

     float _Ratio;
      fixed4 frag (v2f input) : SV_Target
      {
        float2 v = float2(input.uv.x * 200 * _Ratio, input.uv.y * 200) ;

        float  f = 5 * ( (sin(v.x) * 0.5 + 0.5) + (sin(v.y) * 0.5 + 0.5) );
        return fixed4(fixed3(0.1, 0.9, 1.0),  1-f);        
      }
      ENDCG
    }
  }
}

 
 

シェーダで水玉模様を作る原理

ここでは、ドットを打たないところ以外は透明にしたいのでBlendのタイプとQueue、Render Typeを指定しています。この辺は次のUnity Shaderの記事も参考にしてください。
 
nn-hokuson.hatenablog.com

重要なのはfragメソッドの中に書いているフラグメントシェーダです。少しややこしく見えるかもしれませんが、キモはsin(v.x)+sin(v.y)を計算しているところです。z = sin(x)+ sin(y)の計算結果は次のようになります。

f:id:nn_hokuson:20181001190113j:plain:w300

この山の高さを透明度にすることで頂上付近のみがドットとして表示されるという仕組みです。山の頂上だけをピックアップするからドットに見える、というのは上の図を横から見て考えたほうが分かりやすいかもしれません。

f:id:nn_hokuson:20181001185859p:plain:w400

Unityでシェーダを使って、その他の図形を書きたい場合は次の記事も参考にして下さい。

nn-hokuson.hatenablog.com

Prefabのシェーダを差し替える

シェーダができたところで、既存の平面検出シェーダと差し替えましょう。まずは今作成したシェーダをアタッチしたマテリアルを作成します。ARPlaneShaderを選択した状態で、右クリックして「Create」→「Material」を選択してください。

f:id:nn_hokuson:20181001190557p:plain:w200

このマテリアルをARKItの検出平面のPrefabに設定します。UnityARKitPlugin/Examples/Common/Prefabs/の中にあるdebugPlane→Planeオブジェクトのシェーダを今作成したCustom/ARPlaneShaderに変更してください。

f:id:nn_hokuson:20181001190801j:plain

これで、ビルドしてARKitを実行して平面を検出すると、次のように水玉模様が描かれた平面が検出されます。

f:id:nn_hokuson:20181001192028j:plain