Modeller için animasyonlu dokular; Gölgelendirici nasıl yazılır?


9

Roket Ligi'ni izliyordu ve animasyonlu çıkartmalar ve tekerlekler olduğunu fark ediyordu.

görüntü.

Yukarıdaki görüntüdeki etkilere benzer bir şey uygulamak istiyorum.

Tekerlek efektini yapmak için Birlik Gölgelendiricisi yazmaya nasıl başlayabilirim?

Shaders hakkında çok şey bilmiyorum, ancak animasyon efektini yapmak için standart Unity Shader'ı düzenleyebilir miyim?


3
Gölgelendiriciler, kayan bir doku kadar basit bir şey için bile, burada kesinlikle çözümdür. Unity, _Timekaydırma efektini kir elde etmek için (köşe) gölgelendiricideki doku koordinatlarınıza ekleyebileceğiniz yerleşik bir değişkene sahiptir . Altıgen etkisi de oldukça basit olacaktır. Sorunuzu yalnızca bir etkiyi vurgulayacak şekilde düzenlerseniz ve "Bunu bir Unity gölgeleyicisinde nasıl uygulayacağım" diye sorarsanız, muhtemelen size yardımcı olabiliriz. Gölgelendiricinin ışıklandırmaya / gölgelemeye yanıt vermesi gerekip gerekmediğini belirttiğinizden emin olun, çünkü bunun nasıl yazılacağı üzerinde etkisi vardır.
DMGregory

Bilgi için teşekkürler. Sorumu değiştirdim, bu biraz daha iyi mi? Işıklandırma ve gölgeleme hakkında gerçekten bir şey bilmiyorum, bu yüzden Shader'ları daha iyi anlayana kadar bunu dışarıda bıraktım. Sanırım onları isterdim, ama standart gölgelendiriciden parçaları kopyalayabilirim değil mi?
JacketPotatoeFan

3
Bu gece biraz sonra bir cevapta genişleyeceğim (yine de cevap vermek isterse beni dövmekten çekinmeyin!) - ama genellikle aydınlatmayı "Yüzey Gölgelendirici" olarak kullanan bir Birlik gölgelendiricisi yazarsınız ancak ışığa ihtiyaç duymayan bir "Işıksız Gölgelendirici" olarak yazmak daha kolaydır. Bana bu jantlar yanmıyor gibi görünüyor (kenardaki hafif gölgeler SSAO'ya benziyor), bu yüzden yeni başlayanlar için aydınlatmayı fotoğrafın dışında bırakardım. Açıklığa kavuşturabilir misiniz: tam olarak burada gösterilen geometrik deseni mi yoksa keyfi dokuları dışarı doğru kaydırma ve bunları gökkuşağı rengini mi almak istiyorsunuz?
DMGregory

Çok teşekkürler, beni başlatmak için verdiğiniz bilgiler harika olurdu. Gölgelendiriciler yazabilen insanlara gerçekten hayranım, Unity Shaders için birkaç makaleye baktım ve evet, çok kafa karıştırıcı. Ben sadece dokular (veya doku uvs?) Kaydırma yeterince iyi ve renklendirme yeteneği ile düşünüyorum.
JacketPotatoeFan

Yanıtlar:


13

Nasıl bir araya geldiğini görebilmeniz için bunu birkaç katman halinde oluşturacağım.

Create --> Shader --> UnlitVarlıklar menüsünde veya Proje penceresindeki sağ tıklama bağlam menüsünü seçerek Unity'de yeni bir gölgelendirici oluşturarak başlayın .

Üst blokta _ScrollSpeeds, dokunun her yönde ne kadar hızlı hareket ettiğini kontrol etmek için bir parametre ekleyeceğiz :

Properties
{
    _MainTex ("Texture", 2D) = "white" {}
    _ScrollSpeeds ("Scroll Speeds", vector) = (-5, -20, 0, 0)
}

Bu, malzeme denetçisinde "Scroll Speeds" (Scroll Speeds) adıyla yeni bir 4 bileşenli float özelliğini ortaya çıkarır ( betiğe bir publicveya Serializeddeğişken eklemeye benzer MonoBehaviour)

Ardından o.uv, varsayılan gölgelendiriciye yalnızca iki satır ekleyerek doku değişkenlerini ( ) kaydırmak için Vertex gölgelendiricisinde bu değişkeni kullanacağız :

sampler2D _MainTex;
float4 _MainTex_ST;
// Declare our new parameter here so it's visible to the CG shader
float4 _ScrollSpeeds;

v2f vert (appdata v)
{
    v2f o;
    o.vertex = UnityObjectToClipPos(v.vertex);
    o.uv = TRANSFORM_TEX(v.uv, _MainTex);

    // Shift the uvs over time.
    o.uv += _ScrollSpeeds * _Time.x;

    UNITY_TRANSFER_FOG(o,o.vertex);
    return o;
}

Bir dörtlü tokatlayın ( Kenney tarafından güzel bir ücretsiz zürafa dokusu ile ) ve şunları elde edersiniz:

Üzerinde tekrarlayan bir zürafa olan dörtlü.

Bir halkada dokunun dışa doğru kaymasını sağlamak için, örümcek ağı gibi alt bölümlere ayrılmış bir kafes kullanabiliriz, uv v koordinatı merkezden dışarı doğru artar. Ancak bu, kendi başına testere şekilli bazı eserler verecektir. Bunun yerine, parça başına UV'leri nasıl hesaplayabileceğimizi göstereceğim.

Bu, hem trig & length işlemleri (temel matematikten daha pahalı) hem de parça başına texcoordları hesaplarken donanımdaki doku verilerini tahmin etmek ve önbelleğe almak kadar etkili olmadığından, sadece enterpolasyona kıyasla biraz daha maliyetlidir. köşeler arasında. Ancak bunun gibi küçük bir özel efekt için aşırı değil.

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

    // Shift the UVs so (0, 0) is in the middle of the quad.
    o.uv = v.uv - 0.5f;

    UNITY_TRANSFER_FOG(o,o.vertex);
    return o;
}

