#ue4fest#ue4fest
UNREAL FEST EAST 2018
#ue4fest#ue4fest
UE4のライティング解体新書
~効果的なNPRのためにライティングの仕組みを理解しよう~
田中達大(ソレイユ株式会社)
梶井祐(Winter Crown Works)
#ue4fest#ue4fest
自己紹介
#ue4fest#ue4fest
• 田中達大
ソレイユ株式会社 シニアソフトウェアエンジニア
業界歴30年近く。ここ7年ほどはUnreal Engineと付き合っ
てます。自社、他社のUE4タイトルを複数受け持ち、CGを中心
に技術全般を担当してます。
自己紹介
#ue4fest#ue4fest
• 梶井祐
WinterCrownWORKS プログラマー
インディーゲーム制作の傍ら、各法人会社様開発タイトルの
グラフィックス方面のテクニカルサポートを行う。
主にプロファイル、高速化の提案、実装等を担当。
自己紹介
#ue4fest#ue4fest
・UE4はフォトリアルな物理ベースシェーディングを得意とす
るゲームエンジンですが、NPR(ノンフォトリアル)なタイ
トルも多数あります。
・特に日本のタイトルはNPRが多いように思います。
・NPRだからってライトを無視しては良い表現になりません。
むしろNPRだからこそライティングの理解が大事。
・UE4のライティングの仕組みを解説しつつ、フォワードとデ
ィファードの有利不利な点も解説します。
・UE4のバージョンは4.20をベースに話します。
はじめに
#ue4fest#ue4fest
• 数式とか難しい話はそんなにしません。
• 写真撮影OKですが、シャッター音がしないアプリを使いまし
ょう。
• スライドはすぐに公開するので、撮影しなくて大丈夫です。
はじめに
#ue4fest#ue4fest
• 前提条件
• ライトの種類
• 直接光と間接光
• 平行光源と点光源(面光源は扱わない)
• 環境光(スカイライト)
• レンダリングの種類
• ディファードレンダリング
• フォワードレンダリング
• ディファードとフォワードのパフォーマンス比較
アジェンダ(1/2)
#ue4fest#ue4fest
• ディファードライティングの過程を追う
• エンジンを改造してライティングを拡張するポイント
アジェンダ(2/2)
#ue4fest#ue4fest
前提条件
まず最初に、このセッションで扱うライティングについて整理しておきます。
#ue4fest#ue4fest
ライティングとはライトを当てることです(当たり前)
• UE4におけるライティングは、シーンに置かれたメッシュな
どにシーンに置かれたライトの影響を計算して、最終的に色
を出力することです。
• 概ね物理法則に従っているが、省略や近似も多い。
• このセッションでは間接光はUnreal Lightmassを扱います。
LPVなどの他のライティングシステムには言及しません。
• AreaLightに関しても話が複雑になるので、無いものとして語
ります。
ライティングとは
#ue4fest#ue4fest
ライトの種類
UE4におけるライトの種類を整理します。
#ue4fest#ue4fest
• UE4で扱うライトには大きく分けて、直接光と間接光があり
ます。
• 直接光は物体に直接あたってるライト、間接光は他の物体に
あたって反射した結果のライト。
• 直接光は描画時にライティング計算されますが、間接光は
Lightmassで事前計算され、ライトマップやボリュームテクス
チャに格納されたものを描画時に利用して計算されます。
直接光と間接光
#ue4fest#ue4fest
左の球は間接光あり、
右の球は間接光なし。
左は空の色を反映して
少し青くなり、影の部
分に地面から反射した
間接光が当たっている
のが良くわかります。
エディタで見ると
#ue4fest#ue4fest
Skylightを無効にする
とこんな感じです。
間接光の影響は
非常に大きい!
間接光が無いと影の部
分は真っ暗になってし
まいます。
キャラクターのマテリアルの確認
はSkylight無効の状態で行った方が
良いかも。
エディタで見ると(Skylight off)
#ue4fest#ue4fest
意外と知らない人が多いのですが、間接光の強
さはピクセル単位で調整できます。
去年の講演でも話しましたが、マテリアルの「
アンビエントオクルージョン」はそのまま間接光
の強さを0~1で指定します。
0にすると、そのピクセルは間接光の影響を受け
なくなります。
あらかじめ計算されたアンビエントオクルージ
ョンマップを入力すると、遮蔽度が高いところに
は間接光の影響が弱くなります。
間接光って切れるの?
#ue4fest#ue4fest
• ライトのタイプがMovableかStationaryのライト
• レンダリングパス内で各ライトから計算される。
• 基本的な構成は1つのStationaryなDirectional Lightと、必要に
応じてMovableかStationaryなPoint LightやSpot Light。
• 要するに、太陽光とシーンに配置された点光源というのがス
タンダードな構成。
UE4の直接光
#ue4fest#ue4fest
• あらゆるStaticなライト(Skylightも)
• リアルタイムには計算されず、ライトビルド時に計算されて、
ライトマップテクスチャに書き込まれる。
• 静的オブジェクトは、そのオブジェクトに対してライトマッ
プが生成される。
• 動的オブジェクトは、ライトビルド時に生成されたVolumetric
Lightmapを元に間接光が計算される。
(以前はIndirect Light Cacheをもとに計算されていた)
UE4の間接光
#ue4fest#ue4fest
• 平行光源は方向だけを持ち、範囲を持たない。
• が、4.20からはDynamicな平行光源が範囲を持つカプセルと
して計算されるようになった。
• 点光源は特定の座標から広がり、距離によって減衰するライ
ト。全方向に広がるのがPoint Light、特定の方向に広がるのが
Spot Light。
• 4.20でArea Lightも実装されたが、複雑なので割愛。
平行光源と点光源
#ue4fest#ue4fest
• UE4では主にSkylight。
• 実際にはシーンをキャプチャしたキューブマップによるライ
ティングが行われる。上からの空の色と下からの地面の色で
ぼんやり照らすイメージ。
• StaticなSkylightの影響は間接光として焼き込まれる。
環境光
#ue4fest#ue4fest
重いか重くないかって言うと静的なライトよりは重いです。
静的なライトは事前計算なので毎フレーム計算する必要はあ
りませんが、動的なライトは毎フレーム計算されます。
だったら静的なライトだけでよくね?
・・・と思うかもしれませんが、動的なライトにしかできな
いことがあります。
動的なライトって重くない?
#ue4fest#ue4fest
• ライト、カメラの方向に応じたシェーディング
• 動的な影、動いている物体のセルフシャドウ
• スペキュラの生成
動くものを正しく描画するには動的なライトが必要です。
静的なライトだけでは物体やカメラが移動してもシェーディ
ングに変化がありません。
動的なライトにしかできないこと
#ue4fest#ue4fest
• できるだけStationaryにしましょう。
• Point Light、Spot Lightは範囲を狭く、ライトどうしの範囲が
重ならないように。
• 不要ならCast Shadowを切る。ライティングよりも影の生成
の方が重い。
影についてはStationary Lightの方が軽いと一概には言えない
ので、スミオさんのブログを参考にしてください。
Stationary Lightの影について
動的なライトを軽くするには
#ue4fest#ue4fest
違いがわかりやすいように、スペキ
ュラを設定しました。左が間接光あり、
右が間接光無しです。
Directional Light以外は取り除いてあ
ります。
Stationary Directional Lightについてもう少し
#ue4fest#ue4fest
Directional Lightを無効にしました。
地面からの反射光で左側がうっすら照
らされています。リフレクションは出
てますが、これはスクリーンスペース
リフレクションです。
Stationary Directional Lightについてもう少し
#ue4fest#ue4fest
Stationaryなライトがない状態でライ
トビルドすると光源が無いので間接光
もなくなり、真っ黒になります。
空の色は変わりませんが、空はUnlit
なマテリアルで作られているからです。
Stationary Directional Lightについてもう少し
#ue4fest#ue4fest
Directional LightをStaticに変更して
ライトビルドをかけます。この状態で
は太陽光に相当するDirectional Lightも
間接光として扱われています。
一見、ライティングされているよう
に見えますが、スペキュラがなくなっ
ています。
光源と視点から計算されるスペキュ
ラは光源が無いと描画のしようがあり
ません。
Stationary Directional Lightについてもう少し
#ue4fest#ue4fest
Directional Lightに限らず、Point
LightもStationaryやMovableならスペキ
ュラが生まれます。
Staticなライトは種類にかかわらずス
ペキュラを生成しません。
Stationary Point Lightについても
#ue4fest#ue4fest
• StationaryやMovableなDirectional Lightは必ずシーンにひとつ
だけ配置してください。複数配置すると不具合の原因になる
ことがあります。
• Directional Lightは範囲が無いのでシーン全体に影響します。
Directional Lightについて注意
#ue4fest#ue4fest
スペキュラ(鏡面反射)はリフレクションの疑似表現と捉え
て良いかと思います。シーン全体の正確なリフレクションを計
算するには膨大な計算が必要ですが、特に強く光を反射する部
分を擬似的に計算したものです。
特にPBRなどの写実的な表現において物体の質感を表現する
一番大きな要素がスペキュラだと思います。
Roughness,Specular,Metallic、すべてスペキュラとリフレク
ションを制御するパラメーターです。
スペキュラについて余談
#ue4fest#ue4fest
Unreal Lightmass
ライトビルドに関してざっと解説
#ue4fest#ue4fest
• 解説しようと思いましたが、篠山さんが詳しくまとめてくれ
てるので、こちらをどうぞ。
Lightmass Deep Dive 2018 Vol.1: Lightmass内部アルゴリズム概
要(Lightmap編)
Unreal Lightmass
#ue4fest#ue4fest
要点だけ。
• Staticなライト、Static Meshは配置しただけでは静的なライテ
ィングがされません。必ずライトビルドしましょう。
• 特にパフォーマンスを見る場合は必ずライトビルドが必要。
• この表示が出ている状態はライトビルドされてません。
1 unbuilt objects、1つだけでもパフォーマンス全体に大きな
影響を与えることがあります。必ずビルドしましょう。
Unreal Lightmass
#ue4fest#ue4fest
ディファードとフォワード
UE4にはディファードレンダリングとフォワードレンダリングの2種類の
ライトレンダリング方式があります。
#ue4fest#ue4fest
• 大きな違いはLightingの過程。
ForwardRenderingではマテリアルのレンダリング時にライテ
ィングが行われる。
DeferredRenderingではモデルのLightingに必要な情報をワー
クバッファ(GBUFFERと呼ばれる)に出力した後にポスト
処理としてLightingを行う。
Lighting処理を遅延させる事からDeferredRenderingと呼ばれ
る
違い
#ue4fest#ue4fest
表示モード
→バッファを
可視化
→OverView
出典:Epic Gamesから無料で配布されている Soul:City パック
#ue4fest#ue4fest
• BaseColor
• Roughness
• Specular
• SubSurfaceColor
• Metallic
• WorldNormal
• SceneDepth
• LightingModel
GBUFFERの主な出力
#ue4fest#ue4fest
• GBUFFERがあるDeferredでは画面内の情報をポスト処理で拾
いなおせるため応用の幅が広くなっている。
例えば:
NPRで画面全体のモデルにアウトラインを出して表示カラ
ーをセル調にしたい
といった場合には、NormalやBaseColorを読み取ってポスト
プロセスで処理できた方が流れがシンプルかつ負荷的にも良
い。
(正確には良いケースが多い、実際にはやりたい事次第)
GBUFFERのあるなしの違い?
#ue4fest#ue4fest
では実際のForwardRenderingとDeferredRenderingの
レンダリングフローをテストシーンの描画イベントから追って
いきたいと思います。
レンダリングフロー
#ue4fest#ue4fest
• SoulCityのシーンにて、RenderDocで中身を解析していきま
す。
RenderDocはunrealEngineが使える標準プラグインで、大元
はCryTekのGPU分析ツールがオープンソースになったもので
す。
Pluginを有効にした後はコンソールコマンドから解析したい
シーンで"RenderDoc.CaptureFrame"で1フレームキャプチャ
が行われます。
キャプチャシーン
#ue4fest#ue4fest
フォワードレンダリング
フォワードレンダリングのプロセス
#ue4fest#ue4fest
キャプチャしてみました
#ue4fest#ue4fest
描画パス一覧 1
描画パス名
GPUParticles_PreRender HZB
PrePass DDM_AllOpaque BeginRenderingGBuffer
ResolveSceneDepthTexture BasePass
ComputeLightGrid ResolveSceneDepthTexture
BeginOcclusionTests GPUParticles_PostRenderOpaque
HZB SetupMip 0 RenderVelocity
HZB SetupMip Mip 1 LightCompositionTasks_PrLighting
#ue4fest#ue4fest
描画パス一覧 2
描画パス名
Translucency PostProcessEyeAdaptation
Distortion Downsample
ResolveSceneColor PostProcessWeightedSampleSum
BokehDOFRecombine PostProcessCombineLUTs
VelocityFlattenCS Tonemapper
VelocityGatherCS PostProcessFXAA
MotionBlur SlateUI
#ue4fest#ue4fest
• 使う機能次第で描画パスは増えたり減ったりします。
一杯ありますね・・・。
#ue4fest#ue4fest
• Forward Renderingのキモというかこの描画イベントに役割は
集約されています。
各不透明、Maskedモデルがレンダリングされる場所で、
ForwardRenderingにおいてはBasePass内で、
Fog,DirectionalLight,PointLight,SpotLight,AreaLight,Refrection
Capture,SkyLight,LightCache・・・等が処理されています。
BasePass
#ue4fest#ue4fest
• モデル内でポイントライトやスポットライトをLocalLightとし
て処理する。
適応されるLightはComputeLightGridで画面をグリッドで分け
それぞれのライトの影響範囲と交差したグリッドにLightを収
集している。
• 影響範囲内のReflectionCaptureがモデルのレンダリング時に
SkyLightとmixingして使われる。(そのためピクセル的には当
たってない場所にも若干の判定処理が追加コストでかかる)
Forward Lightingの特徴
#ue4fest#ue4fest
ディファードレンダリング
ディファードレンダリングのプロセス
#ue4fest#ue4fest
こちらもキャプチャしてみました
#ue4fest#ue4fest
描画パス一覧
描画パス名
GPUParticles_PreRender HZB
PrePass DDM_AllOpaque ShadowDepth
ResolveSceneDepthTexture BeginRenderingGBuffer
ComputeLightGrid BasePass
BeginOcclusionTests ResolveSceneDepthTexture
HZB SetupMip 0 1024x1024 GPUParticles_PostRenderOpaque
HZB SetupMips Mips:1 512x512 RenderVelocity
#ue4fest#ue4fest
描画パス一覧 2
描画パス
ResolveSceneDepthTexture ScreenSpaceReflections
GPUPArticles_PostRenderOpaque TAA ScreenSpaceReflections
LightCompositionTasks_PreLighting ReflectionEnvironmentAndSky
ClearTranslucentVolumeLighting BeginRenderingSceneColor
Lights ExponentialHeightFog
InjectAmbineCubemapTranslucenctVolumeLighting Translucency
FilterTranslucentVolume Distortion
#ue4fest#ue4fest
描画パス一覧 3
描画パス
PostProcessEyeAdaptation MotionBlur
SlateUI PostProcessWeightedSampleSum
Downsample PostProcessCombineLUTs
PostProcessWeightedSampleSum Tonemapper
BokehDOFRecombine
VelocityFlattenCS
VelocityGatherCS
#ue4fest#ue4fest
• 大きいグループの描画パスを拾ってきてもForwardRendering
に比べて描画のパスが増えております。
実際何が増えているのか見てみましょう。
こちらはさらに多いですね
#ue4fest#ue4fest
Deferred Renderingのみのパス
描画パス名
LightCompositionTasks_PreLighting ClearTranslucentVolumeLighting
Lights InjectAmbientCubemapTranslucentVolumeLighting
FilterTranslucentVolume ScreenSpaceReflections
ExponentHeightFog TAA ScreenSpaceReflections
ReflectionEnvironmentAndSky
#ue4fest#ue4fest
• 追加で増えているパス達は広い意味でLightingに関連するもの
ばかり。(一部例外がありますがLighting結果に影響を与えま
す)
それぞれのパスに関して簡単に説明していきます。
実は表に書いたものはLighting絡み
#ue4fest#ue4fest
• DeferredDecal
• AmbinetOcclusion
を行うパス。
DeferredDecalsやScreenSpaceAmbientOcclusionを行うにはス
クリーンの情報をGBufferから読み取り処理を行います。
LightCompositionTasks_PreLighting
#ue4fest#ue4fest
AO:LightMaskのGenerate
#ue4fest#ue4fest
AO:LightMaskをSceneにMerge
#ue4fest#ue4fest
AO:AmbientCubeMapを適応
#ue4fest#ue4fest
• 環境光格納のためのVoxelDataのクリア
半透明マテリアルが環境光にアクセスするために必要。
VolumeTextureはテクスチャキャッシュ効率も悪く環境によって
は負荷が高くなりやすいので解像度には注意。
デフォルト64x64x64
ClearTranslucentVolumeLighting
#ue4fest#ue4fest
• 画面内の情報をGBufferから読み取りながらスクリーン内を
Lightingする。
影の生成、影のcomposit、Shading等も行う。
Lights
#ue4fest#ue4fest
• TranslucentVolumeLighting用のVoxelDataにAmbient情報を書
き込む
半透明はレンダリング時に、ここで書き込まれた情報を環境
光としてアクセスして照らされる。
書き込まれるのはPostProcessActorのAmbinentCubeMapで、
設定されたテクスチャがAmbinetとして使用される。
このパスでは半透明が参照するためのAmbientCubeMapを
Voxelに書き込んでいる。
InjectAmbientCubemapTranslucenctVolu
meLighting
#ue4fest#ue4fest
• Voxel内のアーティファクトやノイズを減らすため、ぼかして
ノイズリダクションを行う。
こちらもVoxelに対して行うため、環境によっては結構な負荷
になるので注意。
FilterTranslucentVolume
#ue4fest#ue4fest
• GBufferを元に画面内で行うレイトレース
画面内だけとはいえ、テクスチャアクセス数、計算量の両方
とも多い。
こちらも負荷は高いので注意が必要。
SSRと略される。
ScreenSpaceReflections
#ue4fest#ue4fest
SSR:出力結果
#ue4fest#ue4fest
• ScreenSpaceReflectionのノイズリダクションを行う。
ScreenSpaceReflectionのエイリアシングやカメラの動きによ
るアーティファクトが低減されます。
TAA ScreenSpaceReflections
#ue4fest#ue4fest
TAA SSR: NoiseReductionの結果
#ue4fest#ue4fest
• ReflectionCaptureやSkyLightをシーンにマージするパス。
ForwardRenderingの時にはBasePassでモデル単位にやって
いた処理なのですが、DeferredRenderingではフィルタ的にシ
ーンにマージします。
SSRの結果もマージされ、回り込みの光がForwardに比べてよ
り精度が高く格納されます。
ReflectionEnvironmentAndSky
#ue4fest#ue4fest
Reflection関係をSceneに適応
#ue4fest#ue4fest
• DeferredRenderingでは不透明に対するフォグはフィルタ的に
かける。
半透明に関しては描画ごとになり、設定によって頂点側、ピ
クセル側でかけるのかが分かれる。
Forwardの場合は不透明、半透明ともにモデルのレンダリング
ごとにシェーディング時に適応される。
ExponentHeightFog
#ue4fest#ue4fest
HeightFogの適応後
#ue4fest#ue4fest
フォワードvsディファード
フォワードレンダリング
• 裏でLightingに関するバッフ
ァを加工するパスがなく非
常にシンプル。
結果的に負荷の高い処理が
抑制されている。
しかしその代わりBasePass
内が非常に複雑。
ディファードレンダリング
• Lightingを加工するパスが非
常に多い。
取り回しは非常に柔軟。
デフォルトで使用されるパ
スの負荷が高い。
ゲームによっては調整のた
めにレンダリングの知識が
求められる傾向。
#ue4fest#ue4fest
パフォーマンス対決
で、どっちが速いの?
#ue4fest#ue4fest
比較
#ue4fest#ue4fest
• PC上かつRenderDocでの計測なので精度は低めです。
とはいえ実際には今の段階ではForwardより実際に多くを処理
する設定になっているため、その分は重くなっております。
じゃあ、ForwardRenderingが高速である と位置付けてもよ
いのでしょうか。
Forwardが速そうに見える
#ue4fest#ue4fest
• そもそもForwardになくて、Deferredでのみ走ってるパスがあ
る。
使う使わないもユーザーの手にゆだねられている。
Forwardの見た目に追加効果で入ってる部分がある以上は単純
比較すべきではないのでは?
本当に?
#ue4fest#ue4fest
Deferred Rendering追加パス おさらい
描画パス名
LightCompositionTasks_PreLighting ClearTranslucentVolumeLighting
Lights InjectAmbientCubemapTranslucentVolumeLighting
FilterTranslucentVolume ScreenSpaceReflections
ExponentHeightFog TAA ScreenSpaceReflections
ReflectionEnvironmentAndSky
#ue4fest#ue4fest
それぞれの負荷
描画パス名
LightCompositionTasks_PreLighting 2.074ms ClearTranslucentVolumeLighting 0.009ms
Lights 3.021ms(ただしBasePassから切り離されたLight
処理なので、この分はBasePassが軽くなってる。)
InjectAmbientCubemapTranslucentVolumeLighting
0.009ms
FilterTranslucentVolume 0.017ms ScreenSpaceReflections 1.697ms
ExponentHeightFog 0.097ms TAA ScreenSpaceReflections 0.321ms
ReflectionEnvironmentAndSky 1.08ms
#ue4fest#ue4fest
• LightCompositionTasks_PreLighting = 2.074ms
• ScreenSpaceReflection = 1.697ms
• TAA ScreenSpaceReflections = 0.321ms
この辺りに関しては元々ForwardRenderingでは処理できない
部分なので、オミットしてもForwardと見た目は合うはず。
速度的にはこれで4ms程。
機能をある程度Forwardに準拠させれば特別なイニシアチブは
なさそう。
Forwardに合わせる形で機能をオミット
#ue4fest#ue4fest
• せっかくのDeferredRenderingの恩恵を潰すのは勿体ない。
GBufferがある事で自前の特殊なPostProcessや自前のLighting
パスなどを追加しやすいメリットがある。
結局のところは何をやりたくて、その中で何を残すべきなの
か、選択肢を並べてプロジェクトにとって何が良いかを精査
するべき。
安易に、中身を確認せずに~~をしたから高速、~~だから
安全という事はない。
物事は常にケース・バイ・ケース
とはいえ
#ue4fest#ue4fest
• 今回のやり方ではほぼ差がないところまで調整は可能。
ただし、それも環境次第で、GBufferへの出力自体の負荷が極
端に高くなってしまうような帯域が狭いローエンドなハード
もあります。
その場合ではそもそもDeferredRenderingが選択肢に上がらな
い事もあります。
他にはVR系等で、MSAAを使いたいケースでは
ForwardRenderingを選択せざるを得ない事も・・・。
結果
#ue4fest#ue4fest
• Lightingの負荷はForwardRenderingもDeferredRenderingでも
照らされている面積に依存。
ForwardRenderingのLightingは前世代時からは大きく更新さ
れており、PixelShader内でそのピクセルに影響する必要最小
限のLightが計算されるように設計されております。
そしてDepthPrepassが実行されている事でピクセルの出力は
最小限で済んでいるため、同じLightの環境下では特別
DeferredRenderingのLightが軽いという事もありません。
オマケ:Lightingの負荷説明
#ue4fest#ue4fest
例えばこのポイントライト
#ue4fest#ue4fest
実際には
#ue4fest#ue4fest
これだけ違う
#ue4fest#ue4fest
• 画面内で大きい光源ほど
重い!!
つまりLightingの負荷は?
#ue4fest#ue4fest
• 負荷や描画パスを追っかけるのはProfilerが便利です。
Profilerには色々あり、それぞれ使ってみると勉強になると思
います。
次ページに自分の使った事のあるGPU Profilerの名前を載せて
おきます。
さらにオマケ
#ue4fest#ue4fest
• Pix = Micro Softが提供しているProfiler
• RenderDoc = 現在UE4標準のProfiler、オープンソースでプラ
グインが用意されている。
• Interl Graphics PerformanceAnalizer = intel製 リアルタイム
で描画イベントをハックしたデバッグもできる。
• NSight = NVidia製 RenderDocに比べると敷居は高め
*自分が一番よく使うのはコンソール系のProfiler達です
が・・・。(一番ノイズが少なく詳細なので・・・)
GPUProfileを撮れるProfiler
#ue4fest#ue4fest
• 最近はインディーゲーム制作者が増えて来ております。
コンソールのライセンスも比較的降りるようになっているの
ですが、PCのパフォーマンスを基準にしているとかなり痛い
目を見ます。
特に現在換算で、ちょっと低スペックPCぐらいがコンソール
ぐらいのパフォーマンスだったり、コンソールよりちょい上
のパフォーマンスだったりします。
恐らく初めて触る人は面食らうのではないでしょうか。
PCでのみ制作している事の落とし穴
#ue4fest#ue4fest
• Deferred,Forward関係なく、コンソール触れる環境が手に入
る場合は早めに手に入れコンソールで動かしましょう。
PCで速度がいくら出ていてもあてにはなりません。
PCが一番速度が出やすい環境です。
パフォーマンスで問題が出るとしたらコンソール。
そしてパフォーマンスを正確に計測できるのもコンソール。
Profilerが非常に優秀。
インディーゲーム開発する方へ
#ue4fest#ue4fest
ディファードライティングの
過程を見る
RenderDocでディファードライティングの過程を確認します。
アーティストの方も知っておくと得します。(多分)
#ue4fest#ue4fest
ご存知「サンテンプル」です。
デカールの話もしたいので、壁にデ
カールを貼りました。
上がDBufferデカール、下が通常の
ディファードデカールです
Movableオブジェクトが無いとダイ
ナミックシャドウもつくられないの
で、グレイマンも配置。
ディファードライティングの過程
#ue4fest#ue4fest
まずは深度情報だけ描画します。
このあとのパスで不要な描画を避け
るのが最大の目的です。
また深度情報はこのあとのパスやポ
ストプロセスなど、様々な場所でも
利用されます。
PrePass_DDM_AllOpaque
#ue4fest#ue4fest
ダイナミックシャドウのシャドウマ
ップを生成します。
このシーンでは対象になるのがグレ
イマンだけですが、背景オブジェク
トなどもCast ShadowとDynamic
Shadowが有効なら、シャドウマッ
プに描画されます。
ShadowDepth
#ue4fest#ue4fest
BasePassの前に実行されます。
シーンカラーとDBufferという、DBuffer
デカール専用のバッファにデカールを描
画します。
CompositionBeforeBasePass
#ue4fest#ue4fest
いよいよBasePassです。各種GBufferが
生成されます。
実はこのときにカラーバッファにも出力
があります。(右の画像)
これはLightmassの情報をもとに作成さ
れた間接光のみのカラー情報です。
ここ重要!!
UE4のディファードライティングでは
BasePassで間接光が計算されます。
BasePass
#ue4fest#ue4fest
このパスでディファードデカール
が描画されます。
ディファードデカールは各種
GBufferに書き込まれますが、シー
ンカラーには書き込まれません。
どういうことかというと、ディフ
ァードデカールはそれ自体は間接光
を持たないということになります。
つまり、デカールが貼られたオブ
ジェクトの間接光が適用されます。
LightCompositionTasks_PreLighting
#ue4fest#ue4fest
このパスでGBuffer情報とライト情
報をもとにライティングを行います。
Directional Lightの場合は画面全体の
すべてのピクセルに対しライティン
グ計算を行い、カラーバッファに加
算します。
つまり、間接光に直接光を加算して
いくわけです。
また、シャドウマップはスクリーン
スペースに変換されて、ここで合成
されます。
Lights
#ue4fest#ue4fest
ポイントライトの場合は有効範囲に
だけ処理が行われます。
RenderDocのMesh Outputで見ると、
ポイントライトを中心にスフィアが
描画されているのがわかります。
このスフィア内のピクセルにライテ
ィングされるわけです。
Lights(Point Light)
#ue4fest#ue4fest
スクリーンスペースなリフレクショ
ンを計算します。
この際にGBuffer情報や深度情報も
利用されます。
ScreenSpaceReflections
#ue4fest#ue4fest
Screen Spaceリフレクションに
加え、Skylight由来のリフレクショ
ンや、キャプチャ由来のリフレクシ
ョンをカラーバッファに合成します。
ライティング工程はこれでほぼ完
了になります。
ReflectionEnvironmentAndSky
#ue4fest#ue4fest
ライティング工程まとめ
#ue4fest#ue4fest
ざっと駆け足で、実際の画面の変化を見ながらライティング
の工程を追ってみました。
ライトの構成や、使用するコンポーネントなどで変化する部
分もあります。フォグやブラー、ポストプロセスなどの処理も
行われます。
ライティング工程まとめ
#ue4fest#ue4fest
• 間接光はBasePassで計算される。
この仕組みのため、ディファードデカールはあまりうまく機
能しません。間接光にGBuffer情報をもとにしたライティングが
加算されるので、どうしても半透明のような見た目になります。
これを避けるため、DBufferデカールは専用のバッファを使用
し、期待通りの描画をしてくれますが、スクリーンサイズのバ
ッファを複数作成するのでパフォーマンスが気になります。
重要ポイント
#ue4fest#ue4fest
フォワードと比較
せっかくなので、フォワードに切り替えて比較してみましょう。
#ue4fest#ue4fest
ディファードライティングの最終結果
#ue4fest#ue4fest
フォワードライティングの最終結果
• ディファードデカ
ールが消滅
• スクリーンスペー
スリフレクション
がなくなり、リフ
レクションがやや
劣化
それ以外はあまり差
異が無い画像になっ
ています。
#ue4fest#ue4fest
ライティングのエンジン拡張
独自のライティング計算を拡張するポイント。
ここからはエンジニア寄りの話。アーティストの方はエンジニアにお願い
しよう。
#ue4fest#ue4fest
ライティングを拡張する際は主にEngine/Shadersフォルダに
あるシェーダーコードに手をいれるわけですが、ここで心配事。
ディファードとフォワードで違う拡張が必要なんじゃない
の?
意外と大丈夫!
ほとんどの場合、同じコードでどちらでも機能するよう
になっています。
エンジン拡張の際のディファードとフォワード
#ue4fest#ue4fest
まずはディファードを拡張するのがオススメです。
理由は
• GBufferを見ながらステップバイステップで状態を確認できる。法線の
値とかをRenderDocで確認したりできる。
• ディファードで動いたものはだいたいフォワードでも動く
(ただし、GBuffer情報を使うポストプロセスは無理)
• ディファードだとGBufferに収まるようにパラメータを考える必要があ
るが、フォワードはGBufferを介さないのでパラメータを増やしやすい。
GBuffer構成を考えずにフォワードで拡張してしまうと後からディファ
ードに対応するのが難しくなる。
じゃあどっちで拡張する?
#ue4fest#ue4fest
エンジン拡張の概要
#ue4fest#ue4fest
スライドで説明するよりも、ブログにまとめましたのでこち
らを見てください。ここでは概要だけ説明します。
UE4のShading Modelを拡張する
エンジンのライティング拡張
#ue4fest#ue4fest
• 独自のShading ModelをEngine/Sourceフォルダ内のC++ソー
スコードに追加します。
• 追加したShading Modelの実際のライティング処理をShaders
フォルダ内のShader Codeに追加します。
概要
#ue4fest#ue4fest
ブログの記事では単純なハ
ーフランバートライティング
するShading Modelを追加す
る方法を紹介しています。
Diffuseの計算が違うだけの
とてもシンプルなものです。
変更するソースコードもたっ
たの6ファイルです。
エンジンにShading Modelを追加
#ue4fest#ue4fest
• このスライドを作成した時点での最新版、4.20.3をベースに
します。
• 4.20ではArea Lightの実装のため、シェーダーコードがかなり
変わりました。ライトの計算部分は複雑になりましたが、コ
ードは整理されて、とても見やすくなりました。
• 4.20以前だと実装の仕方が少し変わります。
UE4のバージョンについて
#ue4fest#ue4fest
Shader内の処理の流れ
#ue4fest#ue4fest
ディファード想定です。まずはBasePass。
• BasePassPixelShader.usf
BasePassの処理、マテリアルから取得した情報をGBufferへ
格納します。
• ShadingModelsMaterial.ush
実際にGBufferに格納する処理。ここで追加したShading
ModelのIDをセットします。
実際のシェーダー内での処理の流れ
#ue4fest#ue4fest
次はLightパス。
• DeferredShadingCommon.usf
ShadingModelのID定義とGBuffer情報のデコード
• DeferredLightingCommon.ush
ライトとシャドウを処理して、Shading Modelごとの処理を呼
び出し、結果を加算する。
実際のシェーダー内での処理の流れ
#ue4fest#ue4fest
Shading Modelごとのライティング計算
• ShadingModels.ush
ShadingModelごとに分岐してライティング計算を行います。
ここに独自のライティングを追加するのが目的。
実際のシェーダー内での処理の流れ
#ue4fest#ue4fest
ライティング計算部分
ライティングの計算部分を簡単に解説します。
#ue4fest#ue4fest
こんな関数になっています。
Default Litのライティング部分
#ue4fest#ue4fest
Diffuseの計算はとってもシンプル
AreaLight.FalloffColor 光があたってる範囲。通常は1
Falloff 距離によって減衰する光の強さ、Directionalは1
GBuffer.DiffuseColor ベースカラー
Diffuse_Lambert πで割る
#ue4fest#ue4fest
NoLは法線とライト方向の内積値。
同じ向きなら1、90度なら0、90度以上ならマイナスだが、クリップされて
いるので0になる。
・・・だが、4.20では、dot(N,L)の値とNoLが同じではない。AreaLight対応
のため少し違う値になるが、誤差レベル。
#ue4fest#ue4fest
スペキュラはこの部分。GGXというアルゴリズムで計算されています。
PBRのスタンダードなアルゴリズム。詳しくは関数の中を見てください。
スペキュラの計算要素は法線、光源の向き、視線、Roughnessで、
Metallicが含まれていません。Metallicはスペキュラに直接影響しないという
事になります。
#ue4fest#ue4fest
スペキュラの色とリフレクションの強さに大きく影響します。
Shader Code内でMetallicが使われている部分
GBuffer.SpecularColor = lerp(0.08 * Specular.xxx, BaseColor, Metallic.xxx);
GBuffer.DiffuseColor = BaseColor - BaseColor * Metallic;
スペキュラカラーはスペキュラ値が大きいほどMetallicに指定し
た強度の白に近くなります。
Metallicが強いほどDiffuse色は黒に近くなります。結果的にリフ
レクション要素が強く、はっきり見えます。
じゃあMetallicは何に影響するの?
#ue4fest#ue4fest
こんなマテリアルを用意して試
してみました。
• ベースカラーは緑
• Metallic 1
• Specular 0.5
• Roughness 0
めいっぱい金属でツルツルです。
実際に試してみた
#ue4fest#ue4fest
比較用のマテリアル。
• ベースカラーをShader内と同様
にMetallicで減算
• Metallic 1
• Specular 0.5
• Roughness 0
実際に試してみた(その2)
#ue4fest#ue4fest
左が1つめのマテリア
ル。右が2つめのマテリ
アル。
あれ?めっちゃ緑色で
すね???
Diffuse Colorなくなる
んじゃなかったの?
右は確かに真っ黒。
結果画像
#ue4fest#ue4fest
SkyLight無効にしてみ
ました。
上の方が真っ黒になり
ましたね、SkyLightのリ
フレクションはベースカ
ラーを反映するようです。
結果画像(SkyLightオフ)
#ue4fest#ue4fest
SkyLightに加えてSSR
も無効にしてみました。
完全に真っ黒になりま
した。
結果画像(SkyLight&SSRオフ)
#ue4fest#ue4fest
Metallic=1でもリフレクショ
ンには色が付く
#ue4fest#ue4fest
SphereReflectionCaptureを配置して、
キャプチャで作成されたリフレクション
キューブテクスチャをRenderDocで覗い
てみました。
やはりベースカラーでレンダリングし
てキャプチャしているようです。
リフレクションを覗いてみる
#ue4fest#ue4fest
• Metallicの数値を上げるとDiffuse Colorは0に近づきます。
• しかし、リフレクション計算時のDiffuse Colorは減衰しません。
Metalic=1の場合、そのマテリアルにはライティングの効果が全く無く、
BaseColor * リフレクションの色になるという考え方のようです。
ちょっともやっとします。完全に光を反射するなら、その物体の色がリ
フレクションに影響するのも変じゃない?
「鏡の色は何色?」みたいな話になってきます。
まあ、とにかくMetallicの数値を0より大きくするときは、リフレクショ
ンが有効であることがセットになると意識するのが良さそうです。
Specularは光源の反射、Metallicはシーンの反射ということでしょうか。
Metallicとリフレクション
#ue4fest#ue4fest
ライティング結果の加算
話をもどして、ライティング計算の結果を加算します。
#ue4fest#ue4fest
ライティング結果を最終的に反映させる部分。
LightAccumulator 結果の出力先
LightColor ライトの色
LightMask ライトの効果範囲のマスク。Directionalは常に1
Shadow.SurfaceShadow ダイナミックシャドウの結果
Lighting.Diffuse + Lighting.Specularがシェーディングの結果のDiffuseと
Specular。
LightColor * LightMask * Shadow.SurfaceShadowがライトと影の影響
(Diffuse + Specular) * ライトの影響 * 影の影響
が最終的な結果になります。この結果を加算します。ライトは重なるとその
分明るくなるので、単純に加算していけば良いわけです。
#ue4fest#ue4fest
実はここまで説明したシェーダー部分、点光源も平行光源も
共通の処理になっています。
それどころか、ディファードでもフォワードでも共通です。
実際にはShading Modelごとの処理を呼び出す前に平行光源と
点光源のライトの範囲、減衰の計算がされており、それらをパ
ラメータとしてShading Modelの処理が呼び出されます。
NPRで気をつけるべきポイントは、点光源の場合はFalloffを考
慮しないと明るすぎる結果が返り、画面が真っ白になります。
点光源と平行光源の違いは?
#ue4fest#ue4fest
UE4での動的な影はシェーダー内では2種類にわかれます。
• N dot Lの結果が0以下になった部分。
法線が光源と90度以上離れていて、光の影響を受けないと
みなせる部分。各Shading Model内で計算される。
• シャドウマップから生成されたマスク
これはShading Modelの結果を加算するときに乗算されます。
影に処理を加えたい場合は、この2つの部分に手を入れると
良いでしょう。
影の処理は?
#ue4fest#ue4fest
とはいえ、影の乗算はライティング結果の加算時に行われる
ので、Shading Model内で処理できません。Shading Modelごと
に影の処理を変えたければ一工夫必要で、コードの改変部分が
ちょっと増えます。
また、DeferredLightingCommon.ush内に
こんな分岐があり、影の中はライティング計算がそもそも走ら
ないようになっているので、特殊な影の場合は注意が必要。
影の処理は?
#ue4fest#ue4fest
• Diffuseの計算部分を独自のものにする。LUTを参照したり、計算式を変
えたりで、お手軽にNPRっぽい表現になる。
• SpecularやリフレクションはNPRの場合必要無かったりする場合もある
ので省いてしまって、GBufferを別の用途に使うのもアリ。
• Subsurface Colorの領域が使えるので、ベースカラー以外の色を追加す
ることも可能。影色を別に指定できるようにしたり、スペキュラカラー
を指定できるようにしたり。
• 難しいのは影の扱いと、間接光。特に間接光をカスタマイズするのは難
しい。アンビエントカラーで弱くすることはできます。
ライティングのカスタマイズのコツ
#ue4fest#ue4fest
カスタマイズ例
例えばこんなふうに影に模様をいれたりといった
事も、エンジン内部のライティングを理解していれば、
割と簡単につくれます。
この例はマテリアル側でサブサーフェスカラーに
ハッチングパターンを格納し、シェーダー内で影に
合成しています。
他のオブジェクトが投影する影にも処理ができて
いるのがポイントです。
#ue4fest#ue4fest
まとめ
#ue4fest#ue4fest
• ライティングの仕組み、順番を理解しておきましょう。
• エンジンの改造は割と簡単。でもアップデート時のマージに
は気をつけて。
• NPRを組むときもライティングの基本は理解して組みましょ
う。
• アニメでもイラストでも基本的に光と影を考えて描かれてい
るものです。実際のライティングの法則を少し捻じ曲げるの
がNPRの基本だと思っています。PBRの考え方はそのまま
NPRに繋がります。
まとめ、田中パート
#ue4fest#ue4fest
• 何の機能を使うか、使うべきなのかは作るゲーム次第。
どんなに耳障りの良い機能があってもその機能の負荷やデメ
リット、書かれてない部分での使い勝手などは必ずチームで
対象プラットフォームで確認。
他人の言う お勧めや簡単は あなたの都合、状況を反映し
ているとは限りません。
むしろ考慮してない事の方が多いはずです。
特にコンソールの情報はNDAに守られていて、そこを考慮
した情報は出せません。
確認は超重要‼
まとめ、梶井パート
#ue4fest#ue4fest
ご清聴ありがとうございました。

UE4のライティング解体新書 ~効果的なNPRのためにライティングの仕組みを理解しよう~