この記事は KLab Creative Advent Calendar 2019 の 13日目の記事になります。
こんにちは。KLab株式会社クリエイティブ R&DグループのYojiと申します。
現在クリエイティブR&Dグループでは、研究開発の一環としてハイエンドグラフィックの技術を如何にモバイル上で表現するか、PCやコンシューマからモバイルまでを対象に、ゲーム制作を如何にスケーラブルにおこなっていくか等を目的として、UnityHDRPを使用した高品質なグラフィック表現に取り組んでいます。
検証はPBRをベースとして取り組んでいるのですが、PBRと言うとフォトリアルをイメージされる方も多いかと思います。弊社の開発するタイトルでは、比較的カトゥーン系のノンフォトリアルのグラフィックが多いのですが、カトゥーン系のグラフィックにおいてもPBRを用いる事で様々なメリットが得られると考え、PBRを検証のベースとしています。
メリットの一つに、物理的に正しい値を用いる事での一定のルール化があります。
値を共通のルールにする事で、個々のアーティストの技量に委ねる部分が減り、誰でも一定以上のクオリティで制作をおこなう事ができ、大人数でおこなう3Dゲーム制作においては非常に大きなメリットになってきます。
比較的簡単にクオリティが出せるので、絵作りやデザイン等のよりクリエイティブな部分に時間を使う事ができるようになりますし、制作のアプローチが物理的に正しいかどうかといった判断基準もより明確になるので、何かおかしい?クオリティが上がらないけど何故?どうすればいい?といった原因の突き止めや対策もおこないやすくなります。
今回は、初回という事でUnity HDRPの使用方法や簡単な用語解説等も交えつつ、実際にハイエンドグラフィックのシーン、ライティング制作のアプローチを紹介していきたいと思います。Unityの使用バージョンはUnity2019.9.0b3で、3DアセットのShaderはHDRP Litの使用を前提としています。3DアセットやShaderは制作済みの状態から説明をしていますので、アセットが無い場合はUnityのサンプルアセットを使用されてもよいと思います。
「作例1」今回はこちらのシーンを作例として紹介を行っていきます。
HDRPの環境セットアップについてはUnityBlogの「HD レンダーパイプライン:アーティストのためのクイックスタートガイド」という記事を参考にさせていただきました。
High Definition Render Pipeline Assetが作成されていて、Sceneが空の状態から説明をしていきます。順を追って説明していけるように、初期状態のアセットも一旦全部削除して3Dアセットを配置した状態から開始していきますので、始める前に3Dのアセット以外は削除しておいてください。
まず始めに、空や影等の環境設定をおこなうSceneSettingのAssetを作成します。
こちらが今回主に使用するアセットになります。
Profileも作成されますので、InspectorのProfileを選択して分かり易いように名前を付けておきましょう。
ProjectSettingのHDRP Default Setingsから、Default Volume Profile Assetの項目を選択し、Defaultに先ほど作成したProfile Assetを割当てておきます。
DefaultのProfile Assetと新しく作成したProfile Assetで、二重に効果が掛かる事があるためです。
前準備が整いましたので、実際にシーンのライティングを初めていきましょう。
その前に事前の知識としてライティング成分の分解について簡単に説明しておきます。
実際の物理空間では光が物体に鏡面反射する現象も、拡散反射する現象も全て同じ光源からの反射現象ですが、RealtimeのCG空間では鏡面反射と拡散反射の現象を、それぞれ別のライティングソリューションを用いて表現する事が多いです。
UnityHDRP環境でも複数のライティングソリューションが提供されていますが、どの表現にどのソリューションを用いるか分かり易く整理するため、静的オブジェクト・動的オブジェクトとそれぞれの反射成分に分けてまとめてみました。あくまで一例なので参考までに。
静的オブジェクト (動かない物) |
【鏡面反射成分】 物体の表面で鏡面方向に反射し、目に届く光成分。物体の色成分は持たない。 ※金属の場合は反射の際に電磁波の影響を受け色成分を持ちます。 |
直接光 | ・DirectionalLightやPointLight等 |
スカイライト | ・HDRSky ・Procedural Sky |
||
間接光 | ・ReflectionProbe ・ScreenSpace Reflection(Bake非対応) ・Planar Reflection Probe(Bake非対応) |
||
【拡散反射成分】 物体の表面や内部で複雑に反射した光が目に届く成分。反射する際に一部の波長が吸光され物体の色が視認できるようになります。 ※金属では拡散反射は起こりません |
直接光 | ・DirectionalLightやPointLight等 | |
スカイライト | ・Lightmap ・HDRSky(IBL) ・Procedural Sky(IBL) |
||
間接光 | ・Lightmap | ||
【遮蔽】 物体が光を遮蔽する現象 |
直接光 | ・CasscadeShadow ・Contact Shadow ・MicroShadow |
|
間接光 | ・SSAO ・Planar Reflection Probe(Bake非対応) ・ScreenSpace Reflection(Bake非対応) |
||
動的オブジェクト (動く物) |
【鏡面反射成分】 物体の表面で鏡面方向に反射し、目に届く光成分。物体の色成分は持たない。 ※金属の場合は反射の際に電磁波の影響を受け色成分を持ちます。 |
直接光 | ・DirectionalLightやPointLight等 |
スカイライト | ・HDRSky ・Procedural Sky |
||
間接光 | ・ReflectionProbe ・ScreenSpace Reflection(Bake非対応) ・Planar Reflection Probe(Bake非対応) |
||
【拡散反射成分】 物体の表面や内部で複雑に反射した光が目に届く成分。反射する際に一部の波長が吸光され物体の色が視認できるようになります。 ※金属では拡散反射は起こりません |
直接光 | ・DirectionalLightやPointLight等 | |
スカイライト | ・HDRSky(IBL) ・Procedural Sky(IBL) |
||
間接光 | ・Lightprobe | ||
【遮蔽】 物体が光を遮蔽する現象 |
直接光 | ・CasscadeShadow ・Contact Shadow ・MicroShadow |
|
間接光 | ・SSAO ・Planar Reflection Probe(Bake非対応) ・ScreenSpace Reflection(Bake非対応) |
Unity HDRPではハイダイナミックレンジ(HDR)でデータが扱われていますので、シーンではEXPOSUREのコントロールが必須の要素になります。
ハイダイナミックレンジ(HDR)とは、現実の世界と同じようにとても幅の広い輝度情報をもっているイメージの事で、通常のモニターや端末で見る画像はスタンダートダイナミックレンジ(SDR)とよばれ、8bitの情報でしか表現できませんが、ハイダイナミックレンジ(HDR)は32bitもの情報を持っています。
現実世界の光も、とても大きな幅を持っていて、人間の眼は無意識化に瞳孔を調整し入ってくる光の量にコントロールして最適な見え方を保っています。
暗い所から急に明るい所にでると眩しいと感じる現象も、入ってくる光の量に瞳孔の調整が間に合ってない事からおこります。(時間とともに瞳孔が締まり、次第になれてくるはず)
CGでも、現実に近い光学現象を再現し説得力のある絵作りを行うため、多くの階調が持てるHDRの画像データで表現する事が取り入れられてきました。
データの取り扱いはHDR空間で行われますが、最終的な表示先であるモバイル端末やテレビはLDR空間である事がほとんどですので、HDR空間の光の量をLDR空間の光の量にあてはめて表示する必要があります。最適な光の量にコントロールする機能がExposure機能になります。
HDR空間でのシーン作成では、始めにExposureの設定を必ずおこないます。
先ほど作成したSky and Fog VolumeのAdd OverrideからExposureを作成します。
メニューの一番上に項目があると思います。それほど重要という事ですね。
ModeはEV値(Exposureの値の略)が固定か動的に変化するかを選べます。
動的では実際のカメラのように画面の情報を取得し自動で最適なEV値に調整できます。今回は狙った絵作りができるようFixedで設定していきます。
明るめの室内のイメージにしたいので、EV値はひとまず「10」に設定します。この段階では画面は真っ暗です。以下の表はEV値の目安の一例です。
晴天の屋外 | EV:14 |
明るい室内 | EV:9 |
街燈のある夜景 | EV:4 |
次に、空の設定と空からの環境光の設定をおこないます。空の表現には動的な時間変化に対応したProcedural Skyと、固定のHDRの画像データで表現する手法等があります。今回は設定が比較的簡単なHDRIを使用した空を作成したいと思います。
作りたいシーンにあったHDR画像をUnityProjectの適切なAsset管理場所に保存しておきましょう。画像はデフォルトでは2Dとして扱われているので、HDRIとして扱えるようにInspectorからTextureShapeをCubeに切り替えます。
Sky and Fog Volumeに戻り、Visual EnviromentのSkyTypeをHDRI Skyに切り替えます。合わせてデフォルトで作成されてるPhysically Based Skyは削除しておきましょう。
Add OverrideからHDRI Skyの機能を追加します。
先ほど設定したHDRIを、HDRI Skyの項目に紐づけます。
HDRI SkyのEXPOSUREを設定します。先ほどシーンのExposureを設定したEV値と同じ「EV:10」に設定しました。
HDRI撮影時の環境下の適正露出が分かっていれば適正露出に設定するのがいいと思いますが、分からない場合は環境の数字を目安に設定しておきます。
真っ暗だったシーンに空のイメージが表示され、シーンに配置されている静的オブジェクトに対して空からの鏡面反射成分が情報として加わりました。
画像が暗くて分かりにくいですが、、、
本来、色の要素を持つはずの拡散反射成分がないため、全体的にグレーの見た目になっていると思います。空からの環境光が拡散反射成分に影響するよう設定していきます。このシーンでは背景は静的オブジェクトとして、ライティングの設定を進めていきます。空からの拡散反射光表現にはBakeを使用します。
アセットがStaticになっている事を確認します。
Lighting Settingを開きます。
Environment(HDRP)のProfileに、先ほどリネームしたSettingProfileを設定します。次にStatic Light SkyにHDRISkyを設定しましょう。
Bakeのパラメータを設定していきましょう。
BakedGlobal IlluminationI:ON
LightingMode:ShadowMask(遮蔽をベイクします。)
Lightmapper:ProgressiveGPUを使用します。ProgressiveCPUと比べ高速です。
各Samplesの値は速度と品質に影響するので、PC環境とイテレーション回数に合わ
せて調整します。最初はイテレーション多く確認していくので適度に低い値で大丈夫です。
FilteringとMultiple Importance Sampleはノイズ軽減のためONにしておきます。
Lightmapsize:大きいと品質が上がりますが計算時間が増加します。
Generate Lightingでベイクすると静的オブジェクトにも空の環境光が反映され物体の色が見えてきました。これで、静的オブジェクトの鏡面反射、拡散反射のそれぞれの成分に空からの環境光が反映された状態となりました。
環境光が設定できましたので、次に太陽からの直接光の反射表現を設定していきます。
暑い昼間の太陽光 | 100,000Lux | 5000〜6500K |
曇り | 50,000Lux | 6500K |
日没 | 500Lux | 2000〜3000K |
満月 | 0.2Lux | 4000K |
これで、直接光で空間が照らされ影が入り、鏡面反射・拡散反射ともに表現されましたが、まだまだ情報が足りません。直接光があたり、物体に反射した光の表現が入っていないので、とても単調で暗いシーンになっています。ここから、反射光を表現するGlobal Illuminationの効果を加えていきましょう。Global Illuminationとは、物体に跳ね返った光が相互反射し伝播していくことを表現するレンダリング手法で、省略してをGIと呼ばれる事もあります。
GIを加えるためLighting SettingでLightmapを再度Bakeします。Bake後、反射光が反映され画面全体が明るくなり、グッと良い絵になったかと思います。
画像の壁部分に、ほんのりと床からの黄色い反射色がのっているのが見えると思います。太陽光が床に跳ね返る時に床の反射能によって、光の波長が吸収され壁を照らした結果です。このような反射表現をカラーブリーディングと呼びます。
床の色が青であれば青が反射し、赤であれば赤が反射し、白い壁の色に影響を与えます。
Global Illuminationが反映され少しまともな見た目となりましたが、まだまだ不自然な部分が残っています。
例えば、上図の床面部分では鏡面反射成分の遮蔽がされていないので、空の光が壁を貫通しそのまま映り込んでしまっている事が原因で、とても不自然に見えてしまっています。拡散反射成分の反射光をLightmapで表現したように、鏡面反射成分の反射光(鏡等の映り込みなども同じ現象)も表現する必要があるので、鏡面反射成分に反射光が入るよう設定していきます。
鏡面反射成分の反射光を表現する手法としてReflectionProbeという機能があります。指定の位置から全方位撮影した画像を作成し、それを参照する事で鏡面反射を疑似的に近似します。
まずHierarchyからLight>ReflectionProbeを作成します。
今回は動的なオブジェクトがないので、TypeはBakeを選択します。
ReflectionProbeがオブジェクトに影響を与える範囲を設定します。範囲形状はBOXとSphereの2つから選択します。ここでは部屋に対して範囲は設定し易いBOXを選択して部屋を囲みました。
球の位置からReflectionProbeに使用する画像が撮影されるので、適当な位置に調整します。
位置を決めたら影響範囲を再度確認してBakeします。Bakeが成功すると球に撮影された画像が適用されます。
シーン内のアセットの鏡面反射成分に対し、環境光と遮蔽が反映されたと思います。
Planar Reflection Probeは、設定された範囲のオブジェクトに対して、指定方向から平面的に撮影された画像を鏡面反射用のマップとして使用する機能で、局所的に反射の精度が上がり自然な鏡面反射に近づきます。
但し、Realtimeのみの対応です。平面の一方向のみの撮影なので、水面や地面、壁などの面に対して有効です。では実際に設定していきます。
HierarchyからLight>Planar ReflectionProbeを作成します。
Inspectorで反映したい部分を囲むように調整します。今回は床面に適用したいので床を囲むように設定しました。
Field of view ModeとValueの値で画像を描画する範囲を設定し、適切な見た目に調整します。コントロールがし易いFixedに設定しました。
設定しても、モデルデータの構造によっては画像のように空の光が漏れだしてるケースもあるかと思います。
MaterialのNormalmapの法線方向を参照したり、精度の問題で空が映る事もあるので、今回は空のデータを取得しないように設定しました。
これで、一通りの光の要素が入りました。
さらにシーンに説得力を持たせるため、ライトを少し追加していきたいと思います。先ほど、床の鏡面反射に漏れだした空からの光を対処する為に、空の鏡面反射成分を取り除きましたので、それをエリアライトで補います。
HierarchyからArea Lightを作成します。
窓の外側に配置します。窓枠に近すぎると影がハッキリと落ちてしまい、狙った効果が得られないので少し離して配置します。
Shapeの項目でArealightの大きさを調整します。
空色に近い色を設定し、Intensityは一般的な青空の値の15000ルーメンを設定しました。Shadowの項目では解像度を少しあげ、Shadow Coneも調整し意図していない光の漏れがないように設定します。
Arealightを入れる事で、空からの光が足されて説得力が少し上がっているかと思います。
次にPostprocessingの設定を行っていきます。Postprocessinとは、文字通りレンダリング画面に対して後処理を加える事で、略してポスプロとも呼ばれています。PBR環境ではポスプロの設定でLookが決まるとても重要な工程です。それぞれのアーティストの個性やセンスがでる部分でもあります。それでは、ポスプロの設定を進めていきましょう。
Lightmapで間接光のシャドウがある程度表現されていますが、オブジェクト同士が隣接している場所や、接地している部分で明るく不自然に見えている箇所もあると思います。間接光の遮蔽が正確に計算されていない事が原因です。この計算はとても重い計算になるため、境界面の部分的な遮蔽を近似する表現としてAmbient Occlusionがよく用いられます。
特にRealtimeでは非常に効果的な機能ですので、今回もAmbient Occlusionを使用してみます。
Add OberrideからLighting>Ambient Occlusionを作成します。
パラメータを調整します。Intensity等でOcclusionの強さや影響範囲を調整していきます。あまり入れすぎると不自然に濃い絵になるのでほどほどにしましょう。
今回はIntensity:0.7と、Radiusを0.75にして影響範囲をさげました。
ソファの背もたれと座面の合わせ目や、壁との設置部分にOcclusionが落ちている事が確認出来ると思います。
HDRのシーンの放射輝度を最終出力先である、8bitSDRの0〜1の範囲に階調再現を行う機能です。ハイダイナミックレンジの世界を、知覚的に再現するためTonemapping機能を使用します。
SkyandFogVolumeのInspectorを開きAddOverrideからTonemappingを作成します。
TonemappingのModeにチェックをいれ、「Neutral」を選択しました。
TonemappingのModeにACESという設定もあります。
これは、映画業界の色空間規格のACESを近似したマッピングを行います。
コントラストが強いLookになるので、絵作りのコンセプトに合わせ使用します。
白飛びしていた部分が軽減されているかと思います。
光が溢れた表現を加える機能です。空気感も出るので特に理由がない限り使用をお薦めします。
SkyandFogVolumeのInspectorを開きAdd OverrideからBloomを作成します
Intensityを上げると効果が見えてきます。パラメータを調整しビジュアルのコンセプトに合わせ好みの効果を得ましょう。
Micro ShadowはNormalmapの凹凸に対して、光源からの方向性を持った影を加えます。細かい効果ですが、ディティールが加わりより詳細な表現となりますので、そのシーンでの必要性に応じて使用を検討されるのがいいと思います。
SkyandFogVolumeのInspectorを開き、Add OverrideからShadow>MicroShadowを作成します。
EnableをONにしてOpacityでMicroShadowの透明度を調整します。
今回はOpacityを「0.7」に設定しました。
他にもカラーグレーディングの機能が豊富に用意されています。これらの使用方法は、また次回機会がありましたら紹介していきたいと思います。カラーグレーディングは最終的な絵作りを決定づけるパートなので、時間をかけて説明しないといけませんし。
一通りの設定が完了しました。これまで設定した各項目を再度調整し全体の絵作りをおこないます。最後のこの工程で、クオリティも変わってきますので時間をかけて調整しましょう。ここが一番面白い工程ですね。
色々と調整し、最終的に下図のLookに仕上げました。画像は静止画ですが、全てUnity上でリアルタイムで表現されています。
ExposureやHDRIやライティングを変更し夜のシーンも作成してみました。昼から夜へのシーンの変更自体は簡単に行えるので、クリエイティブ面に沢山の時間を費やせますね。
※アナモルフィックレンズフレアのみPhotoshopでの合成ですが、カラーグレーディング含めUnity HDRP上で完結しています。
こちらは同じシーンにDepth of Fieldをいれたケースです。
別カット
最後にPBR環境でLookを作っていく上でのポイントを少しまとめて記載したいと思います。
現実の環境のように光量が溢れるハイダイナミックレンジの世界では、EVと照度を管理し絵作りをおこなっていく事がとても大事になります。これには制作工程上の大きなメリットもあり、非PBRのアドホックな制作アプローチと違って、絵作りの仕組みを理解し制作する事で、比較的簡単に高品質な結果を得る事ができます。また、昼間・夕方・夜といった時間帯の違うシーン、晴れ・曇り・雨といった天気の違うシーン等への変更も、効率よく制作する事が出来ます。今回のような制作アプローチは、コンシューマゲームに限らず、現在のモバイルゲームにおいても応用出来る有効な制作アプローチであると考えています。
PBR環境でのLook制作は、CGの基礎的な知識の他、カメラやレンズの知識であったり、光学の知識であったり、ライティングの知識であったりと幅広い分野の知識が求められ、それぞれの分野がとても深くどこまで追求しても飽きがこない非常に面白い世界だと思います。興味を持った分野を少しずつ堀り進め、知識を蓄え理解を深めていきたいと思います。
この記事を読まれ、興味を持った方は是非実践してみてください。
有難うございました。
明日のアドベントカレンダーの記事は、「Substance Designerを使ってテクスチャを作る!」です!お楽しみに!
KLabのクリエイターがゲームを制作・運営で培った技術やノウハウを発信します。
合わせて読みたい
KLabのクリエイターがゲームを制作・運営で培った技術やノウハウを発信します。