2011-08-30 22 views
5

我正在尋找優化以下glsl函數,它可以進行cubmap face選擇。它需要一個3分量矢量並返回臉部,臉部和最大組件的texcoords。在GLSL中選擇cubmap face的快速方法

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

優化長度還是速度?另外,如果我記得沒有解決立方體貼圖的內建函數? – Nobody

+4

我會問一個明顯的問題:爲什麼不使用立方體貼圖? '紋理'功能將爲您處理這一切。 –

+0

爲什麼我不能使用實際的立方體貼圖真的有很棒的原因。我希望優化這個功能的速度。 – user920164

回答

0

您可以優化出動態分支。我不確定這是否會改善性能,但在這種情況下,你當然可以嘗試。它有時會提高着色器代碼的性能。

例如,對於第一個條件,你可以/ TRY /像:

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); 

等等......我想這會給你的某種性能提升,如果只是邊際,因爲我在GPU上的知識動態分支在高度分歧時很昂貴,通常應該只用於有條件地消除較大的操作塊。

這是我看到的最明顯的事情。

2

這種方式可能仍是緩慢的,但它不會做任何分支:

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

有用的功能,以簡化你的代碼是:

  • genType sign(genType x),返回-1.0如果x少如果x等於0.0,+1.0如果x大於,則爲0.0,。
  • genType step( genType edge, genType x),其中對於返回值的元素i,返回0.0if x[i] < edge[i],否則返回1.0

此外,我建議創建一個3 * 3的矩陣,它產生一個簡單的矩陣向量乘法的結果。以下代碼應該給出與您的代碼完全相同的結果:

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; 
}