Как я могу воспроизвести эффект искажения частиц 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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.