UnityのShader Graphで透明なシートを作りたい。

やりたい事

単純なメッシュ形状を、透明にしてシート状にみせたいとき、メッシュの裏面も表示しないと。なんの形だか分からないものになってしまいます。シェーダグラフで「透明」かつ「裏面も描画」するには工夫が要るので紹介。

失敗例:Shader Graphの両面描画

今回は表面の色だけを弄るので、PBR Graph shaderを使っています。Shader Graphの両面描画(Two sided)はCull offで実装されています。メッシュ表裏のどちらの面を塗るかの判断をしない、というものでキャラクターのスカートとかに使う説明が多いです。

このTwo sidedをOnにすればOKのように思いますが「透明物体」に限っては罠があります。alpha=0.1ぐらいなら目立たないので気が付かないかもしれません。

これをalpha=1にしてみましょう。

alpha=1のときに作りたい映像は以下です。

対応策

対応策はUnity のマニュアルに書いてあるとおり1回目のPassでCull Frontで描画して、その次のPassでCull Backで書けばOKです。シェーダーグラフには今のところそのための設定はないようです。

https://docs.unity3d.com/ja/2018.4/Manual/SL-CullAndDepth.html

シェーダグラフからコードに変換

shader graphからshader言語に変換して、コード上で書き換えます。変換はMasterノードを右クリックで「Show Generated Code」です。

以下のようにAssetsフォルダで適当なシェーダをスクリプトを作成して、中身をGenerateされた中身に置き換えればそれだけでシェーダとして動きます。

名前の変更

そのままだと、Generateしたシェーダの名前は「PBR Master」になってしまいます。1行目のPBR Masterを「MyShader/Name」など分かりやすい名前にしましょう。命名は/区切り入れるのが普通っぽい。

コピペ部分をincludeにまとめて出す

必須ではないですが、Cull Front/BackにPassをわけて同じ処理を書きます。後からの追加手修正の可能性を考えると、共通部分はまとめたほうがらくかもしれません。コピペ修正の対象なるPassは”Lightmode” = “univarsalFroward”がかいてあるPassです

まとめて出すコードはHLSLPROGAMからENDHLSL部分ですが、pragma部分はくくりだせないので、pragma部分が終わりDefineが始まる所から括りだしはじめます。

 まとめだしの最後はENDHLSLの直前までです。

以上を切り取りして、適当にhoge.hlslとか名付けたファイルに突っ込んでshaderと同じフォルダに突っ込みます。切り取った跡地には#include “hoge.hlsl”を記述すれば、グラフシェーダーで作った通りのshaderが動いているはずです(長い行数のコピペミスが多いので、一旦この段階で確認するの推奨)。

Cull Front/BackのPassを作る

最初のパスの描画であるFrontについてはCull Back(もしくはoff)をCull Frontに書き換えるだけです。

上のpassをコピーして、Cullの設定をbackにします。2回目の描画はDPRDefaultUnlitで描画しています。SRPのマニュアルにあるようにこのパスは本来オブジェクトの周りに外枠などを書く時の後処理用のpassです。今回はそのpassを流用しています。(以下補足2に流用しない方法かいてます)

以上でちゃんと1回目で奥側のcullingを描画して、そのうえに表側を描画できるはずです。

補足1:光と影

比喩ではなくて、Shaderかんけいないですが・・・半透明物体だから光とか良い感じに減衰して伝搬してくれるわけじゃないです。透明フィルムのときは当該オブジェクトのCast shadowをoffにするのがお勧めです。

同様に、光の反射もまともにあるのは物体の中で、一番手前の部分のみです。あと、URPを使ってビビるのはcast shadowをONにしててもスポットライトなどの影が投影されないことです。

単純にデフォルトの設定がadditional LightsのCast Shadowを処理しないようになってるだけなので、スポットライトなどの影を映したいときは気をつけましょう。Assetsフォルダ直下にUnisersalRenderPipelineAssetとあるのでそこが設定ファイルです。

補足2:DRPDefaultUnlitが埋まっている時は?

流用が気持ち悪いとか、すでに枠表現などで使ってる場合もあるでしょう。そんなときはSRPに処理対象のタグを追加します。shader側は単純にLightmode名を決めるだけです。

ここでは適当にfffとしました。でAssetsフォルダ直下のUniversalRenderPipelineAsset_Rendeereを開いて追加で処理passを追加します。設定を記入する「NewRendereObjects」自体がない場合は一番下の「AddRendere Feature」で追加します。

設定すべきはEventとShaderPassesです。今回はTransparent描画の後にcull Backの処理を追加するのでAfter~~~Transparentsを選びます。あとはshaderで設定したLightmode「fff」を設定して終わりです。

補足3:今回のグラフシェーダ

こんなかんじです