Comment reproduire l'effet de particule de distorsion de Quantum Break?


67

Quantum Break a cet effet particule fantastique, c'est un effet de distorsion semblable à du verre brisé. Je veux savoir comment je peux reproduire cet effet? Vous pouvez le voir ci-dessous, et une vidéo complète est disponible sur YouTube :

record_2018_02_05_16_34_26_307

record_2018_02_01_22_27_44_971


4
"Cette question n'a pas reçu assez d'attention." ?
Vaillancourt

@AlexandreVaillancourt Je viens d'épingler cette question pour attirer l'attention, car je pense que c'est utile. Je ne pourrais pas trouver de meilleure raison pour des raisons de prime. S'il y a un problème, je changerai de raison.Merci
Seyed Morteza Kamali le

2
Le but des primes n'est pas vraiment de "poser" des questions; votre raisonnement est un peu hypocrite. Le but des primes est d'attirer l'attention sur des questions qui nécessitent des réponses ou de récompenser des réponses existantes, ce que la vôtre ne fait pas. Il existe déjà des mécanismes en place (le HNQ, sur lequel nombre de vos publications ont été publiées) pour récompenser les sujets jugés utiles et intéressants par la communauté.
Josh

2
Ne soyez pas gourmand. Vous avez déjà obtenu suffisamment de vues et de votes
Casanova

@JoshPetrie tu as raison, je suis désolé, je ne répète pas cet état.J'ai honte afin que tu puisses supprimer ma question des fonctions sans me rendre réputation.Je le fais simplement parce que je pensais que je pourrais peut-être aider les autres.
Seyed Morteza Kamali

Réponses:


100

Particule de pyramide

La forme de la particule par défaut de l'unité est quadruple vous devez d’abord changer cette forme en pyramide en utilisant un objet pyramidal ou transformer les quadruples en pyramides avec un shader géométrique .

image

ahd

Réfraction

Pour créer un effet de verre brisé ( réfraction ), vous pouvez utiliser GrabPass { "TextureName" }le contenu de l’écran pour en extraire une texture.

GrabPass est un type de passe spécial. Il saisit le contenu de l'écran où l'objet est sur le point d'être dessiné dans une texture. Cette texture peut être utilisée dans les passes suivantes pour créer des effets d'image avancés.

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

Utiliser les normales de maillage

Continuons avec un shader qui affiche les normales de maillage dans l'espace mondial. Je l'ai utilisé parce que je voulais regarder une forme brisée en trois dimensions.

normales

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

Distorsion thermique

Pour créer une déformation thermique, vous pouvez utiliser Flow Map

Une carte de flux est une texture qui stocke des informations directionnelles 2D dans une texture. La couleur du pixel détermine la direction dans laquelle elle utilise la texture de coordonnées uv comme base. Plus il y a de couleur, plus la vitesse proportionnelle est rapide. L'exemple vert indique qu'il doit aller en haut à gauche, le centre est neutre et le rouge va en bas à droite. C'est une technique utile pour les matériaux liquides comme l'eau, et une alternative utile à un simple nœud de panoramique.

flow_map

chaleur distorsion

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

un autre exemple en utilisant normal:

coupé

normalmap

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

  }
}

Split RVB

Si vous faites attention à votre premier gif, vous pouvez voir peu de fractionnement RVB.

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

Liens utiles

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

Source sur Github


47
Je suis curieux, avez-vous envisagé de créer un blog de développeurs pour partager des techniques comme celles-ci? Je m'abonnerais à une ressource comme celle-là. :)
DMGregory

7
Je seconde la suggestion! Je surveille quotidiennement vos réponses sur le site Web, car votre approche est toujours créative, détaillée et pourtant simple à comprendre. Les exemples que vous fournissez sont également d'une grande aide.
Altskop

4
En ce qui concerne votre effet de scission RVB: Je porte des lunettes et je ressens toujours un effet similaire naturel provoqué par une aberration chromatique, variant avec la distance de l’écran à l’écran. De la même manière que les lunettes 3D provoquent une discordance entre divers indices de la distance, votre effet interfère avec un détail que mon cerveau interprète pour estimer à quelle distance de l'écran se trouve mon œil. C'est extrêmement désagréable, au point de provoquer la nausée. S'il vous plaît le rendre facultatif si vous choisissez de l'utiliser!
Aoeuid

1
@Aoeuid FWIW, c'est extrêmement désagréable même pour les personnes sans vision correctrice :)
Max

@DMGregory yep: DI pas un site donc je partage mes techniques ici j'ai besoin de votre soutien pour le développement de blog ou site.If vous me soutenez , je serai utile https://www.patreon.com/SeyedMortezaKamaly
Seyed Morteza Kamali
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.