ฉันจะจำลองเอฟเฟกต์อนุภาคการบิดเบือนของ Quantum Break ได้อย่างไร


68

Quantum Break มีเอฟเฟกต์ของอนุภาคที่น่าอัศจรรย์นี้มันเป็นเอฟเฟกต์การบิดเบือนเหมือนกระจกแตก ฉันต้องการทราบว่าฉันสามารถจำลองลักษณะพิเศษนี้ได้อย่างไร คุณสามารถดูได้ด้านล่างและวิดีโอเต็มมีอยู่ใน YouTube :

record_2018_02_05_16_34_26_307

record_2018_02_01_22_27_44_971


4
"คำถามนี้ยังไม่ได้รับความสนใจเพียงพอ" ?
Alexandre Vaillancourt

@AlexandreVaillancourt ฉันเพิ่งตรึงคำถามนี้สำหรับมุมมองเพิ่มเติมและดึงความสนใจเพราะฉันคิดว่ามันมีประโยชน์ฉันไม่สามารถหาเหตุผลที่ดีกว่าด้วยเหตุผลความโปรดปรานหากมีปัญหาฉันจะเปลี่ยนเหตุผลของฉันขอบคุณ
Seyed Morteza Kamali

2
จุดประสงค์ของการได้รับรางวัลไม่ใช่เพียงเพื่อ "ตรึง" คำถามเท่านั้น เหตุผลที่ระบุไว้ของคุณค่อนข้างไม่ตรงไปตรงมา จุดประสงค์ของการจ่ายเงินรางวัลคือการดึงความสนใจไปยังคำถามที่ต้องการคำตอบหรือให้รางวัลคำตอบที่มีอยู่ซึ่งคุณไม่ได้ทำ มีกลไกอยู่แล้ว (HNQ ซึ่งมีการโพสต์จำนวนมากของคุณ) เพื่อให้รางวัลแก่หัวข้อที่ชุมชนรู้สึกว่ามีประโยชน์และน่าสนใจ
Josh

2
อย่าโลภ คุณมีจำนวนการดูและโหวตเพียงพอแล้ว
Casanova

@JoshPetrie คุณถูกฉันขอโทษฉันไม่ทำซ้ำสถานะนี้ฉันละอายใจเพื่อให้คุณสามารถลบคำถามของฉันออกจากคุณสมบัติโดยไม่กลับชื่อเสียงฉันทำเช่นนี้เพราะฉันคิดว่าบางทีฉันอาจจะช่วยคนอื่น
Seyed Morteza Kamali

คำตอบ:


101

อนุภาคพีระมิด

รูปร่างของอนุภาคเริ่มต้นที่เป็นเอกภาพเป็นรูปสี่เหลี่ยม ครั้งแรกที่คุณจะต้องเปลี่ยนรูปทรงปิรามิดนี้โดยใช้วัตถุพีระมิดหรือเปลี่ยนล่ามไปปิรามิดกับ Shader

ภาพ

AWD

การหักเห

ในการสร้างเอฟเฟกต์กระจกแตก ( หักเห ) คุณสามารถใช้ 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
        }
    }
}

การใช้ตาข่ายแบบปกติ

ลองดำเนินการกับ shader ที่แสดงบรรทัดฐานตาข่ายในพื้นที่โลก ฉันใช้มันเพราะฉันต้องการดูรูปร่างที่แตกสามมิติ

ภาวะปกติ

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

การบิดเบือนความร้อน

เพื่อสร้างการบิดเบือนความร้อนคุณสามารถใช้แผนที่การไหล

Flow-map เป็นพื้นผิวที่เก็บข้อมูลทิศทาง 2d ในพื้นผิว สีของพิกเซลเป็นตัวกำหนดทิศทางของการใช้พื้นผิวยูวีพิกัดเป็นฐาน ยิ่งมีสีมากเท่าไหร่ความเร็วของสัดส่วนก็จะยิ่งมากขึ้นเท่านั้น ตัวอย่างสีเขียวบอกให้เลื่อนไปทางซ้ายกึ่งกลางเป็นกลางและสีแดงจะลงไปทางขวา มันเป็นเทคนิคที่มีประโยชน์สำหรับวัสดุของเหลวเช่นน้ำและเป็นทางเลือกที่มีประโยชน์เพียงแค่โหนด panner

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

ตัวอย่างอื่นโดยใช้ปกติ:

ตัดออก

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

หากคุณให้ความสนใจกับ 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 ของคุณ: ฉันสวมแว่นตาและมักจะได้รับผลกระทบที่คล้ายกันที่เกิดขึ้นตามธรรมชาติซึ่งเกิดจากความผิดเพี้ยนของสีซึ่งแตกต่างกันไปตามระยะสายตา ในทำนองเดียวกับที่แว่นตา 3 มิติทำให้เกิดความไม่ตรงกันระหว่างสิ่งต่าง ๆ ที่อยู่ไกลออกไปเอฟเฟกต์ของคุณรบกวนรายละเอียดที่สมองของฉันตีความเพื่อประเมินว่าหน้าจอมาจากตาของฉันมากแค่ไหน มันไม่เป็นที่พอใจอย่างยิ่งจนถึงจุดที่ก่อความรำคาญ กรุณาทำให้มันเป็นตัวเลือกหากคุณเลือกที่จะใช้!
Aoeuid

1
@ Aoeuid FWIW มันไม่เป็นที่น่าพอใจอย่างมากแม้แต่กับคนที่ไม่มีการมองเห็นที่ถูกต้อง :)
สูงสุด

@DMGregory yep: DI ยังไม่มีเว็บไซต์ดังนั้นฉันแบ่งปันเทคนิคของฉันที่นี่ฉันต้องการการสนับสนุนของคุณในการพัฒนาบล็อกหรือเว็บไซต์หากคุณสนับสนุนฉันฉันจะเป็นประโยชน์https://www.patreon.com/SeyedMortezaKamaly
Seyed Morteza Kamali
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.