自分の理想のセルシェーダーを作りたいんですけお 進展あったら下に追記をしていく
閉じる
閉じる

新しい記事を投稿しました。シェアして読者に伝えましょう

×

自分の理想のセルシェーダーを作りたいんですけお 進展あったら下に追記をしていく

2019-05-08 04:03


    きっかけとしてそもそも自分の欲しい表現が組み合わさったセルシェードがなかった
    (機能の一つ一つはどこかのゲームで実装されてるとか、配布されているシェーダーでできるとかですでにある機能)
    ので自分の必要としている機能を組み合わさったのが欲しい
    というので自分なりに頑張ってみた現状が上の画像


    現状の機能として

    1・陰領域、光領域に別々のカラーテクスチャを張ることでの色合いコントロールができる
    現状ライン部分にもテクスチャ張れるようにしているが、これは陰テクスチャに乗算で色を暗くしてあげるだけでいいかもと思っている

    2・ギルティギアであるようなセルシェード用に極端にいじったノーマルと
    押し出しで作成するライン、ハイライト用として形状そのままのノーマルを併用できる
    ただし、ライン、ハイライト用はハードエッジ箇所作れずすべてソフトエッジ
    ハードエッジだと押し出しラインが角で途切れるのを防ぐため
    [Unity] 綺麗なアウトラインシェーダーを作る(このページの理由1を参照)
    またハイライトもこちらのノーマルを使用するのは
    顔などで情報を削るためにノーマルを真っ平らにした時に
    スペキュラも真っ平らなノーマル部分一面にべったりついてしまうのを防ぐため

    3・リムライト+通常のハイライトと角部分にのみハイライトが出る部分を専用テクスチャマスクでコントロールできる
    これは最初から思ってたわけではなく、作ったシェーダーを立方体にあててみたときに
    どこかの面がべったりハイライト色になるのがよろしくなかったため&むしろ手前の角にハイライトほしいと思ったので対応

    そのほか陰領域の広さ、ハイライト領域の広さ、線の太さなどのコントロールパラメーターは一応実装


    で初めてシェーダーを書いてみて
    頂点シェーダー?フラグメントシェーダー?内積は方向が一致してるかどうか出せるやつだということは知ってる
    外積?行列?セマンティクス?
    みたいなところはたっぷりあってだいぶ調べたりもしたんだけども
    そういうどんなシェーダーでも調べなきゃいけないことややらなきゃいかん部分は
    いまだに認識がふわっふわっなので間違った人認識で長々書くことでもないと思う
    ので自分なりに考えた、もしくはほかの方のアイディアを組み合わせた部分だけメモしようと思いましたマル
    (そもそも書いている途中に一回止まって消えたとかもあるのでできるだけ短くしたい……)

    あと割この時点でもと専用のマスク情報とか頂点色情報とか利用しないとどうにもならなくて
    そりゃ配布されているようなセルシェーダーでそんなくそややこしい情報自作しないと最低限の表現もできないよ!みたいな状態になるなら
    自分の理想の機能セットなんか自作でもせんとないわなとか
    (自分のやり方が悪いだけの可能性大とかだけども)


    1のそれぞれの領域で別々のテクスチャを貼るは
    ほかの方が書かれたセルシェーディングを作るための記事を見て少し改変する程度で実装できたので省略
    貼ってある画像は水色と濃い青色の二色なのでなんだけどもこの色はべた塗り1色のテクスチャ貼っているからでテクスチャは貼れている状態


    2についてなんだけども
    前に自作ゆかりさんを作った時に顔とか髪とかのノーマルをセルシェーディング用にいじるということはやってみていて
    その時に「これやっちゃうと法線方向押し出しで作るラインが変な方向に厚みついちゃうじゃーん!?」とか「tda式にあるようなリムライト表現入れたいのに法線いじったせいでリムライト表現がおかしくなっちゃうじゃーん!」とかあったので
    そのときは法線いじる前のメッシュであらかじめ押し出しておいてラインをもうメッシュで作っておいてしまうとか
    リムライトも薄い半透明のポリゴンを重ねることで、そっちでは法線いじらないことでリムライトをそっちでつけるとかでやってたんだけど
    そういうくそめんどくさいうえにポリゴン数三倍界王拳だー!とかなのは避けたいですよね
    とおもったので今回やってみることに

    で、要するに二種類のノーマルを保持できればやりたいことはできるわけなんだけども
    最初は「メッシュ本体の持っているノーマル(セルシェード用)」に「オブジェクトスペースノーマルマップ(ハイライト、ライン用)」をつかえばいいじゃん!と思っていたのだけども
    オブジェクトスペースノーマルマップはどうもunityでは対応していない模様……
    (UE4もだけど)
    どういう風に対応してないかは以下の記事が詳しかったので参考
    SkyrimとUnityとオブジェクトスペースノーマルマップ
    要するにボーンの情報をシェーダー側でとれないから
    ボーン回転で変形した分の法線の変化を入れ込めないということっぽい(雑な理解)

    でどーするのかというとこれまた同じ方の記事で
    「Unity+Skyrim でオブジェクトスペースノーマルマップを活用する」動画の補足
    を参考にして
    ただ自分はあくまで頂点単位で法線情報を持てればいいので
    ノーマルマップをテクスチャでなく頂点カラーとして持つことにした
    (これは最初のオブジェクトスペースのノーマルの時から思っていた部分)
    でタンジェントスペースのノーマル情報を頂点色生成するのにBlenderのスプリクト側で計算してあげないと駄目だったので
    それはこれまた以前ゆかりさんの時に作成した頂点色とオブジェクトスペースノーマルで情報をやり取りするスプリクトに追加で記述
    計算式は上の記事の方が参考にしたというサイトのを自分も参考という名の丸パクリ
    うにばな(ノーマル(法線)基本 と ノーマルマップ合成)
    blenderのpython久々にいじったので多少躓いたというかいまだに誤動作的なことが発生して変な色がつく場合があったりするのだけどなんとかここはうまくいった

    球体のノーマルを転写で焼き付けた状態の立方体(左)と
    そのノーマルを本来の形状+すべてソフトエッジに戻してやるためのノーマル色(右)


    逆にタンジェントスペースを反映してやるというか戻してやるというかをシェーダー側で実装しなきゃいけないんだけども
    そちらの参考
    法線マップと接空間
    新卒エンジニアが Unity でバンプマッピングに挑戦してみた
    その12 頂点座標とUV座標から接ベクトルを求めるちょっと眠い話
    で最初わからなかったのがどちらのブログでもライトの情報をタンジェントスペースに持ってきてあげてとかやっているらしいというところで
    これはノーマルマップが画像だからフラグメントシェーダーのほうでピクセル単位で計算しないとダメなんだけど
    ピクセル単位でタンジェントスペースをオブジェクトスペースに反映させる(戻してやる)という計算は割と重いらしく
    むしろライトをタンジェントスペースに持ってきてあげてから
    ライトとノーマルマップ画像の内積(方向の一致)だけをピクセル単位で計算したほうがはるかに軽いからということらしくどうもこれが標準的な方法?
    ただ自分はノーマルマップという画像でなく頂点色に入れているから
    頂点単位の計算だけで済むというのが一点と
    そもそも法線方向押し出しのアウトラインについて、法線方向に頂点を押し出して移動させるのが
    頂点シェーダーじゃないとできない話でフラグメントシェーダーに移動してから計算ではタイミング的に遅いというのが一点
    (何となく頂点色にノーマル情報入れようと思ってたけども、この方法じゃなかったらこれができなかったということで結果的によかった)
    のため、参考記事からはやり方を改変というかより単純化して処理した

    メッシュに焼き付けたノーマル+頂点色として入れ込んだノーマルでオブジェクトスペースのノーマルマップとして補正できているのが視覚的に色で確認できる状態(左)と
    それを利用して法線方向押し出しでのアウトラインを形成しつつ
    陰影は焼き付けた球体のノーマルを使用している状態(右)


    あともう一つ自分が勘違いしてたポイントだったのでメモしておくけども
    一点目として
    しっかりとした計算まで理解できたわけじゃないのもあって
    「行列をノーマルマップに積算するとタンジェントスペースからオブジェクトスペースに変換できる」
    という認識で
    これが「この状態でやっとメッシュ本来のノーマルと合成可能な同条件のノーマルになった」ということだとばかり思ってたんだけども
    この行列というのはノーマル、副ノーマル、タンジェントで構成されていて
    ということはすでにメッシュ側のノーマルは考慮されているわけで
    「オブジェクトスペースへの変換と同時にメッシュのノーマルとの合成も行っている」
    という認識が正しいっぽい
    (最初はこの辺がわかってなくて「どうやってここから合繊するんだ?」と足したり掛けたりしていたふわふわ具合)

    二点目として行列に入れ込むノーマルの値はどのブログ記事でもだいたいノーマライズかけているけども
    自分の場合だとノーマライズかけちゃうと逆にずれてしまうようで?(自分のやり方のほうがそもそもどこか間違っている可能性が大きい)
    ノーマライズをかけないで行列に入れ込んでやると上画像のようにノーマルの色合いが完全に合った
    (ふわふわすぎるけどもシェーダー的にはノーマライズ処理ないほうが軽いだろうし結果オーライ??)

    でここまでできたので実際にボーン変形したときにもうまくいくのかをテストしたのだけど
    ここでまたうまくいかなかった
    シェーダーもしくはblenderスプリクトのどっちかが間違っているのかといろいろ調べて試したのだけども
    結果的にfbx出力時のオプション設定が原因だったらしい??
    BlenderでUnity向けにFBXをエクスポート:メッシュ編
    この記事の最後のほうに座標系の変換の項目があるのだけども
    これを正しく設定してあげないと(ボーン入れた時だけというのがわからんけども)ノーマルが狂うというかなんかベースとしてのメッシュ側ノーマルの色がかなり強くなる感じで
    合成結果も当然おかしくなっていたということのようだった
    (「!実験的機能!トランスフォームの適用」というオプションを使うのは怖いけどこれ入れないと話にならないっぽい?)
    逆にボーンない場合はこれ必要はないっぽいのだけども
    入れたほうが正常な状態で出力できているようなのでいれておくのがベターなのかなぁ??


    ただまぁこれでやっとボーン入れても二種類のノーマルを確保して動作するシェーダーになった
    (手前の曲がっているのと奥のまっすぐなモデルはunity上でボーン変消させただけで同じモデルデータ、ラインも途切れずにしっかり表現できている)


    で、3のリムライトとハイライトの領域と、角部分にだけハイライトが出るようにとの部分だけど
    これは力押しで微調整の処理を加えてとかで行き当たりばったりな感じ
    ただ逆に難しいことなどはしてないので微調整内容だけメモしておく


    まず最初は自作ゆかりさんでそうしたように「ハイライト+リムライト」で作成したのだけど
    立方体だといい感じにならなかった
    (リムライトの要素が上面すべてにべったり広がってしまうのと、
     立方体も形状通りを使うようにしているとはいえライン描写側の都合上ソフトエッジ的なノーマルを使用しているので奥側角の周辺に違和感のある形でリムライト領域が広がる)

    また画像だと立方体の側面に角がある状態だからまだいいけど
    来方向から見て影がない部分しか見えなくなった時に
    どこが手前側の角だか認識できないというのもあって
    立方体みたいなまっ平ら+角のあるものには別の法則でハイライト出さないと駄目だ、となった

    最初は角がある部分、平らな部分は曲率マップをベイクして
    それをもとに判定してあげればいいのではとか思って曲率ベイクする方法調べて試したりしたのだけども
    最終的にサブスタンスの体験版ダウンロードしてベイクしてみたときに
    球体の表面と立方体の平らな面で
    グレースケールで焼かれた曲率マップの値がフォトショップ上で50%と49%とかで
    1%しか違わないものをうまく処理できるはずがない&曲率マップをベイクするソフトがそもそもあまり見当たらないのでサブスタンス以上の精度で焼いてくれるソフトがあるのかとか
    あったとして(これはサブスタンスでもそうだけど)曲率マップのためだけに購入すんの?
    と会考えると断念したほうが良さそうだった

    結局手書きで専用のマスクテクスチャを作って、
    Rチャンネルに角がどこか(というよりはハイライトのマスクでハイライト出したくない場所を黒くする、角以外もハイライト出したい曲面もマスク範囲に入れることになる)のマスクを
    Gチャンネルにリムライト+ハイライトで処理する部分とそうでない部分を分けるマスクをという形にして張り付けた

    角のハイライトがぶつ切りっぽくなったり
    普通のハイライトも足し算で載せてたらハイライト範囲の終わり際が変に目立ったりしてたのを計算方法変えたりして調整したのだけども
    この辺は変なことをしたわけではない(と思う)ので割愛


    一つだけシェーダー側の処理ではどうにもならなさそうだったので
    モデル側でどうにかした点だけども
    こういった円柱のような曲面と角と平らな面があるものについて
    専用マスク画像はそれぞれ曲面と角を指定するように塗ればいいのだけども
    普通にやると側面の曲面はリムライト+ハイライト領域なので
    上の画像でも下側にちょっと出ているけどもこういった角部分にもリムライトをもとにしたハイライト領域がかなり広範囲にべったり広がってしまう(例によってソフトエッジのノーマルを使用しているため)
    上の画像はこれなら個人的に許容範囲かなというところまで抑えた状態


    やること自体は単純で角付近に1ラインメッシュの割りを入れただけ
    形状的には何の意味も持たない割りになるけど
    頂点色(で補正されるノーマル)的にはこれでなんとか余計なリムライトの広がりを抑えられる感じ


    陰側でも角にハイライトが入るようにして角の位置が感じ取れるように
    (ただ正面側のほぼ白な色あいで入れると強すぎるので弱く明るくなるような処理にした)
    曲面のリムライトも少しだけこの処理を入れている


    現状の状態や
    特殊なことをやってみようとしてひかかった部分のメモはこんなところかなと思うのでいったんこの辺で

    まだ入れたい機能をメモしておく
    というか多すぎてメモしないと忘れそう
    忘れる
    忘れた
    幾つか思い出せないだから早めにメモをしろといったのだ!
    うーん思い出したら追記したり修正したりする……
    欲張りセットみたいな内容なのでどこまでやれるのか謎



    ・ギルティギアでもあった陰の付きやすさの情報
    ハイライト用に作ったマスクのBチャンネルが空いているのでそこに入れ込む予定
    ずっと影出ていてほしいところは真っ黒に自分で縫って+アンビエントオクルージョンベイクするぐらいかなと思う、
    ギルティギアだと見た目はアンビエントオクルージョンっぽくてもアーティストが自分の感覚に従って手で塗り分けているとのことだったが個人製作の工数的に無理っぽいので……
    もの自体はシェーダーで陰影情報が出た時点のところに乗算で混ぜ込むだけで行けるんじゃないのと思っている

    追記
    できたので追記でスクリーンショットを貼っておく
    結局陰の落ちにくさみたいなところもコントロールできたほうがいいんじゃないかと思って
    (通常エミッシブ入れるような設定上光ってる場所とかに使いそうかなぁと)
    Bチャンネルの0.5以下は乗算で0.5以上は加算で混ぜ込むことで処理
    (Bチャンネル1のところは一切影が落ちないように、0の場所は常に影が落ちるようになった
     これは下の項目の「落ち影(ドロップシャドウ)を出したくない」とは違い、セルフシャドウも落ちない(落ちにくくなる)ので、下の項目は別途実装する必要がある)



    ・落ち影を出したくない部分へのマスク情報

    自作ゆかりさんのとき思ったというか以前の記事にも書いたところだけども
    顔に髪の毛の落ち影とか要らね!!
    情報がごちゃごちゃして表情などのもっと重要視したい情報の印象が薄れる!というのが
    ハイライト用に作ったマスクのAチャンネルを使う?
    もしくはBチャンネルの通常を50%のグレーにしておいて
    真っ白な部分には落ち影が入らないように処理するとか?

    追記
    結局アルファに入れた(Bチャンネルの50%以上は陰の入りにくさとして使ってしまったし)
    上の画像では適当な雲模様を入れたので独特な感じだけども
    落ち影が削れている状態になってる
    落ち影を半分程度の濃さにしたいとかのコントロールは難しいけども
    (落ち影が最終シェーディングになるまでにいろんな情報が混ざってしまう為)
    落とす、落とさない程度のコントロールには十分なのでこれで良しとする



    ・部位ごとの線の太さコントロール
    法線方向に押し出す距離(ラインの太さ)自体は数値入れている場所があるので
    そこに乗算するだけで行けると思うので
    太さコントロールの情報をメッシュのどこに入れ込むのかのほうが問題
    普通に考えると頂点カラーのRGBはノーマルで使ったけどAが空いてるじゃんというところなのだけど
    線に関しては+もう一つ情報を入れ込んでみたいと考えているので二つ分空きがいる
    UV2をUVとして利用せず値として利用することになるのかなぁとか思っている状態


    追記
    一応というか一旦はできた
    画像はわかりやすくするためにかなり大きく値を影響させてるけど
    UV2のUの値をもとにして線の強弱を調整できる

    これに関してはblenderだと頂点グループ(ボーンでもつかうウェイト)+アマーチュアでの押し出しで表現できるので
    belderで調整した状態をそのまま持ってきたいなー!というのがあったから
    頂点グループの値をUVのUに変換するスプリクトを追加で組んでたんだけども
    もーそっちのほうが時間かかったよね……というか頂点グループの情報の取り方がわかんなくてうなってた

    blneder側のスプリクトについて
    lineという名前で作った頂点グループの値をとりたいんだけど
    頂点グループのウェイトをとれるアトリビュートには名前の取得できるのがないっていう
    bpy.context.scene.objects.active = objectでオブジェクト取得した後
    object.vertex_groups.nameで名前が取れるんだけど
    object.data.vertices[x].groups[y].weightじゃないとウェイトの値が取れない
    この場合のXは頂点番号、
    Yはその頂点のうちで何番目の頂点グループか?
    よくゲームであるのだと頂点一つにつきウェイト四つまでというところでの話で
    でとにかく全然経由してるルート違うもんだからこのウェイト取得できるのはわかったんですけど
    これlineっていう名前のウェイトであってるんですかねー!???というので割と詰まってたんだけども
    object.vertex_groups.indexで取得できるID番号と
    object.data.vertices[x].groups[y].groupで取得できるID番号が一致してるかどうかで判定できるっぽい
    予め上のでID番号を取得しておいて、下のほうで同じものか判定してという流れになった
    (何となくそれっぽいぞといろいろ試した結果思っただけでどこかに情報があったのを見つけたわけではないので間違ってても知らない)
    ということがわかってなんとかスプリクトのほうは実装できたはーやれやれ

    シェーダー側について
    blenderのほうに話がそれてしまったけどシェーダーのほうは値もらってきて乗算するだけなので割とすぐできたのだけど
    注意点のメモとしてはUV2が存在しないデータの場合unityはUV1のデータもらってきちゃうっぽいという
    なのでこのシェーダー使う場合は専用の傍目めちゃくちゃな状態になっているUV2が必須になってくる
    とはいえそれはノーマル用頂点色の時点での話だしいまさらかー……

    でUVのVに関しては線の太さを別の要素でさらに変化させたかったというのがあって
    それは重力と慣性なのだけども
    といってもなんか物理的に正確に計算を行いたいとかでなく
    重力は線の太さが下のほうにコントロールされる
    慣性は何フレーム前かの位置に線が少しだけ引っ張られる
    といった程度のざっくりとした想定をしてた
    で、Vの値を重力とか慣性といった力の受けにくさ、線の太さの現状維持の力加減の値として入れたかった(これは弾力と表現するのがいいのかなと個人的には思ってる)
    一応そのメッシュデータにいったん入れるだけならできて
    重力も真下に移動させてやるだけだからここまではできた
    (微妙にワールドでY軸のベクトルをローカル軸に変換する方法とかで手間取ってたのでそのヘルパー関数だけ下に明記)
    UnityWorldToObjectDir()
    (unityの用意してくれている座標変換、行列として用意してくれてるからmulで乗算しようねーという場合と、ヘルパー関数として用意してくれてるから値突っ込むだけでいいんすよというのがあって個人的にこれもややこしかったんだけど、今回は後者だった)
    上の画像でも重力の値をバカでかくしてるもんだから線としてのポリゴンが下に大幅にずれているがVの値を見てずれ幅が違っているのは確認できる

    ただ最初に「一旦」と書いたのはここの話で
    まず「慣性」についてだけど
    シェーダーというのはそもそも数フレーム前の情報を維持してくれるような機能を持ってないらしい……うぅむ
    それができれば今の位置と数フレーム前の位置合成してあげて、その割合をVの値を参考にというだけの話だとおもうんですけお……
    で一応テクスチャに書き出すことでその情報を維持しようという試みをしていらっしゃる方もいて
    それをやれば一応できると思うんだけど
    テクスチャに書き出す関係上、すべての頂点がユニークな領域持った状態のUV3がさらに必要になってくると思われるし
    そのうえ自分のゆかりさん頂点数割と多いからその分UV3展開する手間暇や書き出すテクスチャ解像度も大きくなるわけで
    工数と処理付加的に大丈夫なの?ということを考えつつテクスチャに情報を書き出してという手法を学習するモチベーションがうぅん……
    (逆にこれができるならラインだけでなくメッシュ本体にもこの処理入れて形状をゆがませるとかやってアニメ的表現に近づかないかとかしてみたいところなんだけども……)

    もう一つあるのがラインの太さの最低維持をできるようにしないとというのが
    上の画像でもそうだけど重力に相当する値を思いっきり入れたとはいえ
    上部はメッシュの中に入り込んじゃってしまっているわけで
    最低限の太さは維持したうえで変形するようにしなきゃダメじゃね?というのが
    いやいまは重力だけだからワールドノーマルのベクトルのY軸の値で判定してマスク作って
    上向き部分だけmaxで.0.01より下回ってたらとかはできそうではあるんだけども
    慣性のことも考えるとちょっとこの方法では

    というところで一旦打ち止め
    いい方法思いついたりあきらめて力押しでやると決めた場合にはまた追記するかも
    一旦はここまで
    そもそもできるか&できたとしてよい効果になるかわからない慣性&弾力回りは結局中途半端だけど
    それ以前にふつうにできるっしょーと思ってた部分でもわりと手間取った箇所だった……


    ・逆に押し出しラインはカメラが離れたらある程度は太くしたい

    離れるとそもそも消えてほしくないラインも細く見えなくなってしまうのでその補正
    というか調べものしてた時にそういうのを実装しているというシェーダーの実例みかけて
    確かに合ったほうがよさそうだな程度の考えでそのまんまパクリという浅い考え
    追記
    これはすぐできた
    【Unity】カメラが近づくと透明になるシェーダを導入する
    ここの距離をとる部分の一行を拝借
    maxとminと乗算で、上限値、下限値と調整用に数値を少し弱くして
    ライン押し出しの強さの部分に数値混ぜ込み
    ただまぁ一旦いい具合ではという強度に設定したのでほんとに程よい強さなのかは後々調整がいるかも?



    ・ライトの色を反映

    複数ライトに対応させる場合本当は2パス目以降でブレンドで情報重ねないといけないらしいのだけど?
    ライトの色自体は現状でも取得できているのでどうやってませこむのがアニメっぽい色遣いになるかというところでのはなしになるかなという気がする

    また複数のライトについて
    一応今の状態でも精度は低いもののほかのライトも考慮はしてくれているっぽいというのと
    普通のシェーディングならForwardAddでBlendというので情報を重ねればいいのかもだけど
    セルシェードまっとうに処理するならは陰影情報重ねた後にそれをもとに領域分けしないといけないわけで
    パスをまたいで情報受け渡しできるなら最初のパス~ライトの処理終わるまでのパスでは陰影情報だけ処理して
    最後のパスでセルシェードに変えてあげればよさそうだけど
    パスまたいで情報の受け渡しとかできなさそうな??

    追記
    一応できた
    ・色の混ぜ込み
    そもそも銅色を混ぜ込むのかというところであーでもないこうでもないとかやってたのだけども
    基本的にRGBをHSVに変換してHSをライトの色で置き換えてからRBGに戻して
    (RGBとHSVの変換に関してもパクったサイトURLを貼っておく)
    【Unity】RGBをHSVに変換して明るさとかを変えるシェーダー
    RGBの状態で合成素材をlerpで合成しなおすという形になった
    (面の明るさは維持して色だけ変えるのはHSVじゃないとできないけど
    HSVのまま合成しちゃうと今度は水色に赤を半分の割合で混ぜたときにHの値からして緑色になってしまいこれはなんか違うという感じになったので)
    その他もともとの彩度とライトの彩度を比較してマスクを作って混ぜ込み具合を変えたほうがいいか??とかちょこちょこ調整してみてたのだけども一旦これで

    複数ライト
    unityですでにArktoon-Shadersというものを作成された方がいて
    そこの記事をみたところForwardAddでなくてもunity_4LightPosX0等で一応取得できるらしい?
    (ポイントライトを四つまで?)
    VRChatの皆に手軽に綺麗になってほしくて作ったシェーダーの話
    なのでこれで明るさと色を取得するようにした
    色は上のもので同様に処理
    陰影は基本的にはメインライトを主にしないとセルシェーディングとしての色の境目がごちゃごちゃしてくるので
    弱めに混ぜつつ、混ぜ具合はコントロールできるように一応

    ただ上記の記事でも結局ForwardAdd自体はしていて
    メインライト以外でも重要度の高いポイントライト及びディレクショナルライトはこっちじゃないと処理されないっぽい?らしい?
    だとすると自分のシェーダーではいまだにこれは処理できておらず
    また2パス目以降でしか情報を受け取れないのであればセルシェーディングの上から
    普通のシェーディング情報として重ねるしかできないということで
    それはどうなのという感じで保留しようとしていたが
    この追記を書いた後に少しググったところ
    [Unity] ひとつのPass内で複数のライトを使う
    ん?ビルトインのシェーダー変数 増えた?
    というのを見つけて
    unity_LightPosition[n] unity_LightColor[n]などでアクセスできるとのこと?
    だとすればもう少し調べたほうが良さそうかなうーん
    また進展あったら追記します……
    セルシェーディングのシェーダー作るにあたってライト周りのことメモ殴り書き(またもうちょっとわかったり整理できたら追記していくやつ)
    ↑複数ライトはそれだけで話が長くなりそうなので別記事にメモすることにしました


    ・フォグの反映
    unityが用意してくれてる関数?とか仕組みがあるっぽいのでそれいれるだけで行ける??
    そもそもシェーダー側でやることではない?というレベルから調べる
    やらなきゃいけなさそうな予感というか情報を見かけた気がするので念のため記述
    追記
    できた
    といってもunityが用意してくれたヘルパー関数を決まった位置に書き込んだだけなので
    特に備考はなし



    ・テクスチャ書き込みのラインの処理
    テクスチャに書き込んだ本村式ラインをテクスチャにそのまま書き込むよりはマスク情報としてシェーダー側で改めて描写したい
    カメラ距離が離れると線が消えて情報が簡素化されるとかが可能になる気がしているので
    やる場合は陰用テクスチャのアルファチャンネルに入れたい



    ・真っ平らな部分にも真っ平らな様相にあったハイライトを出す
    キューブマップでアニメの窓ガラスとかでみるような斜線的なハイライトを張り付ければ行ける気はする



    ・髪の毛用の別シェーダーを作る
    ハイライトの処理を変えないと駄目、他はそのままでいける?
    俗にいうエンジェルリング的な位置はオブジェクトスペースノーマルの上向きの値を抜き出せばいいと思うけども
    そこから髪の毛の流れに沿って多少削るなり変形させるなりということを考えるとどうしようという感じで……
    最悪テクスチャに書き込めばいいんだろうけど工数的にできれば避けたいなぁとか……



    ・アルファ抜きもしくはカットアウトに対応
    やり方自体調べてない
    この場合法線押し出しラインは邪魔になると思うので髪の毛と同じように別シェーダー扱いになる?



    ・ボーン変形の結果曲面になった場所にリムライト、ハイライトを出現させる
    やり方自体は行けるんじゃないかなあぁと思っているのが
    ボーン変形前の法線方向とボーン変形後の法線方向で内積だして
    方向の不一致が一定以上なら画像として張ったマスクにその範囲を入れ込んでやればいいのではと思っているのだけども
    変形前の通常のノーマルをどこに入れておけばいいんだという
    UV3、UV4使うとかでいけはするんだろうけど流石にごり押し過ぎないかなとか
    追記
    とか思ってたけどこの記事書いた一時間後にダメだこの方法と思った

    形状が曲がる変形しなくても普通にボーンで回転させただけでオブジェクトスペースの法線は変わってしまうわけで平面が曲面になった判定には使えない
    しかもよく考えたらそもそも真っ平らなものとか大体人工物なわけで
    そんなものがグネグネ曲がって曲面になるか?とか
    仮にグネグネ曲がって曲面になるとしてそれってキャラクターが身に着けている時点でベルトとか見たく曲面になってるよね普通?とか
    もともとの話で変形前のベクトルの数値をどこに保存しておくんだというのがあったのに加え
    内積の変化で形状の変化を感知するというのが見当違いの方法だし
    必要かどうかがそもそも怪しいしでこの機能はナシだなー
    というわけで横線引きました



    ・処理負荷とかいうやつ大丈夫なんですかね
    さっぱりわからん

    ある程度できたら自作ゆかりさん持ち込みたいけども
    そもそもちょこちょこ改修しているところで作業中断してるから
    そこから始めないと駄目よな……
    修正し終わったものをMMDで出しなおしてニコニコ立体のデータ更新してから
    unityにも出してみてでも物理演算とかはunityで設定しなおし……?
    とか考えると最終目標まではまた相当時間かかりそう……

    まぁほかにやることあるわけでもなしという人生なので
    暇で珍しくやる気あるとき見つけてはちょこちょこ進めましょ……


    広告
    コメントを書く
    コメントをするには、
    ログインして下さい。