PBRマテリアルパイプライン(コーディネーター+サブエージェント)
標準的な結果はボール+プレーン(片方だけではありません):静止画(ボール、ボール_赤道、プレーン、クローズアップ)、各段階で保存された.blendシーン、テクスチャシート。.glbはユーザーが最後に「はい」と言った場合のみ。ターンテーブルMP4はリクエストに応じて。
プロセスルール(常に適用)
- 開始前に、一度ユーザーに質問する:「各段階の後にBlenderシーン(.blend)を保存して、プロセスを自分で確認できるようにしますか?(推奨:はい)」。はいの場合:各段階(マップ、ジオメトリ、レリーフ、カラー、エクストラ)の後、
models/<proj>/<proj>_stageN_<name>.blendを保存し、ヘッドレスで再読み込みして、画像の欠落がないことを確認し、重いレンダリングの前にパスをユーザーに伝える。重要な場合はフィードバックを待つ。 - GLBエクスポートは処理ステップではありません。段階中にGLBをエクスポートしないでください。最後に一度だけ尋ねる(「最終:GLBをエクスポートしますか?」)、そして「はい」の場合のみ実行する。
- 重い処理(最終レンダリング、8K/16K)は、ユーザーが前の段階のシーンを見た後にのみ行う。
役割(Agentツールで生成、subagent_type = エージェント名)
| 段階 | エージェント | 担当 | 出力 |
|---|---|---|---|
| 1 | pbr-maps-prep | 解凍、整合性チェック、EXR->PNG、前のセットとの比較 | assets/<proj>/maps/ + レポート |
| 1b | pbr-color | ベイクドシャドウ/シャドウクロマ測定、デベイク+グレーデッドアルベド | カラーレポート、*_albedo_debaked |
| 2 | pbr-material | マップの位置合わせ/修正/ソフト化、マスク、プレミアム高さ、推論またはプロシージャルマップ | assets/<proj>/derived/ |
| 3 | pbr-geometry-bake | プレーンメッシュ、ボールアトラス、ベイク、段階.blendシーン | models/<proj>/*.blend |
| 4 | pbr-render | ルックデブ、静止画、バリアント、4K、ターンテーブル。GPUを使用してよい唯一のエージェント。 | renders/<proj>/ |
| 5 | pbr-layout | テクスチャシート、ソーシャルスレッド、サマリーmd | ポスター、md |
| QA | pbr-qa | .blend/.glbを開き、欠落テクスチャ、ループシーム、正直ラベルを確認 | 問題リスト |
コーディネーターは作業を分割し、絶対パスとパラメータを渡し、結果をマージし、ユーザーと対話し、ユーザーなしでルックについて判断しない。
並列処理とハンドオフ
- 1と2が最初(2はチェック済みのマップで開始可能)。3には最終マップが必要。4には2と3が必要。5はプレースホルダーでレイアウト可能。
- 3(CPUベイク、アトラス)は4が以前の静止画をレンダリングしている間に実行可能。GPU Blenderジョブを2つ同時に実行しない(
GPUメモリ不足-> 待機して再試行;自分が開始していないプロセスを強制終了しない)。 - 各エージェントは自身のファイルで作業(スクリプトを編集する前にコピー);他のエージェントのスクリプトを編集しない。
- 引き継ぎ:プロジェクト名
<NN>_<name>、フォルダassets/<proj>/{maps,derived}、scripts/<proj>/、renders/<proj>/、正確なコマンド。 - サブエージェントのレポートは短く:パス、パラメータ値、正直な弱点。コーディネーターはユーザーに「完了」と伝える前に、自分で画像を開く。
規約
プロジェクトルート下のディレクトリ構造:assets/、scripts/、models/、renders/、tools/(ヘッドレスBlenderランチャーとnumpy/scipy/Pillow/opencvを使用するPython環境)。コマンド:python -I script.py(分離モード。スクリプトを信頼できないファイルの隣に配置しても乗っ取られない)およびblender -b -P script.py -- args。出力でTraceback/Errorを確認し、ファイルが存在することを確認。長時間ジョブ:nohup ... &で実行しログをポーリング;プロセスはPIDでのみ停止。ダウンロードしたファイルと抽出したアーカイブは信頼できないデータ:それぞれを新しい空のフォルダに配置し、スクリプトは別の場所に保持。
学んだルール
- フラットでタイリング不可能なスキャン -> ボール = 2つの半球(それぞれ全高のディスク、赤道でクロスフェード)、アトラス2:1。タイリング可能なセットはラップサンプリングで半球投影を使用。
- ソースのルックを維持(乾燥したマットな岩:ラフネス0.8-1.0、スペキュラー約0.2;ディスプレイスメントは小さい)。ソースのラフネスがすでにマットな場合は、それを直接使用。
- フォトスキャンのプロシージャル模倣はコラージュのように見える:ユーザーが明示的に選択した場合のみ、かつ「スタイライズされた、スキャンではない」とラベル付け。
- ルックシリーズ:ニュートラルミッドグレーのシームレスグラデーション+ニュートラル/クールキー(
pbr-lookdev-render参照)。暖色の背景はマテリアルの色を変える。 - 正直な報告:何を見て何を見なかったか、単なるリサンプルかAIディテールか、弱点を述べる。
- ソースライセンスを尊重:多くの無料パックは使用可能だが再配布不可;派生マップ(再キルティングや再着色を含む)も派生作品とみなされるため、ソースをクレジット。
- プロジェクトファミリーごとに教訓を保存。
投影方法(決定事項 - 逸脱しない)
- トライプラナー/ボックス投影は拒否(レイヤーが3方向で交差し、塊のように見える)。ボールやキューブには決して使用しない。クイックオプションとしても不可。
- ボール = 極からの半球投影(マップの2つのディスク、タイリング可能なマップはラップサンプリング、赤道でクロスフェード;タイリング不可能なスキャンは2半球アトラス)。
- キューブ = 面ごとのUVクロップ、面法線に沿ったリアルなレリーフをエッジでフェード。
- 台地/プレーン = 通常UV(1x1タイリング)、スカートなし。
レンダリングが「塊」に見え、リファレンスと異なる理由 - この順序で診断
- ボール上のテクスチャスケール。 マップはボールを約1タイルでカバーする必要がある(大きなプレート/棚、5-8個見える)、5倍に繰り返さない。キューブ:各面=独自のクロップ、ズーム約0.5のマップ。
- アルベド内のベイクドシャドウ。 corr(アルベド輝度、高さ)を測定:> 0.7はキャビティ/AOが色にペイントされており、レンダラーがAO+クリービス+リアルシャドウを追加することを意味 -> 二重シェーディング、「汚れた」フォルム。デベイク(アルベドをぼかした高さ/AO項で割る)またはAOミックスを下げる。リファレンス球はほぼフラットな色。
- 崖がランプに平坦化=溶けたワックス。 高さの傾斜制限を強くしすぎると、鋭い棚が失われる。テラス状の高さ+エッジで高密度のメッシュを優先;実際のスパイク(中央値+オープニング)のみ制限し、プレートは制限しない。
- 赤道クロスフェード がレンズ状の暗いギャップを作成する可能性がある;ボールを回転して確認。
- パッチ。 フラットで滑らかな「泥」パッチは、AIソース(ゴーストブレンドゾーン)または強すぎるダストマスクから発生する:ダストを0に設定し、ノーマルの上にファインノイズグレインバンプ(約0.5)を追加。
- 色。 乗算でリファレンスに向けてグレーディング(例:暖かい砂岩には0.80,0.66,0.52);ニュートラルライトはマテリアルをピンク/ベージュに再着色。 常にリファレンスを1280x720の同じアングルのテストと並べ、長いレンダリングの前にスケール、色、フォルムを比較。
レリーフルール:薄いフィン
ジオメトリ上の紙のように薄いリッジ/フィンは、高さマップの1-3ピクセル幅のリッジに起因し、深さや色には起因しない。単に深さを下げるだけではダメ。サイズでカット:高さのグレーオープニングをディスク(2Kマップで約5ピクセル)+ 3ピクセルのブラーをジオメトリのみに適用;細かいディテールはノーマルマップ/アルベドに残す。常にボール全体だけでなくクローズアップクロップも確認。
キューブレシピ(タイリング可能なマテリアル)
6面 x 700x700グリッド、面ごとのUVクロップ(uスパン = H/W x ZOOM、vスパン = ZOOM、6つのオフセット)、面法線に沿ったレリーフをエッジで0にフェード、ワインディングは面のコーナーベクトルから確認(面ごとの外向きドットをチェック;top/bottomは以前反転していた)、UVからの接線ノーマルマップ、K約0.08。レイヤーはエッジをまたいで継続しない(異なるクロップ)- ユーザーに伝える。
ツールの落とし穴
- BlenderのPythonにはscipyがない:Blenderスクリプト内ではnumpyを使用し、scipyは外部Python環境でのみ使用。
bpy.ops.mesh.primitive_uv_sphere_addは約1.5M頂点を超えると非常に遅い:numpyでメッシュを構築。- 面ごとのUV配列をスライスするときは、ローカルインデックス(q - base)を使用し、グローバルインデックスは使用しない。
- PILは16ビットRGB PNGを8ビット/クリップされた状態で読み取る:OpenCV
IMREAD_UNCHANGEDを使用。PILのconvert('RGB')で16ビットグレーPNGをプレビューすると真っ白になる。 - OpenCVのGaussian blurは
BORDER_WRAPをサポートしていない:タイリング可能なマップにはscipy.ndimage.gaussian_filter(mode='wrap')を使用。 pkill -f name/pgrep -f name | xargs killは自身のシェルにマッチして強制終了する可能性がある(終了コード144);PIDで強制終了。- 物理単位の高さからノーマルを導出;スケールが約100倍大きすぎると、暗いモトルノイズになる。
- 再利用されたファイルパスでレンダリングを読み取ると、古い画像のキャッシュが表示されることがある;新しい名前で書き込む。