Как я могу воспроизвести эффект искажения частиц Quantum Break?

68

Quantum Break имеет этот фантастический эффект частиц, это эффект искажения, как разбитое стекло. Я хочу знать, как я могу повторить этот эффект? Вы можете увидеть это ниже, а полное видео доступно на YouTube :

record_2018_02_05_16_34_26_307

record_2018_02_01_22_27_44_971

Сейед Мортеза Камали
источник
4
«Этот вопрос не получил достаточного внимания». ?
Vaillancourt
@AlexandreVaillancourt Я просто прикрепляю этот вопрос для большего количества просмотров и привлекаю внимание, потому что я думаю, что это полезно. Я не мог найти лучшую причину по причинам щедрости Если есть проблема, я изменю свою причину. Спасибо
Сейед Мортеза Камали
2
Однако цель награды не в том, чтобы просто «приколоть» вопросы; Ваше заявленное обоснование несколько неискренне. Цель вознаграждений - привлечь внимание к вопросам, на которые нужны ответы, или вознаградить существующие ответы, а ваши нет. Уже есть механизмы (HNQ, которые затрагивают многие ваши посты) для поощрения тем, которые сообщество считает полезными и интересными.
Джош
2
Не будь жадным. Вы уже получили достаточно просмотров и голосов
Казанова
@JoshPetrie Вы правы. Извините, я не повторяю это состояние. Мне стыдно, так что вы можете удалить мой вопрос из функций, не возвращая репутацию. Я просто делаю это, потому что я подумала, что, возможно, я помогу другим.
Сейед Мортеза Камали

Ответы:

101

Частица пирамиды

Форма частицы Unity по умолчанию является четырехугольной. сначала вам нужно изменить эту форму на пирамиду с помощью объекта пирамиды или превратить квадраты в пирамиды с помощью геометрического шейдера .

образ

полный привод

преломление

Для создания эффекта разбитого стекла ( Refraction ) вы можете использовать его GrabPass { "TextureName" }, чтобы захватить содержимое экрана в текстуру.

GrabPass - это специальный тип прохода - он захватывает содержимое экрана, на котором объект собирается нарисовать в текстуре. Эту текстуру можно использовать в последующих проходах для создания расширенных эффектов на основе изображений.

https://docs.unity3d.com/Manual/SL-GrabPass.html

record_2018_02_03_23_09_06_370

Shader "Smkgames/GlassRefraction"
{
    Properties{
        _Refraction("Refraction",Float) = 0.05
        _Alpha("Alpha",Range(0,1)) = 1
    }
    SubShader
    {
Tags {"Queue"="Transparent" "RenderType"="Transparent"}

        Blend SrcAlpha OneMinusSrcAlpha

        GrabPass
        {
            "_GrabTexture"
        }

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
            };

            struct v2f
            {
                float4 grabPos : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };
            sampler2D _MainTex;
            float _Alpha,_Refraction;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.grabPos = ComputeGrabScreenPos(o.vertex);
                return o;
            }

            sampler2D _GrabTexture;

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col = tex2Dproj(_GrabTexture, i.grabPos+_Refraction);
                return float4(col.rgb,_Alpha);

            }
            ENDCG
        }
    }
}

Использование нормалей сетки

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

нормативы

record_2018_02_05_18_06_09_41

