技術

ガウシアンフィルタに注意

同じタイトルが並ぶのもあれなので変えてみた。
進捗というほどでもないし主眼が違うし。

DI50_GI10m_GF10_FG64_290sec_GFfixガウシアンフィルタの実装を変えた結果

ガウシアンフィルタだけではなく、特定のデータの近傍のデータを利用する処理には必ずと言っていいほど「端の処理をどうするか?」という問題がある。
デジカメで撮った写真などの2次元の画像データなら、端は上下左右の4つしかないし、そういう場合の端はたいてい人の目から見て重要じゃないので、端の方は処理しないとか、外側に周辺色や黒色が広がってると仮定してボカすとか、適当な実装で問題ない場合が多いと思う。

これが複数のポリゴンの表面色情報などを格納したテクスチャデータだと、同じ二次元画像でも端の処理の重要度が変わってくる。
当然、画像の上下左右端という意味での「端」も存在するが、それに加えポリゴン境界という意味での「端」も存在するからである。
ポリゴン数が多くてテクスチャデータ内の領域が細かく分けられてると、それこそ端だらけという事になる。

これを普通の画像と同じようにボカシてしまえば、テクスチャ空間では隣り合ってるが3次元空間では全く無関係である可能性があるポリゴンの色が滲み出てくることになる。
これを例えばポリゴンの外側のテクセルをゼロとして(つまり外側を黒色とみなして)計算すると、テクスチャをポリゴンに貼りつけたときに、ポリゴンのエッジ付近が暗くなってしまう。
エッジ付近が暗くなるだけならまだマシだが、そもそもぼかし半径より小さい領域があると、その領域全体がかなり暗くなってしまい、最終的にはポリゴン抜けのような見た目になってしまうだろう。

こういう場合、どうやってぼかせばいいか。
答えを言ってしまえば、周辺色(領域の中で一番外側にある色)が外側に広がってると仮定して計算するか、外側で存在しなかったテクセルの分の重みをその他に分配して計算する方法がこの場合は合ってると思う。

しかし前回、後者の方法を実装したつもりだったが、実装に問題があって最終的な結果に悪い影響を与えていた事が判明した。
間接照明のデータにガウシアンフィルタをかけて、それをもとにファイナルギャザリングを行うようにしてたが、結果がやけに明るく色の伝搬も強すぎたのだ。
原因を調べたところ、ボカした結果を直接みるとちゃんとボケてるように見えるのに、ぼかし前のデータの全合計とぼかし後のデータの全合計を比較してみたら、ぼかし後の方が大きくなっていた。
そのせいでファイナルギャザリングが影響を受けてしまったわけだけど、しかしなぜぼかし後に合計が増えてしまったのか。
データを合成するときのウェイトは合計約1.0になるようにしてるので、ほとんど変わらないはずなのに。

問題の実装は以下のようになっていた。

  • 基本的には縦横のぼかしを別に実行する普通のガウシアンフィルタの実装。
  • まず、テクセルごとの処理で、中心から順にガウス関数で求めたウェイトをデータに掛けながら足しあわせつつ(データ合計)、ウェイト自体も有効ウェイトとして足しあわせていく(有効ウェイト合計)。
  • 途中で領域の外に達してしまったら、そこから先は処理を打ち切る、というのを左右別々に行う。
  • 最終的に、「該当テクセルのデータ = データ合計 x (理想状態のウェイト合計(約1.0) / 有効ウェイト合計)」として計算。

で実は、未だにこの実装の何処が問題なのか正直いってよく分からない。
しかし実際に計算して確かめてみると、中心付近の値が周辺よりある程度大きい場合に、全合計が増えてしまうようである。

そこで周辺色を使う方法で実装しなおした結果が冒頭の画像のとおり。
見た瞬間、「あぁ、これは正解だな」と思った。

前回の絵と比べると、色の伝搬具合がかなりリアルになった。
前回の絵も味があると言えなくもないが、ああいう絵になったのは偶然で、もっと微細なポリゴンを含むシーンを試しにベイクしてみたら、微細なポリゴンに近接してる面に激しい色飽和が発生した。

ガウシアンフィルタの実装をしなおしたことで、そういうシーンも正しく計算出来るようになったみたい。

コメントを残す

メールアドレスが公開されることはありません。



※画像をクリックして別の画像を表示

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください