2013-07-14 12 views
6

1つの32ビット浮動変数に2つのfloat値を格納したいとします。エンコードはC#で行われ、デコードはHLSLシェーダで行われます。2つのfloat値を1つのfloat変数に格納する

123.456 -> 12.3 and 45.6 

それができる」:

私がこれまでに見つけた最高のソリューションは、ハードワイヤリングエンコードされた値の小数点以下のオフセットと「キャリア」フロートの整数と小数としてそれらを格納しています負の値を扱うことはできますが、それは問題ありません。

しかし、私はこれを行うより良い方法があるのだろうかと思っていました。

EDIT:タスクの詳細いくつかの詳細:私は頂点データは、フロートとして格納されているユニティで固定データ構造で働いている

。 (Float2はUV、float3は法線など)明らかに余分なデータを適切に追加する方法はないので、これらの制限内で作業しなければならないので、データをエンコードするというより一般的な問題。たとえば、2x2の余分なデータチャネルを転送するために、2次UVデータを犠牲にすることができます。

ターゲットはシェイダーモデル3.0ですが、デコードがSM2.0でも合理的に機能していたかどうかは気にしません。

「妥当」である限り、データの消失は問題ありません。期待される値の範囲は0..64ですが、シェイダー内の任意の範囲に再マップするのが安いので、私はそれを考えようとすると0..1もうまくいくでしょう。重要なことは、可能な限り高い精度を維持することです。負の値は重要ではありません。

+0

@ ZoltanE:エンコードしようとしている変数の範囲を知っていますか? –

+0

@ ZoltanE:DirectXのどのシェーダモデルとバージョンをターゲットにしていますか?このようにエンコードする理由の詳細を教えてください。最後に、[gamedev](http://gamedev.stackexchange.com/)サイトで質問してみると、より良い回答が得られるかもしれません。 –

+3

多分質問http://stackoverflow.com/questions/4811219/pack-four-bytes-in-a-floatがあなたを助けるかもしれません。 – Gnietschow

答えて

2

Gnietschowの勧告に従って、私はYellPikaのアルゴを適合させました。 (ユニティ3DのためのそれのC#。)

float Pack(Vector2 input, int precision) 
{ 
    Vector2 output = input; 
    output.x = Mathf.Floor(output.x * (precision - 1)); 
    output.y = Mathf.Floor(output.y * (precision - 1)); 

    return (output.x * precision) + output.y; 
} 

Vector2 Unpack(float input, int precision) 
{ 
    Vector2 output = Vector2.zero; 

    output.y = input % precision; 
    output.x = Mathf.Floor(input/precision); 

    return output/(precision - 1); 
} 

間に合わせのテストは、以下の統計情報(0..1の範囲で100万のランダムな値のペア)を生成:

Precision: 2048 | Avg error: 0.00024424 | Max error: 0.00048852 
Precision: 4096 | Avg error: 0.00012208 | Max error: 0.00024417 
Precision: 8192 | Avg error: 0.00011035 | Max error: 0.99999940 

4096の精度はそうスイートスポットになる。これらのテストでは、パッキングとアンパックの両方がCPU上で実行されたので、浮動小数点精度でコーナーをカットするとGPUで結果が悪化する可能性があることに注意してください。

これは最高のアルゴリズムかどうかわかりませんが、私の場合は十分です。

+0

'input%precision'部分がなぜ機能するのかを説明してもらえますか?あなたは浮動小数点数と整数でモジュラスを実行していますが、モジュラスは整数でのみ定義されています。 – mrueg

+0

定義は整数に限定されません。 "モジュロ演算は、ある数値を別の数値で除算した余りを求めます"。 7.7で3.3を除算すると、残りの部分は何ですか? – ZoltanE

+0

注: 'input.y'が' 1'を超えていると、これが壊れます。その場合、 'output.y'は' precision 'の値のもう一つの増分を加えるだけです - 'input%precision'は' input.y'の小数部をアンパックすることができ、その整数部分( '精度 ')が' output.x'に追加されます。 – meetar

関連する問題