【Unity / ARFoundation】 AR空間の変形のつなぎ目を滑らかにする


1. はじめに

以前、ARKit3を使ってAR空間上のカメラ映像の一部分を変形させるという記事を書きました。

この記事を書いた時点ではあまり気にならなかったですが、よく見てみると変形のつなぎ目が目立ってしまい、あまり空間に溶け込んでいません。

そこで、今回 AR空間の変形のつなぎ目を滑らかにするようにシェーダーを書き換えてみたので、そのテクニックを紹介します。

2. 準備

基本準備は、ARKit3を使ってAR空間上のカメラ映像の一部分を変形させるに記載しているので、そちらをご覧ください。

3. 実装

変形処理のつなぎ目を滑らかにするため、シェーダー (CameraPlane.shader)を書き換えます。
Planeの中心から遠ざかるにつれ、パラメタを小さくし、つなぎ目では変形させないようにします。
そこで、tex2Dlodを使って、テクスチャ情報から頂点をいじる処理を追加します。
下記の画像をインポートし、_ScopeTexとして利用します。

また、Thresholdによって変形のパラメータを調整できるようにします。
追加する処理はこのような感じです。

float4 deform = tex2Dlod (_ScopeTex, float4(IN.uv.xy,0,0));
float ratio = _Threshold * deform;
float4 _vertex = IN.vertex;
float ampX = 0.1f * sin(_Time * 100 + IN.vertex.x) * ratio;
float ampZ = 0.1f * sin(_Time * 100 + IN.vertex.z) * ratio;
_vertex.xyz = float3(IN.vertex.x + ampX, IN.vertex.y, IN.vertex.z + ampZ);

全文はこちら

CameraPlane.shader
Shader "Custom/CameraPlane"
{
    Properties
    {
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        // _ScopeTexと_Thresholdを追加
        _ScopeTex ("Texture", 2D) = "white" {}
        _Threshold("Threshold", Range(0,10))= 0.0
    }

    SubShader
    {
        Pass
        {
            CGPROGRAM
            #pragma target 3.0
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            struct appdata_t
            {
                float4 vertex : POSITION;
                float4 color : COLOR;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float4 vertex : POSITION;
                float4 color : COLOR;
                float2 uv : TEXCOORD0;
                float2 screenpos : TEXCOORD1;
            };

            sampler2D _MainTex;
            sampler2D _ScopeTex;
            float _Threshold;

            v2f vert(appdata_t IN)
            {
                v2f OUT;
                // --------- : 追加
                float4 deform = tex2Dlod (_ScopeTex, float4(IN.uv.xy,0,0));
                float ratio = _Threshold * deform;
                float4 _vertex = IN.vertex;
                float ampX = 0.1f * sin(_Time * 100 + IN.vertex.x) * ratio;
                float ampZ = 0.1f * sin(_Time * 100 + IN.vertex.z) * ratio;
                // ---------
                _vertex.xyz = float3(IN.vertex.x + ampX, IN.vertex.y, IN.vertex.z + ampZ);

                OUT.vertex = UnityObjectToClipPos(_vertex);
                OUT.uv = IN.uv;
                OUT.color = IN.color;

                float4 objectToClipPos = UnityObjectToClipPos(IN.vertex);
                float4 spreenPos = ComputeScreenPos(objectToClipPos);
                float2 uv = spreenPos.xy/spreenPos.w;

                OUT.screenpos = uv;
                return OUT;
            }

            fixed4 frag(v2f IN) : COLOR
            {
                float2 xy = IN.screenpos.xy;
                half4 c = tex2D(_MainTex, xy);
                return c;
            }
            ENDCG
        }
    }
    FallBack "Diffuse"
}

4. 実行結果

処理を入れる前

変形のつなぎ目がわかる状態になっています。

処理を入れた後

変形のつなぎ目がわからない✨

5. おわりに

今回はARFoundation向けのシェーダーを紹介しましたが、その他のプラットフォームでも適用できそうなテクニックの紹介でした🍎

おまけ

変形処理をちょっと変えたやつです。

参考