70.5K Views
October 26, 22
スライド概要
ゲームにおける3DCGにおいて一般的なトゥーンシェーダーのアウトラインについての主流な実装とそれらの課題および従来の解決策、そこからより発展的な内容として、ハードエッジでも破綻のしづらいアウトラインの実装についての紹介。
こんな人におすすめ:
・テクニカルアーティスト(あるいはそれを目指す人)
・3Dキャラクターモデラー(シェーダーにも興味のある)
・トゥーン調のゲーム・映像作品を作りたい方
受講者が得られる知見:
・トゥーンシェーダーのアウトラインにおける基礎的な知識
・従来のトゥーンシェーダーのアウトライン実装では発生する課題
・それらの課題の解決について、従来の手法と応用的な手法
出演:
礒部 直人 (株式会社ポケラボ)
--
初出: SYNC 2022 #UnitySYNC
https://events.unity3d.jp/sync/
リアルタイム3Dコンテンツを制作・運用するための世界的にリードするプラットフォームである「Unity」の日本国内における販売、サポート、コミュニティ活動、研究開発、教育支援を行っています。ゲーム開発者からアーティスト、建築家、自動車デザイナー、映画製作者など、さまざまなクリエイターがUnityを使い想像力を発揮しています。
トゥーンシェーダー応用編 ~ 楽して破綻のないアウトラインを目指して ~
自己紹介 礒部 直人 株式会社ポケラボ 略歴 ● 2018/3 筑波大学 芸術専門学群 グラフィックデザイン学科 卒 クリエイティブ部 ○ システムサポートチーム ● テクニカルアーティスト 卒業制作でUnityに初めて触った 2019/5 3Dアニメーター・エフェクトアーティストとして ゲーム系の3D業務に従事(未経験) ○ ● 2020年ごろから本格的に Unityを触りだす 2021/8 テクニカルアーティストとして Pokelaboに入社 ○ モバイル向けゲームアプリ開発に従事 ○ シェーダー・ルック開発が主
今回お話しする内容 トゥーンレンダリングにおける アウトラインについて、 ● 現在主流な2つの実装 ● 背面法での従来の工夫 ● エディタ拡張を含めた応用的な手法 を紹介していきます ※基本的にゲーム向けのリアルタイムレンダリングにおける話であることにご留意ください
現在主流なアウトラインの実装 ● 背面法 ● 輪郭検出 こちらの2つについて ユニティちゃんSunny Side Upのモデルを例に 見ていきましょう! © UTJ/UCL
アウトラインの実装① 背面法 ①頂点を法線方向に膨らませるように移動させ モデルの裏面のみを描画する © UTJ/UCL
アウトラインの実装① 背面法 ①頂点を法線方向に膨らませるように移動させ モデルの裏面のみを描画する ②通常のモデルも描画する © UTJ/UCL
アウトラインの実装① 背面法 ①頂点を法線方向に膨らませるように移動させ モデルの裏面のみを描画する ②通常のモデルも描画する 簡単ながら非常に効果が高く、 ずっと使われてきているメジャーな手法 ⇒頂点カラーやテクスチャーで太さの制御も容易 ※オーバードローを考慮すると、先に通常モデル、後にアウトライン描画が◎ © UTJ/UCL
アウトラインの実装② 輪郭検出 ①中間バッファを生成(ワールド法線・深度など) © UTJ/UCL
アウトラインの実装② 輪郭検出 ①中間バッファを生成(ワールド法線・深度など) ②輪郭検出用フィルタ(Sobel, Laplacian)を適用 © UTJ/UCL
アウトラインの実装② 輪郭検出 ①中間バッファを生成(ワールド法線・深度など) ②輪郭検出用フィルタ(Sobel, Laplacian)を適用 ③色を塗る © UTJ/UCL
アウトラインの実装② 輪郭検出 ①中間バッファを生成(ワールド法線・深度など) ②輪郭検出用フィルタ(Sobel, Laplacian)を適用 ③色を塗る 背面法が頂点シェーダ的な実装だったのに対し、 こちらはポストプロセスで画面全体に効果をかけていく やりたい表現によっては非常に効果的 © UTJ/UCL
主流は未だに背面法 トゥーンレンダリングを基調とする作品や、 アニメ・漫画などが原作のゲームの場合、 実装の手軽さ・表現力面から、背面法が 採用されていることが多い印象です © UTJ/UCL
ただし背面法はハードエッジが苦手 ハードエッジ:面ごとにパッキリする ソフトエッジ:隣り合う面の平均をとって 滑らかにする 理想 Sphereのようなモデルは問題ないが、 なにも考慮せずに実装すると… アウトラインは下のCubeのように ひびわれてしまう… 現実
トゥーン調モデルではとても困る 髪の毛束部分のシェーディングのため ハードエッジを使用したいとき…など 髪の毛先のなどではアウトラインが ひび割れたように見えてしまう © UTJ/UCL
トゥーン調モデルではとても困る 髪の毛束部分のシェーディングのため ハードエッジを使用したいとき…など 髪の毛先のなどではアウトラインが ひび割れたように見えてしまう この”背面法がハードエッジに弱い問題”について 従来とられてきた解決策を2つご紹介します © UTJ/UCL
従来の背面法解決策① ベベル ごく細かなベベル面を差し込み すべてソフトエッジにする 疑似的にハードエッジに近い シェーディング効果が得られる デメリット ● モデリング時の工数増 ● ベベル処理後の手戻りが面倒 ● ポリゴン数の増加(微量)
従来の背面法解決策② アウトライン用モデルを持つ ● シェーディング用のモデル ● アウトライン用のモデル それぞれ法線を調整したモデルを持つことで 任意の方向にアウトラインを出せる デメリット ● 法線調整の工数 増 ● データがかさみ、DCCツールでの管理もやや 煩雑に 画像:左はシェーディング用モデル/ 右はアウトライン用モデル
従来の背面法解決策②を言い換えれば 「法線情報が”2種類”欲しい」ということ
提案する解決策 スムーズ法線転写 3Dモデルに Unityで自動的にアウトライン用の法線情報を持たせる 今回これをスムーズ法線転写と呼称します
提案する解決策 スムーズ法線転写 3Dモデルに Unityで自動的にアウトライン用の法線情報を持たせる 今回これをスムーズ法線転写と呼称します ⇒ モデルのインポート時(AssetImporter)で処理 JobSystemを用いて高速に法線の変換・転写処理を行う
参考記事 引用 Jason Ma氏の知乎(中国のQ&Aサイトのようなもの) 【Job/Toon Shading Workflow】 自動生成硬表面模型 Outline Normal https://zhuanlan.zhihu.com/p/107664564
スムーズ法線転写 実装方針 ① 元のモデルAを複製(モデルB) エディタ拡張 ② Bの面を全てスムーズ化 C#, AssetImporter ③ Bの法線を、Aのタンジェント空間に変換 ④ AのUVに格納し、Bを破棄 シェーダー実装 HLSL, アウトライン用パス ⑤ シェーダーのアウトラインパスで、 アウトライン押し出し用方向として利用
スムーズ法線転写 実装 ① 元のモデルAを複製(モデルB) 主な実装部分 AssetDatabase.CopyAsset(モデルAのパス, 複製する先のパス);
スムーズ法線転写 実装 ② Bの面を全てスムーズ化 やってることは fbxのimport設定を 書き換えてるのと同じ 主な実装部分 modelB.importNormals = ModelImporterNormals.Calculate; modelB.normalCalculationMode = ModelImporterNormalCalculationMode.AngleWeighted; modelB.normalSmoothingAngle = 180.0f;
スムーズ法線転写 実装 ③ Bの法線を、Aのタンジェント空間に変換 主な実装部分 ベイクされた法線(Aのタンジェント空間) = tbn.MultiplyVector(モデルBの法線).normalized; ※ tbn … タンジェント空間に変換するための行列を指す( tangent, bitangent, normal)
スムーズ法線転写 実装 ④ AのUVに格納し、Bを破棄 主な実装部分 モデルAのメッシュデータ .SetUVs(チャンネル数 , ベイクされた法線の Vector3配列); AssetDatabase.DeleteAsset(モデルBのパス);
スムーズ法線転写 実装 ⑤ シェーダーで、アウトライン押し出し方向として利用 // GetVertexNormalInputsで法線やタンジェントベクトルを取得 VertexNormalInputs normalInput = GetVertexNormalInputs(input.normalOS, input.tangentOS); // タンジェント空間 ⇒ ワールド空間 行列 float3x3 tangentToWorldMatrix = float3x3(normalInput.tangentWS, normalInput.bitangentWS, normalInput.normalWS); // AssetImporterによってUVにベイクされたスムーズ法線を // ワールド空間に変換 float3 smoothedNormalWS = normalize(mul(input.bakedNormal, tangentToWsTransformMatrix)); output.positionCS = TransformWorldToHClip(vertexInput.positionWS + smoothedOutlineNormalWS * _OutlineWidth);
比較 ハードエッジそのまま スムーズ法線転写 ”ひび割れ”部分にアウトラインが綺麗に出るようになった! © UTJ/UCL
ベイクされた法線はプレビューできる メッシュを選択すると頂点毎のデータにUV3が 追加されていることや、 PreviewウィンドウのUV LayoutからChannel3を 選択することで確認できる ※UV Layoutではx,yの値しか確認できない点に留意
頂点毎に法線を変換する作業はJobSystemで高速に
public struct BakeNormalJob : IJobParallelFor
{
⋮
⋮
private BakeNormalJob(NativeArray<Vector3> vertex, NativeArray<Vector3> normals, NativeArray<Vector4> tangents,
NativeArray<UnsafeHashMap<Vector3, Vector3>> result, bool existColors,
⋮
⋮
void IJobParallelFor.Execute(int index)
{
Vector3 smoothedNormals = Vector3.zero;
for (int i = 0; i < result.Length; i++) {
if (result[i][vertex[index]] != Vector3.zero)
smoothedNormals += result[i][vertex[index]];
else
break;
}
⋮
!注意 実装としてパワフルだとは思いますが、万能な解決策ではありません あくまで ● Unityで処理することでモデリングや管理の手間を抑える ● 見た目もそこそこ綺麗にする ための実装となっております 手調整した法線を持つ方が意図通りのアウトラインを出せる
まとめ トゥーンレンダリングのアウトラインについて以下を紹介 ● ● ● 現在主流な2つの実装 ○ 背面法 ○ 輪郭検出 背面法での従来の工夫 ○ ベベル ○ アウトライン用のモデルを持つ スムーズ法線転写:エディタ拡張を含めた応用 ○ AssetImporterで法線をスムーズ化したモデルを複製し転写 ○ JobSystemで高速化 ○ アーティストの手間いらずでそこそこきれい