Imaginantia

思ったことを書きます

日記 0204

今日はもろもろをやりつつ諸々をやりました。前からやろうとしてた高速化?を。

なんか諸々で「浮動小数点データのbicubic補間」をする機会があったんですけど。

何故かデータがこう、あの、pngにpackされて入ってて。どこかでみた感じなんですけど。

f:id:phi16_ind:20210204051315p:plain

データ1つ取り出すのに4回。さらにbicubic補間なので16回。即ち「値を拾うのに64サンプルする」という処理になっていて。

よくないなとおもっていたので改善しようとしました。

4回になりました

 

まず明らかに最初から浮動小数点で読ませたほうがいいです。なのでpngを読んでexrを吐くコードを書きました。

…あの。どうやら Color には配列アクセスができるんですが Color32 にはできないらしいです。なんじゃそりゃ。

まぁなんやかんやあってできます。

これでサンプル回数は「正しく」16回です。

で。

前から思っていたのが、bicubicで拾うサンプル点をテクスチャ点ど真ん中じゃなくて†いい感じ†にすればいいのではないかと。

つまり、bilinear補間の設定を入れたテクスチャを重み付けて4回サンプルすればbicubic補間の値が拾えるのではないかと。

f:id:phi16_ind:20210204051727p:plain

a_0v_0 + a_1v_1 = (a_0+a_1)\times\mathsf{lerp}(v_0,v_1,a_1/(a_0+a_1)) なので任意の重み付けは一応再現可能なはずなんです。

…って思ってたんだけどうまくいかなくて。ずっとわかんなかったんですが。

a_0a_1 の符号が違うときには外挿をしなきゃいけないことに気づきました。終わりです。

 

…でも逆に言えば符号が同じときにはうまくいってたので、どうにかならんかなと思って。

考えたのが、1行ごとに画素値が正負反転している画像を別に用意するという方法。

つまり a_1 が負なら代わりに v_1 が負だったことにしちゃえばいいじゃんという。「1行毎」なら行数の偶奇によって毎回反転すればいい感じに値が拾えるはず。

じゃあその画像はどれくらい必要なのか、というと…。4つの重みが独立なら8枚必要です。

ですが今回の重みは X と Y に分離できるので「縦」「横」「縦横」で反転する画像を用意すればいいことになりました。

というわけで横幅4倍にして、いい感じにsampleする関数を作りました。

float4 weighted(int2 iuv, float2 wx, float2 wy) {
    bool2 b = (iuv&1) != 0;
    float2 g = 0, w = 0;
    if(wx.x * wx.y > 0) {
        w.x = wx.x + wx.y;
        g.x = wx.y;
    } else {
        w.x = wx.x - wx.y;
        g.x = - wx.y;
        if(b.x) w.x *= -1, g.x *= -1;
        iuv.x += W;
    }
    if(wy.x * wy.y > 0) {
        w.y = wy.x + wy.y;
        g.y = wy.y;
    } else {
        w.y = wy.x - wy.y;
        g.y = - wy.y;
        if(b.y) w.y *= -1, g.y *= -1;
        iuv.x += W*2;
    }
    return sample(iuv + g / w) * w.x * w.y;
}

はい。

で、よさそうだな~と思いつつ、挙動をいろいろ見てみた所、どうやら重みが同符号のときの分岐を一切通ってないことに気づきました。

bicubic補間の係数の性質だと思うんですけど。まぁ確かにそういう挙動をするのかもしれない。多分計算したらわかるのかしら。

まぁ。だから、「縦横」に反転するケースだけを残せば良いということがわかったのです。

f:id:phi16_ind:20210204052908p:plain

そんなわけでこんな感じのテクスチャが生えました。

f:id:phi16_ind:20210204053137p:plain

なめらかに復元できてます。すばらし。

 

というわけで4点sampleでbicubic補間をすることができました。

…と思ったんですが。

f:id:phi16_ind:20210204053300p:plain

よく見るとやばくて。

なんでかな~と思ったんですが。

RGBAHalfのせいな気がした。実は正確にはこれは検証できてないですね… でも自前でbilinearしたときとテクスチャに任せたときで違うってさすがにそれくらいしか…。

で、exrのimport設定をいじろうとしたんですがRGBAFloatで読む方法って無くて。

調べたらAssetPostprocessorを使うとなんかそれっぽいことができることがわかったんですが。

ダメっぽくて。

…諦めて現在に至ります。

 

GPU的にはRGBAFloatの空間は平気で用意できるはずなんですよね (ぶいちゃなので)。Unityが用意してないだけで…。

CustomRenderTextureを1Fだけ走らせてRGBAFloatとして読み込ませるっていうのがまぁありかなぁ…とか思ってます。今。

でもそうするともはや最初のpngで十分なのよね。ね。

とりあえずRGBAFloatにして改善するかをチェックしてからっすね…。


 

完璧にはうまくいきませんでしたがまぁやろうとしたことがちゃんと進んだので良い日でした。

明日は続きをちょっとやりつつKinoを弄ろうかな…。

 

そういえば今日ぶいちゃに行ったんですが (?)。

ふと気づいてしまったことがあって。

私が写真を撮っているのはマジでなんだか撮りたくなったからでそれ以外の何でもないんですけど。

あんまりにこちゃの写真を今まで撮っていなかった気がする (自覚がある) んだけど、今日のロング髪を見てめっちゃ撮りたさに駆られた

…はい。つまり前から変わらず私は概ね銀髪しかみていないということみたいでした。

無意識的な自分の行動にあとから気づくと悲しくなることがあります。かわいいと思ったら銀髪だった事案は今でも変わらず続いています。

まぁしょうがないのでしょうがないんだと思います。というわけであまり深く考えないでください。

いつもありがとうございます。銀髪も。銀髪でない方も。

 

…はい。書こうと思っていたので書いておきました。それだけです。

では。おやすみなさい。