Bagaimana saya bisa meniru efek partikel distorsi Quantum Break?


68

Quantum Break memiliki efek partikel yang fantastis, ini adalah efek distorsi seperti pecahan kaca. Saya ingin tahu bagaimana saya bisa meniru efek ini? Anda dapat melihatnya di bawah, dan video lengkap tersedia di YouTube :

record_2018_02_05_16_34_26_307

record_2018_02_01_22_27_44_971


4
"Pertanyaan ini belum mendapat perhatian yang cukup." ?
Vaillancourt

@AlexandreVaillancourt Saya hanya menyematkan pertanyaan ini untuk lebih banyak tampilan dan menarik perhatian karena saya pikir ini berguna. Saya tidak dapat menemukan alasan yang lebih baik pada alasan karunia. Jika ada masalah, saya akan mengubah alasan saya. Terima kasih
Seyed Morteza Kamali

2
Tujuan pemberian hadiah tidak hanya untuk "menyematkan" pertanyaan; dasar pemikiran Anda agak tidak jujur. Tujuan pemberian hadiah adalah untuk menarik perhatian pada pertanyaan yang membutuhkan jawaban atau untuk menghargai jawaban yang ada, yang tidak Anda lakukan. Sudah ada mekanisme di tempat (HNQ, yang banyak diposkan oleh posting Anda) untuk menghargai topik yang menurut komunitas berguna dan menarik.
Josh

2
Jangan serakah. Anda sudah mendapat cukup banyak tampilan dan suara
Casanova

@JoshPetrie Anda benar, saya minta maaf saya tidak mengulangi keadaan ini. Saya malu sehingga Anda dapat menghapus pertanyaan saya dari fitur tanpa mengembalikan reputasi. Saya hanya melakukan ini karena saya pikir Mungkin saya akan membantu orang lain.
Seyed Morteza Kamali

Jawaban:


101

Partikel Piramida

Bentuk partikel default unity adalah quad. pertama Anda perlu mengubah bentuk ini menjadi piramida dengan menggunakan objek piramida atau mengubah paha depan menjadi piramida dengan shader geometri .

gambar

awd

Pembiasan

Untuk membuat efek pecahan kaca ( Pembiasan ) Anda dapat menggunakan GrabPass { "TextureName" }yang akan mengambil konten layar menjadi tekstur.

GrabPass adalah jenis pass khusus - GrabPass mengambil konten layar tempat objek akan ditarik menjadi tekstur. Tekstur ini dapat digunakan pada lintasan berikutnya untuk melakukan efek berbasis gambar lanjutan.

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
        }
    }
}

Menggunakan mesh normals

Mari kita lanjutkan dengan shader yang menampilkan normals mesh di ruang dunia. Saya menggunakannya karena saya ingin terlihat bentuk tiga dimensi yang rusak.

normals

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
        }
    }
}

Distorsi panas

Untuk membuat distorsi panas, Anda dapat menggunakan flow map

Flow-map adalah tekstur yang menyimpan informasi arah 2d dalam suatu tekstur. Warna piksel menentukan arahnya menggunakan tekstur koordinat-uv sebagai basis. Semakin banyak warna, semakin cepat kecepatan proporsional. Contoh hijau memerintahkannya untuk naik ke kiri, pusatnya netral, dan merah akan turun ke kanan. Ini adalah teknik yang berguna untuk bahan cair seperti air, dan alternatif yang berguna untuk hanya simpul panner.

flow_map

distribusi panas

    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
        }
    }
}

contoh lain dengan menggunakan normal:

memotong

peta normal

smoketile_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

Jika Anda memperhatikan gif pertama Anda, Anda dapat melihat sedikit pemisahan 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
        }
    }
}

Tautan yang Berguna

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

Sumber Di Github


47
Saya ingin tahu, sudahkah Anda mempertimbangkan untuk membuat blog pengembang untuk berbagi teknik seperti ini? Saya akan berlangganan sumber daya seperti itu. :)
DMGregory

7
Saya yang kedua saran! Saya memonitor situs web setiap hari untuk tanggapan Anda, karena pendekatan Anda selalu kreatif, terperinci, namun mudah dipahami. Contoh yang Anda berikan juga sangat membantu.
altskop

4
Mengenai efek split RGB Anda: Saya memakai kacamata dan selalu mengalami efek serupa yang terjadi secara alami yang disebabkan oleh aberasi kromatik, bervariasi dengan jarak mata-ke-layar. Dengan cara yang sama bahwa kacamata 3D menyebabkan ketidakcocokan antara berbagai isyarat tentang seberapa jauh sesuatu itu, efek Anda mengganggu detail yang ditafsirkan oleh otak saya untuk memperkirakan seberapa jauh layar dari mata saya. Ini sangat tidak menyenangkan, sampai mual. Harap jadikan opsional jika Anda memilih untuk menggunakannya!
Aoeuid

1
@Aoeuid FWIW, itu sangat tidak menyenangkan bahkan bagi orang-orang tanpa penglihatan korektif :)
Max

@DMGregory yep: DI belum punya situs, jadi saya membagikan teknik saya di sini. Saya perlu dukungan Anda untuk mengembangkan blog atau situs. Jika Anda mendukung saya, saya akan membantu https://www.patreon.com/SeyedMortezaKamaly
Seyed Morteza Kamali
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.