Wie kann ich den Verzerrungsteilcheneffekt von Quantum Break replizieren?


68

Quantum Break hat diesen fantastischen Partikeleffekt, es ist ein Verzerrungseffekt wie Glasscherben. Ich möchte wissen, wie ich diesen Effekt reproduzieren kann. Sie können es unten sehen und ein vollständiges Video ist auf YouTube verfügbar :

record_2018_02_05_16_34_26_307

record_2018_02_01_22_27_44_971


4
"Diese Frage hat nicht genügend Aufmerksamkeit erhalten." ?
Alexandre Vaillancourt

@AlexandreVaillancourt ich Pin gerade diese Frage für weitere Ansichten und Aufmerksamkeit auf sich ziehen , weil ich denke , es ist useful.I nicht besser Grund auf Prämie Gründe finden könnte , wenn es ein Problem ist , werde ich meine reason.thanks ändern
Seyed Morteza Kamali

2
Der Zweck von Kopfgeldern besteht jedoch nicht nur darin, Fragen "festzunageln". Ihre Begründung ist etwas unaufrichtig. Der Zweck von Kopfgeldern besteht darin, die Aufmerksamkeit auf Fragen zu lenken, die beantwortet werden müssen, oder vorhandene Antworten zu belohnen, was bei Ihnen nicht der Fall ist. Es gibt bereits Mechanismen (das HNQ, auf das viele Ihrer Posts zugreifen), um Themen zu belohnen, die die Community für nützlich und interessant hält.
Josh

2
Sei nicht gierig. Sie haben bereits genug Ansichten und Stimmen
Casanova

@JoshPetrie Sie haben Recht Es tut mir leid, dass ich diesen Zustand nicht wiederhole. Ich schäme mich, dass Sie meine Frage aus den Funktionen entfernen können, ohne den Ruf zurückzugeben.
Seyed Morteza Kamali

Antworten:


101

Pyramidenteilchen

Die Standardteilchenform von Unity ist Quad. Zuerst müssen Sie diese Form in Pyramide ändern, indem Sie ein Pyramidenobjekt verwenden oder Quads in Pyramiden mit einem Geometrie-Shader umwandeln .

Bild

awd

Brechung

Um einen Glasscherbeneffekt ( Refraction ) zu erzeugen GrabPass { "TextureName" }, können Sie diesen verwenden , um den Bildschirminhalt in eine Textur zu packen.

GrabPass ist ein spezieller Pass-Typ - er erfasst den Inhalt des Bildschirms, auf dem das Objekt in eine Textur gezeichnet werden soll. Diese Textur kann in nachfolgenden Durchläufen verwendet werden, um erweiterte bildbasierte Effekte zu erzielen.

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

Verwenden von Mesh-Normalen

Fahren wir mit einem Shader fort, der Mesh-Normalen im Weltraum anzeigt . Ich habe es benutzt, weil ich dreidimensionale gebrochene Form suchen wollte.

Normalen

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

Wärmeverformung

Um die Erstellung Wärmeform können Sie verwenden Flusskarte

Eine Flusskarte ist eine Textur, die 2D-Richtungsinformationen in einer Textur speichert. Die Farbe des Pixels bestimmt, in welche Richtung es die UV-Koordinaten-Textur als Basis verwendet. Je mehr Farbe vorhanden ist, desto schneller ist die Proportionalgeschwindigkeit. Beispiel Grün sagt, es soll nach links oben gehen, die Mitte ist neutral und Rot wird nach rechts unten gehen. Es ist eine nützliche Technik für flüssige Materialien wie Wasser und eine nützliche Alternative zu nur einem Panner-Knoten.

flow_map

Wärmeverzug

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

ein weiteres Beispiel mit normal:

ausgeschnitten

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

  }
}

RGB Split

Wenn Sie auf Ihr erstes GIF achten, sehen Sie eine kleine RGB-Trennung.

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

Nützliche Links

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

Quelle auf Github


47
Ich bin neugierig, haben Sie darüber nachgedacht, ein Entwicklerblog einzurichten, um Techniken wie diese zu teilen? Ich würde so eine Ressource abonnieren. :)
DMGregory

7
Ich stimme dem Vorschlag zu! Ich überprüfe die Website jeden Tag auf Ihre Antworten, da Ihr Ansatz immer kreativ, detailliert und dennoch einfach zu verstehen ist. Die Beispiele, die Sie zur Verfügung stellen, sind ebenfalls eine große Hilfe.
altskop

4
In Bezug auf Ihren RGB-Split-Effekt: Ich trage eine Brille und erlebe immer einen natürlich auftretenden ähnlichen Effekt, der durch chromatische Aberration verursacht wird und mit dem Abstand zwischen Auge und Bildschirm variiert. Genauso wie 3D-Brillen zu einer Fehlanpassung zwischen verschiedenen Hinweisen auf die Entfernung führen, beeinflusst Ihr Effekt ein Detail, das mein Gehirn interpretiert, um zu schätzen, wie weit der Bildschirm von meinem Auge entfernt ist. Es ist äußerst unangenehm, bis zu Übelkeit. Bitte machen Sie es optional, wenn Sie es verwenden möchten!
Aoeuid

1
@Aoeuid FWIW, es ist sehr unangenehm, auch für Menschen ohne Sehkorrektur :)
Max

@DMGregory yep: DI haben kein Ort so teile ich meine Techniken hier brauche ich Ihre Unterstützung für die Entwicklung Blog oder site.If Sie mich unterstützen will ich hilfreich sein https://www.patreon.com/SeyedMortezaKamaly
Seyed Morteza Kamali
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.