record_2018_02_03_23_19_06_705

    Shader "Smkgames/BrokenGlass3D"
{
    Properties{
        _MainTex("MainTex",2D) = "white"{}
        _Alpha("Alpha",Float) = 1
    }
    SubShader
    {
Tags {"Queue"="Transparent" "RenderType"="Transparent"}
 Blend SrcAlpha OneMinusSrcAlpha 


        GrabPass
        {
            "_GrabTexture"
        }

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 grabPos : TEXCOORD0;
                float3 normal :NORMAL;
            };

            struct v2f
            {
                float4 grabPos : TEXCOORD0;
                float4 vertex : SV_POSITION;
                half3 worldNormal :TEXCOORD1;

            };
            sampler2D _MainTex;
            float _Intensity,_Alpha;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.grabPos = ComputeGrabScreenPos(o.vertex);
                o.worldNormal = UnityObjectToWorldNormal(v.normal);
                return o;
            }

            sampler2D _GrabTexture;

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 c = 0;
                c.rgb = i.worldNormal*0.5+0.5;
                float4 distortion = tex2D(_MainTex,i.grabPos)+_Intensity;
                fixed4 col = tex2Dproj(_GrabTexture, i.grabPos+c.r);
                return float4(col.rgb,_Alpha);
            }
            ENDCG
        }
    }
}

Тепловое искажение

Для создания теплового искажения вы можете использовать карту потоков

Карта потока - это текстура, которая хранит 2-ю информацию о направлении в текстуре. Цвет пикселя определяет, в каком направлении он использует текстуру UV-координат в качестве основы. Чем больше цвета, тем быстрее пропорциональная скорость. Зеленый пример говорит, что он должен идти вверх-влево, центр нейтрален, а красный будет падать вправо. Это полезный метод для жидких материалов, таких как вода, и полезная альтернатива просто узлу паннера.

flow_map

heatdistortion

    Shader "Smkgames/HeatDistortion"
{
    Properties{
        _DistortionMap("DistortionMap",2D) = "white"{}
        _Intensity("Intensity",Float) = 50
        _Mask("Mask",2D) = "white"{}
        _Alpha("Alpha",Range(0,1)) = 1
    }
    SubShader
    {
Tags {"Queue"="Transparent" "RenderType"="Transparent"}

        GrabPass
        {
            "_GrabTexture"
        }

        Blend SrcAlpha OneMinusSrcAlpha

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
            };

            struct v2f
            {
                float4 grabPos : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };
            sampler2D _Mask,_DistortionMap;
            float _Alpha,_Refraction;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.grabPos = ComputeGrabScreenPos(o.vertex);
                return o;
            }

            sampler2D _GrabTexture;
            float _Intensity;

            fixed4 frag (v2f i) : SV_Target
            {
                float mask = tex2D(_Mask,i.grabPos);
                mask = step(mask,0.5);
                //mask = smoothstep(mask,0,0.4);
                float4 distortion = tex2D(_DistortionMap,i.grabPos+_Time.y)+_Intensity;
                fixed4 col = tex2Dproj(_GrabTexture, i.grabPos*distortion);
                return float4(col.rgb,mask*_Alpha);

            }
            ENDCG
        }
    }
}

Другой пример с использованием нормального:

отрезать

нормалей

smotile_normal 1

Shader "Smkgames/HeatDistortion2" {
Properties {
        _CutOut ("CutOut (A)", 2D) = "black" {}
        _BumpMap ("Normalmap", 2D) = "bump" {}
        _BumpAmt ("Distortion", Float) = 10
}

Category {

    Tags { "Queue"="Transparent"  "IgnoreProjector"="True"  "RenderType"="Opaque" }
    Blend SrcAlpha OneMinusSrcAlpha
    Cull Off 
    Lighting Off 
    ZWrite Off 
    Fog { Mode Off}

    SubShader {
        GrabPass {                          
            "_GrabTexture"
        }
        Pass {

CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
#pragma multi_compile_particles
#include "UnityCG.cginc"

struct appdata_t {
    float4 vertex : POSITION;
    float2 texcoord: TEXCOORD0;
};

struct v2f {
    float4 vertex : POSITION;
    float4 uvgrab : TEXCOORD0;
    float2 uvbump : TEXCOORD1;
    float2 uvcutout : TEXCOORD2;
};

sampler2D _BumpMap,_CutOut,_GrabTexture;
float _BumpAmt;
float4 _GrabTexture_TexelSize;
float4 _BumpMap_ST,_CutOut_ST;

v2f vert (appdata_t v)
{
    v2f o;
    o.vertex = UnityObjectToClipPos(v.vertex);
    o.uvgrab.xy = (float2(o.vertex.x, o.vertex.y*-1) + o.vertex.w) * 0.5;
    o.uvgrab.zw = o.vertex.zw;
    o.uvbump = TRANSFORM_TEX( v.texcoord, _BumpMap );
    o.uvcutout = TRANSFORM_TEX( v.texcoord, _CutOut );
    return o;
}



half4 frag( v2f i ) : COLOR
{
    half2 bump = UnpackNormal(tex2D( _BumpMap, i.uvbump )).rg;
    float2 offset = bump * _BumpAmt * _GrabTexture_TexelSize.xy;
    i.uvgrab.xy = offset * i.uvgrab.z + i.uvgrab.xy;

    half4 col = tex2Dproj( _GrabTexture, UNITY_PROJ_COORD(i.uvgrab));
    fixed4 cut = tex2D(_CutOut, i.uvcutout);
    fixed4 emission = col;
    emission.a = (cut.a);
    return emission;
}
ENDCG
        }
    }

  }
}

