読者です 読者をやめる 読者になる 読者になる

Onoty3D

Unityに関するメモとか

白枠が描画されるシェーダーを作ってみる

先日ネットをウロウロしている時に、この動画に出会いました。

セルルックなミク動画ですが、ミクを囲む白枠がパネルやシール感を演出し、より2Dっぽく見せています。

MMDに関しては無知なので、この動画ではどのようにこの演出をしているかは不明ですが、Unityの場合はステンシルバッファを利用したマスキングで上手く表現できるのでは、と思いShaderを作成してみました。
ToonOuterFrameShader
なお、浅学なためShaderの記述は無駄や間違いがあるかもしれません。ご注意ください…。

ベースは「Toon/Basic Outline」及び「Toon/Lit」シェーダになります。
これらに手を加え、Outlineの外に更に白枠、さらにダミーで影を描画出来るようにしました。通常の外部ライトによる影はモデルそのものの影しか描画されませんが、本件では白枠を含んだ形のままの影が出ないとパネル感が薄れるため、Shader内でダミーの影を描画しています。

公開したUnityPackageをインポートするとOnoty3D/Shaders配下に以下4つのShaderが取り込まれます。Shader名としては"Onoty3D/Toon/~"といった名前になります。

1. ToonLit : Toon/Litにステンシルバッファへの書き込みを追記したもの
2. ToonLitOutline : Toon/Lit Outlineにステンシルバッファへの書き込みを追記、Outlineの描画はToon/Basic Outlineから移植(UsePassせずにToon/Basic Outlineへの依存を切り離し)
3. ToonLitOuterFrame : 1.にステンシルテストおよびバッファへの書き込みと、白枠/影描画処理を足したもの
4. ToonLitOutlineOuterFrame : 1. 2. 3.の合体

白枠を描画させる場合は3.か4.をご利用ください。
4.を利用したマテリアルを適用すると、以下の感じになります。

適用前
f:id:onoty3d:20151202131859p:plain

適用後
f:id:onoty3d:20151202131930p:plain
※Toon Shaderは内部で影を描画するので、メッシュのReceive Shadowsはチェックをはずした方がいいです。また、ダミーな影を落とすので、Cast ShadowsもOffにしていたほうがいいです。

白枠や影はOutlineと同じ理屈で描画した場合、複数オブジェクトを配置したりすると白枠や影が別のオブジェクトに重なってしまうので、ステンシルバッファを利用して外枠だけが描画されるようにしました。

Outlineと同じ理屈で描画した場合
f:id:onoty3d:20151202132023p:plain

ステンシルバッファ利用(Outlineは他オブジェクト上でも描画されるが、枠と影は描画されない)
f:id:onoty3d:20151202132054p:plain
※後述のパラメータ(ステンシルのリファレンス値)の設定次第で、あえて重ねる事もできます。

弱点としては、Toon/Basic Outlineと同じ方法で枠を太らせているので、平面が鋭角で交差するようなオブジェクトに適用すると線が途切れて残念な感じになります。とりあえずこれはこのまま。
f:id:onoty3d:20151202132403p:plain
参考:Unity のトゥーンシェーダについて調べてみた - 凹みTips

 

以下パラメータ説明

f:id:onoty3d:20151202132558p:plain

標準のToon/Basic Outline、Toon/Litにあるパラメータ以外だけ説明します。

Cull Mode
描画のCullingのモードです。0/1/2 = OFF/FRONT/BACKとなっています。
【2015/12/14 追記】選択肢にする方法を覚えたので、最新版ではスライダーからドロップダウンに変わりました。

f:id:onoty3d:20151214200945p:plain

Stcl Ref Main/Outer Frame/Shadow
ステンシルのリファレンス値です。Mainがモデルそのものの描画、Outer Frameが外枠、Outer Shadowがその影の値です。
バッファの値よりリファレンス値が大きかった場合に描画を行います。
Main>Outer Frame>Outer Shadowになるような数値であればなんでもいいです。
他のShaderと干渉するような場合に数値を変えてみてください。

Outer Frame Color/Width
外枠の色と太さです。白枠以外にも、好きな色に変更できます。

Outer Shadow Color/Offset
影の色と位置です。位置はX,Y以外は数値を指定しても意味はありません。

プロ生ちゃんに適用すると、こんな具合になります。

f:id:onoty3d:20151202132651p:plain

f:id:onoty3d:20151202132659g:plain