Ekranda nasıl doğal yağmur damlaları yapabilirim?


11

Ben yağmur efekti ekranda metaballs ve iz ile damla yapmaya çalışıyorum . Shadertoy bir ipucu bulmak ama nasıl uygulandığını anlamadım:

https://www.shadertoy.com/view/ltffzl

ne yazık ki birçok matematik hesaplamaları var ve ben bir gecikme üretir çünkü birlik içinde kullanamazsınız. açıkçası ben dokular kullanmalıyım ama nasıl iz etkisi olabilir ?!

resim açıklamasını buraya girin

benim fikrim düşmek için bir doku ve iz renderer kullanmak ama nasıl metaballs etkisi olabilir? resim açıklamasını buraya girin


Güncelleme

Bu Makaleyle Metaballs Uygulayabilirim

https://github.com/smkplus/RainFX/tree/master

ama iz hakkında bir fikrim yok

Yanıtlar:


11

Etkiyi "suyun nerede olduğunu gösteren bir haritayı hesapla" diye düşünmelisiniz ki bu haritadan normal bir vektör oluşturun ve bunu bir arka plan doku aramasını dengelemek için kullanın.

Örnek shadertoy'nuzun ne yaptığını parçalayarak, buğu çözmenin nerede olduğunu göstermek için bir "iz" hesaplar:

resim açıklamasını buraya girin

Dairesel yağmur damlalarının normallerini hesaplar,

resim açıklamasını buraya girin

ve sahte kırmaya doku aramasını dengelemek için bu normal haritayı kullanır.

Eğer bir gölgelendiricide post-processing ile yollar yapmak istiyorsanız, sadece biraz cebir kullanarak gölgelendirici "iz" şekli oluşturmak gerekir. Örneğin, aşağıdaki işlevde, bir "titrek yol" ve baş ve kuyruk konik üst üste almak için

float trailDrop(vec2 uv, vec2 id, float t) { 
    // wobbly path
    float wobble = 0.5 + 0.5 
        * cos(120.0 * uv.y) 
        * sin(50.0 * uv.y);
    float v = 1.0 - 10.0 * abs(uv.x - 0.5 + 0.2 * wobble);
    // head
    v *= clamp(30.0 * uv.y, 0.0, 1.0);
    v *= clamp( uv.y + 7.0 * t - 0.6, 0.0, 1.0);
    // tail
    v *= clamp(1.0 - uv.y - pow(t, 2.0), 0.0, 1.0);
    return clamp(v * 10.0, 0.0, 1.0);
}

İşte shadertoy'da kaba bir POC - https://www.shadertoy.com/view/XlBfz1 bir dizi yağmur damlası izi oluşturduğunu gösteriyor. Türev çözünürlüğü nedeniyle küçük çözünürlüklerde grenli görünüyor, ancak tam ekran kullanıyorsanız daha iyi görünmelidir.

Düzenleme: Üst üste binen yağmur damlaları ile bir örnek eklendi

resim açıklamasını buraya girin

Okuyucuya bir egzersiz olarak bırakıldı:

1) Küçük yuvarlak damlaları ekleyin. ilham almak StaticDropsiçin orijinal shadertoy örneğinizdeki işleve bakın .

2) Yüksek kaliteli normal hesaplamalar ekleyin. Gibi #define CHEAP_NORMALSorijinal shadertoy örnekte seçenek ima, yerleşik dFdx düşük sadakat yaklaşımı ve manuel (function 3 kez hesaplanması pahasına) türevleri hesaplayarak daha iyi sonuçlar alabilirsiniz.

3) Sütunlar arasındaki boşluğu rastgele seçmek. Sütunları genişletebilir ve ardından uv.x - 0.5 + 0.2 * wobblex eksenine rastgele bir uzaklık eklemek için biti değiştirebilirsiniz . Ayrıca muhtemelen orijinal örnekten bir sayfa daha çıkarmak ve daha az düzgün bir görünüm elde etmek için birkaç farklı boyutta akış katmanını üst üste katmanlamak isteyeceksiniz.



@DMGregory Not edildi. metaball yorumu kaldırılıyor
Jimmy

Patikanın kendisi solma yoluyla bir tampon aracılığıyla yapılabilir (eski dönüş değeri * .95 + yenidispozisyon). Genellikle insanlar düz bir çizgiyi patlatmak için Perlin gürültüsünü kullanır.
Seyed Morteza Kamali

böyle bir şey shadertoy.com/view/4dy3zR Gürültülü bir iz yapmaya çalıştım ama yapamadım
Seyed Morteza Kamali

7

bu efekti aşağıdaki adımları izleyerek yapabilirsiniz:

parçacık

parçacık

RenderTextuer

RenderTexture'ı kullanarak sonucu saklayabilirsiniz. bu shadertoy'daki multipass örneğidir:

https://www.shadertoy.com/view/ltccRl

iñigo quilez: Shadertoy, "Buffer" başına bir tane olmak üzere birden çok geçiş kullanır. Adından da anlaşılacağı gibi, bu geçişler sonuçları bir arabellekte saklar. Bir tampon sadece bir dokudur. Birlik, dokuları da oluşturmanıza izin verecektir.

