<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_KlayGE游戏引擎</title><subtitle type="text"/><id>http://feed.cnblogs.com/blog/u/40077/rss</id><updated>2012-05-02T04:52:01Z</updated><author><name>龚敏敏</name><uri>http://www.cnblogs.com/gongminmin/</uri></author><generator>feed.cnblogs.com</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/gongminmin/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/40077/rss"/><entry><id>http://www.cnblogs.com/gongminmin/archive/2012/05/02/2478838.html</id><title type="text">KlayGE C++代码风格指南英文版</title><summary type="text">转载请注明出处为KlayGE游戏引擎，本文的永久链接为http://www.klayge.org/?p=1941参考了google的C++风格指南之后，我也照着写出了一份KlayGE C++代码风格指南。主要方针和google的类似，但有几处理念上的区别：允许使用异常，但仅仅用来抛出错误在必要的时候允许小心地使用RTTIconst在所修饰类型的右边可以任意使用boost的库优先使用stream，而不是printf有兴趣的朋友可以参考一下。目前只有英文版，中文版正在翻译中，近期将会问世。</summary><published>2012-05-02T04:52:00Z</published><updated>2012-05-02T04:52:00Z</updated><author><name>龚敏敏</name><uri>http://www.cnblogs.com/gongminmin/</uri></author><link rel="alternate" href="http://www.cnblogs.com/gongminmin/archive/2012/05/02/2478838.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/gongminmin/archive/2012/05/02/2478838.html"/><content type="html">&lt;strong style="word-wrap: break-word; padding: 0px; margin: 0px; font-weight: 700; color: #444444; font-family: Tahoma, 'Microsoft Yahei', Simsun; background-color: #ffffff; "&gt;转载请注明出处为&lt;/strong&gt;&lt;a href="http://www.klayge.org/" target="_blank" style="word-wrap: break-word; padding: 0px; margin: 0px; color: #336699; font-family: Tahoma, 'Microsoft Yahei', Simsun; background-color: #ffffff; "&gt;KlayGE游戏引擎&lt;/a&gt;&lt;strong style="word-wrap: break-word; padding: 0px; margin: 0px; font-weight: 700; color: #444444; font-family: Tahoma, 'Microsoft Yahei', Simsun; background-color: #ffffff; "&gt;，本文的永久链接为&lt;/strong&gt;&lt;a href="http://www.klayge.org/?p=1941" target="_blank" style="word-wrap: break-word; padding: 0px; margin: 0px; color: #336699; font-family: Tahoma, 'Microsoft Yahei', Simsun; background-color: #ffffff; "&gt;http://www.klayge.org/?p=1941&lt;/a&gt;&lt;br style="word-wrap: break-word; padding: 0px; margin: 0px; color: #444444; font-family: Tahoma, 'Microsoft Yahei', Simsun; background-color: #ffffff; " /&gt;&lt;br style="word-wrap: break-word; padding: 0px; margin: 0px; color: #444444; font-family: Tahoma, 'Microsoft Yahei', Simsun; background-color: #ffffff; " /&gt;&lt;span style="color: #444444; font-family: Tahoma, 'Microsoft Yahei', Simsun; background-color: #ffffff; "&gt;参考了google的C++风格指南之后，我也照着写出了一份&lt;/span&gt;&lt;a href="http://www.klayge.org/wiki/index.php/C%2B%2B_style_guide" target="_blank" style="word-wrap: break-word; padding: 0px; margin: 0px; color: #336699; font-family: Tahoma, 'Microsoft Yahei', Simsun; background-color: #ffffff; "&gt;KlayGE C++代码风格指南&lt;/a&gt;&lt;span style="color: #444444; font-family: Tahoma, 'Microsoft Yahei', Simsun; background-color: #ffffff; "&gt;。主要方针和google的类似，但有几处理念上的区别：&lt;/span&gt;&lt;br style="word-wrap: break-word; padding: 0px; margin: 0px; color: #444444; font-family: Tahoma, 'Microsoft Yahei', Simsun; background-color: #ffffff; " /&gt;&lt;br style="word-wrap: break-word; padding: 0px; margin: 0px; color: #444444; font-family: Tahoma, 'Microsoft Yahei', Simsun; background-color: #ffffff; " /&gt;&lt;ul style="word-wrap: break-word; padding: 0px; margin: 0px 0px 0px 14px; color: #444444; font-family: Tahoma, 'Microsoft Yahei', Simsun; background-color: #ffffff; "&gt;&lt;li style="word-wrap: break-word; padding: 0px; margin: 0px 0px 0px 2em; list-style: disc; "&gt;允许使用异常，但仅仅用来抛出错误&lt;/li&gt;&lt;li style="word-wrap: break-word; padding: 0px; margin: 0px 0px 0px 2em; list-style: disc; "&gt;在必要的时候允许小心地使用RTTI&lt;/li&gt;&lt;li style="word-wrap: break-word; padding: 0px; margin: 0px 0px 0px 2em; list-style: disc; "&gt;const在所修饰类型的右边&lt;/li&gt;&lt;li style="word-wrap: break-word; padding: 0px; margin: 0px 0px 0px 2em; list-style: disc; "&gt;可以任意使用boost的库&lt;/li&gt;&lt;li style="word-wrap: break-word; padding: 0px; margin: 0px 0px 0px 2em; list-style: disc; "&gt;优先使用stream，而不是printf&lt;br style="word-wrap: break-word; padding: 0px; margin: 0px; " /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br style="word-wrap: break-word; padding: 0px; margin: 0px; color: #444444; font-family: Tahoma, 'Microsoft Yahei', Simsun; background-color: #ffffff; " /&gt;&lt;span style="color: #444444; font-family: Tahoma, 'Microsoft Yahei', Simsun; background-color: #ffffff; "&gt;有兴趣的朋友可以参考一下。目前只有英文版，中文版正在翻译中，近期将会问世。&lt;/span&gt;&amp;nbsp;&lt;img src="http://www.cnblogs.com/gongminmin/aggbug/2478838.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/gongminmin/archive/2012/05/02/2478838.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/gongminmin/archive/2012/05/01/2477964.html</id><title type="text">Normal2Height工具已经完成</title><summary type="text">转载请注明出处为KlayGE游戏引擎，本文的永久链接为http://www.klayge.org/?p=1930 多年前就想为KlayGE做个Normal2Height的工具，一直没时间，现在终于抽空把它完成了。 缘由 Normal map的来源有多种。游戏开发中常规的做法是根据高模和低模的位置对应关系生成height map，然后用height map生成normal map。这种情况下不必担心是否能得到高精度的height map。但很多低端的做法是让美术直接画normal map，根本没有高模。随着游戏渲染水平的提高，normal mapping（NM）这种1970年代的技术已经...</summary><published>2012-05-01T08:20:00Z</published><updated>2012-05-01T08:20:00Z</updated><author><name>龚敏敏</name><uri>http://www.cnblogs.com/gongminmin/</uri></author><link rel="alternate" href="http://www.cnblogs.com/gongminmin/archive/2012/05/01/2477964.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/gongminmin/archive/2012/05/01/2477964.html"/><content type="html">&lt;div style="font-weight:bold"&gt;&lt;span dir="ltr"&gt;转载请注明出处为&lt;a href="http://www.klayge.org/"&gt;KlayGE游戏引擎&lt;/a&gt;，本文的永久链接为&lt;a href="http://www.klayge.org/?p=1930"&gt;http://www.klayge.org/?p=1930&lt;/a&gt;&lt;/span&gt; &lt;/div&gt; &lt;p&gt;多年前就想为KlayGE做个Normal2Height的工具，一直没时间，现在终于抽空把它完成了。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;缘由&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;Normal map的来源有多种。游戏开发中常规的做法是根据高模和低模的位置对应关系生成height map，然后用height  map生成normal map。这种情况下不必担心是否能得到高精度的height map。但很多低端的做法是让美术直接画normal  map，根本没有高模。随着游戏渲染水平的提高，normal  mapping（NM）这种1970年代的技术已经不能满足需要了，越来越多的游戏开始过渡到更精确的parallax  mapping（PM）、parallax occlusion mapping（POM）甚至displacement  mapping（DM）。他们除了normal map，还需要有height map才能工作。所以如果normal  map是手绘而成，就会因为缺乏height map而无法升级。如果能反过来，从normal map生成height  map，就能在一定程度上解决这个问题。&lt;/p&gt; &lt;p&gt;比较一下normal mapping和parallax occlusion mapping，就可以明显地看出来在视差、遮挡效果和真实感上，POM远胜于NM。&lt;/p&gt; &lt;div id="attachment_1932"  aligncenter"="" style="width: 610px"&gt;&lt;a href="http://www.klayge.org/wp/wp-content/uploads/2012/05/nm.jpg"&gt;&lt;img wp-image-1932"="" title="Normal mapping" src="http://www.klayge.org/wp/wp-content/uploads/2012/05/nm.jpg" alt="Normal mapping" width="600" height="418" /&gt;&lt;/a&gt;&lt;p&gt;使用Normal mapping渲染&lt;/p&gt;&lt;/div&gt; &lt;div id="attachment_1933"  aligncenter"="" style="width: 610px"&gt;&lt;a href="http://www.klayge.org/wp/wp-content/uploads/2012/05/pom.jpg"&gt;&lt;img wp-image-1933"="" title="Parallax occlusion mapping" src="http://www.klayge.org/wp/wp-content/uploads/2012/05/pom.jpg" alt="Parallax occlusion mapping" width="600" height="418" /&gt;&lt;/a&gt;&lt;p&gt;使用Parallax occlusion mapping渲染&lt;/p&gt;&lt;/div&gt; &lt;p&gt;&lt;strong&gt;算法&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;我实现的算法是基于NVIDIA在SIGGRAPH 2011上提到的&lt;a href="http://developer.download.nvidia.com/assets/gamedev/docs/nmap2displacement.pdf" target="_blank"&gt;Generating Displacement from&amp;nbsp;Normal Map for use in 3D Games&lt;/a&gt;。我就不详细讨论了，有兴趣的朋友可以看原始pdf。这里指讨论一下基本的想法。&lt;/p&gt; &lt;p&gt;从height map计算normal map靠的是差分，所以直觉上从normal map计算height map就需要积分。但因为normal map保存的时候经过量化，误差比较大，造成不同的积分路径无法收敛到同一个值。&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.klayge.org/wp/wp-content/uploads/2012/05/route.png"&gt;&lt;img size-full=""  wp-image-1934"="" title="route" src="http://www.klayge.org/wp/wp-content/uploads/2012/05/route.png" alt="Accumulate height in different routes" width="578" height="280" /&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;所以NV的方法是，先根据normal map计算depth difference map（DDM）。然后对DDM上的每个pixel，根据极坐标从小到大的顺序累计几圈，得到最终的height。&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.klayge.org/wp/wp-content/uploads/2012/05/Accumulate.png"&gt;&lt;img size-full=""  wp-image-1936"="" title="Accumulate" src="http://www.klayge.org/wp/wp-content/uploads/2012/05/Accumulate.png" alt="Accumulate" width="600" height="217" /&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;就是这样简单的累积算法，就能得到不错的效果。对于这样的normal map：&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.klayge.org/wp/wp-content/uploads/2012/05/normal.jpg"&gt;&lt;img size-full=""  wp-image-1937"="" title="normal" src="http://www.klayge.org/wp/wp-content/uploads/2012/05/normal.jpg" alt="Input normal map" width="512" height="512" /&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;可以恢复出height map：&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.klayge.org/wp/wp-content/uploads/2012/05/height.jpg"&gt;&lt;img size-full=""  wp-image-1938"="" title="height" src="http://www.klayge.org/wp/wp-content/uploads/2012/05/height.jpg" alt="" width="512" height="512" /&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;虽然比原始的高精度height map模糊，但在用于POM和DM的时候在视觉上看不出区别。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;总结&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;在有了Normal2Height这样的工具之后，老土的normal mapping都可以顺利地进化到更精致的渲染效果。同时，对原有美术流水线的影响几乎为0。&lt;/p&gt; &lt;p&gt;理论上，还可以尝试通过求解Poisson Equation来得到精度更高的height。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/gongminmin/aggbug/2477964.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/gongminmin/archive/2012/05/01/2477964.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/gongminmin/archive/2012/05/01/2477961.html</id><title type="text">FFT镜头效果的新进展</title><summary type="text">转载请注明出处为KlayGE游戏引擎，本文的永久链接为http://www.klayge.org/?p=1920 FFT镜头效果已 经完成，并集成入KlayGE开发版中，命名为FFTLensEffectPostProcess。除此之外，还写了一个命令行工具，用于产生镜头效果的 纹理。虽然FFT的方法能在一个pass内产生各种复杂的镜头效果，但目前性能低于默认的多重gaussian blur。其中最主要的开销来自于FFT本身，下面就着重就讨论一下GPU FFT的进展和未来。前不久我在用Pixel Shader实现FFT的 时候，提到了用Compute Shader来实现FFT效率可以更高。之前O</summary><published>2012-05-01T08:19:00Z</published><updated>2012-05-01T08:19:00Z</updated><author><name>龚敏敏</name><uri>http://www.cnblogs.com/gongminmin/</uri></author><link rel="alternate" href="http://www.cnblogs.com/gongminmin/archive/2012/05/01/2477961.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/gongminmin/archive/2012/05/01/2477961.html"/><content type="html">&lt;div style="font-weight:bold"&gt;&lt;span dir="ltr"&gt;转载请注明出处为&lt;a href="http://www.klayge.org/"&gt;KlayGE游戏引擎&lt;/a&gt;，本文的永久链接为&lt;a href="http://www.klayge.org/?p=1920"&gt;http://www.klayge.org/?p=1920&lt;/a&gt;&lt;/span&gt; &lt;/div&gt;&lt;p&gt;&lt;a title="FFT镜头效果解析" href="http://www.klayge.org/2012/03/22/fft%e9%95%9c%e5%a4%b4%e6%95%88%e6%9e%9c%e8%a7%a3%e6%9e%90/"&gt;FFT镜头效果&lt;/a&gt;已 经完成，并集成入KlayGE开发版中，命名为FFTLensEffectPostProcess。除此之外，还写了一个命令行工具，用于产生镜头效果的 纹理。虽然FFT的方法能在一个pass内产生各种复杂的镜头效果，但目前性能低于默认的多重gaussian blur。其中最主要的开销来自于FFT本身，下面就着重就讨论一下GPU FFT的进展和未来。&lt;/p&gt;&lt;p&gt;前不久我在用&lt;a title="基于Pixel Shader的FFT已经完成" href="http://www.klayge.org/2012/04/12/%e5%9f%ba%e4%ba%8epixel-shader%e7%9a%84fft%e5%b7%b2%e7%bb%8f%e5%ae%8c%e6%88%90/"&gt;Pixel Shader实现FFT&lt;/a&gt;的 时候，提到了用Compute Shader来实现FFT效率可以更高。之前Ocean的例子里就有用于实现波浪模拟的CS4 FFT（从NV的例子改进而成），它的输入和输出是1D Buffer的形式。为了更通用，在进入KlayGE核心的时候改成了2D Texture的形式。可惜的是，CS4不能写入纹理，就需要增加一个把Buffer转成纹理的PS。CS5的实现基本类似于CS4，但改为直接读写纹 理。现在CS4和CS5的FFT都已经实现完毕，终于可以比较一下性能。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;算法的差异&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;由于输出的限制，pixel shader的FFT只能实现最简单的radix-2算法，每次输入2个复数、生成2个复数。而compute shader支持任意写入，所以可以实现更复杂的radix-4、radix-8甚至multi-radix。在这里我实现的是radix-8，每次处理 8个复数。所以512&amp;#215;512只需要6个pass，比PS的18个pass少得多。&lt;/p&gt;&lt;p&gt;另一个区别在于，因为CS4的限制，CS4 FFT的数据都以float2的Buffer来保存（实部和虚部），只有3通道，每个pixel的RGB是排列成R0/R1/R2&amp;#8230;Rn G0/G1/G2&amp;#8230;Gn B0/B1/B2&amp;#8230;Bn的形式。而在PS和CS5的实现中，仍然保留R0G0B0A0/R1G1B1A1/R2G2B2A2&amp;#8230;RnGnBnAn的排列，并 且是4通道的。所以单从计算来说，CS4少一个通道，标量的计算量和带宽耗用量都会小于PS和CS5。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;性能比较&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;这里的输入是512&amp;#215;512，分别在高端、中端、低端显卡上同时比较了正向FFT和逆向IFFT。&lt;/p&gt;&lt;table border="0"&gt;     &lt;tbody&gt;         &lt;tr&gt;             &lt;th&gt;&lt;/th&gt; &lt;th&gt;NV GTX580 FFT/IFFT (ms)&lt;/th&gt; &lt;th&gt;AMD HD6670 FFT/IFFT (ms)&lt;/th&gt; &lt;th&gt;NV 9800GT FFT/IFFT (ms)&lt;/th&gt; &lt;th&gt;NV NVS4200M FFT/IFFT (ms)&lt;/th&gt;         &lt;/tr&gt;         &lt;tr&gt;             &lt;th&gt;PS&lt;/th&gt;             &lt;td&gt;2.12/2.28&lt;/td&gt;             &lt;td&gt;7.09/7.22&lt;/td&gt;             &lt;td&gt;7.99/8.16&lt;/td&gt;             &lt;td&gt;33.30/33.30&lt;/td&gt;         &lt;/tr&gt;         &lt;tr&gt;             &lt;th&gt;CS4&lt;/th&gt;             &lt;td&gt;0.70/0.70&lt;/td&gt;             &lt;td&gt;2.44/2.47&lt;/td&gt;             &lt;td&gt;3.33/3.45&lt;/td&gt;             &lt;td&gt;10.36/9.80&lt;/td&gt;         &lt;/tr&gt;         &lt;tr&gt;             &lt;th&gt;CS5&lt;/th&gt;             &lt;td&gt;0.76/0.76&lt;/td&gt;             &lt;td&gt;2.40/2.39&lt;/td&gt;             &lt;td&gt;不支持&lt;/td&gt;             &lt;td&gt;8.86/8.81&lt;/td&gt;         &lt;/tr&gt;     &lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;从结果可以看出，CS4的实现能比PS快2倍左右，一方面来自于radix-8带来的计算量减小，另一个方面来自于pass数减少。有趣的是，除了 高端的GTX580，其他卡上CS5都比CS4略快。在NV的卡上，以64-bit为单位的IO效率高于其他格式，这一点也给CS4带来了一定的优势。&lt;/p&gt;&lt;p&gt;反过来，这个结果也说明了CS5还有优化的空间。CS5多做了1/3的计算，IO效率也不不是最高的，却能于CS4相似甚至更快。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;未来&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;这个版本里的FFT镜头效果暂时告一段落，除了继续优化之外，以后还有很多算法级别的改进值得尝试。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;数据格式&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;现在所有的中间格式都是ABGR32F。如果用ABGR16F的话，在暗处将会出现一些artifact。如果这样的artifact在可以接受的 范围内，或者用其他补偿方法来改进16F的精度，速度就能大大提高。输入和输出格式则不受限制。输入格式可以用ABGR16F、或者更少的 B10G11R11F，输出格式可以用ABGR16F。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;纯实数FFT&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;因为输入数据是张只有实数部分的图像，对纯实数做FFT的结果是头尾对称的，可以利用这一点做算法上的改进。FFTW里面，这个变换称为r2c。对 n长度的输入它只需要输出n/2+1个复数，而不用n个，IO和计算量都可以减小。另一个尝试的方向是DCT。作为FFT的特例，经过特殊寻址安排的 DCT也符合卷积定理。所以用输入输出都是纯实数的DCT也能减少IO。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;sFFT&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;今年一月，MIT的一个团队提出了&lt;a href="http://groups.csail.mit.edu/netmit/sFFT/results.html" target="_blank"&gt;Spare Fast Fourier Transform（sFFT）&lt;/a&gt;的算法。在输入信号稀疏的情况下，sFFT能比传统FFT快之百倍。由于用于镜头效果的输入仅仅是亮度大于某个阈值的pixel，稀疏程度非常高，所以也可能可以利用sFFT来进行加速。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/gongminmin/aggbug/2477961.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/gongminmin/archive/2012/05/01/2477961.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/gongminmin/archive/2012/04/22/2464982.html</id><title type="text">Forward框架的逆袭：解析Forward+渲染</title><summary type="text">转载请注明出处为KlayGE游戏引擎，本文地址为http://www.klayge.org/2012/04/21/forward%e6%a1%86%e6%9e%b6%e7%9a%84%e9%80%86%e8%a2%ad%ef%bc%9a%e8%a7%a3%e6%9e%90forward%e6%b8%b2%e6%9f%93/ AMD在7900系列显卡发布的时候同时推出了Leo demo， 并说明它不是用近年流行的Deferred框架渲染完成，而是用到了一种叫Forward+的框架。这个框架不需要Deferred的大带宽要求，却仍能 实时渲染上千光源。EG2012上有篇新paper叫做Forwa.</summary><published>2012-04-22T06:58:00Z</published><updated>2012-04-22T06:58:00Z</updated><author><name>龚敏敏</name><uri>http://www.cnblogs.com/gongminmin/</uri></author><link rel="alternate" href="http://www.cnblogs.com/gongminmin/archive/2012/04/22/2464982.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/gongminmin/archive/2012/04/22/2464982.html"/><content type="html">&lt;div style="font-weight:bold"&gt;&lt;span dir="ltr"&gt;转载请注明出处为&lt;a href="http://www.klayge.org/"&gt;KlayGE游戏引擎&lt;/a&gt;，本文地址为&lt;a href="http://www.klayge.org/2012/04/21/forward%e6%a1%86%e6%9e%b6%e7%9a%84%e9%80%86%e8%a2%ad%ef%bc%9a%e8%a7%a3%e6%9e%90forward%e6%b8%b2%e6%9f%93/"&gt;http://www.klayge.org/2012/04/21/forward%e6%a1%86%e6%9e%b6%e7%9a%84%e9%80%86%e8%a2%ad%ef%bc%9a%e8%a7%a3%e6%9e%90forward%e6%b8%b2%e6%9f%93/&lt;/a&gt;&lt;/span&gt; &lt;/div&gt; &lt;p&gt;AMD在7900系列显卡发布的时候同时推出了&lt;a href="http://developer.amd.com/samples/demos/pages/AMDRadeonHD7900SeriesGraphicsReal-TimeDemos.aspx" target="_blank"&gt;Leo demo&lt;/a&gt;， 并说明它不是用近年流行的Deferred框架渲染完成，而是用到了一种叫Forward+的框架。这个框架不需要Deferred的大带宽要求，却仍能 实时渲染上千光源。EG2012上有篇新paper叫做Forward+: Bringing Deferred Lighting to the  Next  Level，讲述的就是这个方法。但目前作者还没有放出该论文的全文，这里我只能通过只言片语和AMD的文档来解析这个神奇的Forward+。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Tiled-based Deferred Shading&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;在进入正题之前，我们先回顾一下Intel在SIGGRAPH Courses 2010里提到的&lt;a href="http://visual-computing.intel-research.net/art/publications/deferred_rendering/" target="_blank"&gt;Tiled-based Deferred Shading&lt;/a&gt;。它的算法框架是：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;生成G-Buffer，这一步和传统deferred shading一样。&lt;/li&gt; &lt;li&gt;把G-Buffer划分成许多16&amp;#215;16的tile，每个tile根据depth得到bounding box。&lt;/li&gt; &lt;li&gt;对于每个tile，把它的bounding box和light求交，得到对这个tile有贡献的light序列。&lt;/li&gt; &lt;li&gt;对于G-Buffer的每个pixel，用它所在tile的light序列累加计算shading。&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;在原先的deferred框架下，每个light需要画一个light volume，以决定它会影响到哪些pixel（也就是light culling）。而用tiled based的方法，只需要一个pass就可以对所有的光源进行求交。如果用了AMD在&lt;a href="http://developer.amd.com/samples/demos/pages/ATIRadeonHD5800SeriesRealTimeDemos.aspx" target="_blank"&gt;Mecha demo&lt;/a&gt;中用到的OIT方法，还可以做一个per-tile linked list，直接把light序列存在链表里。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Forward+ Rendering&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;有了Tiled-based Deferred Shading的基础，理解Forward+就变得简单多了。Forward+  Rendering和Tiled-based Deferred Shading的关系就好比原先的Forward Shading和Deferred  Shading，所以我们可以照猫画虎一次：&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Z-prepass，很多forward shading都会用这个作为优化，而在forward+中，这个变成了必然步骤。&lt;/li&gt; &lt;li&gt;把Z-Buffer划分成许多16&amp;#215;16的tile，每个tile根据depth得到bounding box。&lt;/li&gt; &lt;li&gt;对于每个tile，把它的bounding box和light求交，得到对这个tile有贡献的light序列。&lt;/li&gt; &lt;li&gt;对于每个物体，在PS中用该pixel所在tile的light序列累加计算shading。&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;从这里可以看出，前两步与Tiled-based deferred shading大同小异，但只需要Z-Buffer，而不需要很消耗带宽的G-Buffer（&lt;a title="KlayGE 4.0中Deferred Rendering的改进（二）：拥挤的G-Buffer" href="http://www.klayge.org/2011/11/28/klayge-4-0%e4%b8%addeferred-rendering%e7%9a%84%e6%94%b9%e8%bf%9b%ef%bc%88%e4%ba%8c%ef%bc%89%ef%bc%9a%e6%8b%a5%e6%8c%a4%e7%9a%84g-buffer/"&gt;G-Buffer最小也要32bit color + 32bit depth&lt;/a&gt;）。第三步是完全一样的。第四部由于用了forward，可以有forward的各种好处：&lt;/p&gt; &lt;ul&gt; &lt;li&gt;复杂材质&lt;/li&gt; &lt;li&gt;支持硬件AA（虽然我一直认为硬件AA多算了很多东西，是一种巨大的浪费）&lt;/li&gt; &lt;li&gt;带宽利用率高&lt;/li&gt; &lt;li&gt;支持透明物体&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;由于light已经在步骤3中cache了，所以也可以不像传统的forward那样，把材质和光源搅在一起。加上shader中动态分支的能力， 不难实现类似deferred那样的巨量光源支持。由于带宽省了很多，Forward+的速度能比Deferred快。在原paper里的性能比较足以说 明这个问题。&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.klayge.org/wp/wp-content/uploads/2012/04/Forward+VSDeferred.png"&gt;&lt;img size-full=""  wp-image-1897"="" title="Forward+VSDeferred" src="http://www.klayge.org/wp/wp-content/uploads/2012/04/Forward+VSDeferred.png" alt="Forward+  VS Deferred" width="600" height="248" /&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;另一个有趣的地方是透明物体的渲染。虽然我在KlayGE中用Deep G-Buffer的方法解决了&lt;a title="KlayGE 4.0中Deferred Rendering的改进（三）：透明的烦恼" href="http://www.klayge.org/2011/11/29/klayge-4-0%e4%b8%addeferred-rendering%e7%9a%84%e6%94%b9%e8%bf%9b%ef%bc%88%e4%b8%89%ef%bc%89%ef%bc%9a%e9%80%8f%e6%98%8e%e7%9a%84%e7%83%a6%e6%81%bc/"&gt;纯Deferred下透明物体的渲染&lt;/a&gt;。 正如很多读者指出的，这么做所带来的带宽翻倍在很大程度上拖慢了整个系统。在Forward+中，第一步生成Z-prepass的时候，可以采用双Z- Buffer的办法，一个放不透明物体的Z，另一个放透明物体的Z。在第二步计算tile bounding  box的时候，不管透不透明都放在一起计算一个总的bounding box。后面步骤不变，就能原生支持透明物体。&lt;/p&gt; &lt;p&gt;由于有了Z-Buffer，其他原先对Deferred有利的效果，比如GI、SSR，都可以直接应用。SSAO、SSVO之类的方法，如果需要考虑pixel normal，就需要适当的修改才能应用上。&lt;/p&gt; &lt;p&gt;在AMD的demo中，步骤2和3是用compute shader实现的。而在&lt;a href="http://www.pjblewis.com/articles/tile-based-forward-rendering/" target="_blank"&gt;Tiled-based Forward Rendering&lt;/a&gt;这篇blog中，他完全用PS实现了per-tile linked list，但仍然需要D3D11的UAV特性。所以Forward+还没法再D3D11之前的硬件上实现。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;总结&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;所谓三十年河东三十年河西，作为Forward框架的新发展，Forward+给我们提供了一个新思路。这样的竞争性发展总比所有资源都投到一方、忽视另一方要好。&lt;/p&gt; &lt;p&gt;从贡献程度来看，最有突破性的其实不是Forward部分，其实是Tiled-based。Forward+只能算作Tiled-based  Deferred Shading的&amp;#8220;Forward化&amp;#8221;。顺便说一下，很多移动平台的GPU在硬件上支持Tiled-based  Rendering（TBR），也是利用它来最大化计算相关性和带宽利用率。不支持TBR的Tegra就吃亏许多了。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/gongminmin/aggbug/2464982.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/gongminmin/archive/2012/04/22/2464982.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/gongminmin/archive/2012/04/22/2464981.html</id><title type="text">基于Pixel Shader的FFT已经完成</title><summary type="text">转载请注明出处为KlayGE游戏引擎，本文地址为http://www.klayge.org/2012/04/12/%e5%9f%ba%e4%ba%8epixel-shader%e7%9a%84fft%e5%b7%b2%e7%bb%8f%e5%ae%8c%e6%88%90/ 上周末把GPU Gems 2里的GPU FFT在KlayGE里实现了一下，经过优化和调整，昨晚已经进入KlayGE的开发版本中。完整的FFT Lens Effects也会很快集成进去。 这里用到的是那篇文章中提到的方法1，因为经过测试，方法2在现代GPU上速度不如方法1。我做的改进是把原来的3张查找表合并成1张，并都用 1.</summary><published>2012-04-22T06:57:00Z</published><updated>2012-04-22T06:57:00Z</updated><author><name>龚敏敏</name><uri>http://www.cnblogs.com/gongminmin/</uri></author><link rel="alternate" href="http://www.cnblogs.com/gongminmin/archive/2012/04/22/2464981.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/gongminmin/archive/2012/04/22/2464981.html"/><content type="html">&lt;div style="font-weight:bold"&gt;&lt;span dir="ltr"&gt;转载请注明出处为&lt;a href="http://www.klayge.org/"&gt;KlayGE游戏引擎&lt;/a&gt;，本文地址为&lt;a href="http://www.klayge.org/2012/04/12/%e5%9f%ba%e4%ba%8epixel-shader%e7%9a%84fft%e5%b7%b2%e7%bb%8f%e5%ae%8c%e6%88%90/"&gt;http://www.klayge.org/2012/04/12/%e5%9f%ba%e4%ba%8epixel-shader%e7%9a%84fft%e5%b7%b2%e7%bb%8f%e5%ae%8c%e6%88%90/&lt;/a&gt;&lt;/span&gt; &lt;/div&gt; &lt;p&gt;上周末把&lt;a href="http://developer.nvidia.com/node/72" target="_blank"&gt;GPU Gems 2里的GPU FFT&lt;/a&gt;在KlayGE里实现了一下，经过优化和调整，昨晚已经进入KlayGE的开发版本中。完整的&lt;a title="FFT镜头效果解析" href="http://www.klayge.org/2012/03/22/fft%e9%95%9c%e5%a4%b4%e6%95%88%e6%9e%9c%e8%a7%a3%e6%9e%90/" target="_blank"&gt;FFT Lens Effects&lt;/a&gt;也会很快集成进去。&lt;/p&gt; &lt;p&gt;这里用到的是那篇文章中提到的方法1，因为经过测试，方法2在现代GPU上速度不如方法1。我做的改进是把原来的3张查找表合并成1张，并都用 16F而不是32F的格式保存输入输出数据。在GTX580上，512&amp;#215;512的数据量，PS版本的FFT花费0.94ms左右，能达到CPU  FFTW的75倍速度。但即便如此，对于lens effect那样的应用来说还是有点慢。所以接下去考虑用Compute  Shader来实现FFT，pass数会减少到1/3。PS每次处理2个数，512&amp;#215;512需要log(512) + log(512) =  18个pass；CS每次可以处理8个数，所以只要6个pass。在Ocean的例子里有个CS4的FFT，需要多两个texture和buffer互转 的pass。CS5的FFT将会更干净，效率更高。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/gongminmin/aggbug/2464981.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/gongminmin/archive/2012/04/22/2464981.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/gongminmin/archive/2012/04/22/2464977.html</id><title type="text">NV GTX680对GTX580：另一个视角</title><summary type="text">转载请注明出处为KlayGE游戏引擎，本文地址为http://www.klayge.org/2012/03/31/nv-gtx680%e5%af%b9gtx580%ef%bc%9a%e5%8f%a6%e4%b8%80%e4%b8%aa%e8%a7%86%e8%a7%92/ 2年前，D3D11显卡刚出来没多久的时候，我曾经做过一个《NV GTX480对ATI HD5870：另一个视角》，用DX SDK的D3D11例子来对当时巅峰的显卡进行各个单项的性能评测。时过境迁，现在NV GTX680已经上市，硬指标对比如下表所示。 GTX 680 GT...</summary><published>2012-04-22T06:56:00Z</published><updated>2012-04-22T06:56:00Z</updated><author><name>龚敏敏</name><uri>http://www.cnblogs.com/gongminmin/</uri></author><link rel="alternate" href="http://www.cnblogs.com/gongminmin/archive/2012/04/22/2464977.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/gongminmin/archive/2012/04/22/2464977.html"/><content type="html">&lt;div style="font-weight:bold"&gt;&lt;span dir="ltr"&gt;转载请注明出处为&lt;a href="http://www.klayge.org/"&gt;KlayGE游戏引擎&lt;/a&gt;，本文地址为&lt;a href="http://www.klayge.org/2012/03/31/nv-gtx680%e5%af%b9gtx580%ef%bc%9a%e5%8f%a6%e4%b8%80%e4%b8%aa%e8%a7%86%e8%a7%92/"&gt;http://www.klayge.org/2012/03/31/nv-gtx680%e5%af%b9gtx580%ef%bc%9a%e5%8f%a6%e4%b8%80%e4%b8%aa%e8%a7%86%e8%a7%92/&lt;/a&gt;&lt;/span&gt; &lt;/div&gt;&lt;p&gt;2年前，D3D11显卡刚出来没多久的时候，我曾经做过一个《&lt;a title="NV GTX480对ATI HD5870：另一个视角" href="http://www.klayge.org/2010/04/29/nv-gtx480%e5%af%b9ati-hd5870%ef%bc%9a%e5%8f%a6%e4%b8%80%e4%b8%aa%e8%a7%86%e8%a7%92/"&gt;NV GTX480对ATI HD5870：另一个视角&lt;/a&gt;》，用DX SDK的D3D11例子来对当时巅峰的显卡进行各个单项的性能评测。时过境迁，现在NV GTX680已经上市，硬指标对比如下表所示。&lt;/p&gt;&lt;table border="1" cellpadding="0" cellspacing="0"&gt;     &lt;tbody&gt;         &lt;tr&gt;             &lt;th&gt;&lt;/th&gt; &lt;th&gt;GTX 680&lt;/th&gt; &lt;th&gt;GTX 580&lt;/th&gt;         &lt;/tr&gt;         &lt;tr&gt;             &lt;td&gt;制程（nm）&lt;/td&gt;             &lt;td&gt;28&lt;/td&gt;             &lt;td&gt;40&lt;/td&gt;         &lt;/tr&gt;         &lt;tr&gt;             &lt;td&gt;晶体管数量（Million）&lt;/td&gt;             &lt;td&gt;3540&lt;/td&gt;             &lt;td&gt;3000&lt;/td&gt;         &lt;/tr&gt;         &lt;tr&gt;             &lt;td&gt;Die大小（mm^2）&lt;/td&gt;             &lt;td&gt;294&lt;/td&gt;             &lt;td&gt;520&lt;/td&gt;         &lt;/tr&gt;         &lt;tr&gt;             &lt;td&gt;显存（MB）&lt;/td&gt;             &lt;td&gt;2048&lt;/td&gt;             &lt;td&gt;1536&lt;/td&gt;         &lt;/tr&gt;         &lt;tr&gt;             &lt;td&gt;SM数量&lt;/td&gt;             &lt;td&gt;8&lt;/td&gt;             &lt;td&gt;16&lt;/td&gt;         &lt;/tr&gt;         &lt;tr&gt;             &lt;td&gt;核心配比&lt;/td&gt;             &lt;td&gt;1536:128:32&lt;/td&gt;             &lt;td&gt;512:64:48&lt;/td&gt;         &lt;/tr&gt;         &lt;tr&gt;             &lt;td&gt;核心频率（MHz）&lt;/td&gt;             &lt;td&gt;1006-1058&lt;/td&gt;             &lt;td&gt;772&lt;/td&gt;         &lt;/tr&gt;         &lt;tr&gt;             &lt;td&gt;shader频率（MHz）&lt;/td&gt;             &lt;td&gt;N/A&lt;/td&gt;             &lt;td&gt;1544&lt;/td&gt;         &lt;/tr&gt;         &lt;tr&gt;             &lt;td&gt;显存频率（MHz）&lt;/td&gt;             &lt;td&gt;6008&lt;/td&gt;             &lt;td&gt;4008&lt;/td&gt;         &lt;/tr&gt;         &lt;tr&gt;             &lt;td&gt;像素填充率（GP/s）&lt;/td&gt;             &lt;td&gt;32.2&lt;/td&gt;             &lt;td&gt;37.06&lt;/td&gt;         &lt;/tr&gt;         &lt;tr&gt;             &lt;td&gt;纹理填充率（GT/s）&lt;/td&gt;             &lt;td&gt;128.8&lt;/td&gt;             &lt;td&gt;49.41&lt;/td&gt;         &lt;/tr&gt;         &lt;tr&gt;             &lt;td&gt;显存带宽（GB/s）&lt;/td&gt;             &lt;td&gt;192&lt;/td&gt;             &lt;td&gt;192.4&lt;/td&gt;         &lt;/tr&gt;         &lt;tr&gt;             &lt;td&gt;总线宽度（bit）&lt;/td&gt;             &lt;td&gt;256&lt;/td&gt;             &lt;td&gt;384&lt;/td&gt;         &lt;/tr&gt;         &lt;tr&gt;             &lt;td&gt;API&lt;/td&gt;             &lt;td&gt;D3D11.1&lt;br /&gt;             OpenGL 4.2&lt;br /&gt;             OpenCL 1.2&lt;/td&gt;             &lt;td&gt;D3D11.1&lt;br /&gt;             OpenGL 4.2&lt;br /&gt;             OpenCL 1.1&lt;/td&gt;         &lt;/tr&gt;         &lt;tr&gt;             &lt;td&gt;Gflop/s&lt;/td&gt;             &lt;td&gt;3090.4&lt;/td&gt;             &lt;td&gt;1581.1&lt;/td&gt;         &lt;/tr&gt;         &lt;tr&gt;             &lt;td&gt;TDP（watts）&lt;/td&gt;             &lt;td&gt;195&lt;/td&gt;             &lt;td&gt;244&lt;/td&gt;         &lt;/tr&gt;         &lt;tr&gt;             &lt;td&gt;Gflop/s-watt&lt;/td&gt;             &lt;td&gt;15.85&lt;/td&gt;             &lt;td&gt;6.48&lt;/td&gt;         &lt;/tr&gt;     &lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;从指标上可以看出，GTX680的 SP数量急剧提高（512-&amp;gt;1536），但SM数量见到原来的一半（16-&amp;gt;8），所以每个SM内的SP个数从32猛增到192。这对scheduler是极大的考验。&lt;/p&gt;&lt;p&gt;由于配置上的较大不同，性能能有多高看理论值不行，还是得实际跑程序才能知道。这次的评测仍然分三轮进行，分别评测传统图形流水 线，DirectCompute和Tessellation的性能。测试的机器仍是两年前的Dell T5400 Workstation（Xeon E5440&amp;nbsp;4-core，4GB内存），依次装上GTX580和GTX680。两块显卡都是Zotac的公版。操作系统是Win7 64bit，使用传统界面以消除Areo界面的PS开销。显卡驱动分别是Forceware 295.73和Forceware 301.10。DX SDK的版本是June 2010。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;第一轮 传统图形流水线&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;第一论测试的是两块显卡在游戏常见的场景中的图形性能表现，选用的sample是Cascaded shadow depth map，contact hardening shadows， variance shadows 11和Dynamic shadow linkage 11。测试结果如下：&lt;/p&gt;&lt;table border="1" cellpadding="0" cellspacing="0"&gt;     &lt;tbody&gt;         &lt;tr&gt;             &lt;th&gt;&lt;/th&gt; &lt;th&gt;GTX 680&lt;/th&gt; &lt;th&gt;GTX 580&lt;/th&gt;         &lt;/tr&gt;         &lt;tr&gt;             &lt;td&gt;CascadedShadowDepthMap&lt;/td&gt;             &lt;td&gt;332.04&lt;/td&gt;             &lt;td&gt;337.63&lt;/td&gt;         &lt;/tr&gt;         &lt;tr&gt;             &lt;td&gt;Contact Hardening Shadows&lt;/td&gt;             &lt;td&gt;1225.67&lt;/td&gt;             &lt;td&gt;851.30&lt;/td&gt;         &lt;/tr&gt;         &lt;tr&gt;             &lt;td&gt;VarianceShadows11&lt;/td&gt;             &lt;td&gt;305.40&lt;/td&gt;             &lt;td&gt;309.83&lt;/td&gt;         &lt;/tr&gt;         &lt;tr&gt;             &lt;td&gt;DynamicShaderLinkage11&lt;/td&gt;             &lt;td&gt;2716.49&lt;/td&gt;             &lt;td&gt;2620.81&lt;/td&gt;         &lt;/tr&gt;     &lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;很失望吧，除了Contact hardening shadows，GTX 680并没有比GTX 580提高多少，甚至还有所下降。但领先的那个例子恰恰是计算量和带宽要求最大的。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;第二轮 DirectCompute&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;盛传GTX 680的GPGPU能力不如从前，第二轮就来测试DirectCompute这个GPGPU能力。&lt;/p&gt;&lt;table border="1" cellpadding="0" cellspacing="0"&gt;     &lt;tbody&gt;         &lt;tr&gt;             &lt;th&gt;&lt;/th&gt; &lt;th&gt;GTX 680&lt;/th&gt; &lt;th&gt;GTX 580&lt;/th&gt;         &lt;/tr&gt;         &lt;tr&gt;             &lt;td&gt;NBodyGravityCS11&lt;/td&gt;             &lt;td&gt;675.10&lt;/td&gt;             &lt;td&gt;374.28&lt;/td&gt;         &lt;/tr&gt;         &lt;tr&gt;             &lt;td&gt;AdaptiveTessellationCS40&lt;/td&gt;             &lt;td&gt;1031.88&lt;/td&gt;             &lt;td&gt;938.46&lt;/td&gt;         &lt;/tr&gt;         &lt;tr&gt;             &lt;td&gt;HDRToneMappingCS11&lt;/td&gt;             &lt;td&gt;3308.63&lt;/td&gt;             &lt;td&gt;2815.89&lt;/td&gt;         &lt;/tr&gt;     &lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;GTX 680在三个例子中都得到了领先的地位，最明显的是NBodyGravityCS11，达到了1.8x的提升。我认为和这个例子的计算量大、但分支较少有关。一个SM包含那么多的SP，对于分支diverse的代价是很大的。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;第三轮&amp;nbsp;Tessellation&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Tessellation一直是NV的强项，这次GTX 680的tessellator再次有了提升。&lt;/p&gt;&lt;table border="1" cellpadding="0" cellspacing="0"&gt;     &lt;tbody&gt;         &lt;tr&gt;             &lt;th&gt;&lt;/th&gt; &lt;th&gt;GTX 680&lt;/th&gt; &lt;th&gt;GTX 580&lt;/th&gt;         &lt;/tr&gt;         &lt;tr&gt;             &lt;td&gt;DetailTessellation11&lt;/td&gt;             &lt;td&gt;1077.48&lt;/td&gt;             &lt;td&gt;983.20&lt;/td&gt;         &lt;/tr&gt;         &lt;tr&gt;             &lt;td&gt;PN-Triangles&lt;/td&gt;             &lt;td&gt;2481.89&lt;/td&gt;             &lt;td&gt;2376.34&lt;/td&gt;         &lt;/tr&gt;         &lt;tr&gt;             &lt;td&gt;SimpleBezier11&lt;/td&gt;             &lt;td&gt;4373.63&lt;/td&gt;             &lt;td&gt;3884.52&lt;/td&gt;         &lt;/tr&gt;         &lt;tr&gt;             &lt;td&gt;SubD11&lt;/td&gt;             &lt;td&gt;923.32&lt;/td&gt;             &lt;td&gt;578.62&lt;/td&gt;         &lt;/tr&gt;     &lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;也达到了全部领先的程度。最复杂的SubD11提升1.6x。&lt;/p&gt;&lt;p&gt;以上三个测试可以看到，GTX 680并没有传说中的GTX 580&amp;#215;3的性能，至少，在DX SDK sample的分辨率和复杂程度下没达到。但是可以看到的一个趋势是，对计算量和带宽要求越大的例子，GTX 680的提升就越大，所以其实在大部分时候它的能力是没有完全发挥出来的。分支的程度也比较影响GTX 680，所以应该在shader/kernel级别明智使用分支。另一个重要的事情在于驱动，对比2年前的测试，虽然GTX 580比GTX 480只是多了32个SP，但由于驱动的改进，性能却有非常明显的提升，部分例子甚至达到了3倍。目前GTX 680的驱动刚处于非常初级的状态，相信过一段时间成熟了才会达到GTX 680的最佳状态。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;额外测试&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;在测完DX SDK的例子之后，我与顺便测试了KlayGE的例子。这里选了两个比较有代表性的例子，分别是Deferred和Forward流水线。分辨率是1280&amp;#215;800，高于DX SDK sample的800&amp;#215;600。&lt;/p&gt;&lt;table border="1" cellpadding="0" cellspacing="0"&gt;     &lt;tbody&gt;         &lt;tr&gt;             &lt;th&gt;&lt;/th&gt; &lt;th&gt;GTX 680&lt;/th&gt; &lt;th&gt;GTX 580&lt;/th&gt;         &lt;/tr&gt;         &lt;tr&gt;             &lt;td&gt;Deferred rendering&lt;/td&gt;             &lt;td&gt;150.55&lt;/td&gt;             &lt;td&gt;139.84&lt;/td&gt;         &lt;/tr&gt;         &lt;tr&gt;             &lt;td&gt;Shadow cubemap&lt;/td&gt;             &lt;td&gt;267.38/330.78&lt;/td&gt;             &lt;td&gt;259.08/239.07&lt;/td&gt;         &lt;/tr&gt;     &lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;Deferred rendering的例子情况类似于前面的评测。比较有趣的是Shadow cubemap的例子。和《&lt;a title="不争气的geometry shader" href="http://www.klayge.org/2011/07/26/%e4%b8%8d%e4%ba%89%e6%b0%94%e7%9a%84geometry-shader/"&gt;不争气的geometry shader&lt;/a&gt;》 一样，这里分别测试了6 pass cubemap和1 pass cubemap。斜杠之前的FPS是6 pass的。在以前的显卡上，不管是NV还是AMD，通过geometry shader完成render to cubemap都比6 pass还慢。但在GTX 680上，GS终于翻身了，彻底打败6 pass的做法。从这个角度也可以看出GTX 680的硬件性能提升。&lt;/p&gt;&lt;p&gt;总的来说，GTX 680并没有官方宣传的&amp;#8220;恐怖&amp;#8221;性能。但凭借工艺的进步，在那个Die大小的情况下能达到这样的速度是很不容易的。期待下半年的旗舰GK110。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/gongminmin/aggbug/2464977.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/gongminmin/archive/2012/04/22/2464977.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/gongminmin/archive/2012/03/23/2414108.html</id><title type="text">FFT镜头效果解析</title><summary type="text">转载请注明出处为KlayGE游戏引擎，本文地址为http://www.klayge.org/2012/03/22/fft%e9%95%9c%e5%a4%b4%e6%95%88%e6%9e%9c%e8%a7%a3%e6%9e%90/3DMark11的whitepaper里突出了用FFT实现镜头效果的方法。这里指的镜头效果包括bloom和泛光等，一般在HDR的tone mapping之前做。传统镜头效果Bloom是最常见的效果。一般就用一个gaussian blur完成。但那样的结果缺乏层次感，只是亮的一片。在Halo等游戏中，用了较为复杂的bloom方式。它先把HDR image做多次downs</summary><published>2012-03-23T10:28:00Z</published><updated>2012-03-23T10:28:00Z</updated><author><name>龚敏敏</name><uri>http://www.cnblogs.com/gongminmin/</uri></author><link rel="alternate" href="http://www.cnblogs.com/gongminmin/archive/2012/03/23/2414108.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/gongminmin/archive/2012/03/23/2414108.html"/><content type="html">&lt;p&gt;&lt;strong&gt;&lt;span dir="ltr"&gt;转载请注明出处为&lt;a href="http://www.klayge.org"&gt;KlayGE游戏引擎&lt;/a&gt;，本文地址为&lt;a href="http://www.klayge.org/2012/03/22/fft%e9%95%9c%e5%a4%b4%e6%95%88%e6%9e%9c%e8%a7%a3%e6%9e%90/"&gt;http://www.klayge.org/2012/03/22/fft%e9%95%9c%e5%a4%b4%e6%95%88%e6%9e%9c%e8%a7%a3%e6%9e%90/&lt;/a&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.3dmark.com/wp-content/uploads/2010/12/3DMark11_Whitepaper.pdf" target="_blank"&gt;3DMark11的whitepaper&lt;/a&gt;里突出了用FFT实现镜头效果的方法。这里指的镜头效果包括bloom和泛光等，一般在HDR的tone mapping之前做。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;传统镜头效果&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Bloom是最常见的效果。一般就用一个gaussian blur完成。但那样的结果缺乏层次感，只是亮的一片。在Halo等游戏中，用了较为复杂的bloom方式。它先把HDR image做多次downsample，在每一次上都分别作gaussian blur，然后再以一定的权重混合起来，得到富有层次的bloom。&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.klayge.org/wp/wp-content/uploads/2012/03/bungie_bloom.jpg"&gt;&lt;/a&gt;&lt;/p&gt;&lt;div align="center"&gt;&lt;a href="http://www.klayge.org/wp/wp-content/uploads/2012/03/bungie_bloom.jpg"&gt;&lt;img size-full="" wp-image-1854"="" title="bungie_bloom" src="http://www.klayge.org/wp/wp-content/uploads/2012/03/bungie_bloom.jpg" alt="Bungie Bloom" height="375" width="600" /&gt;&lt;/a&gt;&lt;/div&gt;Bungie的Bloom方法，来自&lt;a href="http://www.bungie.net/images/Inside/publications/presentations/lighting_material.zip" target="_blank"&gt;Lighting and Material of HALO 3&lt;/a&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;对于bloom本身这样已经基本可以了，但如果要增加更多镜头眩光的效果，比如DX SDK里HDRLighting的Star Effect，就得再增加更多的pass。而且如果blur的kernel很大的话，速度也会有严重下降。比如在不少游戏里也开始使用类似Star Trek 11里面的横向镜头眩光，几乎需要一个全屏大小的kernel，对于实时应用来说是伤不起的。（J.J. Abrams在不少片子里都用了这种横向的lens flare）&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.klayge.org/wp/wp-content/uploads/2012/03/Mograph_lensflare.jpg"&gt;&lt;/a&gt;&lt;/p&gt;&lt;div align="center"&gt;&lt;a href="http://www.klayge.org/wp/wp-content/uploads/2012/03/Mograph_lensflare.jpg"&gt;&lt;img size-full="" wp-image-1856"="" title="Mograph_lensflare" src="http://www.klayge.org/wp/wp-content/uploads/2012/03/Mograph_lensflare.jpg" alt="Lens flare" height="338" width="600" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;FFT方法&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;其实所有这些镜头效果都是blur，也就是用一个kernel去卷积每一个像素。数学上有个卷积定理：&lt;/p&gt;&lt;p&gt;&lt;img src="http://www.forkosh.com/mathtex.cgi?%5Cmathcal%7BF%7D%28f%20%5Cstar%20g%29=%5Cmathcal%7BF%7D%20%28f%29%20%5Ccdot%20%5Cmathcal%7BF%7D%20%28g%29" style="float:top;" alt="" border="0px" /&gt;&lt;/p&gt;&lt;p&gt;即&lt;img src="http://www.forkosh.com/mathtex.cgi?f%20%5Cstar%20g=%20%5Cmathcal%7BF%7D%5E%7B-1%7D%5Cbig%5C%7B%5Cmathcal%7BF%7D%20%28f%29%20%5Ccdot%20%5Cmathcal%7BF%7D%20%28g%29%5Cbig%5C%7D" style="float:top;" alt="" border="0px" /&gt;&lt;/p&gt;&lt;p&gt;其中&lt;img src="http://www.forkosh.com/mathtex.cgi?%5Cstar" style="float:top;" alt="" border="0px" /&gt;表示卷积，&lt;img src="http://www.forkosh.com/mathtex.cgi?%5Cmathcal%7BF%7D" style="float:top;" alt="" border="0px" /&gt;表示傅里叶变换，&lt;img src="http://www.forkosh.com/mathtex.cgi?%5Cmathcal%7BF%7D%5E%7B-1%7D" style="float:top;" alt="" border="0px" /&gt;表示傅里叶逆变换。也就是说，&lt;strong&gt;函数卷积的傅里叶变换是函数傅里叶变换的乘积&lt;/strong&gt;。所以，所与那些镜头效果需要的卷积都可以在FFT之后的频域上用一次乘法完成。不管你要多少层bloom、多少个star、多大的kernel，&lt;strong&gt;全都在1 pass内解决&lt;/strong&gt;。&lt;/p&gt;&lt;p&gt;整个算法的框架非常简单：&lt;/p&gt;&lt;ol&gt;     &lt;li&gt;对输入图像做FFT&lt;/li&gt;     &lt;li&gt;把FFT过的kernel图像和1的结果做逐像素复数乘法&lt;/li&gt;     &lt;li&gt;逆FFT&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;这就完成了所有的镜头效果。举个实际例子：&lt;/p&gt;&lt;p&gt;输入图像（来自&lt;a title="Scene Player初始版本完成" href="http://www.klayge.org/2012/03/21/scene-player%e5%88%9d%e5%a7%8b%e7%89%88%e6%9c%ac%e5%ae%8c%e6%88%90/"&gt;前不久刚完成的Scene Player&lt;/a&gt;）&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.klayge.org/wp/wp-content/uploads/2012/03/input.jpg"&gt;&lt;/a&gt;&lt;/p&gt;&lt;div align="center"&gt;&lt;a href="http://www.klayge.org/wp/wp-content/uploads/2012/03/input.jpg"&gt;&lt;img size-large="" wp-image-1862"="" title="input" src="http://www.klayge.org/wp/wp-content/uploads/2012/03/input-1024x640.jpg" alt="Input image" height="375" width="600" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;在FFT之前需要downsample到512&amp;#215;512大小，并且只保留亮的部分（bright pass）：&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.klayge.org/wp/wp-content/uploads/2012/03/bright_pass.jpg"&gt;&lt;/a&gt;&lt;/p&gt;&lt;div align="center"&gt;&lt;a href="http://www.klayge.org/wp/wp-content/uploads/2012/03/bright_pass.jpg"&gt;&lt;img size-full="" wp-image-1868"="" title="bright_pass" src="http://www.klayge.org/wp/wp-content/uploads/2012/03/bright_pass.jpg" alt="Bright pass" height="512" width="512" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;FFT的结果，分别是实数部分和虚数部分：&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.klayge.org/wp/wp-content/uploads/2012/03/real.png"&gt;&lt;/a&gt;&lt;/p&gt;&lt;div align="center"&gt;&lt;a href="http://www.klayge.org/wp/wp-content/uploads/2012/03/real.png"&gt;&lt;img size-full="" wp-image-1866"="" title="real" src="http://www.klayge.org/wp/wp-content/uploads/2012/03/real.png" alt="Real part" height="512" width="512" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.klayge.org/wp/wp-content/uploads/2012/03/imag.png"&gt;&lt;/a&gt;&lt;/p&gt;&lt;div align="center"&gt;&lt;a href="http://www.klayge.org/wp/wp-content/uploads/2012/03/imag.png"&gt;&lt;img size-full="" wp-image-1867"="" title="imag" src="http://www.klayge.org/wp/wp-content/uploads/2012/03/imag.png" alt="Imagin part" height="512" width="512" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;kernel图像，在Paint.net里面随便画的&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.klayge.org/wp/wp-content/uploads/2012/03/kernel.jpg"&gt;&lt;/a&gt;&lt;/p&gt;&lt;div align="center"&gt;&lt;a href="http://www.klayge.org/wp/wp-content/uploads/2012/03/kernel.jpg"&gt;&lt;img size-full="" wp-image-1863"="" title="kernel" src="http://www.klayge.org/wp/wp-content/uploads/2012/03/kernel.jpg" alt="Kernel image" height="512" width="512" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;kernel也做FFT之后，把两者进行复数相乘，&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div align="center"&gt;&lt;img src="http://www.forkosh.com/mathtex.cgi?re=re_1%20%5Ccdot%20re_2-im_1%20%5Ccdot%20im_2" style="float:top;" alt="" border="0px" /&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div align="center"&gt;&lt;div&gt;&lt;p&gt;&lt;img src="http://www.forkosh.com/mathtex.cgi?im=re_1%20%5Ccdot%20im_2+re_2%20%5Ccdot%20im_1" style="float:top;" border="0px" alt="" /&gt;&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;/div&gt;&lt;p&gt;其中re和im分别表示实部和虚部。&lt;/p&gt;&lt;p&gt;逆FFT的结果&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.klayge.org/wp/wp-content/uploads/2012/03/restore.jpg"&gt;&lt;/a&gt;&lt;/p&gt;&lt;div align="center"&gt;&lt;a href="http://www.klayge.org/wp/wp-content/uploads/2012/03/restore.jpg"&gt;&lt;img size-large="" wp-image-1864"="" title="restore" src="http://www.klayge.org/wp/wp-content/uploads/2012/03/restore-1024x640.jpg" alt="Restore image" height="375" width="600" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;叠加回原图&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.klayge.org/wp/wp-content/uploads/2012/03/output.jpg"&gt;&lt;/a&gt;&lt;/p&gt;&lt;div align="center"&gt;&lt;a href="http://www.klayge.org/wp/wp-content/uploads/2012/03/output.jpg"&gt;&lt;img size-large="" wp-image-1865"="" title="output" src="http://www.klayge.org/wp/wp-content/uploads/2012/03/output-1024x640.jpg" alt="Output" height="375" width="600" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;唯一剩下的问题就是如何得到kernel的图像。目前我想到的方法是提供一个交互工具，由美术手工绘制，旁边显示最终结果。可以预定义一些pattern，在工具中迭加使用。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;未来&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;FFT镜头效果的算法已经探索完成。目前的实验里，FFT调用的是&lt;a href="http://www.fftw.org/" target="_blank"&gt;FFTW库&lt;/a&gt;，下一步将会在GPU上实现FFT（有PS的版本和CS的版本），这样就能把整条流水线在GPU上，替换掉现在HDR post process里的bloom部分。&lt;/p&gt;&lt;p&gt;FFT还可以用于其它跟卷积有关的操作中，以后我会探索用FFT完成DoF、Bokeh、Motion blur、SSAO等常用的效果。Again，仍是在一个pass内完成。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/gongminmin/aggbug/2414108.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/gongminmin/archive/2012/03/23/2414108.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/gongminmin/archive/2012/03/23/2414105.html</id><title type="text">Scene Player初始版本完成</title><summary type="text">转载请注明出处为KlayGE游戏引擎，本文地址为http://www.klayge.org/2012/03/21/scene-player%e5%88%9d%e5%a7%8b%e7%89%88%e6%9c%ac%e5%ae%8c%e6%88%90/这几天KlayGE更新变少，主要是在做ScenePlayer。正如其名，Scene Player的作用是把场景描述文件的内容“播放”出来。目前场景描述文件是手工写的，以后会用Scene Editor来生成。ScenePlayer初始版本在原有Deferred Rendering的框架上加入了脚本驱动的系统，可以完全通过Python脚本来控制灯、摄像机</summary><published>2012-03-23T10:27:00Z</published><updated>2012-03-23T10:27:00Z</updated><author><name>龚敏敏</name><uri>http://www.cnblogs.com/gongminmin/</uri></author><link rel="alternate" href="http://www.cnblogs.com/gongminmin/archive/2012/03/23/2414105.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/gongminmin/archive/2012/03/23/2414105.html"/><content type="html">&lt;p&gt;&lt;strong&gt;&lt;span dir="ltr"&gt;转载请注明出处为&lt;a href="http://www.klayge.org"&gt;KlayGE游戏引擎&lt;/a&gt;，本文地址为&lt;a href="http://www.klayge.org/2012/03/21/scene-player%e5%88%9d%e5%a7%8b%e7%89%88%e6%9c%ac%e5%ae%8c%e6%88%90/"&gt;http://www.klayge.org/2012/03/21/scene-player%e5%88%9d%e5%a7%8b%e7%89%88%e6%9c%ac%e5%ae%8c%e6%88%90/&lt;/a&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;这几天KlayGE更新变少，主要是在做ScenePlayer。正如其名，Scene Player的作用是把场景描述文件的内容&amp;#8220;播放&amp;#8221;出来。目前场景描述文件是手工写的，以后会用Scene Editor来生成。&lt;/p&gt;&lt;p&gt;ScenePlayer初始版本在原有Deferred Rendering的框架上加入了脚本驱动的系统，可以完全通过Python脚本来控制灯、摄像机、物体的运动。也顺便加入了projective texture的支持。现在已经有多个例子可以通过场景描述文件在ScenePlayer中执行了。&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.klayge.org/wp/wp-content/uploads/2012/03/ScenePlayer.jpg"&gt;&lt;img size-full="" wp-image-1850"="" title="ScenePlayer" src="http://www.klayge.org/wp/wp-content/uploads/2012/03/ScenePlayer.jpg" alt="ScenePlayer" width="600" height="388" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/gongminmin/aggbug/2414105.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/gongminmin/archive/2012/03/23/2414105.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/gongminmin/archive/2012/02/20/2359168.html</id><title type="text">kfx格式的复活</title><summary type="text">转载请注明出处为KlayGE游戏引擎，本文地址为http://www.klayge.org/2012/02/20/kfx%e6%a0%bc%e5%bc%8f%e7%9a%84%e5%a4%8d%e6%b4%bb/老用户一定记得，在KlayGE 3.9之前，用来表示effect的.fxml都需要通过一个python写成的编译器进行离线编译，生成.kfx格式才能给runtime使用。在 3.9里引入了rapidxml，可以直接在runtime读取xml文件，流程变短，开发效率提高了。但随着这两年shader越写越复杂，编译 shader所花的时间越来越多，在载入的时候每次都编译shader，一来浪</summary><published>2012-02-20T03:44:00Z</published><updated>2012-02-20T03:44:00Z</updated><author><name>龚敏敏</name><uri>http://www.cnblogs.com/gongminmin/</uri></author><link rel="alternate" href="http://www.cnblogs.com/gongminmin/archive/2012/02/20/2359168.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/gongminmin/archive/2012/02/20/2359168.html"/><content type="html">&lt;p&gt;&lt;strong&gt;&lt;span dir="ltr"&gt;转载请注明出处为&lt;a href="http://www.klayge.org"&gt;KlayGE游戏引擎&lt;/a&gt;，本文地址为&lt;a href="http://www.klayge.org/2012/02/20/kfx%e6%a0%bc%e5%bc%8f%e7%9a%84%e5%a4%8d%e6%b4%bb/"&gt;http://www.klayge.org/2012/02/20/kfx%e6%a0%bc%e5%bc%8f%e7%9a%84%e5%a4%8d%e6%b4%bb/&lt;/a&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;老用户一定记得，在KlayGE 3.9之前，用来表示effect的.fxml都需要通过一个python写成的编译器进行离线编译，生成.kfx格式才能给runtime使用。在 3.9里引入了rapidxml，可以直接在runtime读取xml文件，流程变短，开发效率提高了。但随着这两年shader越写越复杂，编译 shader所花的时间越来越多，在载入的时候每次都编译shader，一来浪费时间，二来浪费计算。&lt;/p&gt;&lt;p&gt;KlayGE的模型格式.meshml也有过这样的问题，后来通过一个JIT在载入的时候动态把xml的.meshml编译成二进制 的.model_bin，之后的载入速度就极大提高了。既不需要离线编译，也不用担心读取效率。因此，引入一个effect JIT也成了理所当然的事情。所以，事隔多年后，kfx格式原地满血复活。&lt;/p&gt;&lt;p&gt;原先的kfx目标是把effect的东西保存成二进制，以便runtime读取；现在的目标是减少时间和计算的浪费。因此，虽然扩展名仍是kfx， 要装的东西仍是二进制的effect，但文件格式和能力并没有也不需要和以前的兼容了。新的格式不光有原先的二进制effect部分，更是可以在同一个文 件中保存不同API编译后的shader。目前支持的有HLSL bytecode、GLSL、ESSL。不同的渲染插件可以选择自己能处理的格式读取。将来还将支持更多的二进制格式，尤其是OpenGL ES上的，以应对孱弱的OpenGL ES GLSL编译器。&lt;/p&gt;&lt;p&gt;顺便说说4.0上的.fxml_bin格式。因为Android上没有Cg，所以当时应急引入了.fxml_bin，把在PC上JIT好的ESSL 存在里面。这样Android上只要直接读取ESSL就可以了，不涉及Cg。但因为只是个应急方案，并没有仔细设计，每个fxml_bin只能保存一个 shader。以至于一个fxml可能编译生成许许多多不同的fxml_bin存在目录下。现在终于可以都删掉了。&lt;/p&gt;&lt;p&gt;现在比较一下用了新kfx后的载入速度吧。就选用&lt;a href="http://www.klayge.org/wiki/index.php/Samples#Deferred_Rendering"&gt;Deferred Rendering&lt;/a&gt;这个shader最多最复杂的例子。&lt;/p&gt;&lt;table border="0"&gt;     &lt;tbody&gt;         &lt;tr&gt;             &lt;td&gt;&lt;br /&gt;             &lt;/td&gt;             &lt;td&gt;使用kfx之前（秒）&lt;/td&gt;             &lt;td&gt;使用kfx之后（秒）&lt;/td&gt;             &lt;td&gt;加速（秒）&lt;/td&gt;         &lt;/tr&gt;         &lt;tr&gt;             &lt;td&gt;D3D11&lt;/td&gt;             &lt;td&gt;4.8&lt;/td&gt;             &lt;td&gt;2.6&lt;/td&gt;             &lt;td&gt;2.2&lt;/td&gt;         &lt;/tr&gt;         &lt;tr&gt;             &lt;td&gt;OpenGL&lt;/td&gt;             &lt;td&gt;6.0&lt;/td&gt;             &lt;td&gt;2.6&lt;/td&gt;             &lt;td&gt;3.4&lt;/td&gt;         &lt;/tr&gt;         &lt;tr&gt;             &lt;td&gt;OpenGL ES&lt;/td&gt;             &lt;td&gt;28.2&lt;/td&gt;             &lt;td&gt;25.3&lt;/td&gt;             &lt;td&gt;2.9&lt;/td&gt;         &lt;/tr&gt;     &lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;D3D11插件省去了组装HLSL、编译HLSL的时间，大约2.2秒。OpenGL的shader需要经历Cg-&amp;gt;传统GLSL-&amp;gt; 现代GLSL的流程，用了kfx之后这些都省掉，所以省下了最多的时间。OpenGL ES和OpenGL流程一样，但ESSL较简单，所以加速没那么明显。需要注意的是OpenGL ES还需要的25秒基本上花在载入纹理上了。因为OpenGL ES模拟器不支持DXT5、SRGB等，需要在载入的时候动态转换成ABGR8，相当慢。以后可能会发展出一个Platform compiler，针对不同平台把资源离线编译出最适合的格式，从根本上解决这个问题。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/gongminmin/aggbug/2359168.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/gongminmin/archive/2012/02/20/2359168.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/gongminmin/archive/2012/02/13/2349467.html</id><title type="text">OpenGL驱动的陷阱：ATI篇，再续</title><summary type="text">转载请注明出处为KlayGE游戏引擎，本文地址为http://www.klayge.org/2012/02/13/opengl%e9%a9%b1%e5%8a%a8%e7%9a%84%e9%99%b7%e9%98%b1%ef%bc%9aati%e7%af%87%ef%bc%8c%e5%86%8d%e7%bb%ad/AMD的OpenGL驱动问题很多，是个众所周知的事情。以前我也写过《OpenGL驱动的陷阱：ATI篇》和《OpenGL驱动的陷阱：ATI篇，后续》来阐述这个问题，当时最新的驱动是Catalyst 10.10。过了一年多的时间，AMD的驱动和KlayGE的代码都有了不少变化，情况又如何呢</summary><published>2012-02-13T07:04:00Z</published><updated>2012-02-13T07:04:00Z</updated><author><name>龚敏敏</name><uri>http://www.cnblogs.com/gongminmin/</uri></author><link rel="alternate" href="http://www.cnblogs.com/gongminmin/archive/2012/02/13/2349467.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/gongminmin/archive/2012/02/13/2349467.html"/><content type="html">&lt;p&gt;&lt;strong&gt;&lt;span dir="ltr"&gt;转载请注明出处为&lt;a href="http://www.klayge.org"&gt;KlayGE游戏引擎&lt;/a&gt;，本文地址为&lt;a href="http://www.klayge.org/2012/02/13/opengl%e9%a9%b1%e5%8a%a8%e7%9a%84%e9%99%b7%e9%98%b1%ef%bc%9aati%e7%af%87%ef%bc%8c%e5%86%8d%e7%bb%ad/"&gt;http://www.klayge.org/2012/02/13/opengl%e9%a9%b1%e5%8a%a8%e7%9a%84%e9%99%b7%e9%98%b1%ef%bc%9aati%e7%af%87%ef%bc%8c%e5%86%8d%e7%bb%ad/&lt;/a&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;AMD的OpenGL驱动问题很多，是个众所周知的事情。以前我也写过《&lt;a title="OpenGL驱动的陷阱：ATI篇" href="http://www.klayge.org/2010/11/01/opengl%e9%a9%b1%e5%8a%a8%e7%9a%84%e9%99%b7%e9%98%b1%ef%bc%9aati%e7%af%87/"&gt;OpenGL驱动的陷阱：ATI篇&lt;/a&gt;》和《&lt;a title="OpenGL驱动的陷阱：ATI篇，后续" href="http://www.klayge.org/2010/12/21/opengl%e9%a9%b1%e5%8a%a8%e7%9a%84%e9%99%b7%e9%98%b1%ef%bc%9aati%e7%af%87%ef%bc%8c%e5%90%8e%e7%bb%ad/"&gt;OpenGL驱动的陷阱：ATI篇，后续&lt;/a&gt;》来阐述这个问题，当时最新的驱动是Catalyst 10.10。过了一年多的时间，AMD的驱动和KlayGE的代码都有了不少变化，情况又如何呢？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;失败的例子&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;在去年的驱动上，发现的问题主要有三个（&lt;a href="http://www.klayge.org/trac/ticket/58" target="_blank"&gt;ticket #58&lt;/a&gt;）：&lt;/p&gt;&lt;ol&gt;     &lt;li&gt;Deferred Rendering和Global Illumination中，GI的效果只在第一帧出现。没找到原因。&lt;/li&gt;     &lt;li&gt;Detailed Surface和JudaTex Viewer中，纹理显示混乱。没找到原因。&lt;/li&gt;     &lt;li&gt;GPU Particle System和Particle editor中，粒子没有显示出来。GS编译失败。&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;更新到Catalyst 12.1后（也可能在11.12或者11.11就更新了，我没测试），问题1直接得到解决，问题3的GS也能编译成功，但仍没有粒子显示，并且在 validate shader的时候打印GS输出的component过多。于是我把GL_GEOMETRY_VERTICES_OUT_EXT强制设置成32后问题解 决。由于GLSL里面不能像HLSL，用[maxvertexcount(4)]这样的方式在shader里指定最大顶点输出个数，必须通过调用 glProgramParameteriEXT(glsl_program, GL_GEOMETRY_VERTICES_OUT_EXT, n)来设定。把n定在32，而不是1024这样的大数字之后GLSL program的link和validate都能顺利通过。当然，这个问题的最终解决方案还是应该在未来的&lt;a title="HLSL bytecode to GLSL编译器的第一步" href="http://www.klayge.org/2012/02/09/hlsl-bytecode-to-glsl%e7%bc%96%e8%af%91%e5%99%a8%e7%9a%84%e7%ac%ac%e4%b8%80%e6%ad%a5/" target="_blank"&gt;HLSL bytecode to GLSL编译器&lt;/a&gt;里完成。&lt;/p&gt;&lt;p&gt;对于问题2，我曾经花了很多时间都没找出原因。后来偶然发现AMD的驱动上返回的PS最大纹理单元只有16（虽然它的硬件至少支持32），而 Juda Texture用到了17个纹理单元。所以一改成根据最大纹理单元数自动调整Juda Texture的shader，这个问题就迎刃而解了。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;失败的函数&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;这几个函数是在原先的测试中发现过陷阱，这次再重新测试。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;glBlitFramebufferEXT&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;问题依旧。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;glClearBuffer*&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;已经正常了！&lt;/p&gt;&lt;p&gt;&lt;strong&gt;glBeginConditionalRender&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;本以为所有的例子终于再次都能跑的时候，Deferred Rendering和Post Processing又挂了，都是渲染几帧之后就驱动失去响应，自动重启GPU的大毛病。和&lt;a title="OpenGL驱动的陷阱：ATI篇" href="http://www.klayge.org/2010/11/01/opengl%e9%a9%b1%e5%8a%a8%e7%9a%84%e9%99%b7%e9%98%b1%ef%bc%9aati%e7%af%87/"&gt;前文&lt;/a&gt;提 到的症状类似，于是轻车熟路地把OGLConditionalRender::BeginConditionalRender和 EndConditionalRender注掉，问题解决。所以还是AMD驱动的那个老毛病，glBeginConditionalRender和 glEndConditionalRender必须配对调用，否则一定会失去响应。在去年的驱动上，这会直接死机，必须强制关机才行。现在好多了，只要等 几秒钟，让驱动重启即可。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;glCopyImageSubDataNV&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;这是个新问题。在Catalyst 12.1上，增加了GL_NV_copy_image这个扩展的支持（是的，NV的扩展，也许没多久就会改成EXT甚至ARB）。但测试发现其结果和用glBlitFramebufferEXT一样，显示混乱。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/gongminmin/aggbug/2349467.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/gongminmin/archive/2012/02/13/2349467.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry></feed>
