Làm cách nào tôi có thể sao chép hiệu ứng hạt méo của Quantum Break?


68

Quantum Break có hiệu ứng hạt tuyệt vời này, đó là hiệu ứng méo như thủy tinh vỡ. Tôi muốn biết làm thế nào tôi có thể tái tạo hiệu ứng này? Bạn có thể xem video bên dưới và một video đầy đủ có sẵn trên YouTube :

hồ sơ_2018_02_05_16_34_26_307

hồ sơ_2018_02_01_22_27_44_971


4
"Câu hỏi này đã không nhận được đủ sự quan tâm." ?
Alexandre Vaillancourt

@AlexandreVaillancourt Tôi chỉ cần đặt câu hỏi này để có nhiều lượt xem hơn và thu hút sự chú ý bởi vì tôi nghĩ nó hữu ích. Tôi không thể tìm thấy lý do tốt hơn về lý do tiền thưởng Nếu có vấn đề gì tôi sẽ thay đổi lý do của mình. Cảm ơn
Seyed Morteza Kamali

2
Mục đích của tiền thưởng thực sự không chỉ là "ghim" câu hỏi; lý do đã nêu của bạn là hơi không lịch sự. Mục đích của tiền thưởng là thu hút sự chú ý vào các câu hỏi cần câu trả lời hoặc thưởng cho các câu trả lời hiện có, điều mà bạn không làm. Hiện đã có các cơ chế (HNQ, mà nhiều bài đăng của bạn đạt được) để thưởng cho các chủ đề mà cộng đồng cảm thấy hữu ích và thú vị.
Josh

2
Đừng tham lam. Bạn đã có đủ lượt xem và lượt bình chọn
Casanova

@JoshPetrie bạn nói đúng Tôi xin lỗi tôi không lặp lại trạng thái này. Tôi xấu hổ vì vậy bạn có thể xóa câu hỏi của tôi khỏi các tính năng mà không trả lại danh tiếng. Tôi chỉ làm điều này vì tôi nghĩ Có lẽ tôi sẽ giúp đỡ người khác.
Seyed Morteza Kamali

Câu trả lời:


101

Hạt kim tự tháp

Hình dạng hạt mặc định của Unity là quad. trước tiên, bạn cần thay đổi hình dạng này thành hình chóp bằng cách sử dụng đối tượng hình chóp hoặc biến hình tứ giác thành hình chóp bằng một shader hình học .

Hình ảnh, tưởng tượng

ôi

Khúc xạ

Để tạo hiệu ứng kính vỡ ( Khúc xạ ), bạn có thể sử dụng GrabPass { "TextureName" }sẽ lấy nội dung màn hình thành một kết cấu.

GrabPass là một loại pass đặc biệt - nó lấy nội dung của màn hình nơi đối tượng sắp được vẽ thành một kết cấu. Kết cấu này có thể được sử dụng trong các lần truyền tiếp theo để thực hiện các hiệu ứng dựa trên hình ảnh nâng cao.

https://docs.unity3d.com/Manual/SL-GrabPass.html

bản ghi_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
        }
    }
}

Sử dụng quy tắc lưới

Chúng ta hãy tiến hành với một shader hiển thị các quy tắc lưới trong không gian thế giới. Tôi đã sử dụng nó bởi vì tôi muốn nhìn hình dạng ba chiều bị phá vỡ.

thông thường

hồ sơ_2018_02_05_18_06_09_41

hồ sơ_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
        }
    }
}

Biến dạng nhiệt

Để tạo méo nhiệt, bạn có thể sử dụng sơ đồ dòng chảy

Sơ đồ dòng là một kết cấu lưu trữ thông tin định hướng 2d trong một kết cấu. Màu của pixel xác định hướng đi của nó bằng cách sử dụng kết cấu tọa độ uv làm cơ sở. Càng nhiều màu thì tốc độ tỷ lệ càng nhanh. Ví dụ màu xanh lá cây bảo nó đi lên bên trái, trung tâm là trung tính và màu đỏ sẽ đi xuống bên phải. Đây là một kỹ thuật hữu ích cho các vật liệu lỏng như nước và là một thay thế hữu ích cho chỉ một nút panner.

Flow_map

say nắng

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

một ví dụ khác bằng cách sử dụng bình thường:

cắt ra

bình thường

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

  }
}

Chia RGB

Nếu bạn chú ý đến gif đầu tiên của bạn, bạn có thể thấy chia nhỏ 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
        }
    }
}

Liên kết hữu ích

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

Nguồn trên Github


47
Tôi tò mò, bạn đã xem xét việc thiết lập một blog nhà phát triển để chia sẻ các kỹ thuật như thế này chưa? Tôi đã đăng ký một tài nguyên như thế. :)
DMGregory

7
Tôi thứ hai gợi ý! Tôi theo dõi trang web mỗi ngày để biết phản hồi của bạn, vì cách tiếp cận của bạn luôn sáng tạo, chi tiết và dễ hiểu. Các ví dụ bạn cung cấp cũng rất hữu ích.
altskop

4
Về hiệu ứng tách RGB của bạn: Tôi đeo kính và luôn gặp hiệu ứng tương tự xảy ra tự nhiên do quang sai màu, thay đổi theo khoảng cách từ mắt đến màn hình. Theo cùng một cách mà kính 3D gây ra sự không khớp giữa các tín hiệu khác nhau về khoảng cách của một thứ gì đó, hiệu ứng của bạn can thiệp vào một chi tiết mà não tôi diễn giải để ước tính màn hình cách mắt tôi bao xa. Nó cực kỳ khó chịu, đến mức buồn nôn. Hãy làm cho nó tùy chọn nếu bạn chọn sử dụng nó!
Aoeuid

1
@Aoeuid FWIW, nó cực kỳ khó chịu ngay cả với những người không có tầm nhìn chính xác :)
Tối đa

@DMGregory yep: DI chưa có trang web nên tôi chia sẻ các kỹ thuật của mình ở đây Tôi cần sự hỗ trợ của bạn để phát triển blog hoặc trang web. Nếu bạn hỗ trợ tôi, tôi sẽ rất hữu ích https://www.patreon.com/SeyedMortezaKamaly
Seyed Morteza Kamali
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.