Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

RenderTextureの正しいα値は?

2,406 views

Published on

Aiming × KLab コラボMeetup!
RenderTextureの正しいα値は?

Published in: Software
  • Be the first to comment

RenderTextureの正しいα値は?

  1. 1. RenderTextureの 正しいα値は? KLab株式会社 クライアントエンジニア 中島将浩 1
  2. 2. 自己紹介 氏名: 中島将浩 経歴 筑波大学(数学専攻)→HAL東京→KLab2016年入社 得意分野 クライアントサイド、設計やロジック グラフィックAPI周辺 好きなゲーム アクション、音ゲー、JRPG 2
  3. 3. RenderTextureに書き込まれているα値を 気にしたことありますか? 3
  4. 4. RenderTextureとは 普通はカメラを置いて画面に描く RenderTextureとは、画面の代わりにテクスチャに描画する技術 描画結果は当然テクスチャであるため、ポリゴンに貼り付けることができる 例えば、テレビモニタで中継しているような表現が可能 4
  5. 5. RenderTexture活用事例 Anima2DやLive2Dを利用した、パーツごとに動かす類のアニメーション このキャラクターをα値を使ってフェードアウトすると…… 重なった部分が出ちゃう 許容しているケースが多いが、Live2Dだと 結構悲惨なことになる 5
  6. 6. RenderTexture活用事例 そこでRenderTexture RenderTextureを経由して出すことで重なり部分も綺麗にフェードアウト 6
  7. 7. ところが 7
  8. 8. RenderTextureの問題 画面に直接 RenderTexture経由 微妙に色味が違う 8
  9. 9. RenderTextureの問題 Q. これの正体は? A. カメラのClearColor 9
  10. 10. RenderTextureの問題 なぜこんな問題が? 画面に直接描画した場合 背景画像 + オブジェクト のαブレンド RenderTextureを経由して描画した場合 背景画像 + (ClearColor + オブジェクト) のαブレンド 10
  11. 11. αブレンドのおさらい αブレンドとは二つの色X, Yを、合計が1になるような係数で線形和を取ること 例 0.3 * X + 0.7 * Y 0.5 * X + 0.5 * Y など 色の重み付き平均と言ってもよい 0.7とか0.5といった係数をα値という 11
  12. 12. αブレンドのおさらい Q. 画面に描く場合は? A. すでに書かれている色と、これから描こうとする色のαブレンド DstColorの上にSrcColorを重ねようとした場合には↓の式になる (1 - α) * DstColor + α * SrcColor 12
  13. 13. αブレンドのおさらい (1 - α) * DstColor + α * SrcColor 実はこの式の(1 - α)やαの部分はある程度好きな係数にカスタマイズ可能 アルファブレンドのシェーダーではこうなっているというだけ ・1 ・0 ・α ・1 - α ・書き込み先のα値 などから好きな係数にカスタマイズ可能 13
  14. 14. αブレンドのおさらい 例 1 * DstColor + α * SrcColor : α付き加算合成 1 * DstColor + 1 * SrcColor : αなし加算合成 0 * DstColor + 1 * SrcColor : 一方的な上書き (1 - α) * DstColor + (1 - α) * SrcColor : 謎合成 14
  15. 15. RenderTextureの問題 なぜこんな問題が? 画面に直接描画した場合 背景画像 + オブジェクトのαブレンド RenderTextureを経由して描画した場合 背景画像 + (ClearColor + オブジェクト) のαブレンド 問題1: ClearColorの色が混ざってしまっている 問題2: RenderTextureのα値が正しく制御されていない 15
  16. 16. 図解(全てα=0.5とする) 背景 0.25倍 パーツA 0.25倍 パーツB 0.5倍 背景 ClearColor 0.25倍 パーツA 0.25倍 パーツB 0.5倍 16
  17. 17. 図解 さも当然のようにClearColorが背景の居場所に鎮座している…… 背景 ClearColor 0.25倍 パーツA 0.25倍 パーツB 0.5倍 17
  18. 18. 方針 1. ClearColorをなかったことにする 2. ClearColorにかかっている係数は本来背景にかかるはずのものなので、それ をRenderTextureのα値に書き込んでおく 3. RenderTextureのRGBは「α反映済みのRGB」として扱う P-MAPに近い これで、背景のような顔をして居座っているClearColorを追い出せる 背景 ClearColor 0.25倍 パーツA 0.25倍 パーツB 0.5倍 18
  19. 19. ClearColorをなかったことにする ClearColorのRGBを0にしてしまえばよい 方針 背景 ClearColor 0.25倍 パーツA 0.25倍 パーツB 0.5倍 19
  20. 20. 背景 ClearColor 0.25倍 パーツA 0.25倍 パーツB 0.5倍 ClearColorにかかっている係数は本来背景にかかるはずのものなので、それを RenderTextureのαとして残す ClearColorにかかっている係数とは? (1 - A.A) * (1 - B.A) * … の形になっているはず * (1 - A.A) * (1 - B.A) 方針 20
  21. 21. 背景 ClearColor 0.25倍 パーツA 0.25倍 パーツB 0.5倍 Unityではα値のブレンド係数を次のように変更することで実現 (1 - α) * DstColor + 0 * SrcColor 併せて、ClearColorのα値を1にしておくことで … * (1 - B.A) * (1 - A.A) * 1 = (1 - A.A) * (1 - B.A) * … の形にすることができる * (1 - A.A) * (1 - B.A) 方針 21
  22. 22. 背景 ClearColor 0.25倍 パーツA 0.25倍 パーツB 0.5倍 RenderTextureのRGBは「α反映済みのRGB」として扱う 背景の上に描画する際のブレンド設定を次のようにすればよい α * DstColor + 1 * SrcColor * (1 - A.A) * (1 - B.A)* (1 - A.A) * (1 - B.A) 方針 22
  23. 23. α * DstColor + 1 * SrcColor DstColorは背景色でαはRenderTextureのα値のこと RenderTextureのα値には(1 - A.A) * (1 - B.A)が入っているはず SrcColorはRenderTextureのRGBで、こちらも0.25 * A + 0.5 * Bが入っているはず なので、係数は1でよい 方針 背景 ClearColor 0.25倍 パーツA 0.25倍 パーツB 0.5倍 * (1 - A.A) * (1 - B.A)* (1 - A.A) * (1 - B.A) 23
  24. 24. 背景 0.25倍 パーツA 0.25倍 パーツB 0.5倍 背景 ClearColor 0.25倍 パーツA 0.25倍 パーツB 0.5倍 * (1 - A.A) * (1 - B.A)* (1 - A.A) * (1 - B.A) 方針 24
  25. 25. RenderTextureに描画する際のClearColorを(0, 0, 0, 1)にする RenderTextureに描画する際のα値のブレンド設定を下のようにする (1 - α) * DstColor + 0 * SrcColor RenderTextureを画面に描画する際のRGBのブレンド設定を下のようにする α * DstColor + 1 * SrcColor 手順まとめ 25
  26. 26. RenderTextureに描画する際のClearColorを(0, 0, 0, 1)にする Unity上での手順 26
  27. 27. RenderTextureに描画する際のα値のブレンド設定を下のようにする (1 - α) * DstColor + 0 * SrcColor RenderTextureを画面に描画する際のRGBのブレンド設定を下のようにする α * DstColor + 1 * SrcColor Unity上での手順 27
  28. 28. 結果 同じになった!! 28
  29. 29. 短所がいくつか ・同じ実装なのに複数箇所に実装がばらけている(ひとつでも欠けたら死ぬ) ・実装から意図が読みづらいし、コメントを書こうにも一箇所にまとまってない ・理屈をコメントだけで説明しづらい とはいえ、ひとつだけ欠けた場合の見た目がわりかしわかりやすいので、こけた 時の発見は早い そもそもα値のせいで起こる問題なので、ディザ合成にすることで回避も可能 補足 29
  30. 30. 実装当時は全然記事がなかったが、二日前にQiitaの記事に上がっていた! 詳細な理屈は省かれているので、併せて参考にしてもらえれば幸いです https://qiita.com/luckin/items/43a8a98a88a3ba20e92b 補足 30
  31. 31. ご清聴ありがとうございました 31
  32. 32. 今回紹介した方法は、RenderTextureのα値として正しい値なのではなく、このロ ジックを成立させるためのピースでしかないように見えるかもしれない ところが、実はそこそこ正しい値で、正確にいうと今回の (1 - A.A) * (1 - B.A) * … は(1 - α)に相当する値である そのまま背景色に乗算している点とも辻褄が合っている 補足 32
  33. 33. α値というのは、自然現象に置き換えると遮光率と言える (α値が0.9だったら、後ろの光を0.1だけ通している) つまり(1 - α)は透過率で、複数枚重ねた時の透過率はそれぞれの積で求まる、と いうのが直感的に正しそう つまり、透過率は次の式 (1 - α1) * (1 - α2) * (1 - α3) * … 補足 33
  34. 34. 透過率 + 遮光率 = 1 となるのがアルファブレンドなので、透過率が (1 - α1) * (1 - α2) * (1 - α3) * … なら遮光率(つまりα値)は 1 - ((1 - α1) * (1 - α2) * (1 - α3) * …) の形になる 補足 34
  35. 35. 今回の (1 - A.A) * (1 - B.A) * … は(1 - α)に相当する値であると書いたが、つまり遮光率ではなく透過率の方を保 存していることになる(だから、背景色にそのまま係数として掛けてよい) 本質的には遮光率を残そうが透過率を残そうが大した違いはないが、厳密には正 しいα値が残っているとは言えない 補足 35

×