fixed4 frag (v2f i) : SV_Target
{
    // Convert our texture coordinates to polar form:
    float2 polar = float2(
           atan2(i.uv.y, i.uv.x)/(2.0f * 3.141592653589f), // angle
           length(i.uv)                                    // radius
        );

    // Apply texture scale
    polar *= _MainTex_ST.xy;

    // Scroll the texture over time.
    polar += _ScrollSpeeds.xy * _Time.x;

    // Sample using the polar coordinates, instead of the original uvs.
    // Here I multiply by MainTex
    fixed4 col = tex2D(_MainTex, polar);

    // apply fog
    UNITY_APPLY_FOG(i.fogCoord, col);
    return col;
}

Bu bize böyle bir şey verir (burada malzemedeki döşeme parametrelerini arttırdım, böylece ne olduğunu daha net - çemberin sadece tek bir tekrarını sarmak bozuk ve garip görünüyor)

Dörtlü merkezden dışa doğru yayılan zürafaları döşemek

Son olarak, dokuyu kayan bir gradyanla renklendirmek için, degradeyi ikinci bir doku olarak ekleyebilir ve birlikte çoğaltabiliriz.

İlk önce yeni texture parametresini en üste ekliyoruz:

Properties
{
    _MainTex ("Texture", 2D) = "white" {}
    _TintTex("Tint Texture", 2D) = "white" {}
    _ScrollSpeeds ("Scroll Speeds", vector) = (-5.0, -20.0, 0, 0)
}

Ve CGPROGRAM bloğumuzda ilan edin, böylece CG gölgelendirici görebilsin:

sampler2D _MainTex;
float4 _MainTex_ST;

// Declare our second texture sampler and its Scale/Translate values
sampler2D _TintTex;
float4 _TintTex_ST;

float4 _ScrollSpeeds;

Ardından, her iki dokuyu kullanmak için parça gölgelendiricimizi güncelleyin:

fixed4 frag(v2f i) : SV_Target
{
    float2 polar = float2(
           atan2(i.uv.y, i.uv.x) / (2.0f * 3.141592653589f), // angle
           length(i.uv)                                    // radius
        );

    // Copy the polar coordinates before we scale & shift them,
    // so we can scale & shift the tint texture independently.
    float2 tintUVs = polar * _TintTex_ST.xy;
    tintUVs += _ScrollSpeeds.zw * _Time.x;

    polar *= _MainTex_ST.xy;
    polar += _ScrollSpeeds.xy * _Time.x;

    fixed4 col = tex2D(_MainTex, polar);
    // Tint the colour by our second texture.
    col *= tex2D(_TintTex, tintUVs);

    UNITY_APPLY_FOG(i.fogCoord, col);
    return col;
}

Ve şimdi zürafamız gerçekten trippy oluyor:

çok uzak adamım ...

Biraz daha sanatsal doku seçimi ve kaydırma oranları ile, bu soruda gösterilene oldukça benzer bir etki yaratabilir.


