3D场景优化
一) 有效的性能评测 
                         
  对于任何一个3D应用程序来说,追求场景画面真实感是一个无止尽的目标,其结果就是让我们的场景越来越复杂,模型更加精细,这必然给图形硬件带来极大的负荷以致于无法达到实时绘制帧率。因此,渲染优化是必不可少的。在渲染优化之前,我们需要对应用程序性能进行系统的评测,找出瓶颈,对症下药。对于3D应用程序来说,影响性能的十分多,同时不同的硬件配置条件下,瓶径也会有所不同。因此,对应用程序进行有效的性能评测,不仅需要对整个渲染管线原理有深入地了解,此外借助一些评测工具能让我们的工作事倍功半。
  我们知道渲染流水线的速度是由最慢的阶段决定首先,因此对一个3D应用程序进行评测,首先要分析影响渲染性能的瓶颈是在CPU端还是GPU端,由此来绝对我们优化的对象。由于目前的图形加速硬件都具有强大的,这个瓶径往往出现在CPU端,我们可以通过一些工具获得这个信息,如Nvidia的NVPerfHUD。在评测选项中,我们可以查看CPU和GPU繁忙度这项,当CPU繁忙度是100%时,GPU还不是时,我们知道性能的瓶颈在CPU端,我们必须CPU端的操作,同时尽量的“喂饱”GPU,把一些费事的计算移值到GPU上,例如硬件骨骼蒙皮。当GPU端是瓶颈时,说明GPU超荷负载,有可能是因为有过多的渲染填充,也就是多边形数量太多(当前强大的GPU使得这种情况并不多见。
    CPU上的瓶颈产生有两个方面,一是因为复杂AI计算或低效的代码,二是由于不好的渲染批处理或资源管理。对于第一种情况,我们可以利用VTurn这类的工具,把应用程序中所有函数调用时间从大到小的排列出来,我们就很容易知道问题所在。对第二种情况来说,同样利用NVPerfHUD,我们可以查看每帧的DP数目,看看批的数量是否过多(有一个具体的换算公式),查看纹理内存的数目,是否消耗了过多的显存。利用这些工具,我们基本上能够定位应用程序的瓶颈。在应用程序内部,编写一个内嵌的profiler功能,能更加便利的进行评测,此外利用Lua这样的脚本程序,让我们运行时调试,也能提高评测的效率。
(二) 静态场景优化
静态场景包括了地形、植被、建筑物等一般不改变位置的实体集合,对它的优化是场景优化中最重主要的内容。本文就静态场景优化的常见问题进行了探讨。
1 批的优化
    批是场景优化中的最重要的概念之一,它指的是一次渲染调用(DP),批的尺寸是这次渲染调用所能渲染的多边形数量。每个批的调用都会消耗一定的CPU时间,对于显卡来说,一个批里的多边形数量远达不到最大绘制数量。因此尽可能将更多的多边形放在一个批里渲染,以此来减少批的数目,最终降低CPU时间,是批的优化基本原则。然而事情往往不尽如人意,有些情况下原有的批会被打破,造成额外的开销,如纹理的改变或不同的矩阵状态。针对这些问题,我们可以采用一些方法来尽量避免它,已达到批尺寸的最大化。
(1)合并多个小纹理为一张大纹理     
    在某个场景中,地面上有十多种不同的植被,它们除了纹理不同外,渲染状态都是一样。我们就可以把它们的纹理打包成一个大纹理,再为每个植被模型指定UV,这样我们就可以用一个渲染调用来渲染所有的物体,批的数量就从十多个降为一个。这种方法比较适合对纹理精度要求不高,面数不会太多的物体。
(2)利用顶点shader 来统一不同矩阵的情况   
    即使场景中的所有物体材质都一样,如果它们的矩阵状态不同(特别是场景图管理的引擎),也会打碎原有的批。利用顶点shader技术可以避免这种情况,因为可以把要乘的变换矩阵通过常量寄存器传到shader程序中,这样统一了物体的矩阵状态,可以放在一个批里渲染。
2 渲染状态管理
    渲染状态是用来控制渲染器的渲染行为,在D3D中是setRenderState,通过改变渲染状态,我们可以设置纹理状态、深度写入等等。改变渲染状态对显卡来说,是个比较耗时的工作,因为显卡执行API必须严格按照渲染路径,当渲染状态变化时,显卡就必须执行浮点运算来改变渲染路径,因此给CPU和GPU带来时间消耗(CPU必须等待),渲染状态变化越大,所要进行的浮点运算越多。因此将渲染状态进行有效的管理,尽可能 减少其变化,对渲染性能影响巨大。(新六代的显卡Geforce8系列中将一些常见的状态参数集存储在显卡核心中,当渲染状态状态发生变化,可以直接读取保存的参数集,以消除不必要的开销)。绝大部分的3D引擎都会按照渲染状态对PASS进行分组渲染。
3 LOD
    LOD这个已经被人讨论烂掉的技术我就不多废话了,简单谈谈一些实际应用。地形的LOD我就不多说了,方法太多了,不过感觉目前情况下最实用的还是连锁分片的方法。对于模型LOD,自动减面的算法,如VDPM(渐近网格子)并不少见,但是效果都很一般。常规的做法还是让美工做低模进行替换,对于复杂场景来[来源:GameRes.com]说,模型LOD的效果还是比较明显的。材质LOD就需要一些技巧,例如可以将雾后的物体,包括地形等统一成一种材质,采用雾的颜色,这样就统一了渲染状态,至于是否要打包成一个DP就要看具体情况了(这个统一的材质最好把光照影响关掉,这也是比较费时的)。至于角色模型的LOD和普通模型LOD相类似,低模减少了顶点数,自然减少了蒙皮计算量。个人认为骨骼LOD不是特别的必要,看具体的情况。
4 场景管理的优化
    场景管理的优化包括场景分割,可见性剔除等,有很多的参考文章,这里就不多说了,谈些个人的心得。现在的室外场景一般采用quadtree或octree,当我们在性能评测时发现遍历树的过程比较慢时,有可能有两个原因。一是树的深度设置的不合理,我们可以很容易寻找到一个最佳的深度。另一个原因可能是我们为太多数量 众多,但体积很小的物体分配了结点,造成结点数量的冗余。解决方法是把这些小物体划分到他们所在的大的结点中。
    可见性剔除是最常见优化方法,我们常用的是视锥裁减,这也是非常有效的。视锥裁减也是许多优化方法,这里就不详说了。遮挡裁减也是经常被用到的方法,常见的有地平线裁减。但是在有些情况下,遮挡裁减的效果并不明显,如当CPU使用率已经是100%时,CPU端是瓶颈,这时进行遮挡裁减计算消耗CPU时间,效果就不明显。但是有些情况下利用一些预生成信息的方法,降低遮挡裁减计算的复杂度,提高遮挡裁减计算的效率,对场景性能会一定的改善。
3D场景优化的更多相关文章
- 点云深度学习的3D场景理解
		
转载请注明本文链接: https://www.cnblogs.com/Libo-Master/p/9759130.html PointNet: Deep Learning on Point Sets ...
 - 3D性能优化 | 说一说glTF文件压缩
		
引言 最近做T级互动,需要使用到3D模型.相信大家和我一样,在开始着手的时候,一定会有这么些问题: 1.如何选择3D模型的导出格式 2.如何对模型文件进行优化 3.在大流量的项目中兼容性怎么样 让我们 ...
 - OSG  3D场景渲染编程概述
		
OSG是Open Scene Graphic的缩写,是基于C++平台的使用OpenGL技术的开源3D场景开发. vs环境安装或者是在Ubuntu中环境的安装网上教程很多,都是大同小异的,认真操作容易成 ...
 - Python>>>创建一个简单的3D场景
		
首先安装PyOpengl pip install PyOpenGL PyOpenGL_accelerate
 - UI和3D场景同时都需要响应触摸事件
		
比如战斗场景,UI和3D场景同时都需要响应触摸事件,如果同时响应可能就会出现触摸UI的时候影响到了3D部分.为了解决这个问题在判断3D响应之前要先判断手指是否点击在UI上. 以前NGUI的时候都是自己 ...
 - Seen.js – 使用 SVG 或者 Canvas 渲染 3D 场景
		
Seen.js 渲染3D场景为 SVG 或者 HTML5 画布.Seen.js 包含对于 SVG 和 HTML5 Canvas 元素的图形功能的最简单的抽象.所有这个库的其它组件都是不用关心将要渲染的 ...
 - Ngui 五种点击事件实现方式及在3d场景中点透的情况
		
http://www.unity蛮牛.com/thread-22018-1-1.html ngui作为unity界面插件之一中,无疑是最好用,使用最多的了从自学unity到现在界面一直使用它 由于它的 ...
 - css3创建3D场景
		
浏览器本身是一个2维平面,对于3D的情况,实际上是增加了一个维度(深度),所以我们需要创建一个3D场景.这时浏览器不仅仅是一个平面了,更像是一个窗口,我们透过这个窗口去观察里面的三维世界.所谓的创建3 ...
 - [Unity3D]Unity3D游戏开发之在3D场景中选择物体并显示轮廓效果
		
大家好,我是秦元培,欢迎大家关注我的博客,我的博客地址是blog.csdn.net/qinyuanpei. 在<仙剑奇侠传>.<古剑奇谭>等游戏中,常常须要玩家在一个3D场景中 ...
 
随机推荐
- 拆分Sql列中内容的拆分
			
拆分Sql列中内容的拆分. /*按照符号分割字符串*/ create function [dbo].[m_split](@c varchar(2000),@split varchar(2)) retu ...
 - CSS中常用的字体单位:px、em、rem和%的区别
			
在刚接触CSS时,px用的比较多,也很好理解,可是用久了就会发现有些缺陷,特别是在做响应式开发的时候. 那这么多单位到底在什么时候用什么单位合适呢?今天就来探讨一下. 先大致解释一下这些单位的意思: ...
 - 利用 random 与 tertools 模块解决概率问题
			
Python 中的 random 与 tertools 模块可以得到伪随机数与排列.组合,下面利用这两个模块求解一些有趣的概率问题. 一.random 与 tertools 模块 random 模块常 ...
 - HDOJ 1466 计算直线的交点数
			
将n 条直线排成一个序列,直线2和直线1最多只有一个交点,直线3和直线1,2最多有两个交点,......,直线n 和其他n-1条直线最多有n-1个交点.由此得出n条直线互不平行且无三线共点的最多交点数 ...
 - C#&java重学笔记(函数)
			
C#部分 1.写在函数定义的()中的关键字: a.params关键字:用来满足函数的参数为数组时,而数组的长度不固定的情况.且该关键字只能用来修饰数组型参数.这样一修饰,就达成了类似JavaScri ...
 - 用VBS将PPT转为图片
			
'使用方法:把ppt文件拖放到该文件上. '机器上要安装Powerpoint程序 On Error Resume Next Set ArgObj = WScript.Arguments pptfile ...
 - 由浅入深了解Thrift之结果封装
			
一.thrift返回结果封装 Thrift文件添加版本号,方便对thrift的版本进行控制 服务与返回的数据类型分开定义 在项目中使用Thrift提供RPC服务时,很多情况下我们都会将返回的结果进行封 ...
 - [C++]不能被继承的类
			
前面讲到,派生类的构造函数和析构函数会自动调用基类的构造函数和析构函数,那么要让一个类不能被继承,那么就将它的构造函数和析构函数私有函数(派生类可以访问保护函数).那么怎样才能得到该类的实例呢? 这倒 ...
 - 项目中用到的SQL-总结
			
基本sql总结: Group by的理解:having子句,分组函数 Group by使用的限定: 1.出现在Select列表中的字段或者出现在order by后面的字段,如果不是包含在分组函数中,那 ...
 - shell如何自动输入密码
			
shell如何自动输入密码 http://linux.ctocio.com.cn/171/12162171.shtml