В Unity, как я могу сделать сетку «порталом» или вырезом, который показывает базовое изображение

#unity3d

#unity3d

Вопрос:

В Unity я хочу создать эффект, в котором произвольная форма (квадрат или куб) действует как «портал», который показывает изображение. Независимо от того, в какую сторону вращается объект или какова перспектива камеры, изображение «внутри портала» всегда направлено в одном и том же направлении.

Прозрачная плоскость показывает шаблон

На этом изображении у меня есть 3D-плоскость, которая показывает текстуру шахматной доски, как вырез в сцене. Каким бы способом ни был повернут объект plane или установлена камера, изображение внутри портала остается полностью неподвижным. Внутреннее изображение не перемещается и не искажается.

Я хочу иметь возможность делать это с несколькими объектами в сцене. Таким образом, сфера может быть порталом к фиксированному изображению собаки, или куб может быть порталом в мозаичный узор. Было бы полезно даже знать название этого эффекта. Должен ли я писать шейдер для этого?

Комментарии:

1. Вам нужно будет написать шейдер, но это довольно тривиально. Похоже, вы просите о «фоновом» изображении, которое фиксировано относительно экрана, а не «мира». Термин, который вы ищете, — это «Текстура пространства экрана» (или УФ).

Ответ №1:

Это называется шейдером экранного пространства. В то время как большинство шейдеров вычисляют uv-координаты на основе местоположения пикселя в сетке, эти шейдеры используют местоположение на экране. Вот отличная статья о них.

Горячий совет: это обычно используется при рендеринге второй камеры в текстуру рендеринга для создания порталов в 3D-пространства.

Возможно, вам придется поиграть с тайлингом, чтобы получить правильное соотношение сторон вашей текстуры, этот шейдер предполагает, что он совпадает с вашим экраном, то есть 16: 9

 Shader "Ahoy/Screen Space Texture"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
        Tags { "Queue"="Transparent" "RenderType"="Transparent"}

        Pass
        {
            CGPROGRAM

            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

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

            struct v2f
            {
                float4 vertex : SV_POSITION;
                float2 uv : TEXCOORD0;
                float4 screenPos:TEXCOORD1;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                o.screenPos = ComputeScreenPos(o.vertex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                float2 uvScreen = i.screenPos.xy / i.screenPos.w;
                uvScreen = TRANSFORM_TEX(uvScreen,_MainTex);
                return tex2D(_MainTex, uvScreen);
            }
            ENDCG
        }
    }
}