Yukarıda gösterdiğim sürümle iki küçük eser görebilirsiniz:

  • Dairenin merkezine yakın yüzler gergin / sıska / sivri hale gelir, daha sonra dışarı doğru hareket ettikçe ezilir / genişler.

    Bu bozulma, çevre çevresinde sabit sayıda yüzümüz olduğu için olur, ancak yükseklikleri aynı kalırken, yayıldıkları çevre yarıçap arttıkça genişler.

    Logaritmik bir eğri izlemek için doku örneğinin dikey bileşenini yeniden düzenleyerek bunu düzeltebiliriz, bu nedenle yarıçap arttıkça doku tekrarları daha da ayrı ve merkeze daha yakın olur. (Aslında, bu bize daha küçük ve daha küçük zürafaların sonsuz bir gerilemesini veriyor ...)

  • Dörtlü sol ortada bir veya iki bulanık pikselden oluşan bir satır var.

    Bunun nedeni, GPU'nun hangi filtrelemenin kullanılacağını anlamak için iki bitişik doku örneği koordinatına bakmasıdır. Numuneler birbirine yakın olduğunda, dokunun büyük / kapalı olarak görüntülendiğini ve en ayrıntılı mip seviyesini gösterir. Örnekler birbirinden ayrıldığında, dokuyu küçük bir zumda veya çok uzakta göstermemiz gerektiğini tahmin ediyor ve ışıltılı yumuşatma yapaylıkları elde etmememiz için daha küçük / bulanık bir mipmap'tan örnekler.

    Sorun burada, kutupsal koordinatlarda -180 ila 180 derece arasında sarmal noktadayız. Dolayısıyla, sayısal koordinatları onları birbirinden uzak görünmelerine neden olsa bile, aslında yinelenen doku alanımızdaki benzer noktalardan örnek alıyoruz. Bunu düzeltmek için kendi örnekleme gradyan vektörlerimizi sağlayabiliriz.

İşte bu düzeltmeleri içeren bir sürüm:

fixed4 frag(v2f i) : SV_Target
{
    float2 polar = float2(
           atan2(i.uv.y, i.uv.x) / (2.0f * 3.141592653589f), // angle
           log(dot(i.uv, i.uv)) * 0.5f                       // log-radius
        );

    // Check how much our texture sampling point changes between
    // neighbouring pixels to the sides (ddx) and above/below (ddy)
    float4 gradient = float4(ddx(polar), ddy(polar));

    // If our angle wraps around between adjacent samples,
    // discard one full rotation from its value and keep the fraction.
    gradient.xz = frac(gradient.xz + 1.5f) - 0.5f;

    // Copy the polar coordinates before we scale & shift them,
    // so we can scale & shift the tint texture independently.
    float2 tintUVs = polar * _TintTex_ST.xy;
    tintUVs += _ScrollSpeeds.zw * _Time.x;

    polar *= _MainTex_ST.xy;
    polar += _ScrollSpeeds.xy * _Time.x;

    // Sample with our custom gradients.
    fixed4 col = tex2Dgrad(_MainTex, polar, 
                           _MainTex_ST.xy * gradient.xy,
                           _MainTex_ST.xy * gradient.zw
                         );

    // Since our tint texture has its own scale,
    // its gradients also need to be scaled to match.
    col *= tex2Dgrad(_TintTex, tintUVs,
                          _TintTex_ST.xy * gradient.xy,
                          _TintTex_ST.xy * gradient.zw
                         );

    UNITY_APPLY_FOG(i.fogCoord, col);
    return col;
}

2
Biri yapabileceğiniz birkaç küçük iyileştirme: 1) v yönü için logaritmik bir eğri kullanmak, dışa doğru kayarken dokunun şeklini korumasına yardımcı olur (ortadaki bir noktaya daralmak yerine, sonsuz küçük kopya zinciri elde edersiniz. 2) kendi doku gradyanlarınızı hesaplamak ve kullanmak tex2Dgrad, filtrenin yapısını , açının -pi'den + pi'ye sarıldığı yerde sabitler (bu, sol taraftaki bulanık piksellerin ince çizgisidir). İşte daha mavi ile rötuş sonucu
DMGregory

Şaşırtıcı, ayrılmak için teşekkürler. Shader'ların asla yazamayabileceğim bir şey olduğunu hissediyorum (özellikle "kutup" için yaptığınız şeyler gibi, matematik şeyler benim için hiçbir şey ifade etmiyor, çünkü sadece çok temel matematik becerilerim var).
JacketPotatoeFan

1
Bu tür insanlar genellikle sadece arardı. ;) Sadece klavyeyi kapatacak kadar yapıyorum. Farklı matematik işlevleriyle oynamayı deneyin ve sonuçlara bakın - matematiğin geometrik olarak ne yaptığını görselleştirmeme yardımcı olacak böyle bir araca sahip olmak, pratiğimi ilk etapta nasıl aldığımdır. (Özellikle gölgelendiricilerle değil, WhiteCap adlı eski bir WinAmp görselleştiricisi ...) Gölgelendirici matematik korkunç bir şekilde yanlış gittiğinde bile, bakmak gariptir. : D
DMGregory
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.