夜風のMixedReality

xRと出会って変わった人生と出会った技術を書き残すためのGeekなHoloRangerの居場所

Hex表現を使用した出現シェーダーを作る その⑦ HoloLensにビルドする

本日はShader枠です。

先日よりHex表現を使用した出現シェーダーを開発しています。

先日はSpatialMesh用に調整を行いました。

今回はこのシェーダーを実機で確認していきます。

〇SpatialMeshのマテリアルの設定

今回はMRTKv2.8を使用しています。またMRTKのプロジェクトおよび基礎的なシーン構築は完了している前提で進めていきます。

①シーン上のMixedRealityToolkitを選択しInspectorウィンドウからMixedRealityToolkitのProfileを確認します。

②MixedRealityToolkitコンポーネントのSpatialAwarenessタブを開きます。

MRTKv2のProfilerはデフォルトでは編集ができません。もしデフォルトの状態の場合はCloneを選択します。

③使用しているSpatialMesh ObserverのProfileの最下部のDisplay SettingsDisplayOptionに指定されているマテリアルスロットにHexシェーダーを使用したマテリアルをアタッチします。

今回の場合はOcclusion Materialにアタッチします。

以上でSpatialAwarenessに反映されるようになります。

〇ユーザーの動きに追従

今回はエフェクトの位置とユーザーの立ち位置を同期させるために次のようなスクリプトを作成しました。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class UserPosShader : MonoBehaviour
{

    [SerializeField] private float y;
    [SerializeField] private Vector3 pos;
    [SerializeField] private Material _targetmat;

    void Update()
    {
    
         pos = Camera.main.transform.position;
         pos = new Vector3(-pos.x, -pos.z, 0);
         
        _targetmat.SetVector("_userPos", pos);
    }
}

行っていることは自分自身(Camera.main)のポジションをマテリアルのパラメータに渡しているだけです。

渡す際に今回はxz平面の水平面でエフェクトをかけたいためpos.yをpos.zに置き換えて実質Vector2として渡しています。

シーン上の適当なオブジェクトにこのコンポーネントをアタッチしてHexシェーダーを使用したマテリアルをtargetmatにアタッチすることで機能します。

〇実機で確認

実機で確認すると次のようになります。

www.youtube.com

実機でも稼働を確認できました。

自分の足元だけエフェクトがかかればよいのですが、Y座標軸(鉛直軸)に対してもエフェクトが発生しており、これが個人的に少し良くないと思っているのでもう少し調整が必要そうです。

〇シェーダー一覧

Shader "Unlit/SpatialHexShader(WorldCircle)"
{
    Properties
    {
         _MainColor("Color",color) = (0,0,0,0)
         _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;
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            struct v2f
            {
                float4 vertex : SV_POSITION;
                float3 worldPos: TEXCOORD1;
                UNITY_VERTEX_OUTPUT_STEREO
            };

            float4 _MainColor;
            float _Scale;
            float _Power;
            float4 _EmissionColor;
            float3 _userPos;
            
            v2f vert(appdata v)
            {
                v2f o;
                UNITY_SETUP_INSTANCE_ID(v); 
    UNITY_INITIALIZE_OUTPUT(v2f, o); 
    UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz; //worldPos
                return o;
            }

            fixed4 frag(v2f i) : SV_Target
            {
                float2 Hex;
                float2 HexUV;
                float HexPos;
                float2 HexIndex;
                Hexagon(i.worldPos.xz, _Scale, HexIndex, HexPos, HexUV, Hex);

                fixed4 col = _MainColor;
                float StepHex = 1- step(float3(Hex,Hex.x), smoothstep(0.1,0.8, distance(i.worldPos.xz* _Power, _userPos)));
                
               col *=  StepHex; 
                float3 emission = _EmissionColor.rgb*smoothstep( 0.1, 0.8,distance(i.worldPos.xz* _Power, _userPos));
                emission *= 1-Hex.x;
               col.rgb += emission;
  
                return col;
            }
            ENDCG
        }
    }
}