“Duvarların arkasına bakın” efekti nasıl oluşturabilirim?


103

İlahiyat: Orijinal Sin 2 , güzel bir şeffaf görünüme sahiptir. Duvarların arkasına gittiğimde, bir sıçrama maskesi görünecek ve oyunun etrafında hareket ettiğimde değişiyor. Çözünmüş bir gölgelendirici gibi ve metaball etkisi var.

Oyuncular duvarların arkasına geçtiğinde dinamik bir sıçrama maskesi yaratarak bu etkiyi nasıl çoğaltabilirim?

İstediğiniz efekti bu YouTube videosu ile hareket halinde görebilirsiniz .

görüntü


3
Merhaba, ötesinde ek şeyler talep ederek, sorunuza kapsam kayması eklediğiniz görülüyor. Bu aşamada - özellikle ek bir davranış talebinizle kısmen geçersiz kılınan, tam bir cevap alındıktan sonra - gereksinimlerinizi genişletmek yerine yeni bir soru sormakta daha iyi olabilirsiniz. Ödül bu detaylar için olsaydı, yeni bir soru sorarak, sorununuzu açıklayarak, bu soruyu moderatör dikkatinin ödül için geri ödeme talep etmesi için işaretleyerek ve ödülü yeni soru üzerine göndererek iyi yaparsınız.
doppelgreener

2
Bu soruyu kapsamdaki sürünme nedeniyle önceki bir duruma geri aldım. Ödülün eklenmesi ile kapsam değişikliği içeren düzenleme arasındaki zaman göz önüne alındığında, bu soruya farklı cevaplar almak istediğinizi varsayalım, bu yüzden ödülü bırakacağım. @Doppelgreener tarafından önerildiği gibi, yeni gereksinimleriniz için başka bir soru sormanızı öneririm.
Alexandre Vaillancourt

Özür oh @AlexandreVaillancourt ben değiştirmek için zincir questions.thanks sevmiyorum çünkü, ben sadece benim soruya bir seçenek eklemek bilemedim ...
Seyid Murtaza Kamali

Yanıtlar:


163

Maskeleme

Bu efekti yapmak için, bir şablon Tamponu kullanarak nesneleri maskeleyebilirsiniz.

Şablon tamponu, ekrana çizilen her piksel için ilave bir 8bit tam sayı (yani 0-255 arası bir değer) saklamanıza izin veren genel amaçlı bir tampondur. Gölgelendiriciler, ekrandaki piksellerin rengini belirlemek için RGB değerlerini ve derinlik arabelleğine çizilen piksellerin derinliği için z değerlerini hesapladığında, bunlar ayrıca bu piksellerin her biri için isteğe bağlı bir değeri şablon arabelleğine yazabilirler. Bu şablon değerleri daha sonra sorgulanabilir ve piksellerin ekranda nasıl birleştirilmesi gerektiğini belirlemek için sonraki gölgelendirici geçişleriyle karşılaştırılabilir.

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

https://alastaira.wordpress.com/2014/12/27/using-the-stencil-buffer-in-unity-free/

http://www.codingwithunity.com/2016/01/stencil-buffer-shader-for-special.html

görüntü

Maske Stencil:

Stencil 
{
    Ref 1 // ReferenceValue = 1
    Comp NotEqual // Only render pixels whose reference value differs from the value in the buffer.
}

Duvar kalıbı:

Stencil
{
    Ref 1 // ReferenceValue = 1
    Comp Always // Comparison Function - Make the stencil test always pass.
    Pass Replace // Write the reference value into the buffer.
}

Uygulayalım.

bunu maske olarak kullanın:

Shader "Custom/SimpleMask"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _CutOff("CutOff", Range(0,1)) = 0
    }
    SubShader
    {
        LOD 100
        Blend One OneMinusSrcAlpha
        Tags { "Queue" = "Geometry-1" }  // Write to the stencil buffer before drawing any geometry to the screen
        ColorMask 0 // Don't write to any colour channels
        ZWrite Off // Don't write to the Depth buffer
        // Write the value 1 to the stencil buffer
        Stencil
        {
            Ref 1
            Comp Always
            Pass Replace
        }

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

            sampler2D _MainTex;
            float4 _MainTex_ST;
            float _CutOff;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);

                o.uv = TRANSFORM_TEX(v.uv, _MainTex);

                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col = tex2D(_MainTex, i.uv);
                float dissolve = step(col, _CutOff);
                clip(_CutOff-dissolve);
                return float4(1,1,1,1)*dissolve;
            }
            ENDCG
        }
    }
}

bunu duvar olarak kullan:

