2
1

More than 3 years have passed since last update.

ARFoundation 色を反転するShader、デバイスに合わせて背景を切り替える

Last updated at Posted at 2021-07-26

ARFoundation3.0.1
ARKit3.0.1
ARCore3.0.1 で動作可能。

Packages→ARKitXRPlugin→ARKitBackgroundをコピーする
43E61D6B-9C00-44EC-ADAE-57D1E9981400_4_5005_c.jpeg

名前をARKit InvertColorに変更する
EB55BE07-A358-4F69-A85D-BCBBE1EEE95D_4_5005_c.jpeg

ARCoreInverColorも同様に作成する
475A4F08-E903-46C4-88E1-9846C26DB2F0_4_5005_c.jpeg

ARKit InvertColorとARCore InvertColorに下記を追加する

ARKitInvertColor.Shader
Shader "CameraBackground/ARKitInvertColor"
{
    Properties
    {
        _textureY ("TextureY", 2D) = "white" {}
        _textureCbCr ("TextureCbCr", 2D) = "black" {}
    }
    SubShader
    {
        Cull Off
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            ZWrite Off
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            float4x4 _UnityDisplayTransform;

            struct Vertex
            {
                float4 position : POSITION;
                float2 texcoord : TEXCOORD0;
            };

            struct TexCoordInOut
            {
                float4 position : SV_POSITION;
                float2 texcoord : TEXCOORD0;
            };

            TexCoordInOut vert (Vertex vertex)
            {
                TexCoordInOut o;
                o.position = UnityObjectToClipPos(vertex.position);

                float texX = vertex.texcoord.x;
                float texY = vertex.texcoord.y;

                o.texcoord.x = (_UnityDisplayTransform[0].x * texX + _UnityDisplayTransform[1].x * (texY) + _UnityDisplayTransform[2].x);
                o.texcoord.y = (_UnityDisplayTransform[0].y * texX + _UnityDisplayTransform[1].y * (texY) + (_UnityDisplayTransform[2].y));

                return o;
            }

            // samplers
            sampler2D _textureY;
            sampler2D _textureCbCr;

            fixed4 frag (TexCoordInOut i) : SV_Target
            {
                // sample the texture
                float2 texcoord = i.texcoord;
                float y = tex2D(_textureY, texcoord).r;
                float4 ycbcr = float4(y, tex2D(_textureCbCr, texcoord).rg, 1.0);

                const float4x4 ycbcrToRGBTransform = float4x4(
                        float4(1.0, +0.0000, +1.4020, -0.7010),
                        float4(1.0, -0.3441, -0.7141, +0.5291),
                        float4(1.0, +1.7720, +0.0000, -0.8860),
                        float4(0.0, +0.0000, +0.0000, +1.0000)
                    );

                // 1 から元の RGBA 値を引くことで色を反転する
                float4 result = float4(1, 1, 1, 1) - mul(ycbcrToRGBTransform, ycbcr);

#if !UNITY_COLORSPACE_GAMMA
                // Incoming video texture is in sRGB color space.
                //If we are rendering in linear color space, we need to convert.
                result = float4(GammaToLinearSpace(result.xyz), result.w);
#endif // !UNITY_COLORSPACE_GAMMA

                return result;
            }
            ENDCG
        }
    }
}
ARCoreInvertColor.Shader
Shader Shader "CameraBackground/ARCoreInvertColor"
{
    Properties
    {
        _MainTex("Texture", 2D) = "white" {}
    }

    // For GLES3
    SubShader
    {
        Pass
        {
            ZWrite Off
            Cull Off

            GLSLPROGRAM

#pragma only_renderers gles3

#ifdef SHADER_API_GLES3
#extension GL_OES_EGL_image_external_essl3 : require
#endif // SHADER_API_GLES3

            uniform mat4 _UnityDisplayTransform;

#ifdef VERTEX
            varying vec2 textureCoord;

            void main()
            {
#ifdef SHADER_API_GLES3
                float flippedV = 1.0 - gl_MultiTexCoord0.y;
                textureCoord.x = _UnityDisplayTransform[0].x * gl_MultiTexCoord0.x + _UnityDisplayTransform[1].x * flippedV + _UnityDisplayTransform[2].x;
                textureCoord.y = _UnityDisplayTransform[0].y * gl_MultiTexCoord0.x + _UnityDisplayTransform[1].y * flippedV + _UnityDisplayTransform[2].y;
                gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
#endif // SHADER_API_GLES3
            }
#endif // VERTEX

#ifdef FRAGMENT
            varying vec2 textureCoord;
            uniform samplerExternalOES _MainTex;

#if defined(SHADER_API_GLES3) && !defined(UNITY_COLORSPACE_GAMMA)
            float GammaToLinearSpaceExact (float value)
            {
                if (value <= 0.04045F)
                    return value / 12.92F;
                else if (value < 1.0F)
                    return pow((value + 0.055F)/1.055F, 2.4F);
                else
                    return pow(value, 2.2F);
            }

            vec3 GammaToLinearSpace (vec3 sRGB)
            {
                // Approximate version from http://chilliant.blogspot.com.au/2012/08/srgb-approximations-for-hlsl.html?m=1
                return sRGB * (sRGB * (sRGB * 0.305306011F + 0.682171111F) + 0.012522878F);

                // Precise version, useful for debugging, but the pow() function is too slow.
                // return vec3(GammaToLinearSpaceExact(sRGB.r), GammaToLinearSpaceExact(sRGB.g), GammaToLinearSpaceExact(sRGB.b));
            }
#endif // SHADER_API_GLES3 && !UNITY_COLORSPACE_GAMMA

            void main()
            {
#ifdef SHADER_API_GLES3
                vec3 result = texture(_MainTex, textureCoord).xyz;

#ifndef UNITY_COLORSPACE_GAMMA
                result = GammaToLinearSpace(result);
#endif // !UNITY_COLORSPACE_GAMMA
                // 1 から元の RGBA 値を引くことで色を反転する
                gl_FragColor = vec4(1, 1, 1, 1) - vec4(result, 1);
#endif // SHADER_API_GLES3
            }

#endif // FRAGMENT
            ENDGLSL
        }
    }

    FallBack Off
}

