【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).
図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つです.
- _MainTexという名前の2Dプロパティ
- _Colorという名前のColorプロパティ
- "Queue"="AlphaTest"のタグ
- "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)
図2 シェーダにプロパティを追加した様子
次に,Unityのインスペクタ上で_MainTexに適切なテクスチャを設定してください(図3).
図3 インスペクタ上でテクスチャを設定した様子
すると,正しいAOがレンダリングされます(図4).
図4 レンダリング結果には正しいAOが適用されている(UTS2)
*ここで,_MainTexに適切なテクスチャを指定しないと,正しくAOが描画されず,アーティファクトが出現します(図5).
図5 _MainTexを設定しなかった場合.図形の周囲に不要なAOが現れている.
Mnmrshader1_3_Clippingの場合
1,2,3,については問題ありません.4について変更する必要があります.
SubShaderブロック内のTagsブロックに存在する"RenderType"の値を"TransparentCutout"に変更してください(図6).
図6 シェーダーを変更した様子
すると,正しいAOがレンダリングされます(図7).
図7 レンダリング結果には正しいAOが適用されている(MMS)
補足
この問題の根本的な原因は,SSAOに利用しているDepthNormalsテクスチャに正しく法線が描き込まれないことです(図8). DepthNormalsのためのビルトインシェーダーでは_MeinTexと_Colorに基づいて法線のカットアウトを計算しており,これらのプロパティを正しく設定する必要があります.
図8 DepthNormalsテクスチャのNormalを可視化した例.(左)対処前(右)対処後
また,どちらのシェーダーも裏面カリングをOFFにできますが,ポリゴンの裏面はDepthNormalsに法線が描かれないため,AOが透けたままです(図9).
図9 裏面は背景のAOが透ける
余談:Transparent系シェーダーに変更しポストエフェクトを回避する
オブジェクト全体にSSAOがかからなくてよいならば,シェーダーをRenderQueueおよびRenderTypeがTransparentのものに変更するという手もあります.
マテリアルに適用するシェーダーを変更するだけなので,簡単な方法です.
また,エフェクトを無視してしまうので,ポリゴンの裏表を問いません.
例)
- UnityChanToonShader/NoOutline/ToonColor_DoubleShadeWithFeather_Transparent
- MMS/Mnmrshader1_3_Transparent
RenderQueueがTransparentのシェーダーを持つオブジェクトはSSAOの処理を無視し,背景のSSAOが透けることなく描画されます.
ただし,オブジェクトにSSAOがかからないためシーン内の他のオブジェクトと見た目が異なるようになります.また,Cutoutの結果がオブジェクトの形状に影響を与えている場合に影が透過を無視した形になるという欠点があります(図10).
図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:あくまでシェーダーに詳しくない筆者が対症療法的な対策をした記録であることをご承知おきください.本記事の内容よりも有効,または根本的な対処法が存在する可能性があります.