PBRの理論|物理ベースの3原則とマップの値域・典型的な誤値を解説

夕宮たいだ

ふぁ……みんな〜、CG基礎講座の第1回だよぉ。テーマはぁ、PBR。なんとなく使ってる人、多いよねぇ。今回はぁ、雰囲気で済ませてた部分を、いっしょに言語化していこ〜。

本記事は、3DCG制作の現場で当たり前のように使われている PBR(Physically Based Rendering=物理ベースレンダリング) の理論を、ゲーム開発の実務目線で整理する記事です。「物理ベース」とは、光の反射や吸収を現実世界の物理法則に近い計算で行うレンダリング手法のことを指します。

「PBRワークフローで作りました」という言葉は便利ですが、その中身を説明できないままだと、エンジン(Unity / Unreal Engineなどのゲーム実行環境)に持ち込んだときに色が合わない・金属感がチープに見える・ノーマル(凹凸表現用のマップ)が逆向きといった問題に対処できません。本記事は、そうした「雰囲気PBR」から一歩抜け出すための入口として書いています。

なお、本文では「DCC」という略語が頻出します。これは Digital Content Creation(デジタルコンテンツ制作) の略で、Maya・Houdini・Blender・Substance Painter など、3Dモデルやテクスチャを作る制作ソフトをまとめて指す業界用語です。「DCC側で作って、エンジン側で表示する」という流れを覚えておくと、以降の説明が読みやすくなります。

目次

この記事のゴール

ひとことで:PBRの理論的支柱と、現場で踏むべき値域を理解することです。

  • 「物理ベース」が意味する3点(エネルギー保存・微小面理論・観測ベースのパラメータ化)を自分の言葉で説明できる
  • メタル/ラフネススペキュラー/グロシネス の違いと、ゲーム業界で前者が主流である理由を説明できる
  • BaseColor / Metallic / Roughness / Normal / AO / Height の役割と典型的な誤値を識別できる
  • DCCとエンジンで見え方が一致しない主因を切り分けられる

用語の定義

ひとことで:本記事で頻出する基本ワードを最初に整理しておきます。

用語ひとこと定義
PBRPhysically Based Rendering の略。物理法則に「だいたい従う」反射モデルで描く方式
DCCDigital Content Creation の略。Maya / Houdini / Blender / Substance Painter などの制作ソフト群を指す
BRDFBidirectional Reflectance Distribution Function(双方向反射率分布関数)の略。光が表面でどう反射するかを決める数式モデル
アルベド物体本来の色(ライティングや影の影響を含まない値)
BaseColorアルベドに「金属の反射色」も含めた、PBRの基本マップ
Metallic金属か非金属かを示すパラメータ(基本は0か1)
Roughness表面のミクロな粗さ(0=鏡面、1=完全マット)
Normal(ノーマルマップ)面の凹凸を擬似的に表現するためのテクスチャ。RGB値が法線ベクトルの向きを表す
AOAmbient Occlusion の略。くぼみが光を遮って暗くなる効果を、あらかじめ焼き込んだテクスチャ
微小面理論(マイクロファセット)表面を「無数の小さな鏡」の集合とみなす考え方
テクセルテクスチャ上のピクセル(Texture + Pixel)。テクスチャ解像度を語るときの基本単位
HDRIHigh Dynamic Range Image の略。明暗の幅が広い環境光画像(球面に貼って反射の光源として使う)
sRGB / Linearテクスチャの色空間。BaseColor は sRGB、その他のマップ(Roughness/Metallic/Normal/AO)は Linear が原則

PBRって何だっけ?(Tier 1:基本概念)

ひとことで:物理法則に「だいたい従う」反射モデルで描く方式です。

PBR(Physically Based Rendering)は、現実世界の光の振る舞いに沿った形で表面の反射を計算するアプローチの総称です。「物理を完璧にシミュレートする」のではなく、「物理的に矛盾しない範囲で近似する」という温度感が現場の実態に近い理解になります。

PBR以前と以後で何が変わったか

PBR以前のワークフローでは、ライティング条件ごとにテクスチャを描き分けることが普通でした。たとえば「夕焼けシーン用にハイライトを赤くしたディフューズを別途用意する」「暗いシーン用に明るく描いたバージョンを足す」といった対応です。これはアーティストの感覚に依存し、シーンが変わるたびに作業が増えるという課題がありました。

