LUTを使用してモバイルデバイスのTrig Heavyシェーダーを高速化する


10

私が取得しようとしていますこのシェーダを本当に古いのiDevice上で実行するだけでなく、最終的にはアンドロイド。

コードをフラグメントごとに2つの正弦関数に下げても、シェーダーは約20 fpsで実行されます。

私は古いシェーディングテクニックの本から一枚の葉を取り、事前定義されたTrig値の束を保持する配列を作成し、どういうわけかそれらを使用してシェーダーを近似することを検討しました。

上でリンクしたシェーダーでは、trig関数に送られる値を丸めることにより、マウスを左に動かすと(ダウンしている間)、シェーダーの品質が低下することをすでにシミュレートしています。左側に非常に近く、完全に異なるかなりクールなシェーダーのように見えるため、実際にはかなりクールです。

とにかく、私には2つのジレンマがあります。

  1. GLSLシェーダーで定数などの360値の配列を含む最も効率的な方法は何か、わからないのですか?
  2. 0から360までの角度が必要な場合、通常のように数値を範囲内に配置する方法を理解できません(はい、GPUがラジアンを使用していることがわかっています)。

    func range(float angle)
    {
       float temp = angle
       while (temp > 360) {temp -= 360;}
       while (temp < 0)   {temp += 360;}
       return temp;
    }
    

    ただし、GLSLでは、whileループまたは再帰関数を使用できません。


これを実装するのが実用的かどうかはわかりませんが、事前計算された正弦値の間隔を不均等にし、正弦曲線の勾配が最も急であるほど密にクラスタ化された値にして、平準化し、それほど変わらない?これにより、多数の値を保存する必要なく、必要な場所でより高い精度が得られますか?
trichoplax

5
#2に関しては、組み込みmod関数が必要です。あなたが書くでしょうmod(angle, 360.0)
ネイサンリード

1
@trichoplaxのすばらしいアイデアですが、テーブルで値を検索する方法がわかりません。それらをいくつかに集中して配列にしたとしましょう。どのようにして適切なインデックスを見つけることができますか?
J.Doe、2016

6
値を3チャンネルの1Dテクスチャに入れてみませんか?そうすれば、1回のテクスチャルックアップの代償として、罪、余剰、日焼けを解消できます。0-2pi角度を0-1 UVにマッピングし、リピートテクスチャモードを使用する場合、mod呼び出しも不要で、自動的に「折り返し」、保存された値の間ではなく、保存された値の間で線形フィルターされた近似を取得することもできます。最も近いものにスナップします。
ロシア、2016

3
多くの場合、角度を使用せずにsin / cosのペアで開始および終了し、半角などにトリガーIDを使用することで、ジオメトリに使用するときにトリガー関数を排除できます。
ラチェットフリーク2016

回答:


8

[0,360)[0,2π)

  • [0,360][0,1]
  • ループのような間隔調整を行う必要がないという追加の利点があります(とにかくループは必要なく、単にモジュラス演算を使用できます)。GL_REPEATテクスチャのラッピングモードとして使用するだけで、引数> 1でアクセスすると自動的に最初から再開されます(負の引数の場合も同様です)。
  • また、テクスチャフィルターとして使用することで、配列内の2つの値の間を基本的に無料で(または、ほとんど無料であるとしましょう)線形補間する利点も得られGL_LINEARます。これにより、保存していない値も取得できます。もちろん、線形補間は三角関数に対して100%正確ではありませんが、補間を行わないよりは確かに優れてます。
  • RGBAテクスチャー(または必要な多くのコンポーネント)を使用して、テクスチャーに複数の値を格納できます。このようにして、単一のテクスチャルックアップでsinやcosなどを取得できます。
  • [1,1][0,1]float sin = 2.0 * (texValue.r + texValue.g / 256.0) - 1.0;(またはより細かい粒子の場合はさらに多くのコンポーネント)。これにより、マルチコンポーネントテクスチャから再び利益を得ることができます。

もちろん、テクスチャアクセスも完全に無料ではないため、これがより良いソリューションであるかどうか、およびテクスチャサイズとフォーマットの最適な組み合わせが何であるかを評価する必要があります。

テクスチャをデータで満たし、コメントの1つに対処することに関して、テクスチャフィルタリングがテクセルの中心で正確な値を返すこと、つまりテクスチャ座標がテクセルサイズの半分だけ離れていることを考慮する必要があります。したがって、はい、テクセル値を生成.5する必要があります。つまり、アプリケーションコードでは次のようになります。

float texels[256];
for(unsigned int i = 0; i < 256; ++i)
    texels[i] = sin((i + .5f) / 256.f) * TWO_PI);
glTexImage1D(GL_TEXTURE_1D, 0, ..., 256, 0, GL_RED, GL_FLOAT, texels);

uniform float sinTable[361]glUniform1fv[0,360)mod

angle = mod(angle, 360.0);
float value = sinTable[int(((angle < 0.0) ? (angle + 360.0) : angle) + 0.5)];

1
以下は、ルックアップテーブルをテクスチャに格納するための興味深い拡張機能です。N線形テクスチャ補間を使用して、データポイント、サーフェス、ボリューム、ハイパーボリュームの高次補間(線形よりも良い)を取得します。blog.demofox.org/2016/02/22/...
アラン・ウルフ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.