Parçacıkları RenderTexture'a dönüştürmek için bir kamera oluşturdum:

balta

RenderTexture

GrabPassing

Distorsiyon uygulamak için pas alabilirsiniz

Bu yazıda açıkladım:

Quantum Break'in bozulma parçacık etkisini nasıl çoğaltabilirim?

bulanıklık

Lifetime üzerinde alfa rengini kullanarak basit bulanıklığa sahibiz

alphaovertime

gradiant

daha iyi sonuç almak için basit bulanıklığı kullanmak daha iyidir, ancak bulanıklığı nasıl elde ederiz?

Evrişim matrisi

Görüntü işlemede, bir çekirdek, evrişim matrisi veya maske küçük bir matristir. Bulanıklaştırma, bileme, kabartma, kenar algılama ve daha fazlası için kullanılır. Bu, bir çekirdek ile bir imge arasında bir kıvrım yapılarak gerçekleştirilir.

daha fazla bilgi için lütfen bu bağlantıyı takip edin

Çekirdek

 Shader "Smkgames/Convolution"
    {
        Properties
        {
            _MainTex ("Texture", 2D) = "white" {}
            [Enum(kerEdgeDetectionA,1,kerEdgeDetectionB,2,kerEdgeDetectionC,3,kerSharpen,4,kerBoxBlur,5)]
            _Kernel("Kernel", Float) = 1
        }
        SubShader
        {
            // No culling or depth
            Cull Off ZWrite Off ZTest Always

            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;
                float4 _MainTex_TexelSize;

                float3x3 GetData(int channel, sampler2D tex, float2 uv, float4 size)
                {
                    float3x3 mat;
                    for (int y=-1; y<2; y++)
                    {  
                        for(int x=-1; x<2; x++)
                        {      
                            mat[x+1][y+1]=tex2D(tex, uv + float2(x*size.x, y*size.y))[channel];
                        }              
                    }
                    return mat;
                }
                float3x3 GetMean(float3x3 matr, float3x3 matg, float3x3 matb)
                {
                    float3x3 mat;
                    for (int y=0; y<3; y++)
                    {  
                        for(int x=0; x<3; x++)
                        {
                            mat[x][y] = (matr[x][y] + matg[x][y] + matb[x][y]) / 3.0;
                        }
                    }
                    return mat;
                }

                float Convolve(float3x3 kernel, float3x3 pixels, float denom, float offset)
                {
                    float res = 0.0;
                    for (int y=0; y<3; y++)
                    {  
                        for(int x=0; x<3; x++)
                        {
                            res += kernel[2-x][2-y]*pixels[x][y];
                        }
                    }

                    return  res;
                }

                float _Kernel;

                fixed4 frag (v2f i) : SV_Target
                {


                    float3x3 kerEdgeDetectionA = float3x3 (    0.0,  0,  -1.0,
                                                        1.0,  0,  -1.0,
                                                        0.0,  1.0,  0.0);

                   float3x3 kerEdgeDetectionB = float3x3 (0.0,  1.0,  0.0,
                                                 1.0, -4.0,  1.0,
                                                 0.0,  1.0, 0.0);

                   float3x3 kerEdgeDetectionC = float3x3 (-1.0, -1.0, -1.0,
                                                    -1.0,  8.0, -1.0,
                                                    -1.0, -1.0, -1.0);

                   float3x3 kerSharpen = float3x3 (0.0, -1.0, 0.0,
                                                    -1.0, 5.0, -1.0,
                                                    0.0, -1.0, 0.0);



                    float3x3 kerBoxBlur = (1.0/9.0)*float3x3 (    1.0,  1.0,  1.0,
                                                        1.0,  1.0,  1.0,
                                                        1.0,  1.0,  1.0);




                    float3x3 kernelSelection;
                if(_Kernel == 1){
                kernelSelection = kerEdgeDetectionA;
                }else if(_Kernel == 2){
                kernelSelection = kerEdgeDetectionB;    
                }else if(_Kernel == 3){
                kernelSelection = kerEdgeDetectionC;
                }else if(_Kernel == 4){
                kernelSelection = kerSharpen;   
                }else if(_Kernel == 5){
                kernelSelection = kerBoxBlur;
                }

                float3x3 matr = GetData(0, _MainTex, i.uv, _MainTex_TexelSize);
                float3x3 matg = GetData(1, _MainTex, i.uv, _MainTex_TexelSize);
                float3x3 matb = GetData(2, _MainTex, i.uv, _MainTex_TexelSize);
                float3x3 mata = GetMean(matr, matg, matb);


                // kernel
               float4 gl_FragColor = float4(Convolve(kernelSelection,matr,1.0,0.0),
                                            Convolve(kernelSelection,matg,1.0,0.0),
                                            Convolve(kernelSelection,matb,1.0,0.0),
                                            1.0);

                return gl_FragColor;
            }
            ENDCG
        }
    }
}

Kutu bulanıklığı