Shader "Custom/Wall" {
    Properties {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _Glossiness ("Smoothness", Range(0,1)) = 0.5
        _Metallic ("Metallic", Range(0,1)) = 0.0
    }
    SubShader {
        Blend SrcAlpha OneMinusSrcAlpha
        Tags { "RenderType"="Opaque" }
        LOD 200

        Stencil {
            Ref 1
            Comp NotEqual
        }

        CGPROGRAM
        // Physically based Standard lighting model, and enable shadows on all light types
        #pragma surface surf Standard fullforwardshadows

        // Use shader model 3.0 target, to get nicer looking lighting
        #pragma target 3.0

        sampler2D _MainTex;

        struct Input {
            float2 uv_MainTex;
        };

        half _Glossiness;
        half _Metallic;
        fixed4 _Color;

        void surf (Input IN, inout SurfaceOutputStandard o) {
            // Albedo comes from a texture tinted by color
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
            o.Albedo = c.rgb;
            // Metallic and smoothness come from slider variables
            o.Metallic = _Metallic;
            o.Smoothness = _Glossiness;
            o.Alpha = c.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}

Etki Analizi

Prosedürel bir dokuya sahip olmak istiyorsanız , bazı seslere ihtiyacınız var.

görüntüShaderToy'da bu gölgelendiriciyi görebilirsiniz .

Bu etkiyi yapmak için, UV Koordinatlarını kullanmak yerine Polar Koordinatlarını kullanın, sonra onu gürültü dokusuna ayarlayın.

Uv'ler tipik olarak ekrana göre pikseller gibi modaya uygun bir ızgarada düzenlenir (X = genişlik, Y = yükseklik). Ancak kutupsal koordinatlar, x ve ya bitini farklı şekilde kullanır. Biri dairenin merkezinden ne kadar uzakta olduğunu ve diğeri ihtiyaç duyduğunuz şeye bağlı olarak 0-1 aralığında dereceleri belirler.

1600px-sf_radialuvs

Shader "Smkgames/NoisyMask" {
    Properties {
        _MainTex ("MainTex", 2D) = "white" {}
        _Thickness ("Thickness", Range(0, 1)) = 0.25
        _NoiseRadius ("Noise Radius", Range(0, 1)) = 1
        _CircleRadius("Circle Radius", Range(0, 1)) = 0.5
        _Speed("Speed", Float) = 0.5
    }
    SubShader {
        Tags {"Queue"="Transparent" "IgnoreProjector"="true" "RenderType"="Transparent"}
        ZWrite Off 
        Blend SrcAlpha OneMinusSrcAlpha 
        Cull Off

        Pass {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            #pragma target 3.0
            uniform sampler2D _MainTex; uniform float4 _MainTex_ST;
            uniform float _Thickness,_NoiseRadius,_CircleRadius,_Speed;

            struct VertexInput {
                float4 vertex : POSITION;
                float2 texcoord0 : TEXCOORD0;
            };
            struct VertexOutput {
                float4 pos : SV_POSITION;
                float2 uv0 : TEXCOORD0;
                float4 posWorld : TEXCOORD1;

            };
            VertexOutput vert (VertexInput v) {
                VertexOutput o = (VertexOutput)0;
                o.uv0 = v.texcoord0;

                o.pos = UnityObjectToClipPos(v.vertex);
                o.posWorld = mul(unity_ObjectToWorld, v.vertex);
                return o;
            }
            float4 frag(VertexOutput i, float facing : VFACE) : COLOR {

                float2 uv = (i.uv0*2.0+-1.0); // Remapping uv from [0,1] to [-1,1]
                float circleMask = step(length(uv),_NoiseRadius); // Making circle by LENGTH of the vector from the pixel to the center
                float circleMiddle = step(length(uv),_CircleRadius); // Making circle by LENGTH of the vector from the pixel to the center
                float2 polaruv = float2(length(uv),((atan2(uv.g,uv.r)/6.283185)+0.5)); // Making Polar
                polaruv += _Time.y*_Speed/10;
                float4 _MainTex_var = tex2D(_MainTex,TRANSFORM_TEX(polaruv, _MainTex)); // BackGround Noise
                float Noise = (circleMask*step(_MainTex_var.r,_Thickness)); // Masking Background Noise
                float3 finalColor = float3(Noise,Noise,Noise);
                return fixed4(finalColor+circleMiddle,(finalColor+circleMiddle).r);
            }
            ENDCG
        }
    }
    FallBack "Diffuse"
}

Başka bir çözüm ise worley gürültüsü kullanıyor:

2018-01-05_8-16-16

bu gölgelendiriciyi ShaderToy'da görebilirsiniz


metaball

sonra Bu makaleden metaball etkisini ekliyorum : img


Bill yatılı

fazlası var...

Maskenizi döndürmek istiyorsanız, kameranıza bakmak için Bill panosunu kullanabilirsiniz :

 output.pos = mul(UNITY_MATRIX_P, 
              mul(UNITY_MATRIX_MV, float4(0.0, 0.0, 0.0, 1.0))
              + float4(input.vertex.x, input.vertex.y, 0.0, 0.0));

Bu Bill yatılı olan maske:

Shader "Custom/Mask/SimpleMaskBillBoard"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _CutOff("CutOff", Range(0,1)) = 0
        _Radius("Radius", Range(0,1)) = 0.2
        _Speed("speed", Float) = 1
        _ScaleX ("Scale X", Float) = 1.0
        _ScaleY ("Scale Y", Float) = 1.0
    }
    SubShader
    {
        LOD 100
        Blend One OneMinusSrcAlpha
        Tags { "Queue" = "Geometry-1" }  // Write to the stencil buffer before drawing any geometry to the screen
        ColorMask 0 // Don't write to any colour channels
        ZWrite Off // Don't write to the Depth buffer

        // Write the value 1 to the stencil buffer
        Stencil
        {
            Ref 1
            Comp Always
            Pass Replace
        }

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

            sampler2D _MainTex;
            float4 _MainTex_ST;
            float _CutOff;
            float _Speed;
            float _Radius;
            float _ScaleX,_ScaleY;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = mul(UNITY_MATRIX_P, 
                    mul(UNITY_MATRIX_MV, float4(0.0, 0.0, 0.0, 1.0))
                    + float4(v.vertex.x, v.vertex.y, 0.0, 0.0)
                    * float4(_ScaleX, _ScaleY, 1.0, 1.0));

                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col = tex2D(_MainTex, i.uv);
                float dissolve = step(col, _CutOff);
                clip(_CutOff-dissolve);
                return dissolve;
            }
            ENDCG
        }
    }
}

