Mobil cihazlar için trig ağır gölgelendiriciyi hızlandırmak için bir LUT kullanma


10

Bu gölgelendiriciyi gerçekten eski bir iDevice'de ve sonunda Android'lerde çalıştırmaya çalışıyorum .

Kodu parça başına 2 sinüs fonksiyonuna indirdiğimde bile gölgelendirici yaklaşık 20 fps'de çalışır.

Eski gölgeleme teknikleri kitabından bir yaprak almayı ve önceden tanımlanmış trig değerlerinin bir demetini tutan ve bir şekilde gölgelendiriciyi yaklaşık olarak kullanmak için bir dizi oluşturmayı düşündüm.

Yukarıda bağladığım gölgelendiricide, trig işlevine gönderilen değerleri yuvarlayarak farenin daha sol (aşağı) gölgelendiricinin daha az kalitesine gittiğini simüle ediyorum. Aslında oldukça havalı çünkü sol tarafa çok yakın, tamamen farklı ve oldukça havalı bir gölgelendirici gibi görünüyor.

Neyse iki ikilem var:

  1. Sabit veya tek tip bir GLSL gölgelendiricide 360 ​​değer gibi bir dizi elde etmenin en verimli yolunu bilmiyorum?
  2. Genellikle 0 ile 360 ​​arasında bir açı istersem bir aralığa nasıl bir sayı koyacağımı anlayamıyorum (evet, GPU'ların radyan kullandığını biliyorum) bunu yaparım.

    func range(float angle)
    {
       float temp = angle
       while (temp > 360) {temp -= 360;}
       while (temp < 0)   {temp += 360;}
       return temp;
    }
    

    Ancak GLSL, döngülere veya özyinelemeli işlevlere izin vermez.


Bunu uygulamanın pratik olup olmayacağını bilmiyorum, ancak önceden hesaplanmış sinüs değerlerinin eşit olmayan aralıklarla yerleştirilmesine yardımcı olur, sinüs eğrisinin eğiminin en dik olduğu daha yakın kümelenmiş değerlerle ve bu kadar değişmiyor mu? Bu, çok sayıda değer depolamaya gerek kalmadan, gerektiğinde daha yüksek doğruluk sağlar mı?
trichoplax

5
# 2 ile ilgili olarak, yerleşik modişlev istediğiniz şeydir. Sen yazardın mod(angle, 360.0).
Nathan Reed

1
@trichoplax parlak bir fikir ama o zaman tablodaki değerleri nasıl arayabileceğinizi bilmiyorum. Diyelim ki onları daha yoğun olan bir diziye koyduk. Doğru endeksi nasıl bulabiliriz?
J.Doe

6
Değerlerinizi 3 kanallı 1D dokuya koymaya ne dersiniz? Bu şekilde günah, cos ve bronzlaşmayı tek bir doku araması fiyatına alabilirsiniz. 0 - 2pi açısını 0 - 1 UV'ye eşlerseniz ve tekrar doku modunu kullanırsanız, mod çağrısına bile gerek duymazsanız, otomatik olarak 'sarılır' ve ayrıca depolanan değerleriniz arasında doğrusal filtreli yaklaşımlar elde edebilirsiniz. en yakın olana yapıyorum.
russ

3
Çoğu zaman, geometri için kullanıldığında trig fonksiyonlarını açıyı kullanmadan ancak sin / cos çifti ile başlayıp bitirerek ortadan kaldırabilir ve yarım açılar ve benzeri için trig kimliklerini kullanabilirsiniz.
cırcır ucube

Yanıtlar:


8

[0,360)[0,2π)

  • [0,360][0,1]
  • Döngü benzeri aralık ayarınızı yapmak zorunda kalmamanın ek faydasını elde edersiniz (yine de döngülere ihtiyacınız olmaz ve sadece bir modül işlemi kullanabilirsiniz). Sadece GL_REPEATdoku için kaydırma modu olarak kullanın ve > 1 argümanlarıyla (ve benzer şekilde negatif argümanlar için) erişirken otomatik olarak baştan başlar .
  • Ayrıca , doku filtresi olarak temelde ücretsiz olarak (veya diyelim ki neredeyse ücretsiz) dizideki iki değer arasında doğrusal olarak enterpolasyonGL_LINEAR yapmanın avantajını elde edersiniz, böylece bu şekilde kaydetmediğiniz değerleri elde edersiniz. İnterpolasyon doğrusal Tabii trigonometrik fonksiyonlar için% 100 doğru değil, ama o kesinlikle daha var hiçbir interpolasyon.
  • Bir RGBA dokusu (veya ihtiyacınız olan birçok bileşen) kullanarak dokuda birden fazla değer depolayabilirsiniz . Bu şekilde örneğin tek bir doku aramasıyla günah ve cos alabilirsiniz.
  • [-1,1][0,1]float sin = 2.0 * (texValue.r + texValue.g / 256.0) - 1.0;(veya daha ince taneler için daha fazla bileşen). Bu, yine çok bileşenli dokulardan tekrar kazanmanızı sağlar.

Tabii ki bu daha iyi bir çözüm olup olmadığı değerlendirilmelidir, çünkü doku erişimi de tamamen ücretsiz değildir , aynı zamanda doku boyutu ve formatının en iyi kombinasyonunun ne olacağı.

Dokuyu veri ile doldurmak ve yorumlarınızdan birini adreslemek için, doku filtrelemenin texel merkezindeki tam değeri , yani doku boyutunun yarısı kadar koordinat verdiğini düşünmelisiniz. Yani evet, texels değerlerini.5 , yani uygulama kodunda böyle bir şey üretmelisiniz :

float texels[256];
for(unsigned int i = 0; i < 256; ++i)
    texels[i] = sin((i + .5f) / 256.f) * TWO_PI);
glTexImage1D(GL_TEXTURE_1D, 0, ..., 256, 0, GL_RED, GL_FLOAT, texels);

uniform float sinTable[361]glUniform1fv[0,360)mod

angle = mod(angle, 360.0);
float value = sinTable[int(((angle < 0.0) ? (angle + 360.0) : angle) + 0.5)];

1
İşte arama tablolarını dokularda saklamanın ilginç bir uzantısı. (Ab) veri noktaları, yüzeyler, hacimler ve hipervolümlerden daha yüksek mertebe enterpolasyon (doğrusaldan daha iyi) elde etmek için N-lineer doku enterpolasyonunu kullanır. blog.demofox.org/2016/02/22/…
Alan Wolfe
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.