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