2016-09-11 11 views
2

私はゲームで作業していますOpenGL ES 2.0if-elseブランチなしでこの関数を実装する方法は? (GLSL)

可能であれば、フラグメントシェーダーのブランチを削除したいと思います。しかし、私は改善することができない機能があり、:それはこのような状況で役立ちます場合

float HS(in float p, in float c) { 

    float ap = abs(p); 

    if(ap > (c*1.5)) { 
     return ap - c ; 
    } else { 
     return mod(ap+0.5*c,c)-0.5*c; 
    } 

} 

cは、ほとんどの場合で一定です。私は次のようにこの関数を使用します:

vec3 op = sign(p1)*vec3(
    HS(p1.x, cc), 
    HS(p1.y, cc), 
    HS(p1.z, cc) 
); 
+0

このコードのパフォーマンスを向上させたい、または条件を削除しますか?それらは2つの異なるものですから。 –

+0

if-elseブランチを先に削除することで、このコードのパフォーマンスを向上させたいと考えています。 –

+0

それがここでパフォーマンスを改善する最も効果的な方法ではない場合、どうすればよいでしょうか? –

答えて

2

ここでは、ブランチを「削除」するトリックがあります。しかし、より重要なことはコードをベクトル化することです。結局のところ、コンパイラはおそらくあなたのためにブランチを削除しました。

vec3 HSvec(in vec3 p, in const float c) 
{ 
    vec3 ap = abs(p); 
    vec3 side1 = ap - c; 
    const float val = 0.5 * c; 
    vec3 side2 = mod(ap + val, vec3(c)) - val; 

    bvec3 tests = greaterThan(ap, vec3(c*1.5)); 
    return mix(side2, side1, vec3(tests)); 
} 

これは、冗長な計算の多くと同様に、同時に計算の多くをやって排除します。それは、それがこれを行うことが実現することをはるかに少ない可能性があります。

ここでのキーはmixの機能です。 mixは、3番目の引数に基づいて2つの引数の間で線形補間を実行します。しかしboolfloatに変換すると、正確に1.0または0.0になるので、実際にはside1またはside2のいずれかを選択するだけです。そして、この選択は、コンポーネントごとにgreaterThan操作の結果によって定義されます。

+0

それは動作しますが、コードは次のようにする必要があります: 'lessThan(vec3(c * 1.5)、ap)' –

+1

@IterAtor:または 'greaterThan';私たちもそれを持っています。 –

+0

私は今まで「greaterThan」について聞いたことがありません。それは私が探していた答えです。このコードをどのように最適化すればよいか、いくつかのヒントを教えてください。 –

関連する問題