2011-08-30 7 views
5

Szukam optymalizacji poniższej funkcji glsl, która dokonuje wyboru powierzchni z mapą rastrową. Pobiera on wektor 3-składnikowy i zwraca twarz, texcoordy dla twarzy i największy komponent.Szybki sposób wybierania powierzchni z mapą rastrową w języku GLSL

vec4 cubemap(vec3 P) 
{ 
    vec4 Coord; 
    vec3 s = abs(P.xyz); 
    bvec3 b = greaterThan(P.xyz, vec3(0,0,0)); 

    if (all(greaterThanEqual(s.xx, s.yz))) 
    { 
     if (b.x) 
      Coord = vec4(-P.z, -P.y, 0, s.x); 
     else 
      Coord = vec4( P.z, -P.y, 1, s.x); 
    } else 
    if (all(greaterThanEqual(s.yy, s.xz))) 
    { 
     if (b.y) 
      Coord = vec4( P.x, P.z, 2, s.y); 
     else 
      Coord = vec4( P.x, -P.z, 3, s.y); 
    } else 
    { 
     if (b.z) 
      Coord = vec4( P.x, -P.y, 4, s.z); 
     else 
      Coord = vec4(-P.x, -P.y, 5, s.z); 
    } 

    Coord.xy = ((Coord.xy/Coord.w) + 1.0) * 0.5; 
    return Coord; 
} 
+3

Optymalizować długość lub prędkość? Również jeśli dobrze pamiętam, nie było wbudowanej funkcji, która odnosi się do map? – Nobody

+4

Zadam oczywiste pytanie: dlaczego po prostu nie użyjesz cubemap? Funkcja 'texture' zajmie się tym wszystkim dla ciebie. –

+0

są naprawdę niesamowite powody, dla których nie mogę użyć rzeczywistej mapy cubemap. Mam nadzieję, że zoptymalizuję tę funkcję dla prędkości. – user920164

Odpowiedz

0

Możesz zoptymalizować gałęzie dynamiczne. Nie jestem pewien, czy to poprawi wydajność, ale w tym przypadku z pewnością możesz go wypróbować. Czasami poprawia to wydajność kodu cieniowania.

Na przykład dla pierwszej warunkowej, można/try/coś takiego:

int condition=(s.x>=s.y)*(s.x>=s.z)*(b.x); 
Coord = condition*vec4((1.-2.*condition)*P.z, -P.y, condition, s.x); 

i tak dalej ... Wyobrażam sobie to daje wzrost wydajności jakiegoś rodzaju, jeśli tylko marginalne, ponieważ do moja wiedza Dynamiczne gałęzie na GPU są drogie, gdy są wysoce rozbieżne i zasadniczo powinny być używane tylko do warunkowego eliminowania większych bloków operacyjnych.

To najbardziej oczywiste, co widzę.

2

ten sposób nadal może być powolna, ale to nie robi żadnej rozgałęzienia:

vec2 directionToUV(vec3 v) { 
    vec3 abs = abs(v); 
    float max = max(max(abs.x, abs.y), abs.z); // Get the largest component 
    vec3 weights = step(max, abs); // 1.0 for the largest component, 0.0 for the others 
    float sign = dot(weights, sign(v)) * 0.5 + 0.5; // 0 or 1 

    // Find the uv coordinate 
    float sc = dot(weights, mix(vec3(v.z, v.x, -v.x), vec3(-v.z, v.x, v.x), sign)); 
    float tc = dot(weights, mix(vec3(-v.y, -v.z, -v.y), vec3(-v.y, v.z, -v.y), sign)); 
    vec2 uv = (vec2(sc, tc)/max) * 0.5 + 0.5; 

    // Offset into the right region of the texture 
    float offsetX = dot(weights, vec3(0.0, 1.0, 2.0)); 
    float offsetY = sign; 
    uv.x = (uv.x + offsetX)/3.0; 
    uv.y = (uv.y + offsetY)/2.0; 
    return uv; 
} 
0

Przydatne funkcje, aby uprościć kod to:

  • genType sign(genType x), która zwraca -1.0 jeśli x jest mniej niż 0.0, 0.0, 0.0 jeśli x jest równy 0.0, i +1.0 jeśli x jest większy niż 0.0.
  • genType step( genType edge, genType x), w którym na element i wartości powrotu, 0.0 jest zwrócony if x[i] < edge[i] i 1.0 jest zwrócony w przeciwnym razie.

Ponadto, zaleca się utworzenie macierzy 3 * 3, która daje wynik za pomocą prostego mnożenia wektora macierzy. Poniższy kod powinien dać dokładnie taki sam wynik, jak kod:

vec4 cubemap(vec3 P) 
{ 
    vec3 signV = sign(P); 
    vec3 absV = P * signV; 
    vec3 maxV = step(max(absV.x, max(absV.y, absV.z)), absV.xyz); 

    mat3 cubeMat = mat3(
     vec3(maxV.y + maxV.z * signV.z, 0.0,    maxV.x), 
     vec3(0.0,      maxV.y-1.0,  maxV.y), 
     vec3(maxV.x * -signV.z,   maxV.y * signV.z, maxV.z) 
    ); 

    vec4 Coord; 
    Coord.xyw = cubeMat * P; 
    Coord.z = dot(maxV, vec3(0.0, 2.0, 4.0)) + dot(maxV, (1.0-signV)*0.5); 
    Coord.xy = ((Coord.xy/Coord.w) + 1.0) * 0.5; 
    return Coord; 
}