はかせのラボ

私の頭の中を書いていく雑記ブログです

落ちモノパズル 透過処理出来てたっぽい

あいさつ

どうも、はかせです。
今回はついに絶望から解放された話です。

絶望とは

私が今まで味わってきた絶望の詳細は下記に詳しいです。
hakase0274.hatenablog.com
hakase0274.hatenablog.com
hakase0274.hatenablog.com

詳細は省くとして簡単に言うと
透過処理すると画像が黒くにじむ問題です。

それで「画像 透過処理 黒くにじむ」みたいに調べたら
乗算アルファブレンディングとか出てきて一応それになるよう
BlendStateを弄ったりしたわけですよ。

ただ解決することができなくて遂に
シェーダーという秘術に手を出さなければならないのかと
途方に暮れていたわけです。

絶望の正体

あまりに解決することが出来ず遂に私より出来る人に
実物持って行ってどうにかなりませんかね?と聞いてきました。

そうしたらコードを見る限り
アルファブレンドは出来ているだろうと。
なのでおそらく
ブレンドが適用されていない
②深度バッファに負けている

のどちらかであるだろうという意見をいただきました。

ブレンド適用の確認

これは私の場合はレンダラーがそれぞれ存在しているので
thisポインタを見ての条件ブレイクでちゃんと処理が走っているか確認する
という方法をとることにしました。

一応私が使っているVisualStudio2017にはGPUデバッガーという機能があって
頂点だとかパイプラインだとかの情報を見れるデバッガーがあります。
f:id:hakase0274:20190220230927p:plain
これを使うのが安牌なのですが
私の環境だとドライバとかの兼ね合いなのか
うまく動作しませんでした(´;ω;`)

なので条件ブレイクという手段をとることになりました。
ただこの確認をする前に絶望の正体が判明したので
実施はしていません。

深度バッファの確認

おまわりさん!こいつです!

はいそうです。
犯人は深度バッファというか描画順でした。
私のプログラムでは描画されるものが
Renderメソッドを持ちこのメソッドを呼ぶことで
各オブジェクトが描画を行います。

今回起こっていたことを図にしてみました。
成功時
f:id:hakase0274:20190220232242p:plain
失敗時
f:id:hakase0274:20190220232304p:plain

成功しているときは画像→透過したい画像の順で描画していた時です。
失敗しているときは透過したい画像→画像の順で描画していた時です。

私の場合描画順=生成順なので
エフェクトとかを先に生成した瞬間描画順で失敗が確定するわけですね。

何故こんなことが起こったかというと
深度バッファを有効にしていたからですね。

深度バッファは簡単に言うと画像が重なった時
Zの値を見て(要は奥行き)描画順を決定するものです。

こいつのおかげで今まで描画順を気にせずとも
画像が正常に表示されていました。

ただアルファブレンドとなると話は変わります。
アルファブレンドは描画されているピクセルの色と自身の色とで
最終的なピクセルに表示する色を決定するものです。

それで色が決定するわけなんですが
ここでアルファブレンドと深度バッファが喧嘩を始めます。

透過というのは簡単に言えば前にモノがあるのに
後ろのモノを描画するということです。

そうすると前後の関係を維持する深度バッファが修正をかけます。
後ろにあるモノの描画結果は破棄されます。
そうすると透過しようとしたモノは後ろにある色と
アルファブレンドすることになります。

つまり今までの黒にじみはアルファブレンド
失敗によって起こされたものではなく、
むしろアルファブレンド自体は成功しており
画面クリア色とアルファブレンドしていたのです

私の場合画面クリア色は黒だったので
黒くにじんでいるように見えたわけですね。

実行結果はいかに

さて犯人は描画順とわかったので
後は楽です。

描画順=生成順なのでエフェクトの生成を最後にしてみます。
それではお楽しみの実行結果です。
f:id:hakase0274:20190220234331g:plain

やったー!!!
黒くにじんでないぞー!!!

あとがき

今回は長きに渡り私を苦しめ、絶望の底に叩き落してくれた
透過処理の黒にじみ問題の終幕でした。

ずっとあーでもないこーでもないと悩み、
ネットの文献をあさり解決策を探していたわけですが、
まさか描画順だったとは・・・orz

それでは今回はこの辺でノシ

今回作ったものはgithubに上げました
github.com