見出し画像

[VRCHAT]鏡面加工のワールドを作ろう(初級)

今回はVRC備え付けのミラーをちょっと加工して床に貼るだけです。

公式サンプルはここに入ってます

内容としてはVRCMirrorに設定されているシェーダーと設定を置き換えます。

まず、シェーダーとマテリアルを新規制作し以下のコードを記入、マテリアルにカスタムシェーダーの設定を行ってください。

作ったシェーダーはcustom項目のMirrorReflectionに入っているはずです。

Shader "custom/MirrorReflection"
{
    Properties
    {
        _MainTex("Base (RGB)", 2D) = "white" {}
        [HideInInspector] _ReflectionTex0("", 2D) = "white" {}
        [HideInInspector] _ReflectionTex1("", 2D) = "white" {}

        _Transparency("Transparency", Range(0, 1)) = 1.0
        _MaxDistance("Max Distance to Fade Out", Float) = 10.0
    }
    SubShader
    {
        Tags{ "RenderType" = "Transparent" }
        LOD 100

        Pass
        {
            Blend SrcAlpha OneMinusSrcAlpha
            ZWrite Off

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

            sampler2D _MainTex;
            float4 _MainTex_ST;

            sampler2D _ReflectionTex0;
            sampler2D _ReflectionTex1;

            float _Transparency;
            float _MaxDistance;

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

                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 refl : TEXCOORD1;
                float4 pos : SV_POSITION;
                float3 worldPos : TEXCOORD2;

                UNITY_VERTEX_OUTPUT_STEREO
            };

            v2f vert(appdata v)
            {
                v2f o;

                UNITY_SETUP_INSTANCE_ID(v);
                UNITY_INITIALIZE_OUTPUT(v2f, o);
                UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);

                o.pos = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                o.refl = ComputeNonStereoScreenPos(o.pos);

                o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;

                return o;
            }

            half4 frag(v2f i) : SV_Target
            {
                UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i);

                half4 tex = tex2D(_MainTex, i.uv);
                half4 refl = unity_StereoEyeIndex == 0 ? tex2Dproj(_ReflectionTex0, UNITY_PROJ_COORD(i.refl)) : tex2Dproj(_ReflectionTex1, UNITY_PROJ_COORD(i.refl));

                half4 finalColor = tex * refl;

                float3 camPos = _WorldSpaceCameraPos;
                float dist = distance(i.worldPos, camPos);

                float fadeFactor = saturate(1.0 - (dist / _MaxDistance));
                finalColor.a *= _Transparency * fadeFactor;

                return finalColor;
            }
            ENDCG
        }
    }
}

追加内容は全体の透明度の初期値と、オブジェクトとの距離による透過度の変化の2つです。
置いたオブジェクトごとの距離によっても透明度が変化します

その後VRCMirrorの設定部分を変更します。

Reflect Layers はDefaultのみチェックをいれればオブジェクトのみに反映してくれるはずです。

Camera Clear Flags はNothingにしてしまうと表示がバグってしまうみたいなのでSolid Colorあたりにしておきましょう。

その他反射しないものはその都度見つけてチェックを入れてみてください。

他の項目もいじってどのように変わるかを試してみてください。

追加した透過の設定はこんな感じ

Transparency は0.3~0.4
Max Distance to Fade Out は3~4
辺りにしています。

完成すればこのような感じになるはずです。

テクスチャを設定した場合


光沢感のあるワールドを作りたい人向け。unityのReflection Probeという機能とは異り、
VRC独自の高性能なミラーシステムをマップ全体に被せる方法なのでその分パフォーマンスが落ちる場合があります。
あとVRC内の設定により多少見え方が変動します。


今回は平面に鏡を上から重ねるだけの簡単なパターン。

その他の場所などにも適応したい場合は

①そのオブジェクトを複製し、ミラー用のオブジェクトを上から被せる(今回の応用)
②使いたいシェーダーに今回使用したコードを組み込み、コンポーネントも設定する
③Reflection Probeを使う

この辺だろうか。

~おわりに~

unityはシェーダー制作が重要かもしれない。
で、通常シェーダーはコードで書くんだけれどそれだと視覚的に確認しづい。
そこで登場するのがノードと呼ばれる方式。
設定と設定を線でつなぎ視覚的にも確認しやすい。

blenderでもシェーダー制作でほぼ同じ用途で使用される。
そしてジオメトリーノードという機能では線と線をつなげば3Dモデルが作れたり変形できたりする
原始的かもしれないけどコードでも3Dモデルは作れるということ。

とりあえずはノードいいよねというお話でした。おわり

いいなと思ったら応援しよう!