PBR以後は、「素材としての値」を1セット作っておけば、どのライティング条件でも矛盾しない見た目になる という発想に切り替わります。これが現代のゲーム開発における共通基盤であり、Substance などの素材ライブラリが活用できる前提でもあります。


物理ベースが守っている3つのこと(Tier 1〜2)

ひとことで:「保存」「微小な凹凸」「実測値」の3点で支えられています。

エネルギー保存則の概念図。入射光が反射・吸収・透過に分かれる関係
図1:入射光のエネルギーは反射・吸収・透過の総和を超えない

1. エネルギー保存

入射した光のエネルギーは、反射と吸収と透過の合計で入力を超えない、という原則です。古い手法ではディフューズとスペキュラーを別々に強くしてしまい、結果として「入った光より反射光のほうが多い」非物理的な絵になることがありました。PBRのシェーダは、この超過を内部で抑える仕組みを持っています。

2. 微小面理論(マイクロファセット)

表面を肉眼では見えない 無数の小さな鏡 の集合と捉える考え方です。鏡の向きが揃っていれば鏡面反射に近づき(Roughness低)、ばらついていれば散らばった反射になります(Roughness高)。Roughnessというパラメータは、この鏡の「揃い具合」を1枚のマップで表現したものです。

微小面理論の概念図。滑らかな面と凹凸面で反射光の散らばりが異なる
図2:表面の凹凸が反射の鋭さ・広がりを決める

3. 観測ベースのパラメータ化

PBRが指定する値の多くは、現実の素材を測定した結果 に基づいています。たとえば「ノンメタルの反射率はおよそ4%前後」「金属はBaseColorに反射光の色そのものを入れる」といった、観測由来の指針があります。これがあるおかげで、アーティスト同士やスタジオをまたいでも「この値に揃えれば大丈夫」という共通言語が成立します。

夕宮たいだ

ほよ?「物理ベース」って数式の話かと思ってたけどぉ、実はこの3つを守ってればOKって整理だったんだぁ。意外とシンプルだねぇ。


メタル/ラフネス と スペキュラー/グロシネス の違い(Tier 2)

ひとことで:ゲーム業界では「メタル/ラフネス」が主流です。

PBRには大きく2つのワークフローがあります。最初に違いを表で押さえておきます。

項目メタル/ラフネススペキュラー/グロシネス
マップ構成BaseColor + Metallic + RoughnessDiffuse + Specular + Glossiness
Metallic0または1の二値が基本各テクセルで反射色を直接指定
値域の向きRoughness=0が鏡面、1がマットGlossiness=0がマット、1が鏡面(逆)
ストレージ1chのMetallic + 1chのRoughnessRGBのSpecular + 1chのGlossiness
主流の用途ゲーム(Unreal / Unity / Substance)一部の建築可視化や旧来のVRayワークフロー

ゲーム業界でメタル/ラフネスが選ばれる理由

  • テクスチャ枚数とVRAMが少ない:SpecularがRGBではなくMetallic 1chで済む
  • 誤入力が起きにくい:Metallicは0か1、Roughnessは0〜1の単純なグラデーション
  • 素材ライブラリの大半がこの形式:Substance / Quixel など主要ライブラリがメタル/ラフネス前提
夕宮たいだ

うぐぅ……。GlossinessってRoughnessの逆向きなんだよねぇ。脳内変換むずかしいねぇ。新人さんに渡すマップは、なるべくメタル/ラフネスで揃えると事故が減るよぉ。

メタル/ラフネスとスペキュラー/グロシネスの2つのワークフローのマップ構成比較
図3:2系統のワークフローと対応するマップの違い

主要マップの役割と典型的な誤値(Tier 2〜3)

ひとことで:マップごとに「越えてはいけない値域」と「カラースペース」があります。