RGB Split

Если вы обратите внимание на свой первый GIF, вы можете увидеть небольшое разделение RGB.

u_rgb_seperation_ar

Shader "Hidden/RgbSplit"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _NoiseTex1 ("Noise Texture A", 2D) = "white" {}
        _NoiseTex2 ("Noise Texture B", 2D) = "white" {}
    }
    SubShader
    {

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

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

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

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                return o;
            }

            sampler2D _MainTex,_NoiseTex1,_NoiseTex2;
            float3 colorSplit(float2 uv, float2 s)
{
    float3 color;
    color.r = tex2D(_MainTex, uv - s).r;
    color.g = tex2D(_MainTex, uv    ).g;
    color.b = tex2D(_MainTex, uv + s).b;
    return color;
}

float2 interlace(float2 uv, float s)
{
    uv.x += s * (4.0 * frac((uv.y) / 2.0) - 1.0);
    return uv;
}

    fixed4 frag (v2f i) : SV_Target
    {

    float t = _Time.y;

    float s = tex2D(_NoiseTex1, float2(t * 0.2, 0.5)).r;

    i.uv = interlace(i.uv, s * 0.005);
    float r = tex2D(_NoiseTex2, float2(t, 0.0)).x;

    float3 color = colorSplit(i.uv, float2(s * 0.02, 0.0));

    return float4(color, 1.0);

            }
            ENDCG
        }
    }
}

Полезные ссылки

https://www.fxguide.com/featured/time-for-destruction-the-tech-of-quantum-break/

Источник на Github

Сейед Мортеза Камали
источник
47
Мне любопытно, вы рассматривали возможность создания блога для разработчиков, чтобы делиться подобными методами? Я бы подписался на такой ресурс. :)
DMGregory
7
Я второе предложение! Я отслеживаю ваши ответы каждый день, так как ваш подход всегда креативный, подробный и в то же время простой для понимания. Приведенные вами примеры также очень помогают.
altskop
4
Что касается вашего эффекта расщепления RGB: я ношу очки и всегда испытываю естественный подобный эффект, вызванный хроматической аберрацией, зависящей от расстояния между глазами. Точно так же, как 3D-очки вызывают несоответствие между различными признаками того, насколько далеко что-то находится, ваш эффект мешает детализации, которую мой мозг интерпретирует, чтобы оценить, насколько далеко экран от моего глаза. Это крайне неприятно, до тошноты. Пожалуйста, сделайте это необязательным, если вы решите использовать его!
Aoeuid
1
@ Aoeuid FWIW, это очень неприятно даже для людей без корректирующего зрения :)
Макс
@DMGregory yep: У меня нет сайта, поэтому я делюсь своими методами здесь, мне нужна ваша поддержка в разработке блога или сайта. Если вы поддержите меня, я буду полезен https://www.patreon.com/SeyedMortezaKamaly
Seyed Morteza Kamali