LoginSignup
50
35

More than 1 year has passed since last update.

【Unity】lilToonのTipsなど

Last updated at Posted at 2021-07-13

先日私がリリースいたしましたUnity向けシェーダー「lilToon」についての話です。
公開直後ながら既に多くのご支援をいただいており、心より感謝申し上げます。
今回の記事はlilToon向けの話になりますが、BlendingやステンシルやVR向けのシェーダー処理の解説も含まれており、他シェーダーにも応用できる内容も含まれておりますので是非ご活用ください。

目次

Blending関連

乗算合成

  1. 透過モード半透明にする
  2. 詳細設定から基本設定を開く
  3. Unlit化を1にする
  4. 詳細設定からレンダリング設定を開く
  5. Forwardを開きSrcBlend RGBZeroに、DstBlend RGBSrcColorにする
  6. ForwardAddを開きSrcBlend RGBZeroに、DstBlend RGBOneにする

(解説)
まず、二重にライティングされて暗くなるのを防ぐためにUnlitのシェーダーを用いる必要があったのでUnlit化しています。
そしてBlendについてですが、Srcがシェーダーで計算した色、Dstが既に描画されている色を表しています。
SrcBlend RGBZeroに、DstBlend RGBSrcColorにする』という操作で、Src * Zero + Dst * SrcColor = Dst * SrcColorとなり乗算合成となるわけです。

ステンシル関連

照れシェイプキーや前髪の影を肌の上だけに出す

  1. 肌のマテリアルを選択
  2. 詳細設定からステンシル設定を開く
  3. Refの数値を0以外にし、PassReplaceにする
  4. 肌の上に描画したい物のマテリアルを選択
  5. Refの数値を肌で設定したものに合わせ、CompEqualにする
  6. レンダリング設定からRenderQueueの数値を肌のマテリアルより大きい数値にする

オブジェクトの縁だけにアウトラインを出す

  1. 詳細設定からステンシル設定を開く
  2. Refの数値を2つとも0以外にする(数値は合わせる)
  3. 上にある本体側のPassReplaceにする
  4. 下にある輪郭線のCompNotEqualにする

【2021/07/20追記】ステンシルを半透明にする

ここでは眉毛を髪の毛の上に描画する場合の手順について解説します。
1~6までは普通のステンシル設定なのでわかる方は読み飛ばしてください。
1. 眉毛のマテリアルを選択
2. 詳細設定からステンシル設定を開く
3. Refの数値を0以外にし、PassReplaceにする
4. 髪のマテリアルを選択
5. Refの数値を眉で設定したものに合わせ、CompNotEqualにする
6. レンダリング設定からRenderQueueの数値を肌のマテリアルより大きい数値にする
7. 髪のマテリアルを複製
8. 髪のメッシュのMaterialsSizeを2に増やし、Element 1の方に複製したマテリアルを割り当てる
9. 複製したマテリアルを選択
10. 透過モードを半透明にする
11. シェーダーを_lil/[Optional] lilToonOverlayに変更
12. Refの数値を眉で設定したものに合わせ、CompEqualにする
13. 透明度を調整する

(解説)
ステンシルというのはスクリーン上で行えるマスク操作のようなものです。
オブジェクトを描画する際に色や奥行き情報が書き出されますが、一緒にステンシルの数値を書き出すことで様々なマスク操作を行うことができます。
Passというのは数値をどのように書き換えるかの設定で、例えばKeepならもともとあった数値をキープしますし、ReplaceならRefの数値に置き換えます。
Compはどのような条件でオブジェクトを描画するかの設定で、Alwaysならオールウェイズ描画してくれますし、NotEqualならRefとイコールじゃないときに描画します。
照れシェイプキーや髪影の設定はアーティスト視点から見ても結構気になる部分なので、クリスタのクリッピング感覚でマスク処理できるというのは知っておくだけで役に立つと思います。
【2021/07/20追記】
ステンシルを半透明にする方法を追記しました。
シェーダーのパス数を増やせば同様のことを行えますが、URPではパイプラインの編集が必要になるためマテリアルを分けています。
今回使用したlilToonOverlayはメインパスのみ使用するシェーダーになっているため普通のシェーダーを利用する場合より負荷を抑えられます。

その他

環境光を無視して常に影を出す

  1. 詳細設定から影設定を開く
  2. 環境光の強さを下げる

(解説)
この環境光の強さは影の色だけに影響し、アバター自体の明るさに影響はありません。
lilToonではStandardShaderに近づけるためにEnvironment Lighting(環境光)を取得して影の色を補正するようになっています。
なので、StandardShaderが明るくなる状況ではlilToonも明るくなって影が薄くなります。

indirectCol = lerp(indirectCol, albedo, environmentLighting * _ShadowEnvStrength);

輪郭線の太さを一定にする

  1. 詳細設定から輪郭線設定を開く
  2. 太さを補正のチェックを外す

(解説)
距離に応じた太さの補正が無効化されます。
カメラがキャラクターに近づいたときに線が太くなり気になることがありますが、ワールド空間でのカメラ座標と頂点座標の距離を元に太さを補正することでこの問題を緩和できるようになっています。

if(_OutlineFixWidth) outlineWidth *= saturate(length(_WorldSpaceCameraPos.xyz - positionWS.xyz));

ワールドに関係なくガチ恋距離

  1. 詳細設定からシェーダー設定を開く
  2. 距離クリッピングキャンセラーをオンにしてApply

(解説)
普通にゲームや映像を作っている分にはクリッピング距離はそこまで気になりませんが、VRでは「顔を近づけて物を見る」という場面が出てくるので近づくと消えてしまうのは没入感を下げてしまう要因になるかと思います。
カメラ側でクリッピング距離を小さくしてあげるのがベストですが、クリッピング距離近くなったときにメッシュを圧縮するような処理を加えることでも回避できます。

#if defined(UNITY_REVERSED_Z)
    // DirectX
    if(output.positionCS.w < _ProjectionParams.y * 1.01 && output.positionCS.w > 0) output.positionCS.z = output.positionCS.z * 0.0001 + output.positionCS.w * 0.999;
#else
    // OpenGL
    if(output.positionCS.w < _ProjectionParams.y * 1.01 && output.positionCS.w > 0) output.positionCS.z = output.positionCS.z * 0.0001 - output.positionCS.w * 0.999;
#endif

アルファマスクを使いたい

焼き込みのみの対応となっていたため、次バージョンで追加いたします。
焼き込みは透過マテリアルにした際にメインテクスチャの下に現れるアルファマスクを焼き込みから行えます。
【2021/07/16追記】
lilToon v1.1にてアルファマスクに対応いたしました。
アルファマスクを割り当て後にスライダーで透明度の調整、調整したテクスチャの焼き込みが行えます。

顔だけ明るかったり暗かったりする

開発中から気になっていたのですが、これはNot Importantなスポットライト(頂点ライト)では形状を考慮できないというUnityの仕様によるものです。
次バージョンで頂点ライティングを無効化するプロパティを追加して、Avatar3.0のメニューなどから状況に応じてオンオフできるようにします。
回避策が見つかり次第修正したいところですが、ポイントライト・スポットライトを区別できる変数はなさそう……?
【2021/07/16追記】
lilToon v1.1にて頂点ライトの強度が調整可能になりました。
基本設定より頂点ライトの強度を0にすることでこの問題の修正ができます。

50
35
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
50
35