TOP > Unity > 自作シェーダー 前編

自作シェーダー 前編
[ Unity ]

UnityでToonなシェーダーを自作して自分が満足できるまでいじった話。
書いてたら長くなって疲れたので前後編に。


はじめに。

今回はモデル作成からの流れでUnityのシェーダを自作した話です。
最初は適当にネットで落ちているものを参考にコピペすればいいやと思っていたんですが、触っているうちにあれもしたいこれもしたいとなって、気づいたら色々いじってました。
どんなことをしたのか、備忘録的に書いておきます。

後編はこちら

Toon(とぅーん)

まずはベースになる「Toon」から。
「Toon」とは...つまりアニメっぽい感じです。
たとえばこんなかんじ
  • 左:Standard
  • 右:Toon
  • toon
    明暗がハッキリクッキリとします。

    これについてはこちらのサイトを参考に作成
    Rampテクスチャの色を白〜黒にして使用しました。
  • 【Unityシェーダ入門】トゥーンシェーダを自作してみる
  • アウトラインの付け方

    アウトラインは、絵でいうところの主線ですね。線画情報。
    「法線方向に押し出す」がよく使われている手法らしいんですが、それだとカクカクしたモデルで隙間ができる問題が付いて回るらしいですね。
    でもこの記事でデレステがこの方法だと書いてあったのでとりあえず試してみました。

    こちらを参考に実装しました
  • Unityでシェーダー描いてみたい
  • outline1
    しかし、これだとなんか物足りない...。

    そこで色々探した結果(それまで目を反らしていたともいう)ポストプロセスという手法も検討することにしました。
    ポストプロセスとは...なんかカメラ側で撮影した画像をあとから調整する感じ?
    撮影後加工?そんなかんじだと思ってる。

    で、色々探してこちらを参考にさせていただくことに。
  • 【Unity】セルシェーディングを1から作ってみるメモ その3 脱Post-process【Shader】
  • outline2
    これはいい感じなので、アウトラインはこれで決定。

    ちなみにアウトライン色は単に黒ではなく、RGBをHSV変換して少し暗くした色にしています。
    参考はこちら
  • 【Unity】RGBをHSVに変換して明るさとかを変えるシェーダー

  • 正直、シェーダーの実装、ここまででもいいんじゃないかな?とか思ってました。
    この時点でよくわかってなかったし。

    法線マップ

    色々あって、法線マップを適用したくなっちゃいました。
    法線マップとは...まっ平らな面に凸凹の情報を与えられる魔法のような仕組みです。
    参考はこちら
  • Unity シェーダーチュートリアル ノーマルマップ
  • この何もない壁が
    wall1
    法線マップ適用で突然それっぽくなります
    wall2

    個人的に、途中でふざけてレンガを適用したゴブリンがけっこう気に入ったり。
    goblin

    ハイライト...?

    とてもアニメっぽい表現になったし、法線マップも適用できたし、もういいかな?と思ったところで気づきました。
    ハイライトがない。
    これまで色々シェーダーをいじりながら調べたのでだんだんわかってきてます。
    ハイライトを入れるなら、スペキュラーとグロスをいじればいいかな?
    ということで適用したのがこちら
    highlight1

    ・・・なんか物足りない。(二度目)

    光り方が自然すぎて、逆になんか変というか、アニメっぽくなくなってる気がします。
    アニメっぽいハイライトってなんだ。
    視点がどうこう関係なく、なんかこう白くなるアレ。アレがほしい。
    (注:R18的なアレを隠す魔法の光ではない)

    ということで、ここはRampで対応することにしました。
    (壁の色が変わったのは、前回撮影までColorを適用するのを忘れていたから...。あまり影響ないので気にしないでください)
    highlight2

    The 露骨!

    うん、これくらいの方が好み。いいかんじ。
    ちなみに実装方法はRampテクスチャをこうしておいて
    ramp
    取得できた値を2倍して適用してます。
    一番右がRGB(172,172,172)。右から2番目がRGB(128,128,128)。 これにより255以上の数値を取得してめっちゃ明るくして光らせてます。
    一番左はRGB(0,0,0)なので2倍しても0。一番濃い影は真っ黒のままです。
    手法として正しいのかはわかりません...。

    しかし、見た目は好みなので、ヨシ!

    影が出ていない!

    ハイライトを入れた後に気づきました。
    この人たち、影が落ちていないんです...。おばけかな?
    shadow1

    まずはなぜ影が落ちていないのかの調査から・・・も何も、Toonで参考にさせてもらったサイトではCustom Lighting Modelでatten(=attenuation, 減衰)を無視してますね...。
    これを適用してあげれば、影が落ちました。

    shadow2

    (なんかさらっと書いてますが、これに気づくまでには結構時間がかかりました。だってattenが何かなんて気にもしてませんでしたから。使ってないなら要らないんだろ、くらいに。)

    影の単純化(前編)

    さて、ここまでやれば今度こそもういい感じかな?と思ってじーっと画面を眺めていて、ふと思いました。

    画 面 が 濃 い
    shadow3

    なんか影が邪魔。すごく邪魔。画面的に煩い。
    なければ文句を言い、あったらあったで文句を言う。わがまま。

    ここで思いつくのは、影を落とすのをやめて丸影にしようという考え。
    頭の中ではRagnarokOnlineの影を想像しています。
    「足元に丸い影さえあればいい」。

    じゃあどう実装しよう?と考えた時に思いついたのは次の2パターン
  • 影を落とすのをやめて、足元に半透明の黒い丸を置く
  • 影を落とすのをやめて、代わりに影を落とすオブジェクトを置く

  • 同じようでいて影の実現方法としてはちょっと違います。
    実際に影を落とすか、そもそも影をオブジェクトにしてしまうかの違い。

    1つめをやるとジャンプとかした時に影オブジェクトだけ床に置いてくるの面倒くさそうなので却下。影が落ちる位置に段差があると影が浮く不具合もありそう。

    2つめもうどうかなぁ...なんて思いながら調べてみると、同じことを考えた人がいたらしく以下の記事を見つけました。
  • 【Unity】影の表現を軽量化するアイディア

  • ふむふむ。カプセルを利用。
    そしてどうやらこの方法は処理の軽量化にも一役かうようですね。
    ついでにProjectorなんて方法があることも知ったけど無視。

    ただ、「SkinnedMeshRendererのCast ShadowsとReceive ShadowsをOFFにする」が気になりました。
    「Receive ShadowsをOFFにする」とどうなるか。
    せっかく前項で影を落としたのに、建物の影に入ってもキャラクターが影を受けなくなってしまいます。

    左:Receive ShadowsをON
    右:Receive ShadowsをOFF
    shadow4

    これなら左がいいに決まってます。
    ということは、なんとかして自分に影が落ちないようにしながら影用にMeshRendererなオブジェクトをおけばいいということ...なのかな?

    ということで試しました。とりあえずカプセル。
    キャラの影描画をOFFにして、カプセルはShadow onlyに。
    サイズと位置を調整して...Cull Frontすればいいじゃん、と専用のshaderを作成。
    結果がこちら

    左:カプセルそのまま配置。足元にカプセルの影が落ちて暗い
    右:Cull Frontした図。前面がないせいで影の開始位置が遠い
    shadow5

    だめだこりゃ...。

    とりあえずこの時点ではカプセルサイズを小さくして、なるべく違和感を無くして妥協することに。

    最終的にはカプセルをやめて影用オブジェクトを自作してますが、長くなってきたので続きは後編に。

    まとめ

    次回へ続く

    後編の内容
  • 影の調整
  • 透過する物体
  • 金属っぽさを出したい
  • 作業日
    2020/04/28 〜 2020/05/05




    • Unity

    TOP > Unity > 自作シェーダー 前編

    Page Top