2016-09-07 20 views
6

sonraki kodu kullanarak Unity3D otomatik çift doğrusal filtreleme algoritması çoğaltmak çalışıyorum:Bu teknik, doğrusal olmayan filtreleme değilse nedir?

fixed4 GetBilinearFilteredColor(float2 texcoord) 
{ 
    fixed4 s1 = SampleSpriteTexture(texcoord + float2(0.0, _MainTex_TexelSize.y)); 
    fixed4 s2 = SampleSpriteTexture(texcoord + float2(_MainTex_TexelSize.x, 0.0)); 
    fixed4 s3 = SampleSpriteTexture(texcoord + float2(_MainTex_TexelSize.x, _MainTex_TexelSize.y)); 
    fixed4 s4 = SampleSpriteTexture(texcoord); 

    float2 TexturePosition = float2(texcoord)* _MainTex_TexelSize.z; 

    float fu = frac(TexturePosition.x); 
    float fv = frac(TexturePosition.y); 

    float4 tmp1 = lerp(s4, s2, fu); 
    float4 tmp2 = lerp(s1, s3, fu); 

    return lerp(tmp1, tmp2, fv); 
} 

fixed4 frag(v2f IN) : SV_Target 
{ 
    fixed4 c = GetBilinearFilteredColor(IN.texcoord) * IN.color; 
    c.rgb *= c.a; 
    return c; 
} 

ben bilenear için orada gördük tek olduğu için doğru Algoritmlerin kullanıyordum düşündü. Nokta filtreleme içinde ve (varsayılan peri gölgelendirici maded) özel çift doğrusal shader kullanarak:

  • 1º dokusunu: Ama çoğaltılamaz aynı doku ile birlik kullanarak çalıştı.
  • 2º doku: Varsayılan sprite shader

ile Bilinear filtresinde Ve bu sonucudur:

enter image description here

Onların farklı olduğunu görmek ve ayrıca bazı yoktur yapabilirsiniz Z ekseni içinde dönerken hareketli grafiğin merkez dışında kalmasını sağlayan yer değiştirmem.

Neyi yanlış yaptığım hakkında bir fikrin var mı? Unity3D ne yapıyor hakkında herhangi bir fikrin var mı? Unity3D varsayılan filtrelemeye uyan başka bir algoritma var mı?

Çözüm

burada arayın diğer kişiler için Nico'nun kodu ile komple kod çözümü ile Güncelleme:

fixed4 GetBilinearFilteredColor(float2 texcoord) 
{ 
    fixed4 s1 = SampleSpriteTexture(texcoord + float2(0.0, _MainTex_TexelSize.y)); 
    fixed4 s2 = SampleSpriteTexture(texcoord + float2(_MainTex_TexelSize.x, 0.0)); 
    fixed4 s3 = SampleSpriteTexture(texcoord + float2(_MainTex_TexelSize.x, _MainTex_TexelSize.y)); 
    fixed4 s4 = SampleSpriteTexture(texcoord); 

    float2 TexturePosition = float2(texcoord)* _MainTex_TexelSize.z; 

    float fu = frac(TexturePosition.x); 
    float fv = frac(TexturePosition.y); 

    float4 tmp1 = lerp(s4, s2, fu); 
    float4 tmp2 = lerp(s1, s3, fu); 

    return lerp(tmp1, tmp2, fv); 
} 

fixed4 frag(v2f IN) : SV_Target 
{ 
    fixed4 c = GetBilinearFilteredColor(IN.texcoord - 0.498 * _MainTex_TexelSize.xy) * IN.color; 
    c.rgb *= c.a; 
    return c; 
} 

Ve sonuçla görüntü testi:

enter image description here

Neden tam olarak 0.5 çıkarma?

Eğer test ederseniz, atladığı bazı kenar durumlarını göreceksiniz (piksel - 1).

cevap

6

Gerçekte yaptığınız şeye daha yakından bakalım. 1D vakasına yapışacağım çünkü görselleştirmek daha kolay.

Bir piksel diziniz ve bir doku konumunuz var. Sanırım, _MainTex_TexelSize.z, piksel koordinatları verecek şekilde ayarlanmıştır. , Sen pikselleri 2 alacak (en yakın nokta örnekleme varsayarak) örnekleme ile

Pixels

: Bu (kutular kutulara piksel uzay koordinatlarına aşağıda piksel sayısını ve numaraları pikselleri, sayıları temsil) elde ediyoruz ve 3. Ancak, lerp için enterpolasyon koordinatının aslında yanlış olduğunu görüyorsunuz. Doku konumunun kesirli kısmını (yani 0.8) geçireceksiniz, ancak 0.3 (= 0.8 - 0.5) olmalıdır. Bunun arkasındaki mantık oldukça basittir: Bir pikselin ortasına gelirseniz, piksel değerini kullanmak istersiniz. İki piksel arasında tam ortada yerleşirseniz, her iki piksel değerinin ortalamasını (yani, 0.5 arası bir enterpolasyon değeri) kullanmak istersiniz. Şu an, temelde soldaki yarım piksellik bir sapma var.İlk sorunu çözmek zaman

, ikinci bir fark var:

Bu durumda

Pixels

, aslında piksel 1 ve 2 no'lu karışımı istediğiniz Ama her zaman sağ gittiğiniz için Numune alımınız, 2 ve 3 arasında karışacaksınız. Yine yanlış enterpolasyon değeriyle.

Çözüm oldukça basit olmalıdır:

fixed4 c = GetBilinearFilteredColor(IN.texcoord - 0.5 * _MainTex_TexelSize.xy) * IN.color; 
: doku piksel genişliğinde Çıkar yarısı Aşağıdakilerden birini (değişkenler bence şeyleri tutmak varsayarak) sadece muhtemelen onunla bir şey yapmadan önce koordinat

Sonuçların farklı olmasının bir başka nedeni de, Birlik'in aslında farklı bir filtre kullanması olabilir. bicubic (ama bilmiyorum). Ayrıca, mipmap'lerin kullanımı sonucu etkileyebilir.

İlgili konular