Bir kutu bulanıklığı (kutu doğrusal filtresi olarak da bilinir), sonuçtaki görüntüdeki her pikselin giriş görüntüsündeki komşu piksellerin ortalama değerine eşit bir değere sahip olduğu bir uzaysal alan doğrusal filtresidir. Düşük geçişli ("bulanıklaştırma") bir filtredir. 3'e 3 kutu bulanıklığı matris olarak yazılabilir

https://en.wikipedia.org/wiki/Box_blur

1_oos3y1ztoewgsubpdnbvea

Shader "Smkgames/Simple Box Blur"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
        Blend SrcAlpha OneMinusSrcAlpha


        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;
            float4 _MainTex_TexelSize;

            float4 box(sampler2D tex, float2 uv, float4 size)
            {
                float4 c = tex2D(tex, uv + float2(-size.x, size.y)) + tex2D(tex, uv + float2(0, size.y)) + tex2D(tex, uv + float2(size.x, size.y)) +
                            tex2D(tex, uv + float2(-size.x, 0)) + tex2D(tex, uv + float2(0, 0)) + tex2D(tex, uv + float2(size.x, 0)) +
                            tex2D(tex, uv + float2(-size.x, -size.y)) + tex2D(tex, uv + float2(0, -size.y)) + tex2D(tex, uv + float2(size.x, -size.y));

                return c / 9;
            }

            float4 frag (v2f i) : SV_Target
            {
                float4 col = box(_MainTex, i.uv, _MainTex_TexelSize);
                return col;
            }
            ENDCG
        }
    }
}

blurbox

Tekrarlama

önceki kareyi kaydetmek için Rendertexture'ı kullanabilirsiniz. böylece önceki kareyi yakalayıp bulanıklaştırabilirsiniz. bunu tekrarlayarak bulanıklık elde edersiniz.

0fe28c6167db2132d4bb8677fc1b2050 - leandro-Erlich-arjantin

Normal

float4 distortion = tex2D(_MainTex,i.uv);
float3 distortionNormal = UnpackNormal(distortion);

record_2019_03_03_21_35_45_417

Sonuç

Son gölgelendirici:

Shader "Smkgames/BrokenGlass3D"
{
    Properties{
        _MainTex("MainTex",2D) = "white"{}
        _NormalIntensity("NormalIntensity",Float) = 1
        _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 uv : TEXCOORD0;
                float2 grabPos : TEXCOORD1;
                float3 normal :NORMAL;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 grabPos : TEXCOORD1;
                half3 worldNormal :TEXCOORD2;
                float4 vertex : SV_POSITION;

            };
            sampler2D _MainTex;
            float _Intensity,_Alpha;

            v2f vert (appdata v)
            {
                v2f o;
                o.uv = v.uv;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.grabPos = ComputeGrabScreenPos(o.vertex);
                o.worldNormal = UnityObjectToWorldNormal(v.normal);
                return o;
            }

            sampler2D _GrabTexture;
            float _NormalIntensity;

            fixed4 frag (v2f i) : SV_Target
            {
                float4 distortion = tex2D(_MainTex,i.uv);
                float3 distortionNormal = UnpackNormal(distortion);
                distortionNormal.xy *= _NormalIntensity;
                normalize(distortionNormal);
                fixed4 col = tex2Dproj(_GrabTexture, i.grabPos+float4(distortionNormal.rgb,0));
                return col;
            }
            ENDCG
        }
    }
}

ömür boyu alfa renk kullanmadan:

record_2019_03_03_21_48_36_273

ömür boyu alfa renkli kullanarak:

record_2019_03_03_21_48_19_786

Kaynak mevcut:

https://github.com/smkplus/RainDrop

Fazlası var!

ayrıca Ripples yapabilirsiniz

record_2019_03_04_22_10_25_457

kullanışlı bağlantılar

https://80.lv/articles/breakdown-animated-raindrop-material-in-ue4/

https://seblagarde.wordpress.com/2013/01/03/water-drop-2b-dynamic-rain-and-its-effects/


1

Aslında bu yıllar önce bir soru vardı , ama birlik ile ilgili değil (maalesef). Bağlantılı sununun 57. slaytına bakarsanız, tablo tabanlı bir yaklaşımdan bahsederler.

Bir var biraz ilgili ilginç bulabileceği Fizik SE soru. Bağlantılı sorudaki droplet.pdf bağlantısı kesildi, ancak yine de Wayback Machine'de. Birkaç yüzeyden akan suyun matematiğinin bir kısmına gider. Damlacıklar daha önce yağmur damlaları tarafından daha önce kullanılan yollarda seyahat etmeyi tercih eder, örneğin (bkz. S926).

Muhtemelen her bir "yağmur damlası" nın kafalarını ve kuyruklarını modelleyebilir ve biraz zig ve zag yapmasına izin verebilirsiniz. İki uzun yağmur damlası çarpıştığında, bunların daha büyük ve daha hızlı hareket eden bir yağmur damlası haline gelmesini sağlayabileceğinizi düşünüyorum. Su hacmi aynı kalır. Sadece yerçekimi kuvvetleri, cama yapışma ve kohezyon kuvvetleri tarafından hareket ettirilir ve şekillendirilir.

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.