scenario-blender-uv-baking について
UV展開とテクスチャベイクを行うBlender制作者向けのスキルです。テクスチャ手法に応じたシーム配置に加え、テクセル密度や余白、投影を測定する手順を備えています。
主な機能
- 01テクスチャ手法に合わせたシーム設計
- 02テクセル密度の測定と正規化
- 03UVの展開、整列、パッキング
- 04投影計測と押し出し量の適応ベイク
- 05UVとベイク結果のレビュー
活用シーン
- 01ゲームアセットのUVとベイクマップを準備
- 02UVアイランドの重なりと余白を確認
- 03ハイポリからローポリへ法線とAOをベイク
- 04ベイクの反転ピクセルを特定
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ scenario-labs/ skills --skill scenario-blender-uv-bakingインストール後、Claude Code で/scenario-blender-uv-bakingを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/critique.mdexpert-notes.mdprocedures.mdsources.mdscripts/bx_uvbake.py詳細
UV 展開とベイク
熟練者レベルの UV では、テクスチャリング手法に合わせて継ぎ目を配置し、テクスチャサイズより先にテクセル密度を設定し、ピクセル単位で正確なパディングを設けてパックします。熟練者のベイクでは、投影距離を推測せずに測定し、ピクセル単位で、かつ斜光の下で評価します。一度目視しただけで判断することはありません。以下の各段階には測定可能な合格基準があり、scripts/bx_uvbake.py が算出します。ここで名前を挙げた関連スキルが利用可能なスキルにない場合は、ユーザーにインストールを依頼してください(npx skills add scenario-labs/skills --skill <name>)。無人で作業を続ける場合は、ツールのスキーマをもとに進め、不足しているスキルを明示してください。
必須の事前知識: scenario-blender-expert(実行チャネル、レビューの反復、5.2 API の変更点)。
基本方針(専門家との違い)
- 継ぎ目はテクスチャリング手法に合わせます。 Kaspar(2021、2D ペイント):継ぎ目はできるだけ少なくし、髪、服、手足の内側に隠します。Blender Studio ガイド(2024、同じ著者):3D でペイントする場合やベイクする場合は、少ないより多い継ぎ目を設けます。伸びによるコストのほうが大きいためです。ゲーム用ベイクには厳格なルールが加わります。すべてのハードエッジを継ぎ目にしないと、ノーマルマップに亀裂が生じます(Lampel、Gambrell、On Mars 3D、Polycount)。
- 追加のカットが必要なのは、閉じたシェルと長いチューブだけです。 Morren:それ自体で閉じているものには、カットが1つ必要です。Gambrell:テープで留めた紙の輪は、隠れる位置でそれぞれ1か所カットします。ただし、穴のあるアイランド(目の穴がある顔、ワッシャーなど)は、カットしなくても問題なく展開できます。
cut_to_disksはテスト展開を行い、伸びが生じる場合に限ってカットします[追加。すべてをカットすると、羊の大きなアイランドが折り畳まれてしまったため]。 - 展開方法は測定対象であり、5.2 のデフォルトは CONFORMAL です。 常に
method=を渡します。Suzanne では、Minimum Stretch が最も均一な密度(ばらつき1.38)になり、Angle Based が最も良好な角度を実現し、Conformal は面積で不合格になります(5.89)。平坦なハードサーフェスのアイランドでは、3つの方法ともほぼ同じ結果になります。unwrap(method="BEST")はアイランドごとに方法を選択し、自身に折り重なるアイランドは除外します。 - まず密度を決め、次にテクスチャサイズを決めます(Huge Menace)。目標値:FPS 10.24 px/cm、武器 20.48、三人称視点 5.12、トップダウン視点 2.56。優先順位はカメラに応じて決めます。顔、手、正面を高くし、足裏、口の中、背面を低くします(SpeedChar、Kaspar)。テクスチャセットの密度を合わせる際は、密度の高いセットを縮小します。もう一方を拡大してはいけません(Gambrell)。
- まっすぐにし、次に均等化し、傾けずにパックします(Lampel):本当に長方形のクワッドから Follow Active Quads を実行し、ピン留めして、残りを再展開し、CARDINAL でパックします。パディングはピクセル数で指定します。res/128(2K では16 px)を、FRACTION のマージン margin = gap/(2*res) として渡します。
- 投影を測定し、押し出し距離を推測せず、全体に適用する単一の値を信用しないでください。 Ryan King の 0.01、次に 0.02 という値は、そのシーン固有のものでした。SpeedChar は6つの値を手作業で試し、顔の問題を直した値で脇の下の問題が発生しました(「ある場所の問題を直すと、別の場所で問題が発生します」、E6QMhGuhyoc [00:26:23])。レイはローポリ側から開始し、
max_ray_distanceは押し出した開始位置からの距離を数えます。適応型ベイクでは、表面の手前側にヒットする最小の押し出し距離をテクセルごとに保持します。羊のモデルでは、反転したテクセルが7.5%から1.2%に減少しました[確認済み]。 - ベイクしたライティングが異なる場所では、UV を重複させないでください(SpeedChar:AO にゴーストが出る場合は、テクセルが共有されています)。スタックまたはミラーリングした複製は、ベイク前に 0-1 の範囲からタイル1つ分だけ正確に移動します(Polycount)。0-1 の範囲内では、最後にベイクされたアイランドが優先されるためです。
- ベイクはピクセル単位で、かつライトの下で評価します。 青色が 0.5 未満なら、レイは裏側にヒットしています。完全に平坦なら、レイはヒットしていません。AO が全面白なら、距離が短すぎます。押し出し距離を変えても位置が変わらない反転ピクセルは、設定ではなくジオメトリの問題を示しています[羊のモデルで確認済み]。Multires ベイクではレイが飛びません。同じ表面での反転テクセルは0.09%でした。
最初に確認する項目
| 入力 | 変更点 | 指示がない場合のデフォルト |
|---|---|---|
| ターゲット | シーム、対称性、UDIM とセット、三角形分割 | ゲームエンジン、マテリアルごとに 0-1 セットを 1 つ |
| テクスチャリング方法 | シームの数と見えやすさ | 3D ペイント/Substance:シームは背面にあってもかまいません |
| カメラ | 密度と優先順位 | 三人称視点 512 px/m、最も近い視点に合わせてタイルを決定 |
| テクスチャ予算 | 解像度、セット、UDIM 数 | セットごとに 2048;texture_size_for で決定 |
| 変形 | 関節を避けたシーム、タンジェント空間法線 | キャラクター:タンジェント空間、固有 UV |
| ハイソース | Selected to Active と Multires のどちらを使うか | 別個のスカルプト:Selected to Active |
| エンジンの規約 | 法線の緑チャンネル | OpenGL(Blender、Unity、glTF);Unreal では directx=True |
ワークフロー
- 事前確認。 スケールを適用します(On Mars 3Dでは、問題の「大半を修正」します)。非マニフォールドジオメトリ、重複、裏面をクリアします(SpeedChar)。MirrorモディファイアーとSolidifyモディファイアーを使うか決めます。UVがある場合は、
island_topologyとuv_qaのアイランドを比較します。ファイル内のシームフラグは、リトポロジー時のマークが残っていることが多いため、再アンラップの前にseams_from_uv_islands(Lampel)を実行します。ゲート:スケールが1、bx_auditで問題なし、トポロジーテーブルを確認済み。 - シーム。 ハードサーフェス:
seams_from_sharp(obj, 30, mark_sharp=True)。オーガニック:パーツラベル(頭、耳、手足、胴体の前面と背面、足裏、口の内側、まぶた)を作成します。ラベルは、references/expert-notes.mdにあるKasparとMorrenのシームマップに従い、その後seams_from_groups(obj, labels)を実行します。特定のカットにはseam_path(obj, v_a, v_b, view_dirs)を使います。次にcut_to_disks(obj, view_dirs=[camera])を実行します。ゲート:must_cutが空であること。チェッカーレンダーで、ブリーフ上シームを許容できない主要領域を横切るシームがないこと。 - アンラップ。
unwrap(obj, method="BEST")、またはアイランドの種類に適したメソッドを使います。ゲート:unsolved_facesが0(失敗してもオペレーターはFINISHEDを返します)、folding_islandsが空(それ以外の場合はseams_from_groups(..., faces=folding_faces)を実行して、再度アンラップします)、角度のp95が15~20度以下。 - 整列。 グリッド状のアイランド(ハードサーフェス、衣服、ストランド)は、スケーリングの前に
straighten(obj)を実行します。ゲート:チェッカー上でストライプがまっすぐであること。 - テクセル密度。
normalize_texel_density(obj, target, res, weights)を実行し、続けてtexture_size_for(obj, target)を実行します。ゲート:アイランド間のばらつきが10~20%以内、または意図した優先度比率であること。 - パック。
pack(obj, tex_res=res)を実行します。密度を厳密に保つにはscale=False、オーガニックなアイランドにはallow_any=Trueを使います。UDIMの場合は、各リージョンをパックしてからmove_to_tileを実行します。ゲート:uv_qaで重なりが0、間隔が少なくともres/128、境界からの距離が少なくともgap/2、カバレッジが0.70以上、または例外について説明があること。 - 外観確認。
uv_layout_image、checker_review、distortion_review(metric="angle")を使います。references/critique.mdに従って評価します。 - ベイク準備。
prepare_low(low, triangulate=game, sharp_from_uv_islands=hard_surface)を実行します。ハイポリに対するシルエットを確認します(bx_audit.audit(low, high=...))。貫通しているパーツや動くパーツを分離します(explode、軸は1つ)。measure_projectionを実行します。miss_pctが2未満、wrong_part_pctが1未満であること。そうでない場合はケージを使う、分離する、またはペアごとにベイクします。 - ベイク。 まず
bake_high_to_low(low, highs, out, res=512)を実行し、次に最終解像度で実行します。デフォルトでは適応型の押し出しを使い、レンダー対象から他のすべてのオブジェクトを非表示にします。Multiresの場合はbake_multiresを使います。追加機能:bake_id、curvature_from_normal。ゲート:sanity[...]["problems"]が空(反転テクセルは2%未満、注記は0.2%から)、16ビットPNGであること。反転テクセルが残る場合は、map_problem_reviewを実行して場所を確認します。sweep_projectionで押し出しを変えても移動しないと分かった場合は、数値ではなくジオメトリを修正します(フィット、穴、薄いパーツ)。 - レビューと接続。
bake_review(low, highs, paths, out)を実行します。マップを適用したローポリが、斜光下でハイポリのように見えることを確認します。その後hookup_mapsを実行します。測定値と、未検証の項目を報告します。
数値
| 値 | 基準 | 出典 |
|---|---|---|
| 10.24 / 20.48 / 5.12 / 2.56 px/cm | FPSワールド / FPS武器 / サードパーソン / トップダウン | Huge Menace [00:12:28] |
| 密度の不一致が10~20%なら視認できない | アイランド間またはセット間 | Gambrell [01:36:16] |
| カバレッジ70%超、スタジオの最低基準は75% | 0~1タイルあたり | Gambrell [01:31:56], Huge Menace [00:16:27] |
| アイランド間の隙間は解像度/128(1K/2K/4Kで8/16/32 px) | テクスチャ解像度 | Lampel [00:38:01], On Mars 3D [00:11:18] |
| FRACTIONのマージンm:隙間2m、境界m | Blenderパック | 検証済み |
| ベイクマージンは解像度/128、2Kで16 px | テクスチャ解像度 | On Mars 3D、ダイジェスト |
| 円柱の側面数:最低6、推奨8 | ローポリのシルエット | On Mars 3D [00:03:48] |
| サンプル数:法線は16、AOは128、反復中は1のみ | アンチエイリアスとノイズ | Gambrell/Marmoset 16、SpeedChar 4x4、検証済み |
| テストベイク512、最終2048 | 反復サイクル | SpeedChar [00:59:09] |
| AO距離はバウンディングボックスの対角線の約0.2倍(デフォルトは10単位) | アセットサイズ | [追加]、効果を検証済み |
| 角度誤差のp95は、有機的な形状で最大15度、平面で3度 | コーナーごと | [追加]、5.2.1の測定値に基づく |
| 有機的なキャラクターでのBlenderパッカー:55~62% | 2Kで16 pxの隙間 | 羊で測定(複数回実行) |
| 反転テクセル:シングルパスで7.3~7.8%、アダプティブで2.2%(スカルプト)/1.2%(高密度で一貫) | 選択範囲からアクティブへ、羊 | 測定済み |
| 2048ベイク、18.6万ポリゴンのハイポリ:1パスの法線+AOは4.4秒、アダプティブは25秒 | Metal GPU、ヘッドレス | 測定済み |
品質ゲート
コード:q = uv_qa(obj, res)、続いてuv_verdict(q, "game" or "film", priorities=...)。
unwrap()["unsolved_faces"]と["folding_islands"]。measure_projection()。
bake_high_to_low()["sanity"](反転、完全な平面、単位長でない値、AOの黒と白)。疑わしい場合は
bpy.ops.uv.select_overlap()でオーバーラップをクロスチェックします。テストではラスタライズ結果と一致しました。
視覚的確認:レイアウトPNG(アイランド、マゼンタのオーバーラップ)、正面、側面、斜め前方
およびプロダクションカメラからのカラーチェッカー(正方形が正方形であること、文字が正立していること、継ぎ目が隠れていること)、角度と密度のヒートマップ、
bake_reviewシート(ハイポリ、ローポリ、ローポリ+マップ)、サニティチェックでピクセルにフラグが立った場合のmap_problem_review。
よくある間違い
| 間違い | こう見える | 修正方法 |
|---|---|---|
method を指定せずに uv.unwrap() を実行する | コンフォーマル展開で領域が歪む | method= を渡すか、unwrap(method="BEST") を使用する |
| FINISHED を信頼する | 閉じた島に古い UV が残り、再パックされる | まず UV をゼロにし、面積がゼロの面がないか確認する(unwrap() が実行します) |
| Islands from Seams を使わずに再展開する | レイアウトが失われ、リトポロジーのマークがシームとして使われる | 最初に seams_from_uv_islands を実行する |
| すべての島をディスク状にカットする | 切れ目や折りたたまれた島ができる | 測定に基づく cut_to_disks(デフォルト)を使用する |
| 直線化後のパック回転を ANY にする | グリッドが傾き、線がギザギザになる | CARDINAL |
| Blender のマージンを 0.005 にする | パディングが島のスケールに左右される | FRACTION、gap/(2*res) |
| ターゲットノードがアクティブでも選択されていない | ベイクがエラーなしで CANCELED を返す | 選択してアクティブ化し、FINISHED をアサートする |
| Low が Multires としてスカルプトを保持している | ほぼ平坦なノーマルマップになる | ベイク時のレンダーレベルを 0 にする(bake_high_to_low が実行します) |
| max_ray が押し出し距離より短い | マップのちょうど 90% が平坦になる | ray = 押し出し距離 + 内向きの深さ |
| 薄くて近接したパーツ(頭の耳など)に、単一の押し出し距離を使う | 反転したパッチができ、隣接パーツがベイクされる | アダプティブベイク(デフォルト)、分離、またはペアごとのベイクを使う |
| AO 中にほかのオブジェクトがレンダー対象になっている | AO が黒くなる | それらをレンダー対象から隠す。アクティブな Low は遮蔽物になりません |
| デフォルトの AO 距離を 10 にする | AO が全体的に暗くなる、または平坦になる | アセットの対角線の約 0.2 倍にする |
| 重なった UV を 0-1 内でベイクする | 片側のディテールが両側に現れる | 固有の UV を使うか、offset_stacked を使用する |
| 島の内部にハードエッジがある | ひび割れのような線ができる | シームにするか、prepare_low(sharp_from_uv_islands=True) を使う |
| ベイク後に UV を編集する | シームやタンジェントが一致しなくなる | 絶対に編集せず、再ベイクする |
Blender 5.2 のメモ
uv.unwrapのデフォルトは CONFORMAL です。失敗した場合、島の古い UV を維持して再パックします。use_weights/weight_group(デフォルトのグループは "uv_importance")があり、Minimum Stretch で重要度の重みを設定できます。重みを付けた上半分の UV 面積は 31% から 74% になりました[検証済み]。- 同期選択はデフォルトで有効です(5.0)。
BMLoopUVにあるのはuvとpin_uvのみです。Edit Mode の切り替え後、me.uv_layers[...]への参照は古くなるため、名前を保持してください。 pack_islands(udim_source="CLOSEST_UDIM")をヘッドレスで実行すると、1002 にある領域が 1001 に戻ってパックされました。先にパックしてから移動してください。uv.move_on_axisには UV エディターが必要です。- ベイク:ターゲットは選択され、かつアクティブである必要があります(5.0)。オペレーターのデフォルト値はシーンのデフォルト値と異なります(
use_clearは False と True、EXTEND と ADJACENT_FACES)。すべて明示的に指定してください。選択からアクティブへのベイクでは、低解像度側のレンダー評価が使われます(Multires の render_levels、シェイプキー)。Multires の設定はobject.bake_image()のscene.render.bake.use_multiresにあります。PNG として保存した浮動小数点画像は 16 ビットです。Normal Map ノードのconventionは OPENGL/DIRECTX です(5.1)。UDIM タイルにはimage.tile_add(fill=True)が必要です。 - Auto Smooth はなくなりました(4.1)。スムーズシェーディングとシャープエッジを使用してください。Triangulate の「Keep Normals」は
keep_custom_normalsです。
参考資料
references/expert-notes.md:タイムスタンプ、意見の相違、判断条件、私が測定した 5.2.1 の結果を含む専門家の判断です。シーム、密度、ベイク戦略を選ぶ際に読み込んでください。references/procedures.md:テスト済みのパイプライン(ハードサーフェス、キャラクター、フィルム/UDIM、Multires、ベイク修正ループ)と、テストで実行した未加工の bpy スニペットです。コードを書く前に読み込んでください。references/critique.md:シーム、ストレッチ、密度、パッキング、ベイク設定、ベイク済みマップの評価基準です。プロキシと重大度も記載されています。各ゲートで読み込んでください。references/sources.md:動画、認証情報、URL、最適なタイムスタンプ、ウェブ上の参考資料です。scripts/bx_uvbake.py:モジュールです(各関数の一覧は docstring に記載されています)。