16.4K Views
May 25, 23
スライド概要
2016年の資料なのでちょっと古いです
シェーダちょっとできるクライマー
なぜなに リアルタイムレンダリング リアルタイムの今までとこれから
本日のお品書き • はじめに • レンダリング基礎 • レンダリング手法Q&A • これからの話
はじめに
はじめに • 最近は猫も杓子もDeferred Rendering! – 光源がいっぱい置けるようになった! – ポストプロセスで使える情報が多くなった! • その一方で… – 半透明をできるだけ使わないでと言われる – 不透明マテリアルより半透明マテリアルのほうが出来ることが 少ない – 描画の自由度が低すぎない? • キャラ固有のライトが使えない or 使えるけど制限あり • キャラを描画する前にパーティクル描画したいのに出来ない
はじめに • Deferred Renderingってそんなにいいの? – 利点は間違いなくある – 欠点も間違いなくある • Deferred Renderingを使うべきか? – 作品による – アニメ系だとDeferredじゃなくてもいいんじゃない? • 大量のライトを使うと逆に陰影がおかしくなってしまう • 作品の目指すところとレンダリング手法はマッチしている? – たいていはエンジニアがヒアリングの結果、決定している – 提案したいけど、よく知らないから提案できない
はじめに ならば知ろう!
レンダリング基礎
ポリゴンラスタライザ • 現在のリアルタイムレンダリングで最もよく使われて いる手法 • 処理順序 – – – – ポリゴンの頂点をスクリーン空間に変換 処理を行うべきピクセルを選択 各ピクセルの色を決定 レンダーターゲット(描画バッファ:RT)に描画 • 半透明などの手法でブレンディングする場合は RTの内容をフィードバックする
ポリゴンラスタライザ
ポリゴンラスタライザ 頂点シェーダ スクリーン空間に変換
ポリゴンラスタライザ 頂点シェーダ スクリーン空間に変換 ラスタライザ 塗るピクセルを選択
ポリゴンラスタライザ 頂点シェーダ スクリーン空間に変換 ラスタライザ 塗るピクセルを選択 ピクセルシェーダ 色を塗る レンダーターゲット(RT)
ドローコール • 描画プログラムの命令でDraw~という命令を発行すること、 もしくはその発行の単位 – 通常、同じモデル、同じマテリアル、同じカメラ、同じRTに対し て1ドローコールが行われる • 昔はハードの制約の問題で同じマテリアルだけど複数回のドローコー ルということもあった – ドローコール発行のタイミングで描画に必要な各種設定を収集、 問題がないか検証を行ってGPUに命令を伝える • GPUが処理できる“コマンド”を生成 • これはCPUが行うので、ドローコールはCPU負荷となる
描画パス • 同じような描画設定で発行される複数のドローコールをまと めたもの – 例えば、モデル、パーティクル、UIはそれぞれに描画設定が異な るので、すべて描画した場合は3パス – モデルでも、背景モデル、キャラクタモデルを別々に描画してパ スを分けることもある • 描画レイヤーとも呼ばれる – 同じモデルでも描画する属性の違いによりパスは分割される • トゥーン系レンダリングで、カラーの描画とアウトライン用背面モデ ルの描画を別のパスとして考えることもある
Forward Rendering • Traditional Forward Rendering – 従来タイプの手法は区別するためにこのように呼ばれる • 通常、モデル中の各マテリアルを1ドローコールで描画 する手法 – ピクセルシェーダでライティング/シェーディングを行う – シャドウマップを描画する場合はドローコールが増える • 不透明と半透明で同じシェーダが使用できる – 違いはRTに描き込む際のブレンド設定
Forward Rendering 頂点シェーダ スクリーン空間に変換 ラスタライザ 塗るピクセルを選択 ピクセルシェーダ 色を塗る レンダーターゲット(RT)
Forward Rendering 頂点シェーダ スクリーン空間に変換 ここでライティング/シェーディングを行う ラスタライザ 塗るピクセルを選択 ピクセルシェーダ 色を塗る レンダーターゲット(RT)
Forward Rendering • PS2までは主流の方法 – ハードウェアの制約上、この手法しか取れなかった – 現在のハードウェアでは3DSがこの手法しか使えない – 日本のゲームではPS3でも主流だった • 使用可能なライト数に制限がある – これも主にハードウェアの制約による – 固定シェーダの頃はライト数がハード固定 – プログラマブルシェーダでもシェーダに渡せるパラメータ数に 限界があった
Deferred Rendering • PS3中期くらいから使用されだした手法 – 現在ではほぼ主流と言っていい • 1回のドローコールでG-Buffer(Geometry Buffer)にモデル のジオメトリ、マテリアル情報を描き込む – この段階ではライティング/シェーディングは行わない – すべてのメッシュをG-Bufferに描画したらライティングを行う • ライティングパス – ジオメトリパスでライティング結果を求めず、遅延(Deferred)さ せてライティングを行うのでこう呼ばれる
Deferred Rendering • G-Bufferの例 – – – 画像はUE4のG-Buffer 実際にはこれより多くの情報が描画されている 情報が圧縮されて格納している場合もある • • 少ないG-Bufferで多くの情報を格納するため 情報の使用時にデコードコストがかかる Base Color Roughness World Normal Depth
Deferred Rendering 頂点シェーダ スクリーン空間に変換 ラスタライザ ここが… 塗るピクセルを選択 ピクセルシェーダ 色を塗る レンダーターゲット(RT)
Deferred Rendering 頂点シェーダ スクリーン空間に変換 ラスタライザ こうなる 塗るピクセルを選択 ピクセルシェーダ 色を塗る レンダーターゲット(RT)
Deferred Rendering • メリット – – • 光源を多く使用できる G-Bufferの情報をあとで利用できる デメリット – – – – 半透明が弱い MSAAが使えない シェーダのバリエーションを多く出来ない 描画レイヤーなどの自由度が低い
レンダリング手法Q&A
Deferred Renderingが 昔は使われなかったのはなぜ?
Deferred Renderingの歴史 • 元になったのはSIGGRAPH 1988の論文 – Michael Deering氏による – この時はDeferred Renderingとは呼ばれず、G-Bufferも使ってい ない • G-Bufferに言及した論文はSIGGRAPH 1990の論文 – 斎藤隆文氏、高橋時市郎氏による – この時もDeferred Renderingとは呼ばれていない • 実際に使われ始めたのはPS3/Xbox360世代 – 最初の商用ゲームは『Killzone2』? – なぜこの世代まで使われなかったのか?
Deferred Renderingが使われなかった理由 • 固定シェーダでは実装が難しい – G-Bufferに適切な情報を適切な形で描画できない – G-Bufferから適切な情報を適切な形で取得できない – ピクセルシェーダの実装は初代Xbox • この世代以降なら使える? • 複数のG-Bufferに描画する機能がない – 1回のドローコールで描画可能なRTは1枚だった – 複数のG-Bufferに描画するには複数回のドローコールが必要 – マルチレンダーターゲット(MRT)の実装
マルチレンダーターゲット(MRT) • 1回のドローコールで複数のレンダーターゲットに同時 に描画を行う機能 – PS3/Xbox360世代以降のGPUに追加された機能 • PS3/Xbox360世代は最大4つ • 現在のハイエンドGPUはもっと多い – 同じ解像度のバッファに、同じスクリーンに投影したポリゴン のみ使用できる • 例えば画面4分割をMRTで処理するとかは出来ない – カメラが違うのでスクリーンが違う
マルチレンダーターゲット(MRT) RT枚数に関係なく1回 頂点シェーダ ラスタライザ RT1 ピクセルシェーダ RT2 ピクセルシェーダで 複数のRTに出力 RT3
Deferred Renderingが使われなかった理由 • 日本のゲームにはDeferredは合わないと言われていた – DeferredのデメリットがPS2時代の日本のゲーム作りと合ってい なかった • 特に半透明問題は顕著 – CEDEC 2010のパネルディスカッションでも話題に上がっていた • ここでも日本のゲームに合わないと言われていた • しかし、現在は多くのゲームが採用 – バイオハザード7 – ファイナルファンタジー15 – UE4採用タイトル など
おまけ • PS3になって半透明がすごく遅くなった PS2世代の作り方をするとパフォーマンスは出ない – PS2のメモリ帯域は化け物級 • 48GB/s • PS3が22.4GB/s、PS4が176GB/s – GPU↔バッファ間のやり取りが速い – 半透明はバッファを読み込み、半透明計算後に書き込み – その上解像度は低い • 320x240 • PS3が720p、PS4が1080p • PS3の1/12、PS4の1/27
Deferred Renderingで 多光源を扱えるのはなぜ?
多光源が使える理由 • 現行のGPUではForward Renderingで多光源を扱えない? – ハードウェア的制約は存在しない • 十分な数のライトパラメータをシェーダに送れる – しかし、Traditional Forward Renderingで多光源を扱うことはほ とんどない • では何が問題? – 比較する前に各手法のライティング戦略を知ろう
Forward Renderingのライティング戦略 • シーン内の光源の中から影響を受ける光源を選択する – バウンディングボックスとライトの接触判定 • • – 赤の球が接触しているポイントライト 緑の球は接触していないのでシェーダに送られない より詳細な衝突判定は? • CPUとGPUのコストバランスによる
Forward Renderingのライティング戦略 • ピクセルシェーダでモデルをライティングする – ラスタライザで選択されたピクセルすべてにおいて、 すべてのライトとの計算を行う • 緑のピクセルはどのライトとも接触していない しかし、計算処理は行われる
Forward Renderingのライティング戦略 • 無駄なピクセル処理が多すぎる – – – バウンディングボックスに接触しているが実際のモデルに接触していない 光源 影響を与えるピクセルが極小の光源 光源と一切接触していないピクセル 境界箱に接触しているので選択される しかし効果範囲外なので影響は受けない しっかりとライトの影響を受ける が、描画されるピクセル数は多くない 影響がない範囲のライトは選択されない ライトの影響を受けるがほんのちょっとだけ これらのピクセルはライトの影響を受けない
Deferred Renderingのライティング戦略 • 基本戦略 –ライトの形状に合わせたオブジェクトを描画する • 深度テストを行って描画する • 描画された範囲がライトの影響範囲とみなすことが出来る –ステンシルマスクを使うことで影響範囲はより正確に • ライト形状オブジェクトの裏面を描画する • この際にステンシルバッファの値を1に設定 • 表面を描画する際にステンシルバッファが1ではない部分を描画 • 正しい範囲のピクセルのみライティングできる
Deferred Renderingのライティング戦略 このようなシーンを想定
Deferred Renderingのライティング戦略 ポイントライトの範囲は球
Deferred Renderingのライティング戦略 ポイントライトの範囲は球 裏面のみ描画
Deferred Renderingのライティング戦略 裏面のみ描画
Deferred Renderingのライティング戦略 描画されたピクセルのみステンシル値が”1”
Deferred Renderingのライティング戦略 表面描画が行われ、ステンシル値が”0”の 描画されたピクセルのみステンシル値が”1” ポイントライトの範囲は球 裏面のみ描画 ピクセルが描画される
Deferred Renderingのライティング戦略 最終的に計算されるライティングポイント
Deferred Renderingのライティング戦略 • ディレクショナルライト – – シーン全体に影響を与えるライティング 画面全体を覆う板を描画し、画面内のすべてのピクセルでライ ティング計算を行う このように画面全体を覆う板を描画する 画面すべてのピクセルでシェーダが動作する そのピクセルシェーダ内でライティング計算を行う
Deferred Renderingのライティング戦略 • ポイントライト、スポットライト – 影響範囲を示すメッシュを描画する • – 球、コーン 減衰なしだと無限範囲になってしまうので注意 ポイントライトなら球、スポットライトならコーンを描画 深度テストを行い、描画されたピクセルのみ計算する 特殊な形状のライトも効果範囲を示すモデルで対応できる →CEDEC2010 「Eidosの最新ゲームエンジン詳解」参照
Deferred Renderingのライティング戦略 • IBL(キューブマップ) – グローバルキューブマップならディレクショナルライトと同様 • – ローカルキューブマップなら範囲ボックスを描画 • – シーン全体に影響するため ポイントライト、スポットライトと同様 両方使いたい場合 • • • ローカルキューブを描画して、その範囲をマスク マスクされていない部分にグローバルキューブ描画 ブレンドしたい場合はもうちょっと工夫する必要がある
Deferred Renderingのライティング戦略 • 前述の方法はあくまでも一例 – エンジンによっては別の方法が取られていることもある • • 極小の光源が多い場合はスプライトで描画する手法も Deferredの戦略では不要なピクセルに対するライティン グ計算はほとんど行われない – ピクセルシェーダを軽くすることができる • – ほとんどのゲームではピクセルシェーダがネックになりやすい ライティング計算自体も軽い処理ではない • ピクセルシェーダが重くなる原因の1つ
Deferred vs Forward:多光源 • 実例:昔作ったサンプル – 1024個のライティングサンプルのフレームレート比較 Deferred – Forw ard 境界箱との接触判定なしだが、この数だと差が大きい
Deferred vs Forward:多光源 • ライティング計算を行うピクセルを減らす工夫が Deferred Renderingには存在する – – Traditional Forward Renderingでは不要な計算が多い しかし、現在は不要な計算を減らす手法が存在している • • • • Forward+ Rendering Clustered Rendering 詳細は後述 ライトの影響範囲が大きいと速度差は小さくなる – – 計算する必要があるピクセル数が近づくため Deferred Renderingの際にはライトの影響範囲に注意
Forward RenderingでG-Bufferは使えない?
G-Bufferの使用用途 • Deferred Renderingで作成するG-Bufferの使用用途は多岐 にわたる – – – – 通常のライティング計算 SSAO、SSRなどのスクリーン空間ライティング処理 アウトライン描画などのポストプロセス シェーディングモデルIDを調べて特殊なポストプロセス • • Screen Space Subsurface Scatteringなど Forward Renderingでは深度バッファとカラーバッファの み使用可能 – – 深度がわかれば位置もわかるので、これも使える Deferredに比べると使える情報は少ない
Forward RenderingではG-Bufferは使えない? • • NO! MRT自体はハードウェアの機能であり、Deferredでなけ れば使えないということはない – • ライティングを行うのと同時に別のバッファに必要な情報を出 力すればよい 実例:新生DOOM(Bethesda Softworks/id Software) – 不透明のForward Rendering時に2枚のG-Bufferを描画 • • – – Specular & Smoothness Normal 薄いG-Buffer(thin G-Buffer)と呼んでいる ただし、実装はClustered Forward Rendering
Deferred Renderingはなぜ半透明が弱いのか?
半透明の問題 • 半透明は昔から問題だらけ – 描画順序の問題 • • • 誰もが一度は苦労する 通常はカメラから見て奥にあるものから描画していく 例:水に下半身が浸かっているクリスタルボーイ – – 処理負荷の問題 • • • • • 水とクリボー、どちらを先に描画します? 描画対象のRTから今のカラーを取得する 描画するカラーとRTのカラーをブレンド 描画対象のRTにブレンドしたカラーをコピー RTへのアクセスが2回発生する Deferredでの問題はこれらではない
Deferredでの半透明の問題 • そもそも半透明でブレンドされるべき色とは? – – – 描画する半透明オブジェクトの色 描画されるピクセルに描画済みの色 この2つをブレンド値とブレンド関数によってブレンド 1枚目のトライアングル 2枚目のトライアングル α=0.5 結果
Deferredでの半透明の問題 • そもそも半透明でブレンドされるべき色とは? – – – • 描画する半透明オブジェクトの色 描画されるピクセルに描画済みの色 この2つをブレンド値とブレンド関数によってブレンド 2つの色はライティング結果の色 – Forwardの場合はRTに描画する段階でライティング済み • – 2つの色はライティング済み Deferredの場合は?
Deferredでの半透明の問題 • モデルを描画する段階ではライティングされていない – • この段階ではブレンドができない ライティングパス後にブレンドする? – G-Bufferには1ピクセルにつき1つのジオメトリ/マテリアル情報 しか保存できない • – 不透明と半透明の同居はできない 不透明か半透明の情報はG-Bufferに存在しない • 双方のライティング結果を参照できない → 半透明に対して何らかの戦略が必要
Deferred Renderingの半透明戦略 その1 • 半透明だけForward Rendering – – 多くの描画エンジンで採用している手法 Forwardでも描画順序は不透明→半透明 • • メリット – – • この不透明描画部分のみDeferredに置き換えた印象 屈折表現が可能 半透明に関してのみ描画レイヤーの調整は比較的しやすい デメリット – Deferredのメリットは活かせない • • – 多光源の実装は難しい G-Bufferを使うポストプロセス対応が難しい シェーダが増える • 同じ処理でもForward用とDeferred用を用意する必要がある
Deferred Renderingの半透明戦略 その2 • ディザによるアルファ抜きを使う – – 16色時代のドット絵の半透明表現と同じ手法 時間軸方向にディザパターンを変えていけば穴が開いているだけには見えなくなる • – UE4ではDitherTemporalAAと呼ばれている • • http://monsho.blog63.fc2.com/blog-entry-148.html メリット – – – • この場合はTemporal AAを使う必要がある Deferred Renderingのライティング機能がフルに使用可能 ポストプロセスにも対応 戦略 その1と共存可能 デメリット – – 透明度が変化する状況に弱い Temporal AAによるゴースティングが目立つ • 動きの激しいVFXでは使用しづらい
Deferred Renderingの半透明戦略 その3 • 半透明を使用可能なDeferred Rendering手法を用いる – 代表例:Deep G-Buffer • • G-Bufferをレイヤー化する手法 Depth Peelingという手法で各ピクセルごとに異なる深度でレイヤ ー分けが可能 – • • http://marina.sys.wakayama-u.ac.jp/~tokoi/?date=20081123 半透明順番問題、SSAOの隠れた部分の精度問題にもある程度対応 できる レイヤー数分のG-Bufferが必要なのでメモリが厳しい – 2~3レイヤーが限界では? – 不透明レイヤー以外は薄いG-Bufferを使う手もあり
Deferred Renderingの半透明戦略 その4 • G-Bufferの段階でブレンドしてしまう – – • 正しい結果にはならない 使い道を限定すれば悪くない手法 代表例:バイオハザード7の水 – ベースカラーと法線を不透明物体に対してブレンド可能 • – 深度バッファは描き込む • – ブレンド値はそれぞれの要素ごとに設定可能 ライティングは水の位置を用いて行われる https://cedil.cesa.or.jp/cedil_sessions/view/1488
Deferred Renderingの半透明戦略 その5 • Order Independent Transparency (OIT)を使う – – 半透明の順番を正しく処理するための手段 リンクリスト方式なら各ピクセルの正しい情報を保持できる • • メリット – – • http://www.slideshare.net/hgruen/oit-and-indirect-illumination-using-dx11linked-lists 正確なライティングとブレンドが可能 半透明の描画順序問題も解消できる デメリット – – 屈折の対応は少し難しいか? 重すぎて使い物にならな…げふんげふん
Deferred Renderingの半透明戦略 その6 • パストレーシングを使う – – • メリット – – – • いわゆるレイトレ 半透明のみ、不透明はDeferredで ブレンドはかなり正確にできる 屈折にかなり正確に対応できる 実装は比較的やりやすそう デメリット – – ライティングは限定的にしないとリアルタイムは難しそう スプライトパーティクルに対応すると速度は厳しそう • ソリッドオブジェクト限定なら検証の価値はあるかも