优化3D图形渲染通道负载

文章来源:CAD世界网

一般来说, 定位渲染通道瓶颈的方法就是改变渲染通道每个步骤的工作量, 如果吞吐量也改变了, 那个步骤就是瓶颈.。找到了瓶颈就要想办法消除瓶颈, 可以减少该步骤的工作量, 增加其他步骤的工作量。

   一般在光栅化之前的瓶颈称作”transform bound”, 三角形设置处理后的瓶颈称作”fill bound”定位瓶颈的办法:
  • 1.改变帧缓冲或者渲染目标(Render Target)的颜色深度(16 到 32 位), 如果帧速改变了, 那么瓶颈应该在帧缓冲(RenderTarget)的填充率上。

  • 2.否则试试改变贴图大小和贴图过滤设置, 如果帧速变了,那么瓶颈应该是在贴图这里。

  • 3.否则改变分辨率.如果帧速改变了, 那么改变一下pixel shader的指令数量, 如果帧速变了, 那么瓶颈应该就是pixel shader. 否则瓶颈就在光栅化过程中。

  • 4.否则, 改变顶点格式的大小, 如果帧速改变了, 那么瓶颈应该在显卡带宽上。

  • 5.如果以上都不是, 那么瓶颈就在CPU这一边。

  • 优化方法36条:

  • 1.尽量减少无用的顶点数据, 比如贴图坐标, 如果有Object使用2组有的使用1组, 那么不 要将他们放在一个vertex buffer中, 这样可以减少传输的数据量。

  • 2.使用多个streamsource, 比如SkinMesh渲染, 可以把顶点坐标和法线这些每一帧都要修改的数据放在一个动态VB中, 其它不需要修改的(如贴图坐标)放到一个静态VB中, 这样就减少了数据传输量。

  • 3.尽量使用16位的索引缓冲,避免32位的. 一方面浪费带宽, 一方面也不是所有的显卡都支持32位的索引缓冲。

  • 4.可以考虑使用vertex shader来计算静态VB中的数据.比如SkinMesh的顶点可以放到vectex shader中计算, 这样就可以避免每一帧都从AGP内存中向显存传送数据. 这样也可以使用静态VB了。

  • 5.坚决避免使用Draw**UP一族的函数来绘制多边形。

  • 6.在设计程序之前好好规划一下显卡内存的使用, 确保framebuffer, 贴图, 静态VB能够正好放入显卡的本地内存中。

  • 7.尽量使顶点格式大小是32字节的倍数.可以考虑使用压缩过的顶点格式然后用vertex shader去解. 或者留下冗余的部分, 使顶点大小刚好使32字节的倍数。

  • 8.顶点在顶点缓冲中的顺序尽量符合绘制的顺序, 考虑使用strips来代替list。

  • 9.如果可能尽量多的使用static vertex buffer代替dynamic vertex buffer。

  • 10.动态VB使用DISCARD参数来lock更新, 使用NOOVERWRITE来添加.尽量不要使用不带参数的lock调用(0)。

  • 11.尽量减少lock的次数, 有些东西并不一定非要每一帧都更新VB, 比如人物动画一般每秒钟更新30次VB基本上就够了。

  • 12.如果是因为需要绘制的顶点数据太多了可以考虑使用LOD, 但是现在的显卡的绘制能力都很强劲, 所以需要权衡一下LOD是否能够带来相应的好处, 如果过分的强化LOD很可能将瓶颈转移到CPU这边。

  • 13.避免过多的顶点计算,比如过多的光源, 过于复杂的光照计算(复杂的光照模型), 纹理自动生成的开启也会增加顶点的计算量. 如果贴图坐标变换矩阵不是单位矩阵, 也会造成顶点计算量的增加, 所以如果纹理变换已经结束, 记得要将纹理变换矩阵设为单位矩阵同时调整贴图坐标。

  • 14.避免Vertex shader指令数量太多或者分支过多, 尽量减少vertex shader的长度和复杂程度. 尽量使用swizzling代替mov。

  • 15.如果图象质量方面的计算(pixel shader)范围很大, 并且很复杂, 可以考虑试试全屏反走样。说不定更快。

  • 16.尽量按照front – back的顺序来绘制。

  • 17.在shader中判断Z值可以避免绘制不可见的象素, 但是nvidia建议简单的shader不要这么做.(Don't do this in a simple shader)。

  • 18.如果可能, 尽量使用vertex shader来代替pixel shader.将计算从逐象素变成逐顶点。

  • 19.尽量降低贴图的大小.过大的贴图可能造成贴图cache过载, 从而导致贴图cache命中降低.过大的贴图会导致显存过载, 这时候贴图是从系统内存中取的。

  • 20.只要可能就用16位色的贴图, 如环境贴图或者shadow map.它们用32位色的贴图实在是浪费。

  • 21.考虑使用DXT 贴图压缩。

  • 22.如果可能,使用简单的贴图过滤或者mip map, 除非必要否则尽量不要使用三线过滤和各项异性过滤. light map 和 环境贴图基本上都不需要使用它们。

  • 23.只有真正需要修改的贴图才使用Dynamic, 并且使用DISCRAD和WRITEONLY来lock。

  • 24.太多的帧缓冲读写可以考虑关闭Z-Writes如有些多pass的渲染中的后续pass或者粒子系统等半透明几何物体(如果可以)。

  • 25.可能的话尽量使用alpha test代替alpha blending。

  • 26.如果不需要stencil buffer就尽量使用16位的Z buffer。

  • 27.减小RenderTarget 贴图的大小, 如shadow map 环境贴图. 可能根本不需要那么大效果就很好。

  • 28.Stencil 和 Z buffer 尽量一起clear. 他们本来就是一块缓冲。

  • 29.尽量减少渲染状态的切换, 尽量一次画尽可能多的多边形。(根据显卡性能决定最多画多少, 不过一般再多也不会多到哪里去。 除非你根本不需要贴图和渲染状态的切换)。

  • 30.尽量使用shader来代替Fixed Pipeline。

  • 31.尽量使用shader来实现来取代Multipass渲染效果。

  • 32.尽量优先先建立重要的资源, 如Render target, shaders, 贴图, VB, IB等等.以免显存过载的时候它们被创建到系统内存中。

  • 33.坚决不要在渲染循环中调用创建资源。

  • 34.按照shader和贴图分组后再渲染.先按照shaders分组再按贴图。

  • 35.Color Stencil Z buffer尽量在一次Clear调用中清除。

  • 36.一个Vertex buffer 的大小在2M-4M之间最好。

你可能感兴趣的:(优化)