2011-08-30 32 views
5

Tôi đang tìm cách tối ưu hóa chức năng glsl sau đây thực hiện lựa chọn khuôn mặt cubmap. Phải mất một vector 3 thành phần và trả về khuôn mặt, texcoords cho khuôn mặt và thành phần lớn nhất.Cách nhanh chóng để chọn khuôn mặt cubmap trong 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

Tối ưu hóa theo chiều dài hoặc tốc độ? Ngoài ra nếu tôi nhớ đúng là không có một hàm dựng sẵn để xử lý các hình lập phương? – Nobody

+4

Tôi sẽ hỏi câu hỏi rõ ràng: tại sao bạn không chỉ sử dụng một cubemap? Hàm 'texture' sẽ xử lý tất cả điều này cho bạn. –

+0

có những lý do thực sự tuyệt vời tại sao tôi không thể sử dụng một sơ đồ khối thực tế. Tôi hy vọng tối ưu hóa chức năng này cho tốc độ. – user920164

Trả lời

0

Bạn có thể tối ưu hóa các nhánh động. Tôi không chắc chắn nếu điều đó sẽ cải thiện hiệu suất, nhưng trong trường hợp này bạn chắc chắn có thể thử nó. Đôi khi nó cải thiện hiệu suất mã đổ bóng.

Ví dụ cho, bạn có thể/thử/cái gì đó có điều kiện đầu tiên như:

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

Và vân vân ... Tôi tưởng tượng này sẽ cung cấp cho bạn tăng hiệu suất của một số loại, nếu chỉ biên, bởi vì để kiến thức năng động của tôi chi nhánh trên GPU là tốn kém khi phân kỳ cao và thường chỉ nên được sử dụng để điều kiện loại bỏ khối lớn hơn các hoạt động.

Đó là điều rõ ràng nhất tôi thấy.

2

Bằng cách này vẫn có thể chậm, nhưng nó không làm bất cứ nhánh:

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

chức năng hữu ích để đơn giản hóa mã của bạn là:

  • genType sign(genType x), mà trả về -1.0 nếu x ít hơn 0.0, 0.0 nếu x bằng 0.0+1.0 nếu x lớn hơn 0.0.
  • genType step( genType edge, genType x), trong đó đối với phần tử i của giá trị trả về, 0.0 được trả về if x[i] < edge[i]1.0 được trả về theo cách khác.

Hơn nữa, tôi khuyên bạn nên tạo ma trận 3 * 3, mang lại kết quả với phép nhân vectơ ma trận đơn giản. Mã sau đây sẽ cho kết quả chính xác giống với mã của bạn:

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; 
} 
Các vấn đề liên quan