2011-08-30 14 views
5

私は、cubmapの顔選択を行う以下のglsl関数を最適化するつもりです。 3成分ベクトルを取り、顔、顔のテクスチャ、最大の成分を返します。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

私は明らかな疑問を尋ねます:なぜあなたはキューブマップを使うのですか? 'texture'関数はこれをあなたのためにすべて処理します。 –

+0

実際のキューブマップを使用できない理由は本当に素晴らしいです。私は速度のためにこの機能を最適化したいと考えています。 – user920164

答えて

0

ダイナミックブランチを最適化することができます。パフォーマンスが向上するかどうかはわかりませんが、この場合は確かに試すことができます。シェーダコードのパフォーマンスが向上することがあります。

例えば最初の条件のために、あなたは/ /のような何かを試みることができる:

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

便利な機能です:xが少ない場合-1.0を返す

  • genType sign(genType x)0.0,0.0,x0.0と等しい場合、+1.0の場合、xがより大きい場合。
  • genType step( genType edge, genType x)戻り値の要素iの場合、0.0が返されます。if 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; 
}