Render M materials and N lights

在 hardware render pipeline 中,若現在場景內有 M 個 material 相異的物件與 N 盞 lights, render 的方式會有幾種選擇?

  • single-pass, multi-light
  • multi-pass, multi-light
  • deferred shading

Single-pass, Multi-light

for each object:
 render object with all lights in one shader

此種作法是最單純且直接,但是此方式會連 hidden surface 也一併 shading ,造成運算上的浪費。此外,當光源數目 N 很大的時候,shader code 必須擴展進而去計算每盞光源的作用。但若是指令數超過 shader model 的限制時(視 shader model 而定),就不得不拆成多個 render pass。

Multi-pass, Multi-light

for each light:
 for each object affected by light:
  render target += BRDF(object, light)

這方式是將每盞燈光的所影響的結果累加於 render target,+= 的部分是透過 ping-pong 的方式在兩個 render target 之間作替換。然而 invisible surface 所造成的計算浪費仍舊沒有獲得解決之道,新增的 geometry pass 也在 vertex transform 與 setup 的部分帶來了額外的開銷。這部份的問題,雖然可以透過粗略的 front-to-back sorting 獲得一些抒解,但 deferred shading 卻對此問題有著更根本的解決方案(當然也會帶來其他的限制)。

Deferred Shading

for each object:
 render lighting properties to G-buffer
for each light:
 render target += BRDF(G-buffer, light)

Deferred shading 之所以能解決 hidden surface 所造成的 shading 浪費,主要是因為它在第一階段先輸出 position, normal 與其他參數至 G-buffer。使第二階段的 lighting 運算能完全作用在 visible 的 fragment 上,同時也有助於降低 light/object 之間的相依性,藉此達到 render 效率的提升。一切看起來似乎都很美好,但故事就這樣結束了嗎?喔!不,故事才剛開始…

Continue reading