• 能不画就不画 // occlusion culling / LOD
  • 能不更新就不更新
  • 能简化就简化 // LOD
  • 能一次画的不要分多次画 // batching / instancing / indirect drawing
  • 相似的东西在一起画 // sorting
  • 能非同步的非同步
  • 能并行的并行
  • 能预计算的预计算
  • 能给GPU算的给GPU算
  • 时间经常可以用空间换
  • 多读书,演算法本身也可以优化
  • 再不行可以降解析度渲染再拉大
  • 实在不行了就砍效果砍功能


谢邀。

这个问题问得很大。真要写绝对够出一本书,甚至是一系列。

所以这里就精神论一下,只谈优化思路。

首先,渲染的最终目的是出图。从这个角度出发:

无论是多大解析度,像素数总是有限的。所谓出图,就是确定每个像素的颜色取值。

显然,渲染性能反比于为了确定一个像素的颜色所需要进行的平均工作量。因此,必须想办法减少渲染单一像素的开销:

  1. 首先渲染方程决定了计算的复杂度。从而会影响性能。在满足画面品质要求的情况下,使用尽可能简单的渲染方程,或者尽可能对方程当中相对固定的部分进行预计算,可以减少计算复杂度;
  2. 减少影响特定像素颜色的因素的个数,这是另外一个重要的点。比如,当场景当中有半透明物体的时候,对于其所覆盖的像素,我们不仅要计算半透明物体的颜色,还需要计算其后面的物体的颜色才能确定最终颜色。另外,对于带有强镜面反射性质的物体表面,我们还要考虑其所反射的物体的颜色才能确定其最终颜色。这些都是巨大的性能损耗;

除了单一像素渲染的开销之外,另外一个对性能有重大影响的方面就是渲染的并行度。理论上,如果一帧画面的所有像素都是同时并行渲染的,那么渲染时间应该只是由其中工作量最大的那个像素决定,而与画面的解析度无关。

但是事实上显然不是这样。这是因为无论是CPU、还是GPU、亦或是作为数据提供和存储的场地的内存,它们的带宽都不是无限的。所以组成一幅画面的数据只能够按照一定的大小一批一批地进入渲染管道,直至渲染完成。

因为CPU/GPU/内存的带宽资源都是有限且固定不变的,所以根据渲染数据流对三者带宽的消耗情况,会在不同的地方出现瓶颈。一般来说,CPU的带宽最小,所以诸如贴图等对数据带宽要求很高的数据对象,最好不要流过CPU。我们要将控制流和数据流分开,让CPU主要专注在控制流上,而让数据流尽量不要通过CPU。

GPU的带宽一般相较于CPU在10倍以上。且GPU的后端就是显示输出,所以我们必须让数据流经过GPU。但是,GPU当中流过的数据流其实也有好几种:

  1. 顶点和索引数据流(元数据流)
  2. 贴图和渲染对象(RT)数据流

而且,由于GPU当中的渲染管线是按照VS-PS这样的方式,后段的贴图和渲染对象数据流其实受制于前段的顶点与索引数据流,所以两者的比例关系就会对性能产生很大的影响。

由于当代GPGPU当中共用一套处理核心来处理这两种数据流,这就使得GPGPU在对顶点和索引数据流的处理能力与对贴图和渲染数据流的处理能力之间有著某种比例关系。比如,在采用Triangle-Strip方式来描述模型的时候,从第三个顶点起,每处理一个顶点就会生成一个三角面。而三角面会被Rasterlizer离散成为一定数量的像素,然后进行像素颜色的计算。

当三角面很大的时候,一个三角面会离散出很多个像素。这可能会使得贴图和渲染对象(RT)数据流流量猛增,但是反过来压迫顶点和索引数据流的处理,使其不能达到饱和处理能力;而顶点和索引数据流的处理受到压迫,最终又会使得GPU无法在短时间内攒齐足够的像素投入后端渲染,从而导致性能的低下;

而当三角面很小的时候,一个三角面可能只能离散出很少的几个像素。为了充分利用GPU和内存的处理带宽,GPU可能不得不等待更多的三角面的离散完成,凑齐足够的像素数才能进入后段的处理。这同样会导致性能的低下。

所以我们要控制好三角面的大小,也就是控制好顶点与像素的比例。对于较远处的模型要通过LOD等方式避免产生大量的小三角形。

贴图在内存上的排布同样十分重要。GPGPU虽然带宽很高,但是对内存的访问延迟也很大。所以当贴图没有被缓存在GPGPU的L1/L2缓存当中的时候,会引起相当显著的等待数据的情况。为了充分利用L1/L2缓存所提供的低延迟特性,我们应该安排好贴图的以下几个方面:

  1. 避免不必要的过大的贴图。因为大的贴图所需要的存储空间很大无法保持或者长期保持在L1/L2缓存当中;
  2. 尽量避免对贴图或者RT的随机访问。因为这会打乱L1/L2当中的数据有效性,导致频繁的L1/L2失效
  3. 采用方便GPU定址的方式重排贴图。比如采用Tile模式,而不是Linear模式
  4. 对贴图采用压缩,减少传输/存储带宽


Real-Time Rendering Resources


直接看《 real time rendering 4th 》中关于性能调优的章节。

ps 还有一本专门关于视频游戏优化的书籍,也可以参考下。《video game optimization》


1.尽量不去渲染看不到的对象,越早剔除越好

2.尽量减少渲染状态的变化,比如把使用相同材质或纹理的对象放在一起渲染

3.能用低精度不用高精度

4.尽量批量提交,减少call draw的调用次数

5.能开硬体加速就用硬体加速


谢邀

列举一下一些很基础的点吧,我平时遇到的问题。

在渲染过程中,不要动态创建新对象,尽量不要用复杂的容器进行搜索

尽可能的使用并行,如cpu的多线程或计算著色器

对三维物体进行处理,过于远的物体不必绘制出它每一个顶点,背部可以cull

尽量在VS中计算所需要的参数,而不是放在PS中。如果它能够在CPU计算好,并且不会再改变,考虑通过uniform传入。如果和顶点相关,考虑作为顶点数据传入,如骨骼信息

绘制时可以先计算在frustum内有哪些对象,它之外的对象不可见,所以不用绘制

使用一些数据结构来管理场景,如Bsp

使用高效的内存池来分配对象

使用simd指令来代替常规的矩阵向量运算,它会带来一定的性能提升

更多可以看看 @Milo Yip 的游戏引擎架构。

另外我这里也有自己写的一个玩具可供参考。

http://www.github.com/froser/gamemachine


谢邀。

如果3D Object比较多,可以采用GPU 并行计算进行渲染提高计算效率。

发布于 2018-12-24继续浏览内容知乎发现更大的世界打开Chrome继续BitDragonflyBitDragonflyOpenGL

很多想当然优化都是负优化..或者对于软绘制来说才算优化!

例如不渲染照相机后面.你就需要判断.讨巧点的引入各种树数据结构.但是你要知道这些都是占用cpu的.兴许不优化都喂不饱gpu呢..

不要提前优化才是王道!

至于优化方法上面已经都说了....


很多想当然优化都是负优化..或者对于软绘制来说才算优化!

例如不渲染照相机后面.你就需要判断.讨巧点的引入各种树数据结构.但是你要知道这些都是占用cpu的.兴许不优化都喂不饱gpu呢..

不要提前优化才是王道!

至于优化方法上面已经都说了....


shader的话,学习一下cuda,然后就会很了解shader优化了。


推荐阅读:
相关文章