A problem with adding more and more lights to a scene is the expense. Every
light you add means yet another light that must be evaluated for the surface.
One way around this is deferred rendering. Look at this demo. There are 50
lights in the scene, and it runs just fine. Normally, you render a surface, and
the fragment color for each pixel is stored, if it's the closest visible
object. This is often called forward rendering. In a deferred rendering
algorithm, you instead store data of some sort in each pixel. There are many
variations, with names such as deferred shading versus deferred lighting. And
here's just one. You could store the position, normal, and material color and
shininess of the closest surface at each pixel. You also draw into the Z-buffer
as usual. I'm not going to get into the details of how you store these various
pieces of data, the point is that you can do so. It's just image data in
another format. With deferred rendering every point light in the scene has an
upper limit as to how far its light goes. This distance forms a sphere. So a
sphere is drawn in a special way for each light. Another way of saying this is
that each light can affect a volume in space. Whatever surfaces we find inside
the sphere are affected by the light. Each light effects a fairly small number
of pixels on the screen, namely whatever area the light sphere covers. This
means that a huge number of lights with a limited radius can be evaluated in
this way. By drawing a sphere, we're telling the GPU which pixels on the screen
are covered by the light and so, should be evaluated. There are variants on
what shapes you draw. A circle, a screen aligned rectangle. Whatever is drawn,
the idea is that the geometry's purpose is to test only the limited set of
pixels potentially in range of the light. This is as opposed to standard
lights, where every light is evaluated for every surface at every pixel. I hope
this give you a flavor of how deferred rendering works. I'm really jumping the
gun, here. You need to know about shader programming to implement these. But
the idea is to treat lights as objects that are rendered into the scene after
all object surface values are recorded. There's some problem cases for
preferred rendering techniques, such as transparency, but it offers a way to
have an incredible number of lights in a scene.
ライトの数が増えると生じるのが負荷の問題です
ライトが一つ増えればそれだけ計算量も増えるからです
遅延レンダリングはその解決法の一つです
このデモには50のライトがあり問題なく機能しています
通常は表面をレンダリングし
ピクセルごとの色情報を格納します
これを前方レンダリングと呼びます
遅延レンダリングでは何らかの情報が
各ピクセルに格納されます
遅延シェーディングや遅延ライティングとも言います
位置、法線、マテリアルの色や輝度の情報を
各ピクセルに格納します
普段どおりZバッファも使います
詳しい説明は割愛しますが
こういうことができるというのが重要です
形式の異なる画像データです
遅延レンダリングでは点光源のライトが届く距離の
上限が決まっています
その距離は球体の形になります
各ライトがそれぞれの球体を描きます
言い換えると各ライトが
空間の中の一定の部分に影響を及ぼすということです
各ライトが描く球体の中に入ったわずかな
部分だけがライトの影響を受けます
このようにして膨大な数のライトが
及ぼす影響を計算しています
球体を描くことでライトの影響が及ぶ範囲を示し
GPUがその情報を受け取り
該当するピクセルを計算します
描く形は円でも長方形でも構いません
ライトが届く範囲内と思われる限られたピクセルを
判断することが目的です 一方一般的なライトの場合は
すべてのライトについて
すべての表面をピクセル単位で計算します
遅延レンダリングの概略についてお話しました
シェーダプログラミングの知識がないと難しいですが
考え方としてはライトをオブジェクトとして扱い
すべての表面の値を記録してから
ライティング計算を行います
透明性などの問題はありますが
多数のライトを設定できるというメリットがあります
在場景裡加越來越多的光會有計算成本的問題
每加一盞光就是所有表面都要計算這盞光的作用
一種解法是 Deferred Rendering
看看這個展示,裡面有 50 盞光,跑起來完全沒問題
通常你在像素上儲存最接近可見的物件表面計算出來的 Fragment 顏色
這通常稱作 Forward Rendering
在 Deferred Rendering 演算法,你在像素上儲存的是資料
有許多變體如 Deferred Shading 跟 Deferred Lighting
這是其中一種
你可以儲存像素上最接近的表面的位置、法向量、材質顏色跟閃亮程度
也跟以前一樣畫到 Z 緩衝區
我不會解釋要如何儲存這些資料
重點是知道做得到,這只是圖像資料的另一種格式
Deferred Rendering 裡每個點光源都有距離上限
這段距離形成一個球
每個光源都用特別方法畫一顆球
換種說法是每盞光能影響一定的空間
在球的範圍內的表面就會受光影響
每盞光只影響螢幕上一小部分的像素,即光的球體包含的區域
代表我們能計算大量範圍有限的光源
畫這個球,我們告訴 GPU 哪些像素被光涵蓋,應該計算光照
偵測的形狀有許多變體,像是圓、對齊螢幕的長方形
不管是什麼形狀,這個幾何的作用在測試出可能在光源範圍內的像素有限集合
這跟標準打光不同,標準打光每個像素上所有的表面都計算每盞光的作用
我希望這樣能讓你大致了解 Deferred Rendering 如何運作
我其實往前跳太多了,你要懂 Shader 程式才能實作這些繪圖方式
基本概念是在記錄所有物件表面資料後把光當成物件畫進場景
Deferred Rendering 有些缺陷,像是無法處理透明
但它提供了在場景內加入極大量光的方法