Son sonuç:

2018-01-04_20-18-39

kaynak mevcuttur: https://github.com/smkplus/Divinity-Origin-Sin-2


kullanışlı bağlantılar

Dünyayı çözerek bu etkiyi uygulayan iyi bir öğretici buldum:

image1

Dünyayı çözülmesi

Dünyayı Çözmek Bölüm 2

görüntü

Shader "Custom/DissolveBasedOnViewDistance" {
    Properties{
        _MainTex("Albedo (RGB)", 2D) = "white" {}
        _Center("Dissolve Center", Vector) = (0,0,0,0)
        _Interpolation("Dissolve Interpolation", Range(0,5)) = 0.8
        _DissTexture("Dissolve Texture", 2D) = "white" {}
    }

        SubShader{
        Tags { "RenderType" = "Opaque" }
        LOD 200


            CGPROGRAM

        #pragma surface surf Standard vertex:vert addshadow

        #pragma target 3.0

        struct Input {
            float2 uv_MainTex;
            float2 uv_DissTexture;
            float3 worldPos;
            float viewDist;
        };



        sampler2D _MainTex;
        sampler2D _DissTexture;
        half _Interpolation;
        float4 _Center;


        // Computes world space view direction
        // inline float3 WorldSpaceViewDir( in float4 v )
        // {
        //     return _WorldSpaceCameraPos.xyz - mul(_Object2World, v).xyz;
        // }


        void vert(inout appdata_full v,out Input o){
            UNITY_INITIALIZE_OUTPUT(Input,o);

         half3 viewDirW = WorldSpaceViewDir(v.vertex);
         o.viewDist = length(viewDirW);

        }

        void surf(Input IN, inout SurfaceOutputStandard o) {


            float l = length(_Center - IN.worldPos.xyz);

            clip(saturate(IN.viewDist - l + (tex2D(_DissTexture, IN.uv_DissTexture) * _Interpolation * saturate(IN.viewDist))) - 0.5);

         o.Albedo = tex2D(_MainTex,IN.uv_MainTex);
        }
        ENDCG
        }
        Fallback "Diffuse"
}

Başka bir şablon öğretici:

Left 4 Dead

Şablon Eğitimi


10
Bu, ön duvardan maskelemenin oyuncu karakterinin önünde olduğu bilgisi dahilinde nasıl yapılacağının iyi bir açıklamasıdır, ancak bu gölgelendiriciyi sadece karakter geometrisinin önünde bulunan duvarlara otomatik olarak uygulamanın bir yolu var mı?
kabarık

10
Fluluffy, karakterin duvarların arkasında olduğunu tespit etmek için Raycast'i kullanabilir, ardından Maskeyi etkinleştirebilir.
Seyed Morteza Kamali
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.