BaseColor

  • 役割:ノンメタルではアルベド、メタルでは反射色そのもの
  • カラースペース:sRGB(gamma空間)
  • 典型的な誤値:ノンメタルが真っ黒(RGB 0,0,0)/真っ白(RGB 255,255,255)。現実の素材は炭でも30前後、新雪でも240程度が上限。30〜240(sRGB 8bit) に収めるのが安全
  • 金属に黒いBaseColor:金や銅の色味を入れず単に暗く塗るのは誤り。金属は色そのものをBaseColorに入れる

Metallic

  • 役割:金属(1)か非金属(0)かを示すバイナリ
  • カラースペース:Linear
  • 二値で扱うべき理由:物理的には「半分金属」の素材は存在しない。ホコリや塗装で覆われた金属を表現したい場合は、Metallicを0.5にするのではなく Roughnessを上げる か、塗装部とベース部をマスクで分けてMetallicを切り替える
  • 錆びた鉄:錆び自体は非金属だが、ベースの鉄部はMetallic=1である必要があるため、マスクで領域を分ける

Roughness

  • 役割:表面のミクロな粗さ。0で完全鏡面、1で完全マット
  • カラースペース:Linear
  • 反転の事故:Glossinessを誤ってRoughnessに入れると、見た目がすべて逆になる。チェックは「磨いた鏡面が黒側に近いか(Roughness=0は黒側)」で判断する
  • 極値の多用:完全鏡面(0)や完全マット(1)は現実にほぼ存在しない。0.05〜0.95 に収めると自然
Roughness値0.1/0.5/0.9の球体比較。値が大きいほど反射が拡散する
図4:Roughnessの違いによる反射の見え方

Normal

  • 役割:表面の凹凸を擬似的に表現する
  • カラースペース:Linear(青みがかった RGB(128,128,255) が「平坦」を意味する)
  • 典型的な誤値:DirectX系(UnrealやUnityのデフォルト)と OpenGL系(Mayaや一部のレンダラ)でG(緑)チャンネルの向きが逆になっており、片方の規格で出力したものをもう一方で読み込むと凹凸が反転する/誤って sRGB で読み込んでしまっている、など。詳細は CR-04 ノーマルマップとタンジェント空間 で扱います

AO(アンビエントオクルージョン)

  • 役割:くぼみの陰影を補強する
  • カラースペース:Linear
  • 典型的な誤値:BaseColorに焼き込んでしまう。AOは別マップとして渡し、エンジン側で乗算するのが原則。BaseColorに焼くと、ライティング条件が変わったときに「日向なのに影が残る」絵になる

Height(ハイト/ディスプレース)

  • 役割:実際にメッシュ(3Dモデルの形状)を変形させる、もしくは Parallax Occlusion Mapping(パララックス・オクルージョン・マッピング:シェーダで擬似的に深い凹凸を見せる手法)用の高さ情報として使う
  • カラースペース:Linear
  • 典型的な誤値:Normalの代わりに使ってしまう(用途が異なる)。Normalは法線を傾け、Heightは実際の凹凸を作る
夕宮たいだ

ぷんぷん。「金属に黒いBaseColor」「Roughnessの反転」「AOをBaseColorに焼き込み」は3大やらかしだよぉ。絶対ダメ。新人さんがハマりがちだから、納品前に必ず確認してねぇ。


DCCとエンジンで見え方がズレる主因(Tier 3〜4)

ひとことで:色空間とトーンマッピングの2つを順番に疑います。

Substance Painter のViewportでは完璧に見えていたのに、Unreal Engineに持ち込んだら「色が薄い」「金属感が違う」となるケースは頻繁に発生します。主因は次の2つです。

1. 色空間(カラースペース)

  • BaseColorは sRGB、その他のマップ(Metallic / Roughness / Normal / AO / Height)は Linear で扱うのが原則
  • エクスポート時にBaseColorをLinearで書き出してしまう、あるいはMetallicをsRGBで読み込ませてしまう、といった指定ミスでズレが生じる
  • Substance PainterのExportでは、Texture Setのテンプレートを「Unreal Engine 4 (Packed)」などエンジン名のプリセットに切り替えると安全

2. トーンマッピング

  • DCCツールとゲームエンジンで、ハイライトの圧縮カーブが違うことがある
  • Substance Painter は ACES(Academy Color Encoding System:映像業界標準の色管理規格)系のカーブをデフォルトに採用しているが、エンジン側の PostProcessVolume(Unrealでポストエフェクトを管理するアクター)設定次第で見え方が変わる

