【VFXGraph】速度マップの位置が0.5ズレる問題の応急処置

# はじめに
Houdiniを使って以下のようなVectorFieldを作成しました。
>
0<x<0.5の時は速度(1,0,0)
-0.5<x<0の時は速度(-1,0,0)
それ以外では速度(0,0,0)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44288/da7c32c8-bfb0-39ef-0ac3-1fb94ef33a6f.png)


上記のVectorFieldを.fgaファイルとしてUnityにインポートし、3Dテクスチャ化したものを
VisualEffectGraphにて速度マップとして使ってみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44288/82ad10d7-6b06-4e8b-6fea-b1150b53f3f1.png)
<img src = "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44288/839dfd10-dc5a-1346-b285-c437c4c30901.png" height = 240>

## 発生した問題
その結果、**「3Dテクスチャ(速度マップ)の位置が0.5ズレる」**という現象が発生しました。
![1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44288/76aebd5f-625c-28cb-deff-1ab1ce348ac7.gif)

座標(0,0,0)を中心とした立方体でパーティクルは発生していますが、速度マップは座標(0.5, 0.5, 0.5)を中心とした分布になっています。

今回、ソースコードを改造することでこの問題が解決したのでメモ書き程度に記事にしたいと思います。

# 環境
Unity2019.1.1f1
Visual Effect Graph - Version 5.13.0 (Preview)

# 対策1 : パーティクルの生成位置を0.5ずらす(間違った対策)
(パッケージの格納フォルダ)\Editor\Models\Blocks\Implementations\Positionフォルダの中にある、
**PositionAABox.cs**の中を見ると以下のようなコードがあります。

```PositionAABox.cs
...
        public override string source
        {
            get
            {
                if (positionMode == PositionMode.Volume)
                {
                    return @"position = Box_size * (RAND3 - 0.5f) + Box_center;";
                }
...
```

ちなみに、```source``` はVisualEffectGraph内部で管理されているコンピュートシェーダーの一部分です。

## コードを書き換える
上記のコードを以下のように書き換えます。

```PositionAABox.cs
...
        public override string source
        {
            get
            {
                if (positionMode == PositionMode.Volume)
                {
                    // return @"position = Box_size * (RAND3 - 0.5f) + Box_center;";
                    return @"position = Box_size * (RAND3) + Box_center;";
                }
...
```


参考:
【Unity】PackageManagerが提供するパッケージのダウンロード先と、パッケージを改造する方法
http://tsubakit1.hateblo.jp/entry/2018/08/16/221016


## 結果
改造した状態でUnityを再起動したところ、以下のようになりました。
![2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44288/8fa74e0c-121f-7802-d58b-c059772631c1.gif)
Position(AABox)の中心が(0.5, 0.5, ,0.5)ズレました。

ぱっと見た感じ正しく見えますが、本来は**(0,0,0)を中心とした速度分布になってほしい**ので、これは間違った対策になります。

**PositionAABox.csは修正前の状態へ戻します**

# 対策2 : 3Dテクスチャのサンプリング位置を0.5ずらす(たぶん正しい対策)
(パッケージの格納フォルダ)\Editor\Models\Blocks\Implementations\Attributeフォルダの中にある、
`AttributeFromMap.cs` を覗くと以下のようなコードがあります。

下記コードの```SamplePosition```が3Dテクスチャのサンプリング位置になっています。

```AttributeFromMap.cs
...
if (SampleMode == AttributeMapSampleMode.Sample2DLOD || SampleMode == AttributeMapSampleMode.Sample3DLOD)
{
    output += string.Format(@"
{0} value = ({0})attributeMap.t.SampleLevel(attributeMap.s, SamplePosition, LOD);
{1}
", GetCompatTypeString(valueType), biasScale);
}
...
```


これを以下のように書き換えます。

```AttributeFromMap.cs
...
if (SampleMode == AttributeMapSampleMode.Sample2DLOD || SampleMode == AttributeMapSampleMode.Sample3DLOD)
{
    output += string.Format(@"
{0} value = ({0})attributeMap.t.SampleLevel(attributeMap.s, SamplePosition + 0.5f, LOD);
{1}
", GetCompatTypeString(valueType), biasScale);
}
...
```

##結果
改造した状態で、Unityを再起動したところ以下のようになりました。
![3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44288/f723832e-2b95-b4be-4e40-36f2e553afe1.gif)

(0, 0, 0)を中心とした速度分布になっています。

## 補足 : attributeMapの定義場所
```attributeMap``` は VFXCommon.cgincの中で定義されている構造体のようです。

 ```Set Velocity from Map``` の Sample Mode を Sample3DLODに設定している場合は attributeMapの型として以下の構造体が使用されるようです。

```(パッケージの格納フォルダ)\Shaders\VFXCommon.cginc
...
struct VFXSampler3D
{`
    Texture3D t;
    SamplerState s;
};
...
```



# 参考リンク
HoudiniでVectorField(.fga)を作成する方法(サンプルプロジェクト付き)
https://forty.hatenadiary.jp/entry/2018/11/07/000250

【Unity】UnityへFGAをインポートしてVisual Effect GraphのVectorFieldとして使う方法
https://forty.hatenadiary.jp/entry/2018/11/07/043600

【Unity】PackageManagerが提供するパッケージのダウンロード先と、パッケージを改造する方法
http://tsubakit1.hateblo.jp/entry/2018/08/16/221016