延迟渲染

From KlayGE
Revision as of 01:38, 27 January 2011 by Gongminmin (Talk | contribs)

Jump to: navigation, search

本文讲述的是KlayGE的Deferred Rendering例子中使用的延迟渲染方法。

Deferred Lighting的框架

KlayGE 3.11的例子已经从Deferred Shading改成了更节省带宽的Deferred Lighting。这里先对Deferred Lighting作一个简要的介绍,并假设读者已经了解了Deferred Shading。

Deferred Lighting的渲染架构可以分为三个阶段:

1. for each object
   {
      填充G-Buffer
   }
2. for each light
   {
      Lighting pass
   }
3. for each object
   {
     执行shading
   }

与Deferred Shading不同的是,shading(也就是和材质相关)的计算仅仅发生在最后一个阶段。所以,G-Buffer中需要保存的信息得到极大地减小,甚至不再需要MRT。

Lighting pass

Lighting pass在Deferred Lighting框架处于核心地位,在这里我打算先把lighting pass解析清楚。一旦lighting pass表达好了,G-Buffer所需要保存的信息,以及shading pass能得到的信息也都清楚了。

我以前的系列文章游戏中基于物理的渲染推出了渲染模型总公式:

LaTeX: L_{o}(\mathbf{v})=\pi\rho(\mathbf{l_c}, \mathbf{v})\otimes \mathbf{c}_{light} (\mathbf{n} \cdot \mathbf{l_c})=(\mathbf{c}_{diff} + \frac {\alpha + 2} {8}(\mathbf{n} \cdot \mathbf{h})^{\alpha} F(\mathbf{c}_{spec}, \mathbf{l_c},\mathbf{h})) \otimes \mathbf{c}_{light} (\mathbf{n} \cdot \mathbf{l_c})

再有N个光源的情况下,每个像素的光照响应就是

LaTeX: L_{o}(\mathbf{v})=\pi\rho(\mathbf{l_{c1}}, \mathbf{v})\otimes \mathbf{c}_{light1} (\mathbf{n} \cdot \mathbf{l_{c1}})

LaTeX: +\pi\rho(\mathbf{l_{c2}}, \mathbf{v})\otimes \mathbf{c}_{light2} (\mathbf{n} \cdot \mathbf{l_{c2}})

LaTeX:  + \ldots

LaTeX: +\pi\rho(\mathbf{l_cN}, \mathbf{v})\otimes \mathbf{c}_{lightN} (\mathbf{n} \cdot \mathbf{l_{cN}})

对于Deferred shading来说,每一个shading pass就是执行一个

LaTeX: \pi\rho(\mathbf{l_cn}, \mathbf{v})\otimes \mathbf{c}_{lightn} (\mathbf{n} \cdot \mathbf{l_cn})

而对于Deferred lighting来说,公式需要重新整理一下:

LaTeX: L_{o}(\mathbf{v})=(\mathbf{c}_{diff} + \frac {\alpha + 2} {8}(\mathbf{n} \cdot \mathbf{h_1})^{\alpha} F(\mathbf{c}_{spec}, \mathbf{l_{c1}},\mathbf{h_1})) \otimes \mathbf{c}_{light1} (\mathbf{n} \cdot \mathbf{l_{c1}})

LaTeX: +(\mathbf{c}_{diff} + \frac {\alpha + 2} {8}(\mathbf{n} \cdot \mathbf{h_2})^{\alpha} F(\mathbf{c}_{spec}, \mathbf{l_{c2}},\mathbf{h_2})) \otimes \mathbf{c}_{light2} (\mathbf{n} \cdot \mathbf{l_{c2}})

LaTeX: +\ldots

LaTeX: +(\mathbf{c}_{diff} + \frac {\alpha + 2} {8}(\mathbf{n} \cdot \mathbf{h_N})^{\alpha} F(\mathbf{c}_{spec}, \mathbf{l_{cN}},\mathbf{h_N})) \otimes \mathbf{c}_{lightN} (\mathbf{n} \cdot \mathbf{l_{cN}})

LaTeX: =\mathbf{c}_{diff}\otimes (\mathbf{c}_{light1} (\mathbf{n} \cdot \mathbf{l_{c1}}) + \mathbf{c}_{light2} (\mathbf{n} \cdot \mathbf{l_{c2}}) + \ldots + \mathbf{c}_{lightN} (\mathbf{n} \cdot \mathbf{l_{cN}}))

LaTeX: + \frac {\alpha + 2} {8}(((\mathbf{n} \cdot \mathbf{h_1})^{\alpha} F(\mathbf{c}_{spec}, \mathbf{l_{c1}},\mathbf{h_1})) \otimes \mathbf{c}_{light1} (\mathbf{n} \cdot \mathbf{l_{c1}})

LaTeX: + ((\mathbf{n} \cdot \mathbf{h_2})^{\alpha} F(\mathbf{c}_{spec}, \mathbf{l_{c2}},\mathbf{h_2})) \otimes \mathbf{c}_{light2} (\mathbf{n} \cdot \mathbf{l_{c2}})

LaTeX: + \ldots

LaTeX: + ((\mathbf{n} \cdot \mathbf{h_N})^{\alpha} F(\mathbf{c}_{spec}, \mathbf{l_{cN}},\mathbf{h_N})) \otimes \mathbf{c}_{lightN} (\mathbf{n} \cdot \mathbf{l_{cN}}))

由于cdiff是到最后的shading pass才计算,所以在每一个light pass里面,diffuse和specular必须分开才能保证结果正确:

LaTeX: Diffuse: \mathbf{c}_{lightn} (\mathbf{n} \cdot \mathbf{l_{cn}})
LaTeX: Specular: ((\mathbf{n} \cdot \mathbf{h_n})^{\alpha} F(\mathbf{c}_{spec}, \mathbf{l_{cn}},\mathbf{h_n})) \otimes \mathbf{c}_{lightn} (\mathbf{n} \cdot \mathbf{l_{cn}})

为了把diffuse和specular放入4个通道的buffer中,就只能牺牲specular的颜色,只剩下亮度,同时cspec也简化成一个标量。所以,lighting pass的计算成了:

LaTeX: float4(1, 1, 1, (\mathbf{n} \cdot \mathbf{h_n})^{\alpha} F(c_{spec}, \mathbf{l_{cn}},\mathbf{h_n})) \times \mathbf{c}_{lightn} (\mathbf{n} \cdot \mathbf{l_{cn}})