詳細な色合わせ手順は CR-12 DCC→エンジンの色合わせ で扱います。本記事では「ズレたら、まず色空間 → 次にトーンマッピング(明るい部分を画面の表示範囲に圧縮するカーブ調整)を疑う」という切り分けの順序だけ覚えてください。

夕宮たいだ

DCCで頑張って合わせてもぉ、エンジンで違って見えると焦るよねぇ……。色空間→トーンマッピングの順で確認するクセをつけると、原因切り分けがラクになるよぉ。気をつけてねぇ。


ハンズオン演習

ひとことで:手元の素材で BaseColor / Metallic / Roughness を分解して並べ、Roughnessだけ段階変化させます。

理屈が分かっていても、自分の目で見ないと身につきません。次の手順で5〜10分の演習を行ってください。

  1. お手元のDCC(Substance Painter / Maya / Blender など)を開き、シンプルな 球体 を1つ配置する
  2. マテリアル(質感設定)を作成し、PBR系シェーダ(Blender なら Principled BSDF、Maya なら aiStandardSurface、Unity なら Standard Shader、Unreal なら Metal Rough マテリアルなど、各ソフトに用意された汎用 PBR シェーダ)を割り当てる
  3. BaseColor:濃いめのグレー(sRGB 100,100,100 程度)の単色を入れる
  4. Metallic:0(ノンメタル)に固定
  5. Roughness0.05 / 0.30 / 0.60 / 0.90 の4パターンを横並びで表示する
  6. 環境ライティング(HDRI:明暗の幅が広い360度の環境光画像。空や室内の光をまるごと再現してくれる素材)を1つだけ与え、それぞれの反射の広がり方を観察する

確認ポイント

  • Roughness=0.05 はハイライトが点状で鋭い
  • 0.30〜0.60 で輪郭がぼやけ、環境の映り込みが「広がる」
  • 0.90 ではハイライトがほぼ消え、マット紙のような見た目になる

応用編:同じ条件で Metallic=1 に切り替えると、BaseColor のグレーが「金属の色」として反射に乗ります。ノンメタル時とどう変わるかを比較すると、Metallicの効きが体感できます。


チェックリスト

ひとことで:納品前に最低限これだけは見直してください。

  • BaseColor のノンメタル領域が 30〜240(sRGB 8bit) に収まっている
  • Metallic は 0または1の二値 になっている(中間値で塗っていない)
  • Roughness が 反転していない(鏡面が黒側に見える)
  • AO は BaseColorに焼き込まれていない(独立マップで渡している)
  • エクスポート時の カラースペース指定 が正しい(BaseColorのみsRGB、他はLinear)
  • Normal の Y軸方向 がエンジン仕様と一致している(DirectX or OpenGL)

よくある間違い・トラブルシュート

ひとことで:症状から原因に逆引きするための一覧です。

症状主な原因対処
金属がプラスチックっぽいBaseColorが暗すぎる、もしくはMetallic=0になっているBaseColorに金属本来の色を入れ、Metallic=1へ
全体が眠い・コントラストがないRoughnessが反転している、もしくは値が高すぎるGlossinessと取り違えていないか確認、エクスポート設定を見直す
凹みが日向でも黒いAOがBaseColorに焼き込まれているAOマップを分離し、エンジン側で乗算する
エンジンで色が薄く感じるBaseColorをLinearで書き出しているsRGBで再エクスポート
凸凹が逆向きに見えるNormalのY軸(緑チャンネル)反転DirectX⇄OpenGLの設定を切り替え
夕宮たいだ

ふぁ……お疲れさま〜。今日のポイントはぁ、「物理ベースは3つの原則で支えられてる」「マップごとに値域とカラースペースのルールがある」「DCC↔エンジン差は色空間→トーンマッピングの順で疑う」だよぉ。次回からはぁ、ノーマルマップやチャンネルパッキングを掘り下げていこ〜。まぁ、そういうことなんだよぉ。


次に読む記事

本記事は CRシリーズ の入口の1本です。理解を深めるために、以下の記事もあわせて読んでみてください。

参考資料

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

目次