2012-03-28 10 views
5

Powiedzmy, że mam 2 gatunki, takie jak ludzie i kucyki. Mają różne systemy szkieletowe, więc jednorodny układ kostny będzie musiał być inny dla każdego gatunku. Czy muszę zaimplementować dwa osobne programy cieniujące zdolne do poprawnego renderowania każdej macierzy kostnej lub czy istnieje sposób dynamicznego zadeklarowania jednolitych tablic i iteracji za pomocą tej dynamicznej tablicy?(OpenGL 3.1 - 4.2) Dynamiczne jednolite tablice?

Pamiętając o osiągach (są tam wszystkie shadery ssące przy rozgałęzieniu decyzji).

Odpowiedz

12

Do OpenGL 4.3, tablice w GLSL musiały mieć stały rozmiar. 4.3 pozwala na użycie obiektów bufora pamięci shaderów, które pozwalają, by ich ostateczna długość była "nieograniczona". Zasadniczo, można to zrobić:

buffer BlockName 
{ 
    mat4 manyManyMatrices[]; 
}; 

OpenGL będzie dowiedzieć się, ile macierze są w tej tablicy w czasie wykonywania na podstawie sposobu korzystania glBindBufferRange. Więc nadal możesz użyć manyManyMatrices.length(), aby uzyskać długość, ale nie będzie to stała czasu kompilacji.

Jednak ta funkcja jest (w czasie tej edycji) bardzo nowa i została zaimplementowana tylko w wersji beta. Wymaga również sprzętu klasy GL 4.x (aka: sprzęt klasy Direct3D 11). Wreszcie, ponieważ używa bloków pamięci modułu cieniującego, dostęp do danych może być wolniejszy, niż można mieć nadzieję.

Jako takie, sugeruję, aby po prostu użyć jednolitego bloku o największej liczbie macierzy, które można użyć. Jeśli stanie się to problemem pamięci (mało prawdopodobne), możesz podzielić swoje moduły cieniujące na podstawie rozmiaru tablicy lub użyć bloków pamięci modułu cieniującego lub cokolwiek innego.

10

Możesz użyć tekstury n-by-1 jako zamiennika dla tablic. Rozmiar tekstury można określić w czasie wykonywania. Używam tego podejścia do przekazywania dowolnej liczby świateł do moich shaderów. Jestem zaskoczony, jak szybko działa pomimo wielu pętli i gałęzi. Na przykład zobacz plik modułu cieniującego polygon.f w pliku jogl3.glsl.nontransp w źródłach jReality.

uniform sampler2D sys_globalLights; 
uniform int sys_numGlobalDirLights; 
uniform int sys_numGlobalPointLights; 
uniform int sys_numGlobalSpotLights; 

...

int lightTexSize = sys_numGlobalDirLights*3+sys_numGlobalPointLights*3+sys_numGlobalSpotLights*5; 

    for(int i = 0; i < numDir; i++){ 
     vec4 dir = texture(sys_globalLights, vec2((3*i+1+0.5)/lightTexSize, 0)); 

...