iwasiblog

イワシブログ - Activity log of an iwasi -

【Unity】Cutout系シェーダーでSSAOが透ける際に行なった対処

【検証環境】

  • Unity 2017.4.12f1 Personal(64bit)

  • ユニティちゃんトゥーンシェーダー Ver.2.0.4.3p1 (ver. 2.0.5 以降修正済み)

  • まんまるしぇーだー_ver_1.3

問題となる現象

ユニティちゃんトゥーンシェーダー2.0 (UTS2)等に同梱されているCutout系シェーダー(テクスチャのアルファやクリッピングマスクで透過を行うシェーダー)を使用した際に,ポストエフェクトのSSAOが正しく適用されず,背景のAOが透けたようになります(図1).

f:id:kuroiwasi:20181002114210p:plain

図1 Cutout系シェーダを適用したオブジェクトが存在するシーンにSSAOをかけた結果

/*

本記事では,Unity 2017.4.12f1上でUnity TechnologiesによるPost Processing Stackに搭載されたSSAO(Screen Space Ambient Occlusion)機能を使用していることを前提とし,以下の2つのシェーダーについて対策*1を述べます.

  • UnityChanToonShader/NoOutline/ToonColor_DoubleShadeWithFeather_TransClipping
  • MMS/Mnmrshader1_3_Clipping

【2018/10/06追記】ユニティちゃんトゥーンシェーダー Ver.2.0.5以降では修正されており,問題の現象は発生しません.

*/

対処法:シェーダーのプロパティ/タグを変更し,適切なAOエフェクトが掛かるようにする

シェーダーを改造し,SSAOが正しく適用されるようにします. 対象となるシェーダで確認が必要な要件は以下の4つです.

  1. _MainTexという名前の2Dプロパティ
  2. _Colorという名前のColorプロパティ
  3. "Queue"="AlphaTest"のタグ
  4. "RenderType"="TransparentCutout"のタグ

ToonColor_DoubleShadeWithFeather_TransClipping の場合

*ユニティちゃんトゥーンシェーダー Ver.2.0.5以降で修正済みです.(2018/10/06)

3,4については問題ありません.1,2を追加する必要があります.

Propertiesブロックの先頭に次のプロパティを追記してください(図2).

_MainTex ("Albedo (RGB)", 2D) = "white" {}
_Color("Color", Color) = (1,1,1,1)

f:id:kuroiwasi:20181002114252p:plain

図2 シェーダにプロパティを追加した様子

次に,Unityのインスペクタ上で_MainTexに適切なテクスチャを設定してください(図3).

f:id:kuroiwasi:20181002114312p:plain

図3 インスペクタ上でテクスチャを設定した様子

すると,正しいAOがレンダリングされます(図4).

f:id:kuroiwasi:20181002114326p:plain

図4 レンダリング結果には正しいAOが適用されている(UTS2)

*ここで,_MainTexに適切なテクスチャを指定しないと,正しくAOが描画されず,アーティファクトが出現します(図5).

f:id:kuroiwasi:20181002114332p:plain

図5 _MainTexを設定しなかった場合.図形の周囲に不要なAOが現れている.

Mnmrshader1_3_Clippingの場合

1,2,3,については問題ありません.4について変更する必要があります.

SubShaderブロック内のTagsブロックに存在する"RenderType"の値を"TransparentCutout"に変更してください(図6).

f:id:kuroiwasi:20181002114339p:plain

図6 シェーダーを変更した様子

すると,正しいAOがレンダリングされます(図7).

f:id:kuroiwasi:20181002114346p:plain

図7 レンダリング結果には正しいAOが適用されている(MMS)

補足

この問題の根本的な原因は,SSAOに利用しているDepthNormalsテクスチャに正しく法線が描き込まれないことです(図8). DepthNormalsのためのビルトインシェーダーでは_MeinTexと_Colorに基づいて法線のカットアウトを計算しており,これらのプロパティを正しく設定する必要があります.

f:id:kuroiwasi:20181002114354p:plain

図8 DepthNormalsテクスチャのNormalを可視化した例.(左)対処前(右)対処後

また,どちらのシェーダーも裏面カリングをOFFにできますが,ポリゴンの裏面はDepthNormalsに法線が描かれないため,AOが透けたままです(図9).

f:id:kuroiwasi:20181002114404p:plain

図9 裏面は背景のAOが透ける

余談:Transparent系シェーダーに変更しポストエフェクトを回避する

オブジェクト全体にSSAOがかからなくてよいならば,シェーダーをRenderQueueおよびRenderTypeがTransparentのものに変更するという手もあります.

マテリアルに適用するシェーダーを変更するだけなので,簡単な方法です.

また,エフェクトを無視してしまうので,ポリゴンの裏表を問いません.

例)

  • UnityChanToonShader/NoOutline/ToonColor_DoubleShadeWithFeather_Transparent
  • MMS/Mnmrshader1_3_Transparent

RenderQueueがTransparentのシェーダーを持つオブジェクトはSSAOの処理を無視し,背景のSSAOが透けることなく描画されます.

ただし,オブジェクトにSSAOがかからないためシーン内の他のオブジェクトと見た目が異なるようになります.また,Cutoutの結果がオブジェクトの形状に影響を与えている場合に影が透過を無視した形になるという欠点があります(図10).

f:id:kuroiwasi:20181002114416p:plain

図10 Transparent系シェーダーを適用した結果

参考

http://amplify.pt/forum/viewtopic.php?f=23&t=455

https://answers.unity.com/questions/936165/transparent-cutout-ssao-problem.html

https://docs.unity3d.com/540/Documentation/Manual/script-ScreenSpaceAmbientOcclusion.html

*1:あくまでシェーダーに詳しくない筆者が対症療法的な対策をした記録であることをご承知おきください.本記事の内容よりも有効,または根本的な対処法が存在する可能性があります.