UnityのARKitについてくる平面検出マーカーって、見やすいですけどイケてないですよね。そこで、Unityのシェーダを使って、ARKitの平面検出マーカーを少しだけかっこよくする方法を紹介します。今回は上のようなドットで書かれた平面マーカーを作ってみましょう。
平面描画用の水玉シェーダを作成する
上のようなドット柄の平面検出マーカーを作るだけなら、ドット模様(水玉模様)のテクスチャを用意して貼り付ければ良い気もしますね。ただ、平面が大きくなるとテクスチャも引き伸ばされるため、あまりきれいな表示になりません。
シェーダを使って描画することで、平面の大きさによらず一定の間隔でドットを打てるのでシェーダを使った方法をオススメします。
水玉シェーダを作成する
まずはシーンビューで右クリックして「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)の計算結果は次のようになります。
この山の高さを透明度にすることで頂上付近のみがドットとして表示されるという仕組みです。山の頂上だけをピックアップするからドットに見える、というのは上の図を横から見て考えたほうが分かりやすいかもしれません。
Unityでシェーダを使って、その他の図形を書きたい場合は次の記事も参考にして下さい。
Prefabのシェーダを差し替える
シェーダができたところで、既存の平面検出シェーダと差し替えましょう。まずは今作成したシェーダをアタッチしたマテリアルを作成します。ARPlaneShaderを選択した状態で、右クリックして「Create」→「Material」を選択してください。
このマテリアルをARKItの検出平面のPrefabに設定します。UnityARKitPlugin/Examples/Common/Prefabs/の中にあるdebugPlane→Planeオブジェクトのシェーダを今作成したCustom/ARPlaneShaderに変更してください。
これで、ビルドしてARKitを実行して平面を検出すると、次のように水玉模様が描かれた平面が検出されます。