ARKitInvertColorマテリアルを作成し、InvertColor.Shaderを選択する。
ARCore InvertColorも同様に作成する。
4C9BC3B9-03C3-44DE-8E1B-6F5B4476FC33_4_5005_c.jpeg

AR CameraのARCameraBackgroundにARKit InvertColorをアタッチする
E6A54015-47EF-4BD8-9E52-64C43107A207.jpeg

デバイスによって背景を切り替える

SelectCameraBackground.csを作成する
B2D8C544-5A8E-4C72-821D-30CE18361563_4_5005_c.jpeg

下記スクリプトを記述する

SelectCameraBackground
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR.ARFoundation;

public class SelectCameraBackground : MonoBehaviour
{
    [SerializeField]
    private Material ARKitCameraBackground;

    [SerializeField]
    private Material ARCoreCameraBackground;

    private ARCameraBackground m_ARCameraBackground;

    void Awake()
    {
        m_ARCameraBackground = GetComponent<ARCameraBackground>();
        //カメラ背景のカスタムマテリアルを有効にする
        m_ARCameraBackground.useCustomMaterial = true;
# if UNITY_IPHONE
        //カスタムマテリアルにARKIt用のマテリアルをセットする
        m_ARCameraBackground.customMaterial = ARKitCameraBackground;
#elif UNITY_ANDROID
        //カスタムマテリアルにARCore用のマテリアルをセットする
        m_ARCameraBackground.customMaterial = ARCoreCameraBackground;
#endif
    }
}

ARCameraにスクリプトをつけ、各マテリアルをアタッチする
75DB5741-5324-454C-B205-7A0F48A1CB1F.jpeg

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1