解决后有微信抢红包神器2017版!Unity3D 2017 ssao错误

他的最新文章
他的热门文章
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)请完成以下验证码
后使用快捷导航没有帐号?
请完成以下验证码
查看: 2957回复: 24
[unity插件]SSAO Pro1.6.1 高品质后处理(百度网盘)
元素币活跃度贡献值
unity3D区版主
土豪金2178
在线时间4758 小时
楼主-元素创造者
引擎插件类型
引擎插件类型:
马上注册成为元素者,获取海量元素资源,结识各路大神级人物
才可以下载或查看,没有帐号?
本帖最后由 orange_ 于
14:30 编辑
价格:150元素币 销售总额:4950元素币 购买人数:33尊敬的游客 ,本内容需要支付 150元素币 来下载,您可以 或者 。也可使用获取 同等点击次数 ,来轻松下载。资源包名: SSAO Pro1.6.1着色器/全屏幕及相机效果发布者:Thomas Hourdel价格:$25适用版本:要求Unity 4.5.0或更高版本。文件大小:4.73MB资源有问题.或者链接不存在.请私信.或者Q群小窗.看到立马解决
↓↓↓↓↓↓插件仅用于学习,禁止商用,为了维护您的个人权益,请支持正版↓↓↓↓↓↓Asset store 链接:22369
http://pan.baidu.com/s/1sl0IR9b
本帖被以下淘专辑推荐:
& |主题: 19, 订阅: 0
还没有设置签名!您可以在此展示你的链接,或者个人主页!
享有帖子相关版权3、其他单位或个人使用、转载或引用本文时必须同时征得该帖子作者和的同意4、所有内容仅供个人学习、研究之用,请勿用于商业用途5、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责6、如本帖侵犯到任何版权问题,请立即告知本站,本站将及时予与删除并致以最深的歉意7、管理员和版主有权不事先通知发贴者而删除本文', this.href);">论坛版权
元素币活跃度贡献值
活跃度兑换使者
在线时间4438 小时
沙发-元素射日者
{:1_141:}大神好厉害
元素币活跃度贡献值
在线时间6356 小时
板凳-元素追月者
想要成大触,天天上元素!
想要成大触,天天上元素!
元素币活跃度贡献值
元素皇, 积分 47970, 距离下一级还需 52030 积分
元素皇, 积分 47970, 距离下一级还需 52030 积分
在线时间667 小时
地板-元素观星者
想要成大触,天天上元素!
还没有设置签名!您可以在此展示你的链接,或者个人主页!
元素币活跃度贡献值
元素侠, 积分 693, 距离下一级还需 1307 积分
元素侠, 积分 693, 距离下一级还需 1307 积分
在线时间10 小时
想要成大触,天天上元素!
还没有设置签名!您可以在此展示你的链接,或者个人主页!
元素币活跃度贡献值
元素者, 积分 389, 距离下一级还需 11 积分
元素者, 积分 389, 距离下一级还需 11 积分
在线时间19 小时
还没有设置签名!您可以在此展示你的链接,或者个人主页!
元素币活跃度贡献值
元素侠, 积分 713, 距离下一级还需 1287 积分
元素侠, 积分 713, 距离下一级还需 1287 积分
在线时间5 小时
大神好厉害大神好厉害
还没有设置签名!您可以在此展示你的链接,或者个人主页!
元素币活跃度贡献值
元素王, 积分 29631, 距离下一级还需 369 积分
元素王, 积分 29631, 距离下一级还需 369 积分
在线时间685 小时
从业不识微元素,做遍项目也枉然
还没有设置签名!您可以在此展示你的链接,或者个人主页!
元素币活跃度贡献值
元素王, 积分 10053, 距离下一级还需 19947 积分
元素王, 积分 10053, 距离下一级还需 19947 积分
在线时间191 小时
天天逛元素,吃喝玩乐啥都有。{:1_146:}{:1_145:}
还没有设置签名!您可以在此展示你的链接,或者个人主页!
元素币活跃度贡献值
元素皇, 积分 69873, 距离下一级还需 30127 积分
元素皇, 积分 69873, 距离下一级还需 30127 积分
土豪金1756
在线时间1311 小时
不错~~~~~~~~~~~~~~~
还没有设置签名!您可以在此展示你的链接,或者个人主页!
元素币活跃度贡献值
元素侠, 积分 1328, 距离下一级还需 672 积分
元素侠, 积分 1328, 距离下一级还需 672 积分
在线时间24 小时
要免费的呀
还没有设置签名!您可以在此展示你的链接,或者个人主页!
元素币活跃度贡献值
元素皇, 积分 41427, 距离下一级还需 58573 积分
元素皇, 积分 41427, 距离下一级还需 58573 积分
土豪金1183
在线时间450 小时
这个应该是作为U3D中的摄像机特效组件来用的吧,效果不错,赞!
还没有设置签名!您可以在此展示你的链接,或者个人主页!
元素币活跃度贡献值
元素王, 积分 11646, 距离下一级还需 18354 积分
元素王, 积分 11646, 距离下一级还需 18354 积分
在线时间200 小时
元素帖子强,满满正能量!
还没有设置签名!您可以在此展示你的链接,或者个人主页!
元素币活跃度贡献值
元素王, 积分 8632, 距离下一级还需 21368 积分
元素王, 积分 8632, 距离下一级还需 21368 积分
在线时间126 小时
带你赚币带你飞,元素里面有正妹!
还没有设置签名!您可以在此展示你的链接,或者个人主页!
元素币活跃度贡献值
元素王, 积分 8703, 距离下一级还需 21297 积分
元素王, 积分 8703, 距离下一级还需 21297 积分
在线时间62 小时
资源甚好,发帖艰辛,且阅且珍惜!
还没有设置签名!您可以在此展示你的链接,或者个人主页!
元素币活跃度贡献值
元素魔, 积分 4095, 距离下一级还需 905 积分
元素魔, 积分 4095, 距离下一级还需 905 积分
在线时间89 小时
非常棒的东西,一直在找
还没有设置签名!您可以在此展示你的链接,或者个人主页!
元素币活跃度贡献值
元素魔, 积分 4686, 距离下一级还需 314 积分
元素魔, 积分 4686, 距离下一级还需 314 积分
在线时间97 小时
还没有设置签名!您可以在此展示你的链接,或者个人主页!
元素币活跃度贡献值
元素魔, 积分 4686, 距离下一级还需 314 积分
元素魔, 积分 4686, 距离下一级还需 314 积分
在线时间97 小时
还没有设置签名!您可以在此展示你的链接,或者个人主页!
元素币活跃度贡献值
元素魔, 积分 4686, 距离下一级还需 314 积分
元素魔, 积分 4686, 距离下一级还需 314 积分
在线时间97 小时
还没有设置签名!您可以在此展示你的链接,或者个人主页!
元素币活跃度贡献值
元素魔, 积分 4686, 距离下一级还需 314 积分
元素魔, 积分 4686, 距离下一级还需 314 积分
在线时间97 小时
大神好厉害
还没有设置签名!您可以在此展示你的链接,或者个人主页!
【拥有1000元素币】你就可以领取
【拥有3000元素币】其实也是很容易的事情
【1W元素币】的持有者,对于很多元素者来说,是一件值得骄傲的事情!
【5W元素币】的持有者是真的土豪!赶快用它做点什么吧!
达成成就【元素贤者】在元素知道
超过20次解决提问者的问题
达成成就【我是界王】在任意元素QQ群联盟,到达【界王】以上
限量版珍贵徽章,参与元素特定活动,元素T恤获取者
元素【鼓励师】职业标志,从此走上了不一样的巅峰之路。元素鼓励师,一句你就湿!
【元素晶石】
只有【元素大神】才能拥有,自由出入元素秘境之钥
【真爱之花】
情人节限量版,据说此花会带来桃花运!
平时一次性兑换土豪金超过3000,圣诞节期间一次性兑换土豪金超过500即可获取!
圣剑-【塞姆里亚】
【剑LV14,主题=5000】-异次元世界中,上古遗留的神秘物质所铸,只有神才有资格观赏,只有最强的神才有机会获取,圣剑之光有扭转乾坤,创造一切的【创世之力】
【拥有10W元素币】才可以获得,您已经富可敌国了,钱对你来说只是一个数字,没有任何别的意义!
圣杖-【安东尼达斯】
【MP20000】异次元世界的物品,有灵性的法杖,他一直默默的等待你的到来,并且会永远的守护你
【贡献1500】散发出某种奇特的光芒,使佩戴的人充满正能量
【贡献3000】女皇也有被男人欺骗的时候,女皇留下一滴眼泪,然后打造成光鲜亮丽的护身符送给了她的新男宠
【2000小时】的在线,感动12个星座所守护的12件黄金圣衣,用它来保卫你的女神(或者男神)吧!
大天使权杖
达成成就【百万扩散王】自己的博客,QQ空间等外网,发表5篇图文并茂的介绍微元素的原创文章
暂时未开放
达成成就【神的速度】最先成为元素神的30个人,或者土豪重金打造
达成成就【元素之神】升级成为元素神
达成成就【土豪是朋友】单次充值2000RMB或以上
24K金矿镐,往元素矿场投资10W元素币
升级到【星球·资源帝】
天降异火,大菠萝曾经火过,直接获取任何一个售价低于6000元素币的资源
【群组碎片】
创建元素QQ群,群主专属徽章,群人数200+
研发中...神秘粘稠液体
【不死鸟羽翼】
天地浩劫,涅槃重生。掌控六界一切资源
【精华100】能够穿破任何物质的神器,包括空间,时间和圣盾,不然岂不是矛盾
达成成就【神级追猎者】在元素悬赏中200次被评为最佳答案
达成成就【元素智者】在元素知道
超过5次解决提问者的问题
达成成就【元素先知】在元素知道
超过200次解决提问者的问题
达成成就【赏金统帅】发布过100次元素悬赏,并被人解决
达成成就【皇室后裔】最先成为元素皇的30个人,或者土豪逆袭获取
什么都别说了,到底上不上车?
守望者【EX】
守望者EX的强大武器
守望者【死神】
死神护法在暗中守护者他的主人,首发大于3
【MP50】这次的冒险才刚刚开始,和所有故事一样,你得先有一个属于自己的法杖!即使他的法力会在30天后消失
【50小时】的学习,已经证明了你自己,这件法袍是你的了,由于使用了简陋的材料,能穿一个月已经不错了!
元素推荐-友情提示 /1
每周一次的扩散大招带来更多元素币收益!
快速登录:扫一扫,访问微社区
后使用快捷导航没有帐号?
签到成功!您今天第{todayrank}个签到,签到排名竞争激烈,记得每天都来签到哦!已连续签到:{constant}天,累计签到:{days}天
当前位置: &
查看: 1320|回复: 1
屏幕空间环境光遮蔽(ssao)(screenspaceambientocclusion(ssao)) unity3d游戏开发手册
本帖为抢楼帖,欢迎抢楼!&
85835/10000排名<font color="#FF昨日变化2主题帖子积分
常驻蛮牛, 积分 5835, 距离下一级还需 4165 积分
常驻蛮牛, 积分 5835, 距离下一级还需 4165 积分
在线时间333 小时
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
才可以下载或查看,没有帐号?
屏幕空间环境光遮蔽 (ssao) (screen space ambient occlusion (ssao))屏幕空间环境光遮蔽 (ssao) (screen space ambient occlusion (ssao))图像效果实时逼近(作为图像后期处理效果)。它使相互接近的起皱、孔和表面变暗。在实际中,这类区域容易封闭或遮蔽 (occlude)环境光,因而会表现得更暗。对于实时环境光遮蔽的最新实现方法,请查看较新的屏幕空间环境光遮蔽 (screenspace ambient obscurance)效果。与其他一样,此效果仅适用于 unity 专业版,并且必须先安装才能使用。应用于场景的 ssao。未使用 ssao 的相同场景(用于比较)。请注意结构或草地符合地面条件的角落处的差异。属性属性:功能:半径 (radius)将引入环境光遮蔽的间隙的最大“半径”。采样计数 (sample count)环境光遮蔽采样次数。较高计数可提供较好质量,但是处理开销较高。遮蔽强度 (occlusion intensity)环境光遮蔽添加的黑暗程度。模糊 (blur)应用于变暗的模糊量。无模糊 (0) 速度快得多,但是变暗的区域具有噪波。缩小采样 (downsampling)执行计算时应采用的分辨率(例如,缩小采样值 2 将以屏幕分辨率的一半工作)。缩小采样可提高渲染速度,不过会牺牲质量。遮蔽衰减 (occlusion attenuation)遮蔽随距离衰减的速度。最小 z (min z)如果存在假象,请尝试增大此值。详细信息ssao 使用图像处理效果逼近环境光遮蔽。其成本完全取决于屏幕分辨率和 ssao 参数,而不是如同真实 ao 一样取决于场景复杂性。但是,逼近容易引入假象。例如,处于屏幕外部的对象不会参与遮蔽,遮蔽量取决于视角和相机位置。请注意,ssao 在处理时间方面的成本非常高,一般只应在高端显卡上使用。使用 ssao 会使 unity 渲染相机的深度+法线纹理,这会增加绘制调用数并产生 cpu 处理开销。但是,深度+法线纹理随后还可以用于其他效果(例如,视野深度 (depth of field))。生成纹理之后,便会在显卡上执行 ssao 效果的其余部分。硬件支持该效果需要带像素着色器 (3.0) 或 opengl es 2.0 的显卡。 此外,还需要深度纹理支持。 pc: 自 2004 年后的 nvidia 卡 (geforce 6)、自 2005 年后的 amd 卡 (radeon x1300)、自 2006 年后的 intel 卡 (gma x3000);移动: 带深度纹理支持的 opengl es 2.0;控制台: xbox 360、ps3。将自动禁用所有不被终端用户显卡支持的图像效果。uniunity 5 ambient occlusion
[]: 杨炎 捡了钱没交公 蛮牛币 降了 2
每日推荐:
138/50排名<font color="#FF昨日变化6主题帖子积分
注册看看, 积分 38, 距离下一级还需 12 积分
注册看看, 积分 38, 距离下一级还需 12 积分
在线时间17 小时
连接呢?楼主我看不到连接啊
每日推荐:&figure&&img src=&https://pic2.zhimg.com/v2-1ca84ef52638dbcbd3dc81bd45b4124c_b.jpg& data-rawwidth=&800& data-rawheight=&499& class=&origin_image zh-lightbox-thumb& width=&800& data-original=&https://pic2.zhimg.com/v2-1ca84ef52638dbcbd3dc81bd45b4124c_r.jpg&&&/figure&&p&原文链接:&a href=&https://link.zhihu.com/?target=http%3A//blog.uwa4d.com/archives/1614.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&你又可以大幅提升项目性能啦! - Blog&/a&&/p&&p&在之前的UWA性能检测与分析报告中,研发团队只能通过加载模块的整体耗时来查看该模块的性能瓶颈。在今天推出的新版本中,我们又前进了一大步:&strong&通过对资源管理进行定量分析,让大家看到每个资源的加载/卸载、每个GameObject的Instantiate/Destroy等具体耗时情况,从而让优化更显直观具象!&/strong&&a href=&www.uwa4d.com&&下面让我们一起来了解这些新特性吧!&/a&&/p&&h2&&strong&新功能特性详细说明&/strong&&/h2&&p&UWA本次新功能的特性主要为&strong&资源加载、GameObject Instantiate/Destroy、GameObject Active/Deactive、资源管理汇总四大功能模块&/strong&,下面小编将一一为大家说明。&/p&&h2&&strong&一、资源加载&/strong&&/h2&&p&重点分析项目通过Resources和AssetBundle的加载开销,说明如下:&/p&&p&&strong&1. AssetBundle资源加载&/strong&&/p&&p&在AssetBundle加载页面中,用户可以看到&strong&每个具体资源在项目检测过程中的具体CPU耗时&/strong&,同时我们在之前版本的基础上还明确了资源的&strong&加载母体AssetBundle信息&/strong&,这样可以帮助研发团队更加方便地定位和优化。&/p&&br&&figure&&img src=&https://pic1.zhimg.com/v2-a7b1057ace60080ae71edc63e902ec99_b.jpg& data-rawwidth=&1513& data-rawheight=&737& class=&origin_image zh-lightbox-thumb& width=&1513& data-original=&https://pic1.zhimg.com/v2-a7b1057ace60080ae71edc63e902ec99_r.jpg&&&/figure&&p&&strong&2. Resource加载&/strong&&br&支持用户在Resource加载页面中对耗时选项进行排序,其资源加载耗时的Top10即可一目了然。&br&&/p&&br&&figure&&img src=&https://pic2.zhimg.com/v2-1fc32af1bffff7fcf5aead9_b.jpg& data-rawwidth=&1513& data-rawheight=&831& class=&origin_image zh-lightbox-thumb& width=&1513& data-original=&https://pic2.zhimg.com/v2-1fc32af1bffff7fcf5aead9_r.jpg&&&/figure&&p&&strong&特别说明:&/strong&该新功能不仅可以让用户看到整体加载耗时和加载次数,同时还可以通过图表来显示具体每次加载的位置和耗时。如下图,资源文件cite_girl(图中右上角)是通过AssetBundle.Load来加载的,可以看到在项目检测过程中,该资源被频繁加载,且每次加载耗时主要集中在100~200ms之间。&br&&/p&&figure&&img src=&https://pic1.zhimg.com/v2-4f05595f2fefc7df6ab591bf9e73db14_b.jpg& data-rawwidth=&1514& data-rawheight=&533& class=&origin_image zh-lightbox-thumb& width=&1514& data-original=&https://pic1.zhimg.com/v2-4f05595f2fefc7df6ab591bf9e73db14_r.jpg&&&/figure&&p&下图中的SpeedRaceUI和UIscene_BJT是通过Resources.Load来加载的,可以看到在项目检测过程中,该资源被频繁加载,前者加载耗时主要集中在300ms左右,后者则主要集中在150ms左右。&br&&/p&&figure&&img src=&https://pic2.zhimg.com/v2-cef6678abc9e3ba_b.jpg& data-rawwidth=&1514& data-rawheight=&430& class=&origin_image zh-lightbox-thumb& width=&1514& data-original=&https://pic2.zhimg.com/v2-cef6678abc9e3ba_r.jpg&&&/figure&&br&&h2&&strong&二、GameObject Instantiate/Destroy&/strong&&/h2&&p&GameObject实例化和销毁耗时同样是研发团队非常希望掌握的一个关键点。在UWA今天更新的版本中,我们将会让研发团队&strong&明确任何一个GameObject在实例化和销毁时的CPU占用情况。大家不仅可以看到最为耗时的GameObject,同时还可以看到其每次触发的时间点。&/strong&&/p&&p&下图中的YX_DCJM_02,在游戏过程中被频繁实例化,且每次耗时均将近100ms,对此,研发团队完全可以考虑将其缓存,以避免后续0.1s的开销。&br&&/p&&figure&&img src=&https://pic1.zhimg.com/v2-6ee2eea48da748aa06cb77b1a008d99a_b.jpg& data-rawwidth=&1514& data-rawheight=&742& class=&origin_image zh-lightbox-thumb& width=&1514& data-original=&https://pic1.zhimg.com/v2-6ee2eea48da748aa06cb77b1a008d99a_r.jpg&&&/figure&&figure&&img src=&https://pic1.zhimg.com/v2-f4eccfb317b19e49e8d468d02b5f498c_b.jpg& data-rawwidth=&1514& data-rawheight=&531& class=&origin_image zh-lightbox-thumb& width=&1514& data-original=&https://pic1.zhimg.com/v2-f4eccfb317b19e49e8d468d02b5f498c_r.jpg&&&/figure&&br&&h2&&b&三、GameObject Active/Deactive&/b&&/h2&&p&GameObject Active/Deactive是研发团队非常容易忽视的,大多数团队认为状态的切换开销甚微,&strong&但正是由于这些“疏忽”导致了某些GameObject的Active/Deactive切换造成了大量的CPU耗时。&/strong&&/p&&p&下图则为游戏检测过程中,shadow的Active/Deactive的操作由于大量次数的累积,都是属于一个较高的耗时。&/p&&figure&&img src=&https://pic4.zhimg.com/v2-a3cbe40de0b7dfc2908c15e_b.jpg& data-rawwidth=&1514& data-rawheight=&737& class=&origin_image zh-lightbox-thumb& width=&1514& data-original=&https://pic4.zhimg.com/v2-a3cbe40de0b7dfc2908c15e_r.jpg&&&/figure&&figure&&img src=&https://pic3.zhimg.com/v2-107bf125c5dcd8_b.jpg& data-rawwidth=&1514& data-rawheight=&738& class=&origin_image zh-lightbox-thumb& width=&1514& data-original=&https://pic3.zhimg.com/v2-107bf125c5dcd8_r.jpg&&&/figure&&figure&&img src=&https://pic2.zhimg.com/v2-a7e6e859ce64d37b5b84bfa_b.jpg& data-rawwidth=&1514& data-rawheight=&433& class=&origin_image zh-lightbox-thumb& width=&1514& data-original=&https://pic2.zhimg.com/v2-a7e6e859ce64d37b5b84bfa_r.jpg&&&/figure&&p&&strong&通过这些功能中的数据,研发团队可以从以下几点进行针对性优化:&/strong&&/p&&ul&&li&针对加载频繁且耗时的资源,可以详细对其资源进行检测,查看是否有进一步优化的空间(比如纹理可检查其分辨率、格式等);&/li&&li&当研发团队明确了加载或实例化的瓶颈后,可针对具体资源、GameObject进行缓存,从而降低其CPU耗时。&/li&&/ul&&br&&h2&&strong&四、资源管理汇总&/strong&&/h2&&p&以UWA的优化经验来看,二八定律同样适用于项目的开发管理,即80%的性能问题集中在20%的资源中。为此,我们将&strong&需要注意的Top10的问题直接反馈给用户(新版本中的“资源管理汇总”界面)&/strong&,用户通过对这些重点对象的快速处理,能在短期时间内达到立竿见影的优化效果。目前主要包括:&/p&&p&&strong&(1)AssetBundle的加载次数Top10&/strong&&br&&/p&&figure&&img src=&https://pic1.zhimg.com/v2-bac14c8154fb8fcc7abc1_b.jpg& data-rawwidth=&2348& data-rawheight=&1383& class=&origin_image zh-lightbox-thumb& width=&2348& data-original=&https://pic1.zhimg.com/v2-bac14c8154fb8fcc7abc1_r.jpg&&&/figure&&p&&strong&(2)资源加载的次数和耗时Top10&/strong&&br&&/p&&figure&&img src=&https://pic3.zhimg.com/v2-be21236b9efdb0e9da17c74e7cb91d2d_b.jpg& data-rawwidth=&2366& data-rawheight=&1392& class=&origin_image zh-lightbox-thumb& width=&2366& data-original=&https://pic3.zhimg.com/v2-be21236b9efdb0e9da17c74e7cb91d2d_r.jpg&&&/figure&&p&&strong&(3)GameObject 实例化/销毁次数和耗时Top10&/strong&&br&&/p&&figure&&img src=&https://pic1.zhimg.com/v2-06a4cecabcebacf7_b.jpg& data-rawwidth=&2360& data-rawheight=&1389& class=&origin_image zh-lightbox-thumb& width=&2360& data-original=&https://pic1.zhimg.com/v2-06a4cecabcebacf7_r.jpg&&&/figure&&figure&&img src=&https://pic1.zhimg.com/v2-95f2c463dd1fe947da843dea73051eeb_b.jpg& data-rawwidth=&2362& data-rawheight=&1108& class=&origin_image zh-lightbox-thumb& width=&2362& data-original=&https://pic1.zhimg.com/v2-95f2c463dd1fe947da843dea73051eeb_r.jpg&&&/figure&&p&&strong&(4)GameObject Active/Deactive次数和耗时Top10&/strong&&br&&figure&&img src=&https://pic2.zhimg.com/v2-082f15d9d5b9090e8bdc2_b.jpg& data-rawwidth=&2363& data-rawheight=&1383& class=&origin_image zh-lightbox-thumb& width=&2363& data-original=&https://pic2.zhimg.com/v2-082f15d9d5b9090e8bdc2_r.jpg&&&/figure&&figure&&img src=&https://pic1.zhimg.com/v2-fa4bb0da8fedfa523d46daa392e4cda5_b.jpg& data-rawwidth=&2365& data-rawheight=&1098& class=&origin_image zh-lightbox-thumb& width=&2365& data-original=&https://pic1.zhimg.com/v2-fa4bb0da8fedfa523d46daa392e4cda5_r.jpg&&&/figure&&/p&&h2&&strong&五、其他更新&/strong&&/h2&&p&&strong&1. 截图功能更新&/strong&&/p&&p&在当前版本中,我们将项目的运行&strong&截图从原来的 5秒/张 提升为 1秒/张&/strong&,从而反映更详细全面的项目运行情况,助您更犀利地洞察每一个性能瓶颈,捕捉任何可以优化的机会!&br&&/p&&figure&&img src=&https://pic1.zhimg.com/v2-7c61f145cca5ff98d46dcd9bd2dfc03f_b.jpg& data-rawwidth=&1384& data-rawheight=&633& class=&origin_image zh-lightbox-thumb& width=&1384& data-original=&https://pic1.zhimg.com/v2-7c61f145cca5ff98d46dcd9bd2dfc03f_r.jpg&&&/figure&&p&&strong&2. iOS SDK 更新&/strong&&br&在当前版本中,我们大力完善了SDK的兼容,主要包括:&/p&&ul&&li&增加了截图功能对Metal的支持,不再限制打包项目时所选择的Graphic API&/li&&li&增加了对使用sLua和ToLua项目的支持&/li&&li&增加了对使用sLua,ToLua和uLua的项目的集成检测功能,用户可以一键检测SDK的集成是否成功&/li&&/ul&&h2&&strong&关于UWA&/strong&&/h2&&p&由侑虎科技开发的游戏/VR应用性能优化平台,目前提供 &a href=&https://link.zhihu.com/?target=https%3A//www.uwa4d.com/%23feature& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&1)性能检测与优化&/a& 和 &a href=&https://link.zhihu.com/?target=https%3A//www.uwa4d.com/%23assetbundle& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&2)资源检测与分析&/a& 两大工具。同时,我们也会万象更新地为大家开发更省心的功能,希望通过它们可以减少开发者反复测试定位问题的时间,从而将更多的精力集中在项目开发和解决问题中,能为大家项目研发省下的任何一分一秒,都是UWA团队的骄傲。&/p&&p&官网:&a href=&https://link.zhihu.com/?target=http%3A//www.uwa4d.com/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&www.uwa4d.com&/a&&br&官方技术博客:&a href=&https://link.zhihu.com/?target=http%3A//blog.uwa4d.com/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&blog.uwa4d.com&/a&&br&官方技术QQ群:(非水群,仅限技术交流)&/p&
原文链接:在之前的UWA性能检测与分析报告中,研发团队只能通过加载模块的整体耗时来查看该模块的性能瓶颈。在今天推出的新版本中,我们又前进了一大步:通过对资源管理进行定量分析,让大家看到每个资源的加载/卸载、…
&figure&&img src=&https://pic1.zhimg.com/v2-d9e7d6d51fa27f75b0e48436dee51b06_b.jpg& data-rawwidth=&692& data-rawheight=&240& class=&origin_image zh-lightbox-thumb& width=&692& data-original=&https://pic1.zhimg.com/v2-d9e7d6d51fa27f75b0e48436dee51b06_r.jpg&&&/figure&&p&制作动画时,往往会使用到“滚动的背景”。如下图所示,一开始图片只显示素材的一部分,然后素材不断滚动。该效果可以模拟横版或飞行游戏的背景图,或实现一些动画效果。尽管有很多方法实现该功能,这里提供一种基于shader的方法。&br&&/p&&figure&&img src=&https://pic1.zhimg.com/v2-d9e7d6d51fa27f75b0e48436dee51b06_b.jpg& data-rawwidth=&692& data-rawheight=&240& class=&origin_image zh-lightbox-thumb& width=&692& data-original=&https://pic1.zhimg.com/v2-d9e7d6d51fa27f75b0e48436dee51b06_r.jpg&&&/figure&&h2&1、编写Shader&/h2&&p&下面的着色器代码实现了“滚动的背景”功能。这里定义了3个变量,其中_MainTex代表背景贴图,_Width代表显示背景的百分比,_Distance代表当前滚动的距离。核心代码为“i.uv.x = frac(i.uv.x*_Width + _Distance);”,其中frac是取小数的函数,如1.23 取出来是 0.23,其功能是将i.uv.x 控制在0到1的范围,进而显示出来。&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&Shader &Lpy/ImageRoll&
Properties
_MainTex (&Main Tex&, 2D) = &white& {}
_Width (&Width&, float) = 0.5
_Distance (&Distance&, float) = 0
Tags {&Queue&=&Transparent& &IgnoreProjector&=&True& &RenderType&=&Transparent&}
Tags { &LightMode&=&ForwardBase& }
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
#pragma vertex vert
#pragma fragment frag
#include &UnityCG.cginc&
sampler2D _MainT
struct a2v
float4 vertex : POSITION;
float2 texcoord : TEXCOORD0;
struct v2f
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
v2f vert (a2v v)
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.uv.x = v.texcoord.x;
o.uv.y = v.texcoord.y;
fixed4 frag (v2f i) : SV_Target
i.uv.x = frac(i.uv.x*_Width + _Distance);
fixed4 c = tex2D(_MainTex, i.uv);
FallBack &Transparent/VertexLit&
&/code&&/pre&&/div&&h2&2、使用材质&/h2&&p&新建一个名为ImageRoll的材质,选择上述编写的shader。设置WIdth和Distance两个参数,如下图所示。只要调整Distance的值,即可看到滚动到不同位置的背景。&/p&&figure&&img src=&https://pic1.zhimg.com/v2-c71acc8f4a0dec5f2dc222_b.jpg& data-rawwidth=&692& data-rawheight=&230& class=&origin_image zh-lightbox-thumb& width=&692& data-original=&https://pic1.zhimg.com/v2-c71acc8f4a0dec5f2dc222_r.jpg&&&/figure&&figure&&img src=&https://pic4.zhimg.com/v2-6a2f2a9e218d2c1797beed_b.jpg& data-rawwidth=&379& data-rawheight=&243& class=&content_image& width=&379&&&/figure&&h2&3、代码中引用&/h2&&p&可以在代码中逐步增加distance 的值,造成背景不断向前滚动的效果。也可以在shader中使用Time相关的方法,实现同样的功能。&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&using UnityE
using System.C
using UnityEngine.UI;
public class ImageRoll : MonoBehaviour {
// Use this for initialization
void Start () {
mtl = image.
// Update is called once per frame
void Update () {
distance += 0.005f;
mtl.SetFloat(&_Distance&, distance);
&/code&&/pre&&/div&&p&将刚创建的材质应用于图片上,即可看到效果。如下图所示。&/p&&figure&&img src=&https://pic1.zhimg.com/v2-1cd0be1d8d2ba59e6b404c7b9ec1bba0_b.jpg& data-rawwidth=&693& data-rawheight=&295& class=&origin_image zh-lightbox-thumb& width=&693& data-original=&https://pic1.zhimg.com/v2-1cd0be1d8d2ba59e6b404c7b9ec1bba0_r.jpg&&&/figure&&br&&p&最后依然到了广告时间:笔者出版的一本Unity3D实战类书籍《Unity3D网络游戏实战》。该书通过一个完整的多人坦克对战实例,详细介绍网络游戏开发过程中涉及到的知识和技巧。书中还介绍了服务端框架、客户端网络模块、UI系统的架构等内容。相信透过本书,读者能够掌握Unity3D网络游戏开发的大部分知识,也能够从框架设计中了解商业游戏的设计思路,感谢大家支持。&/p&&figure&&img src=&https://pic1.zhimg.com/v2-9e629e8fa3c93fe1f563be632d3a1ff2_b.jpg& data-rawwidth=&692& data-rawheight=&692& class=&origin_image zh-lightbox-thumb& width=&692& data-original=&https://pic1.zhimg.com/v2-9e629e8fa3c93fe1f563be632d3a1ff2_r.jpg&&&/figure&
制作动画时,往往会使用到“滚动的背景”。如下图所示,一开始图片只显示素材的一部分,然后素材不断滚动。该效果可以模拟横版或飞行游戏的背景图,或实现一些动画效果。尽管有很多方法实现该功能,这里提供一种基于shader的方法。 1、编写Shader下面的着色…
&figure&&img src=&https://pic1.zhimg.com/v2-ea72b4cf63bcf_b.jpg& data-rawwidth=&1010& data-rawheight=&677& class=&origin_image zh-lightbox-thumb& width=&1010& data-original=&https://pic1.zhimg.com/v2-ea72b4cf63bcf_r.jpg&&&/figure&3D角色头顶会显示文字、图标、血条等,它会跟随角色移动,始终朝向相机,可能还有定制的缩放,一般情况下会考虑用UGUI来做,但完成后发现这样做的效率很低,而且遮挡正确性也保证不了。&p&效率低因为:&/p&&p&1,渲染上每块文字、图片都要用一次drawcall,图片文字又可能是交替出现的没法利用dynamic batching,UGUI的渲染顺序是hierachy从上到下,基本上必然交替出现。一个角色头顶UI就可能要1至5+个drawcall,比角色自身的还多。&/p&&p&2,UGUI的元素都要放到canvas节点下,同步位置、朝向、缩放是很大的消耗,同时会触发canvas重新刷新UI的vertex buffer,虽然是在其他线程上刷新的,但仍然很慢。如果每个头顶UI都配一个canvas挂载角色节点下,实测发现性能更差。下图是100个角色头顶有图标和名字的profiling,可以看到同步pose比整个游戏的渲染还高&/p&&figure&&img src=&https://pic4.zhimg.com/v2-74c22d74a20cfa96c6c528_b.jpg& data-rawwidth=&792& data-rawheight=&327& class=&origin_image zh-lightbox-thumb& width=&792& data-original=&https://pic4.zhimg.com/v2-74c22d74a20cfa96c6c528_r.jpg&&&/figure&&p&遮挡不正确因为:头顶UI属于透明物体,需要从远到近渲染,但是UGUI是根据Hierachy从上到下的,没法根据远近排序,这就会造成远处角色的头顶UI挡住自己角色的,看着别扭,尤其在自由视角的游戏中。&br&&/p&&p&想要效率高必须得在一个drawcall里渲染图文,且能用到dynamic batching,dynamic batching是在渲染线程上进行的还能省主线程时间。不用UI而是当作一般3D物体渲染就能用到引擎的透明排序正确遮挡。&/p&&p&Unity自带的TextMesh可以做到遮挡正确,但是没法同时渲染图文,也没代码可改,所以pass。&/p&&p&Asset Store上找下插件&/p&&p&TextMeshPro是很强大的插件,用SDF(signed distance field有向距离场)的方式使放大的文字锐利很多,但是不支持动态字体,只能是预先生成的bitmap里固定的字,无法满足常用汉字之外的显示,又pass。以后可以说下SDF渲染文字的原理。&/p&&p&SuperTextMesh:能渲染动态文字,富文本支持图文混排,缺点是支持atlas但很弱,资源管理、解析效率内存占用都算不上优秀。好在有源码可以改,就选这个了。&/p&&br&&br&&p&&b&一个drawcall同时渲染图文的方式就是用混合,一个材质带文字和atlas两张贴图,用3套uv进行混合,uv1是文字的,uv2是图片的,uv3表示混合权重,显示文字的quad文字权重为1图片为0,显示图片的quad文字权重为0图片权重为1,sample两张图混合一下就行了。&/b&&/p&&p&性能比之前好很多,下面是2001个带图文的SuperTextMesh,2000个在时刻改变位置。合批到了4个drawcall,更新pose的脚本消耗有数量级的降低。&/p&&figure&&img src=&https://pic1.zhimg.com/v2-f780b0ae7b9bb2b8734820_b.jpg& data-rawwidth=&788& data-rawheight=&821& class=&origin_image zh-lightbox-thumb& width=&788& data-original=&https://pic1.zhimg.com/v2-f780b0ae7b9bb2b8734820_r.jpg&&&/figure&&figure&&img src=&https://pic2.zhimg.com/v2-ad8d8c3b6a36f82d4aa5577_b.jpg& data-rawwidth=&824& data-rawheight=&168& class=&origin_image zh-lightbox-thumb& width=&824& data-original=&https://pic2.zhimg.com/v2-ad8d8c3b6a36f82d4aa5577_r.jpg&&&/figure&&figure&&img src=&https://pic2.zhimg.com/v2-fc74f00420fdde8f54707e_b.jpg& data-rawwidth=&775& data-rawheight=&249& class=&origin_image zh-lightbox-thumb& width=&775& data-original=&https://pic2.zhimg.com/v2-fc74f00420fdde8f54707e_r.jpg&&&/figure&&p&&figure&&img src=&https://pic7.zhimg.com/v2-cb9bc96ebbb859f1f94521d_b.jpg& data-rawwidth=&697& data-rawheight=&255& class=&origin_image zh-lightbox-thumb& width=&697& data-original=&https://pic7.zhimg.com/v2-cb9bc96ebbb859f1f94521d_r.jpg&&&/figure&&br&策划想要的图文基本都能搞定。国内挺多游戏在优化的时候都会发现是UI的瓶颈,UWA的专家们也说见怪不怪了:D&/p&&p&--------------------------------------------------------------&/p&&p&最后附带招聘贴&/p&&p&北京上市游戏公司招聘客户端程序员,手机MMO项目,负责功能逻辑、战斗逻辑,渲染、工具、底层框架其中的一至多项。&/p&&p&要求编程、数据结构、操作系统方面有扎实的基础,聪明好学仔细认真,擅长团队协作,沟通顺畅对事不对人,有相关项目经验或图形学、编辑器开发等特长尤佳。&/p&&p&公司待遇福利不错,项目组有很多高手,公司也有技术积累,有意者站内信联系。&/p&&p&本人邮箱: yesbaba艾特qq点坑&/p&
3D角色头顶会显示文字、图标、血条等,它会跟随角色移动,始终朝向相机,可能还有定制的缩放,一般情况下会考虑用UGUI来做,但完成后发现这样做的效率很低,而且遮挡正确性也保证不了。效率低因为:1,渲染上每块文字、图片都要用一次drawcall,图片文字又…
&figure&&img src=&https://pic3.zhimg.com/v2-db9e0abad553252ebb6db3c_b.jpg& data-rawwidth=&640& data-rawheight=&426& class=&origin_image zh-lightbox-thumb& width=&640& data-original=&https://pic3.zhimg.com/v2-db9e0abad553252ebb6db3c_r.jpg&&&/figure&&h2&&b&&u&前言&/u&&/b&&/h2&&p&&b&什么是我认为的“状态机”?&/b&&/p&&p&首先统一下“状态机”这个概念,状态机包括两个主要部分,一是控制切换状态的中心类;二是各种被切换状态,如移动状态,里面不仅包括人物移动所需播放的动画,还要包括控制人物实际移动的代码。&/p&&p&&b&为什么要把代码抽象封装?&/b&&/p&&p&身为一个(未来)优秀的工程师,需要化繁为简的能力,当看到我的人物类(具体控制人物行走、释放技能等功能的类)因为没有封装而充斥着各种变量各种方法时,我觉得很有必要停下来,好好整理下这个类,这样后面就能干净利落地添加新功能啦~&/p&&h2&&b&&u&正文&/u&&/b&&/h2&&p&先上代码&/p&&div class=&highlight&&&pre&&code class=&language-csharp&&&span&&/span&&span class=&k&&using&/span& &span class=&nn&&UnityEngine&/span&&span class=&p&&;&/span&
&span class=&k&&using&/span& &span class=&nn&&System&/span&&span class=&p&&;&/span&
&span class=&na&&[RequireComponent(typeof(Rigidbody))]&/span&
&span class=&k&&public&/span& &span class=&k&&class&/span& &span class=&nc&&Character&/span& &span class=&p&&:&/span& &span class=&n&&MonoBehaviour&/span&
&span class=&p&&{&/span&
&span class=&k&&private&/span& &span class=&n&&CharacterStateMachine&/span& &span class=&n&&stateMachine&/span&&span class=&p&&;&/span&
&span class=&k&&private&/span& &span class=&kt&&bool&/span& &span class=&n&&onceActionBegain&/span& &span class=&p&&=&/span& &span class=&k&&false&/span&&span class=&p&&;&/span&
&span class=&k&&private&/span& &span class=&kt&&bool&/span& &span class=&n&&_isLive&/span& &span class=&p&&=&/span& &span class=&k&&true&/span&&span class=&p&&;&/span&
&span class=&k&&public&/span& &span class=&kt&&bool&/span& &span class=&n&&isLive&/span&
&span class=&p&&{&/span&
&span class=&k&&get&/span& &span class=&p&&{&/span& &span class=&k&&return&/span& &span class=&n&&_isLive&/span&&span class=&p&&;&/span& &span class=&p&&}&/span&
&span class=&k&&set&/span&
&span class=&p&&{&/span&
&span class=&n&&_isLive&/span& &span class=&p&&=&/span& &span class=&k&&value&/span&&span class=&p&&;&/span&
&span class=&n&&stateMachine&/span&&span class=&p&&.&/span&&span class=&n&&stateParams&/span&&span class=&p&&.&/span&&span class=&n&&isLive&/span& &span class=&p&&=&/span& &span class=&n&&_isLive&/span&&span class=&p&&;&/span&
&span class=&p&&}&/span&
&span class=&p&&}&/span&
&span class=&k&&private&/span& &span class=&kt&&int&/span& &span class=&n&&_stayState&/span& &span class=&p&&=&/span& &span class=&m&&0&/span&&span class=&p&&;&/span&
&span class=&k&&public&/span& &span class=&kt&&int&/span& &span class=&n&&stayState&/span&
&span class=&p&&{&/span&
&span class=&k&&get&/span& &span class=&p&&{&/span& &span class=&k&&return&/span& &span class=&n&&_stayState&/span&&span class=&p&&;&/span& &span class=&p&&}&/span&
&span class=&k&&set&/span&
&span class=&p&&{&/span&
&span class=&n&&_stayState&/span& &span class=&p&&=&/span& &span class=&k&&value&/span&&span class=&p&&;&/span&
&span class=&n&&stateMachine&/span&&span class=&p&&.&/span&&span class=&n&&stateParams&/span&&span class=&p&&.&/span&&span class=&n&&stayState&/span& &span class=&p&&=&/span& &span class=&n&&_stayState&/span&&span class=&p&&;&/span&
&span class=&p&&}&/span&
&span class=&p&&}&/span&
&span class=&k&&private&/span& &span class=&kt&&int&/span& &span class=&n&&_onceActionType&/span& &span class=&p&&=&/span& &span class=&m&&1&/span&&span class=&p&&;&/span&
&span class=&k&&public&/span& &span class=&kt&&int&/span& &span class=&n&&onceActionType&/span&
&span class=&p&&{&/span&
&span class=&k&&get&/span& &span class=&p&&{&/span& &span class=&k&&return&/span& &span class=&n&&_onceActionType&/span&&span class=&p&&;&/span& &span class=&p&&}&/span&
&span class=&k&&set&/span&
&span class=&p&&{&/span&
&span class=&n&&_onceActionType&/span& &span class=&p&&=&/span& &span class=&k&&value&/span&&span class=&p&&;&/span&
&span class=&n&&stateMachine&/span&&span class=&p&&.&/span&&span class=&n&&stateParams&/span&&span class=&p&&.&/span&&span class=&n&&onceActionType&/span& &span class=&p&&=&/span& &span class=&n&&_onceActionType&/span&&span class=&p&&;&/span&
&span class=&p&&}&/span&
&span class=&p&&}&/span&
&span class=&k&&private&/span& &span class=&kt&&float&/span& &span class=&n&&_speed&/span& &span class=&p&&=&/span& &span class=&m&&0.0f&/span&&span class=&p&&;&/span&
&span class=&k&&public&/span& &span class=&kt&&float&/span& &span class=&n&&speed&/span&
&span class=&p&&{&/span&
&span class=&k&&get&/span& &span class=&p&&{&/span& &span class=&k&&return&/span& &span class=&n&&_speed&/span&&span class=&p&&;&/span& &span class=&p&&}&/span&
&span class=&k&&set&/span&
&span class=&p&&{&/span&
&span class=&n&&_speed&/span& &span class=&p&&=&/span& &span class=&k&&value&/span&&span class=&p&&;&/span&
&span class=&n&&stateMachine&/span&&span class=&p&&.&/span&&span class=&n&&stateParams&/span&&span class=&p&&.&/span&&span class=&n&&speed&/span& &span class=&p&&=&/span& &span class=&n&&_speed&/span&&span class=&p&&;&/span&
&span class=&p&&}&/span&
&span class=&p&&}&/span&
&span class=&k&&void&/span& &span class=&nf&&Awake&/span&&span class=&p&&()&/span&
&span class=&p&&{&/span&
&span class=&n&&stateMachine&/span& &span class=&p&&=&/span& &span class=&n&&GetComponent&/span&&span class=&p&&&&/span&&span class=&n&&CharacterStateMachine&/span&&span class=&p&&&();&/span&
&span class=&n&&NotificationCenter&/span&&span class=&p&&.&/span&&span class=&n&&DefaultCenter&/span&&span class=&p&&.&/span&&span class=&n&&AddObserver&/span&&span class=&p&&(&/span&&span class=&k&&this&/span&&span class=&p&&,&/span& &span class=&n&&MainSceneEvent&/span&&span class=&p&&.&/span&&span class=&n&&TriggerSkill&/span&&span class=&p&&);&/span&
&span class=&n&&NotificationCenter&/span&&span class=&p&&.&/span&&span class=&n&&DefaultCenter&/span&&span class=&p&&.&/span&&span class=&n&&AddObserver&/span&&span class=&p&&(&/span&&span class=&k&&this&/span&&span class=&p&&,&/span& &span class=&n&&MainSceneEvent&/span&&span class=&p&&.&/span&&span class=&n&&CharacterLive&/span&&span class=&p&&);&/span&
&span class=&n&&NotificationCenter&/span&&span class=&p&&.&/span&&span class=&n&&DefaultCenter&/span&&span class=&p&&.&/span&&span class=&n&&AddObserver&/span&&span class=&p&&(&/span&&span class=&k&&this&/span&&span class=&p&&,&/span& &span class=&n&&StateMachineEvent&/span&&span class=&p&&.&/span&&span class=&n&&OnceActionChange&/span&&span class=&p&&);&/span&
&span class=&p&&}&/span&
&span class=&k&&public&/span& &span class=&k&&void&/span& &span class=&nf&&Move&/span&&span class=&p&&(&/span&&span class=&kt&&float&/span& &span class=&n&&h&/span&&span class=&p&&,&/span& &span class=&kt&&float&/span& &span class=&n&&v&/span&&span class=&p&&)&/span&
&span class=&p&&{&/span&
&span class=&c1&&//释放技能和移动是冲突的&/span&
&span class=&k&&if&/span& &span class=&p&&(&/span&&span class=&n&&onceActionBegain&/span&&span class=&p&&)&/span&
&span class=&p&&{&/span&
&span class=&n&&stateMachine&/span&&span class=&p&&.&/span&&span class=&n&&stateParams&/span&&span class=&p&&.&/span&&span class=&n&&speed&/span& &span class=&p&&=&/span& &span class=&m&&0&/span&&span class=&p&&;&/span&
&span class=&n&&stateMachine&/span&&span class=&p&&.&/span&&span class=&n&&stateParams&/span&&span class=&p&&.&/span&&span class=&n&&moveVelocity&/span& &span class=&p&&=&/span& &span class=&n&&Vector3&/span&&span class=&p&&.&/span&&span class=&n&&zero&/span&&span class=&p&&;&/span&
&span class=&n&&stateMachine&/span&&span class=&p&&.&/span&&span class=&n&&stateParams&/span&&span class=&p&&.&/span&&span class=&n&&stayState&/span& &span class=&p&&=&/span& &span class=&n&&Convert&/span&&span class=&p&&.&/span&&span class=&n&&ToInt16&/span&&span class=&p&&(&/span&&span class=&n&&CharacterStateMachine&/span&&span class=&p&&.&/span&&span class=&n&&StayStateType&/span&&span class=&p&&.&/span&&span class=&n&&Idle&/span&&span class=&p&&);&/span&
&span class=&c1&&//stateMachine.stateParams.notMove =&/span&
&span class=&p&&}&/span&
&span class=&k&&else&/span&
&span class=&p&&{&/span&
&span class=&kt&&float&/span& &span class=&n&&tmpH&/span& &span class=&p&&=&/span& &span class=&n&&Mathf&/span&&span class=&p&&.&/span&&span class=&n&&Abs&/span&&span class=&p&&(&/span&&span class=&n&&h&/span&&span class=&p&&);&/span&
&span class=&kt&&float&/span& &span class=&n&&tmpV&/span& &span class=&p&&=&/span& &span class=&n&&Mathf&/span&&span class=&p&&.&/span&&span class=&n&&Abs&/span&&span class=&p&&(&/span&&span class=&n&&v&/span&&span class=&p&&);&/span&
&span class=&k&&if&/span& &span class=&p&&(&/span&&span class=&n&&tmpH&/span& &span class=&p&&&=&/span& &span class=&n&&CharacterInfo&/span&&span class=&p&&.&/span&&span class=&n&&StayOffset&/span& &span class=&p&&&&&/span& &span class=&n&&tmpV&/span& &span class=&p&&&=&/span& &span class=&n&&CharacterInfo&/span&&span class=&p&&.&/span&&span class=&n&&StayOffset&/span&&span class=&p&&)&/span&
&span class=&p&&{&/span&
&span class=&n&&stateMachine&/span&&span class=&p&&.&/span&&span class=&n&&stateParams&/span&&span class=&p&&.&/span&&span class=&n&&speed&/span& &span class=&p&&=&/span& &span class=&m&&0&/span&&span class=&p&&;&/span&
&span class=&p&&}&/span&
&span class=&k&&else&/span&
&span class=&p&&{&/span&
&span class=&n&&stateMachine&/span&&span class=&p&&.&/span&&span class=&n&&stateParams&/span&&span class=&p&&.&/span&&span class=&n&&moveVelocity&/span& &span class=&p&&=&/span& &span class=&n&&transform&/span&&span class=&p&&.&/span&&span class=&n&&right&/span& &span class=&p&&*&/span& &span class=&n&&h&/span& &span class=&p&&+&/span& &span class=&n&&transform&/span&&span class=&p&&.&/span&&span class=&n&&forward&/span& &span class=&p&&*&/span& &span class=&n&&v&/span&&span class=&p&&;&/span&
&span class=&n&&stateMachine&/span&&span class=&p&&.&/span&&span class=&n&&stateParams&/span&&span class=&p&&.&/span&&span class=&n&&speed&/span& &span class=&p&&=&/span& &span class=&n&&Mathf&/span&&span class=&p&&.&/span&&span class=&n&&Max&/span&&span class=&p&&(&/span&&span class=&n&&tmpH&/span&&span class=&p&&,&/span& &span class=&n&&tmpV&/span&&span class=&p&&);&/span&
&span class=&p&&}&/span&
&span class=&p&&}&/span&
&span class=&p&&}&/span&
&span class=&k&&void&/span& &span class=&nf&&TriggerSkill&/span&&span class=&p&&(&/span&&span class=&n&&NotificationCenter&/span&&span class=&p&&.&/span&&span class=&n&&Notification&/span& &span class=&n&&skillInfo&/span&&span class=&p&&)&/span&
&span class=&p&&{&/span&
&span class=&k&&if&/span& &span class=&p&&(&/span&&span class=&n&&onceActionBegain&/span&&span class=&p&&)&/span& &span class=&k&&return&/span&&span class=&p&&;&/span&
&span class=&n&&SkillItem&/span& &span class=&n&&skill&/span& &span class=&p&&=&/span& &span class=&p&&(&/span&&span class=&n&&SkillItem&/span&&span class=&p&&)&/span&&span class=&n&&skillInfo&/span&&span class=&p&&.&/span&&span class=&n&&data&/span&&span class=&p&&;&/span&
&span class=&n&&stateMachine&/span&&span class=&p&&.&/span&&span class=&n&&stateParams&/span&&span class=&p&&.&/span&&span class=&n&&onceActionType&/span& &span class=&p&&=&/span& &span class=&n&&skill&/span&&span class=&p&&.&/span&&span class=&n&&skillId&/span&&span class=&p&&;&/span&
&span class=&n&&stateMachine&/span&&span class=&p&&.&/span&&span class=&n&&stateParams&/span&&span class=&p&&.&/span&&span class=&n&&triggerOnceAction&/span& &span class=&p&&=&/span& &span class=&k&&true&/span&&span class=&p&&;&/span&
&span class=&p&&}&/span&
&span class=&k&&void&/span& &span class=&nf&&CharacterLive&/span&&span class=&p&&(&/span&&span class=&n&&NotificationCenter&/span&&span class=&p&&.&/span&&span class=&n&&Notification&/span& &span class=&n&&liveInfo&/span&&span class=&p&&)&/span&
&span class=&p&&{&/span&
&span class=&p&&}&/span&
&span class=&k&&void&/span& &span class=&nf&&OnceActionChange&/span&&span class=&p&&(&/span&&span class=&n&&NotificationCenter&/span&&span class=&p&&.&/span&&span class=&n&&Notification&/span& &span class=&n&&info&/span&&span class=&p&&)&/span&
&span class=&p&&{&/span&
&span class=&n&&onceActionBegain&/span& &span class=&p&&=&/span& &span class=&n&&Convert&/span&&span class=&p&&.&/span&&span class=&n&&ToBoolean&/span&&span class=&p&&(&/span&&span class=&n&&info&/span&&span class=&p&&.&/span&&span class=&n&&data&/span&&span class=&p&&);&/span&
&span class=&p&&}&/span&
&span class=&p&&}&/span&
&span class=&k&&using&/span& &span class=&nn&&UnityEngine&/span&&span class=&p&&;&/span&
&span class=&k&&using&/span& &span class=&nn&&System.Collections.Generic&/span&&span class=&p&&;&/span&
&span class=&k&&using&/span& &span class=&nn&&System&/span&&span class=&p&&;&/span&
&span class=&k&&public&/span& &span class=&k&&class&/span& &span class=&nc&&CharacterStateMachine&/span& &span class=&p&&:&/span& &span class=&n&&StateMachine&/span& &span class=&p&&{&/span&
&span class=&k&&public&/span& &span class=&k&&enum&/span& &span class=&n&&StayStateType&/span& &span class=&p&&{&/span& &span class=&n&&Idle&/span&&span class=&p&&,&/span&&span class=&n&&Victory&/span&&span class=&p&&,&/span&&span class=&n&&Upset&/span&&span class=&p&&,&/span&&span class=&n&&Defend&/span& &span class=&p&&};&/span&
&span class=&k&&private&/span& &span class=&n&&StateMachineParams&/span& &span class=&n&&_stateParams&/span&&span class=&p&&;&/span&
&span class=&k&&public&/span& &span class=&n&&StateMachineParams&/span& &span class=&n&&stateParams&/span&
&span class=&p&&{&/span&
&span class=&k&&get&/span& &span class=&p&&{&/span& &span class=&k&&return&/span& &span class=&n&&_stateParams&/span&&span class=&p&&;&/span& &span class=&p&&}&/span&
&span class=&k&&set&/span&
&span class=&p&&{&/span&
&span class=&n&&_stateParams&/span& &span class=&p&&=&/span& &span class=&k&&value&/span&&span class=&p&&;&/span&
&span class=&p&&}&/span&
&span class=&p&&}&/span&
&span class=&k&&private&/span& &span class=&n&&DieState&/span& &span class=&n&&die&/span&&span class=&p&&;&/span&
&span class=&k&&private&/span& &span class=&n&&StayState&/span& &span class=&n&&stay&/span&&span class=&p&&;&/span&
&span class=&k&&private&/span& &span class=&n&&OnceActionState&/span& &span class=&n&&onceAction&/span&&span class=&p&&;&/span&
&span class=&k&&private&/span& &span class=&n&&MoveState&/span& &span class=&n&&move&/span&&span class=&p&&;&/span&
&span class=&k&&void&/span& &span class=&nf&&Awake&/span&&span class=&p&&()&/span&
&span class=&p&&{&/span&
&span class=&k&&if&/span& &span class=&p&&(&/span&&span class=&n&&stateParams&/span& &span class=&p&&==&/span& &span class=&k&&null&/span&&span class=&p&&)&/span&
&span class=&p&&{&/span&
&span class=&n&&stateParams&/span& &span class=&p&&=&/span& &span class=&k&&new&/span& &span class=&n&&StateMachineParams&/span&&span class=&p&&();&/span&
&span class=&p&&}&/span&
&span class=&p&&}&/span&
&span class=&k&&void&/span& &span class=&nf&&FixedUpdate&/span&&span class=&p&&()&/span&
&span class=&p&&{&/span&
&span class=&n&&ChangeState&/span&&span class=&p&&&&/span&&span class=&n&&State&/span&&span class=&p&&&();&/span&
&span class=&p&&}&/span&
&span class=&k&&public&/span& &span class=&k&&override&/span& &span class=&k&&void&/span& &span class=&n&&ChangeState&/span&&span class=&p&&&&/span&&span class=&n&&T&/span&&span class=&p&&&()&/span&
&span class=&p&&{&/span&
&span class=&k&&if&/span& &span class=&p&&(&/span&&span class=&n&&stateParams&/span&&span class=&p&&.&/span&&span class=&n&&isLive&/span&&span class=&p&&)&/span&
&span class=&p&&{&/span&
&span class=&k&&if&/span& &span class=&p&&(&/span&&span class=&n&&stateParams&/span&&span class=&p&&.&/span&&span class=&n&&triggerOnceAction&/span&&span class=&p&&)&/span&
&span class=&p&&{&/span&
&span class=&n&&currentState&/span& &span class=&p&&=&/span& &span class=&n&&GetState&/span&&span class=&p&&&&/span&&span class=&n&&OnceActionState&/span&&span class=&p&&&();&/span&
&span class=&p&&}&/span&
&span class=&k&&else&/span& &span class=&nf&&if&/span& &span class=&p&&(&/span&&span class=&n&&stateParams&/span&&span class=&p&&.&/span&&span class=&n&&canMove&/span&&span class=&p&&())&/span&
&span class=&p&&{&/span&
&span class=&n&&currentState&/span& &span class=&p&&=&/span& &span class=&n&&GetState&/span&&span class=&p&&&&/span&&span class=&n&&MoveState&/span&&span class=&p&&&();&/span&
&span class=&p&&}&/span&
&span class=&k&&else&/span& &span class=&p&&{&/span&
&span class=&n&&currentState&/span& &span class=&p&&=&/span& &span class=&n&&GetState&/span&&span class=&p&&&&/span&&span class=&n&&StayState&/span&&span class=&p&&&();&/span&
&span class=&p&&}&/span&
&span class=&p&&}&/span&
&span class=&k&&else&/span&
&span class=&p&&{&/span&
&span class=&n&&currentState&/span& &span class=&p&&=&/span& &span class=&n&&GetState&/span&&span class=&p&&&&/span&&span class=&n&&DieState&/span&&span class=&p&&&();&/span&
&span class=&p&&}&/span&
&span class=&n&&NotificationCenter&/span&&span class=&p&&.&/span&&span class=&n&&DefaultCenter&/span&&span class=&p&&.&/span&&span class=&n&&PostNotification&/span&&span class=&p&&(&/span&&span class=&k&&this&/span&&span class=&p&&,&/span& &span class=&n&&StateMachineEvent&/span&&span class=&p&&.&/span&&span class=&n&&HandleParamers&/span&&span class=&p&&,&/span& &span class=&n&&stateParams&/span&&span class=&p&&);&/span&
&span class=&p&&}&/span&
&span class=&p&&}&/span&
&span class=&k&&using&/span& &span class=&nn&&UnityEngine&/span&&span class=&p&&;&/span&
&span class=&k&&public&/span& &span class=&k&&class&/span& &span class=&nc&&MoveState&/span& &span class=&p&&:&/span& &span class=&n&&State&/span& &span class=&p&&{&/span&
&span class=&k&&private&/span& &span class=&n&&Animator&/span& &span class=&n&&animator&/span&&span class=&p&&;&/span&
&span class=&na&&
[SerializeField]&/span&
&span class=&k&&private&/span& &span class=&kt&&float&/span& &span class=&n&&speedMultiplier&/span& &span class=&p&&=&/span& &span class=&m&&2f&/span&&span class=&p&&;&/span&
&span class=&k&&private&/span& &span class=&n&&Rigidbody&/span& &span class=&n&&rb&/span&&span class=&p&&;&/span&
&span class=&k&&private&/span& &span class=&n&&StateMachineParams&/span& &span class=&n&&stateParams&/span&&span class=&p&&;&/span&
&span class=&k&&private&/span& &span class=&kt&&bool&/span& &span class=&n&&canMove&/span& &span class=&p&&=&/span& &span class=&k&&false&/span&&span class=&p&&;&/span&
&span class=&k&&void&/span& &span class=&nf&&Awake&/span&&span class=&p&&()&/span&
&span class=&p&&{&/span&
&span class=&n&&animator&/span& &span class=&p&&=&/span& &span class=&n&&GetComponentInChildren&/span&&span class=&p&&&&/span&&span class=&n&&Animator&/span&&span class=&p&&&();&/span&
&span class=&n&&rb&/span& &span class=&p&&=&/span& &span class=&n&&GetComponent&/span&&span class=&p&&&&/span&&span class=&n&&Rigidbody&/span&&span class=&p&&&();&/span&
&span class=&k&&this&/span&&span class=&p&&.&/span&&span class=&n&&name&/span& &span class=&p&&=&/span& &span class=&s&&&MoveState&&/span&&span class=&p&&;&/span&
&span class=&p&&}&/span&
&span class=&k&&void&/span& &span class=&nf&&FixedUpdate&/span&&span class=&p&&()&/span&
&span class=&p&&{&/span&
&span class=&k&&if&/span& &span class=&p&&(&/span&&span class=&n&&canMove&/span&&span class=&p&&)&/span&
&span class=&p&&{&/span&
&span class=&n&&PerformMovement&/span&&span class=&p&&();&/span&
&span class=&p&&}&/span&
&span class=&p&&}&/span&
&span class=&k&&private&/span& &span class=&k&&void&/span& &span class=&nf&&PerformMovement&/span&&span class=&p&&()&/span&
&span class=&p&&{&/span&
&span class=&k&&if&/span& &span class=&p&&(&/span&&span class=&n&&stateParams&/span&&span class=&p&&.&/span&&span class=&n&&speed&/span& &span class=&p&&&&/span& &span class=&n&&CharacterInfo&/span&&span class=&p&&.&/span&&span class=&n&&StayOffset&/span&&span class=&p&&)&/span&
&span class=&p&&{&/span&
&span class=&n&&rb&/span&&span class=&p&&.&/span&&span class=&n&&MovePosition&/span&&span class=&p&&(&/span&&span class=&n&&rb&/span&&span class=&p&&.&/span&&span class=&n&&position&/span& &span class=&p&&+&/span& &span class=&n&&stateParams&/span&&span class=&p&&.&/span&&span class=&n&&moveVelocity&/span& &span class=&p&&*&/span& &span class=&n&&speedMultiplier&/span& &span class=&p&&*&/span& &span class=&n&&Time&/span&&span class=&p&&.&/span&&span class=&n&&fixedDeltaTime&/span&&span class=&p&&);&/span&
&span class=&p&&}&/span&
&span class=&p&&}&/span&
&span class=&k&&protected&/span& &span class=&k&&override&/span& &span class=&k&&void&/span& &span class=&nf&&AddListeners&/span&&span class=&p&&()&/span&
&span class=&p&&{&/span&
&span class=&n&&NotificationCenter&/span&&span class=&p&&.&/span&&span class=&n&&DefaultCenter&/span&&span class=&p&&.&/span&&span class=&n&&AddObserver&/span&&span class=&p&&(&/span&&span class=&k&&this&/span&&span class=&p&&,&/span& &span class=&n&&StateMachineEvent&/span&&span class=&p&&.&/span&&span class=&n&&HandleParamers&/span&&span class=&p&&);&/span&
&span class=&n&&canMove&/span& &span class=&p&&=&/span& &span class=&k&&true&/span&&span class=&p&&;&/span&
&span class=&p&&}&/span&
&span class=&k&&protected&/span& &span class=&k&&override&/span& &span class=&k&&void&/span& &span class=&nf&&RemoveListeners&/span&&span class=&p&&()&/span&
&span class=&p&&{&/span&
&span class=&n&&NotificationCenter&/span&&span class=&p&&.&/span&&span class=&n&&DefaultCenter&/span&&span class=&p&&.&/span&&span class=&n&&RemoveObserver&/span&&span class=&p&&(&/span&&span class=&k&&this&/span&&span class=&p&&,&/span& &span class=&n&&StateMachineEvent&/span&&span class=&p&&.&/span&&span class=&n&&HandleParamers&/span&&span class=&p&&);&/span&
&span class=&n&&canMove&/span& &span class=&p&&=&/span& &span class=&k&&false&/span&&span class=&p&&;&/span&
&span class=&p&&}&/span&
&span class=&k&&void&/span& &span class=&nf&&HandleParamers&/span&&span class=&p&&(&/span&&span class=&n&&NotificationCenter&/span&&span class=&p&&.&/span&&span class=&n&&Notification&/span& &span class=&n&&info&/span&&span class=&p&&)&/span&
&span class=&p&&{&/span&
&span class=&n&&stateParams&/span& &span class=&p&&=&/span& &span class=&p&&(&/span&&span class=&n&&StateMachineParams&/span&&span class=&p&&)&/span&&span class=&n&&info&/span&&span class=&p&&.&/span&&span class=&n&&data&/span&&span class=&p&&;&/span&
&span class=&n&&animator&/span&&span class=&p&&.&/span&&span class=&n&&SetBool&/span&&span class=&p&&(&/span&&span class=&s&&&isLive&&/span&&span class=&p&&,&/span& &span class=&n&&stateParams&/span&&span class=&p&&.&/span&&span class=&n&&isLive&/span&&span class=&p&&);&/span&
&span class=&n&&animator&/span&&span class=&p&&.&/span&&span class=&n&&SetFloat&/span&&span class=&p&&(&/span&&span class=&s&&&speed&&/span&&span class=&p&&,&/span& &span class=&n&&stateParams&/span&&span class=&p&&.&/span&&span class=&n&&speed&/span&&span class=&p&&);&/span&
&span class=&p&&}&/span&
&span class=&p&&}&/span&
&/code&&/pre&&/div&&p&以上代码给出人物类里怎么调用,状态机里怎么切换,其中一个状态里怎么写。&/p&&p&我犯过的错误:&/p&&p&1. 原来我的Character类里充斥了各种变量,大部分其实都是跟Animator里放出来的几个控制变量相关,现在统一为四个变量,这四个接口是保证其他类能查询到当前人物状态。当时,在尝试写的时候,我试图把这几个变量放到状态机里,因为它们和状态机关系密切,如果外界需要查询人物状态,那就在人物类里通过状态机来查询好了,后来觉得这样做实在麻烦且毫无必要。&/p&&p&2. 没有理解清楚状态机的概念,只是当成了要把动画状态机各种变量包一包而已,开始并没有人物控制代码放到状态里。&/p&&p&3. 没有理解清楚为什么状态机和状态类要继承自MonoBahaviour,按照了过去的老思维想着要在构造函数里传递animator变量,完全忘了有方法可以直接获取的。&/p&&p&4. 把琐碎数据集合到一起传到状态类内部。&/p&&p&&b&最后&/b&&b&状态机和状态类的代码参考了网上的一个帖子&/b&&/p&&p&&a href=&https://link.zhihu.com/?target=https%3A//theliquidfire.wordpress.com//tactics-rpg-state-machine/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Tactics RPG State Machine&/a&&/p&&p&里面过程讲的比较详细,我就不多说了,其实就是看了这个帖子,当时我该怎么用,我也是琢磨了很久,因为知易行难嘛!&/p&&p&作者悄悄话:&/p&&p&1. 通过这半个月的事件,深深觉得要想成为优秀的工程师,我的实践太少了(哇的一声哭出来后悔一月份以过年为借口摸鱼了一个月)。&/p&
2. 出气不要拿机械键盘,砸坏了一个键我的买一套,苦哇~(双飞燕真乃国货精品!)
前言什么是我认为的“状态机”?首先统一下“状态机”这个概念,状态机包括两个主要部分,一是控制切换状态的中心类;二是各种被切换状态,如移动状态,里面不仅包括人物移动所需播放的动画,还要包括控制人物实际移动的代码。为什么要把代码抽象封装?身为…
&figure&&img src=&https://pic1.zhimg.com/v2-c75b6b9214aed4b210b2b_b.jpg& data-rawwidth=&1728& data-rawheight=&1080& class=&origin_image zh-lightbox-thumb& width=&1728& data-original=&https://pic1.zhimg.com/v2-c75b6b9214aed4b210b2b_r.jpg&&&/figure&&h2&写在前面&/h2&&p&
专栏断更了这么久, 实在惭愧. 这段时间又是期末考试又是回家过节, 实在是没时间整理干货来分享. 之前说好的不及时更新就赔钱, @Cathy Chen童鞋已经拿到10大洋的红包了. &/p&&p&
不过从今天开始我就有大把的时间来继续研究图形学啦, 因此会保证更新速度的 ~ &/p&&p&
延续了我对Depth Buffer的一贯兴趣, 本文将介绍&b&SSAO&/b&的基本原理及包括&b&Temporal Coherence SSAO, Selective Temporal Filtering SSAO&/b&在内的优化算法. &/p&&br&&h2&何为&SSAO&&/h2&&p&
Screen Space Ambient Occlusion (以下简称SSAO), 屏幕空间环境光遮蔽. 在具体介绍SSAO之前, 本文先介绍更加广义的Ambient Occlusion (AO). &/p&&p&
简单来说, Ambient Occlusion(以下简称&AO&)是一种基于全局照明中的环境光(Ambient Light)参数和环境几何信息来计算场景中任何一点的&b&光照强度系数&/b&的算法. AO描述了表面上的任何一点所接受到的环境光被周围几何体所遮蔽的百分比, 因此使得渲染的结果更加富有层次感, 对比度更高. &figure&&img src=&https://pic4.zhimg.com/v2-40edd773a01ffb69399c75d_b.jpg& data-rawwidth=&652& data-rawheight=&315& class=&origin_image zh-lightbox-thumb& width=&652& data-original=&https://pic4.zhimg.com/v2-40edd773a01ffb69399c75d_r.jpg&&&/figure&&br&&/p&&p&
图片来自Wiki. 因为老人的皱纹处对外界暴露的部分较少, 使用AO后被遮蔽的部分较多, 渲染后显得更加暗一些, 增加了皱纹的层次感和质感. &/p&&p&
AO的计算公式如下: &/p&&img src=&https://www.zhihu.com/equation?tex=AO%28p%2C+n_%7Bp%7D+%29+%3D+%5Cfrac%7B1%7D%7B%5Cpi+%7D+%5Cint_%7B%5COmega+%7D%5E%7B%7D+V%28p%2C+%5Comega+%29max%28n_%7Bp%7D%2A%5Comega%2C+0%29d%5Comega& alt=&AO(p, n_{p} ) = \frac{1}{\pi } \int_{\Omega }^{} V(p, \omega )max(n_{p}*\omega, 0)d\omega& eeimg=&1&&&p&&img src=&https://www.zhihu.com/equation?tex=n_%7Bp%7D+& alt=&n_{p} & eeimg=&1&&代表点&img src=&https://www.zhihu.com/equation?tex=p& alt=&p& eeimg=&1&&的法线, &img src=&https://www.zhihu.com/equation?tex=%5Comega+& alt=&\omega & eeimg=&1&&代表点&img src=&https://www.zhihu.com/equation?tex=p& alt=&p& eeimg=&1&&切平面正方向的任意单位向量, &img src=&https://www.zhihu.com/equation?tex=V%28p%2C+%5Comega+%29& alt=&V(p, \omega )& eeimg=&1&&是可见函数, 如果点&img src=&https://www.zhihu.com/equation?tex=p& alt=&p& eeimg=&1&&在&img src=&https://www.zhihu.com/equation?tex=%5Comega+& alt=&\omega & eeimg=&1&&方向被遮挡则为1, 否则为0. &/p&&p&
由此可见, 计算AO系数是一个颇为昂贵的操作. 一般离线渲染器都会采用Ray-Tracing(光线追踪)或是简化的Ray-Marching(所谓光线行进)算法, 模拟若干条射线以计算遮蔽百分比. 很明显这种方式不可能应用到实时图形渲染中. 尽管目前有一些实时计算AO的新技术, 但是其性能距离普及还有很长的路要走. &/p&&p&&figure&&img src=&https://pic1.zhimg.com/v2-17b9e68effc23f3bd170ebefd94b9c9d_b.jpg& data-rawwidth=&838& data-rawheight=&536& class=&origin_image zh-lightbox-thumb& width=&838& data-original=&https://pic1.zhimg.com/v2-17b9e68effc23f3bd170ebefd94b9c9d_r.jpg&&&/figure&
上图为基于Ray-Tracing的AO计算模型. 红色的射线表示V = 1, 绿色的射线表示V = 0. &/p&&p&
那么我们能否&b&Trade Off&/b&, 用差一点的渲染结果来获得更高的运行效率呢? 答案是肯定的, 而且方法还远不止一种. 本文将重点放在SSAO上. &/p&&p&
顾名思义, &Screen Space&意味着SSAO并不是场景的预处理, 而是屏幕后期处理. 其原理是在片元着色器中对于屏幕上的每个像素模拟若干个位置随机的采样点, 用被遮蔽的采样点数量百分比来&b&近似&/b&表示光照强度系数. &/p&&br&&h2&SSAO的实现&/h2&&p&
SSAO的实现可分为三个步骤: 计算AO, 模糊/滤波, 与Color Buffer混合. &/p&&p&&b&1. 计算AO&/b&&/p&&p&计算AO的核心问题在于&b&如何取采样点&/b&并判断&b&这些采样点是否被遮蔽&/b&. 我们首先解决第一个问题. 在此我们使用一种指向法线方向的半球形采样块(Sample Kernel), 并在采样块中生成采样点. &b&距离原点越远的点, AO贡献越小&/b&. 采样块如下图所示: &/p&&figure&&img src=&https://pic2.zhimg.com/v2-0e8ef56914ab7bdedebbbd23_b.jpg& data-rawwidth=&380& data-rawheight=&218& class=&content_image& width=&380&&&/figure&&br&&p&
那么我们转入第二个问题: 如何判断下图中的采样点遮蔽情况呢? &/p&&p&&figure&&img src=&https://pic1.zhimg.com/v2-eab494f8c71bf1fec82bd9_b.jpg& data-rawwidth=&352& data-rawheight=&184& class=&content_image& width=&352&&&/figure&
(涂黑的点处在几何体表面内部, 因此判定为被遮蔽)&/p&&p&
一种方法是将采样点全部投影到View Plane上, 相当于获取采样点的UV坐标, 并同时获取Depth Buffer中该UV坐标处的深度值. 随后比较采样点的深度和场景中该点的深度. 如果采样点的深度更大, 说明其被场景遮蔽. 最终将所有采样点的AO贡献求和, 即是该点的AO值. 计算公式如下: &/p&&img src=&https://www.zhihu.com/equation?tex=AO_%7Bn%7D%28p%29+%3D+%5Cfrac%7B1%7D%7Bn%7DC%28p%2C+s_%7Bi%7D+%29++& alt=&AO_{n}(p) = \frac{1}{n}C(p, s_{i} )
& eeimg=&1&&&br&&img src=&https://www.zhihu.com/equation?tex=C%28p%2C+s_%7Bi%7D+%29+%3D+V%28p%2C+s_%7Bi%7D+%29cos%28s_%7Bi%7D+-+p%2C+n_%7Bp%7D++%29D%28s_%7Bi%7D+-+p+%29& alt=&C(p, s_{i} ) = V(p, s_{i} )cos(s_{i} - p, n_{p}
)D(s_{i} - p )& eeimg=&1&&&br&&p&
其中, 函数V前面已经介绍过. 函数D是一个[0, 1]之间的单调递减函数, 距离原点越近的采样点对AO的贡献越大. 一般使用指数函数. &/p&&p&&figure&&img src=&https://pic4.zhimg.com/v2-e53ec439e47cb72ef75ce_b.jpg& data-rawwidth=&1336& data-rawheight=&835& class=&origin_image zh-lightbox-thumb& width=&1336& data-original=&https://pic4.zhimg.com/v2-e53ec439e47cb72ef75ce_r.jpg&&&/figure&上图为原图&/p&&p&&figure&&img src=&https://pic1.zhimg.com/v2-425f9d8a84d9fa052ba3f7ace46a1d1a_b.jpg& data-rawwidth=&2880& data-rawheight=&1800& class=&origin_image zh-lightbox-thumb& width=&2880& data-original=&https://pic1.zhimg.com/v2-425f9d8a84d9fa052ba3f7ace46a1d1a_r.jpg&&&/figure&上图为求得的AO值. 颜色越深代表AO越大. &/p&&p&以下是循环采样部分代码(ii为循环变量): &/p&&div class=&highlight&&&pre&&code class=&language-glsl&&&span&&/span&&span class=&n&&half3&/span& &span class=&n&&randomDirection&/span& &span class=&o&&=&/span& &span class=&n&&RandomSample&/span&&span class=&p&&[&/span& &span class=&n&&ii&/span& &span class=&p&&];&/span&
&span class=&n&&float2&/span& &span class=&n&&uv_offset&/span& &span class=&o&&=&/span& &span class=&n&&randomDirection&/span&&span class=&p&&.&/span&&span class=&n&&xy&/span& &span class=&o&&*&/span& &span class=&n&&scale&/span&&span class=&p&&;&/span&
&span class=&k&&float&/span& &span class=&n&&randomDepth&/span& &span class=&o&&=&/span& &span class=&n&&depth&/span& &span class=&o&&-&/span& &span class=&p&&(&/span& &span class=&n&&randomDirection&/span&&span class=&p&&.&/span&&span class=&n&&z&/span& &span class=&o&&*&/span& &span class=&n&&_Radius&/span& &span class=&p&&);&/span&
&span class=&k&&float&/span& &span class=&n&&sampleDepth&/span&&span class=&p&&;&/span&
&span class=&n&&float3&/span& &span class=&n&&sampleNormal&/span&&span class=&p&&;&/span&
&span class=&n&&DecodeDepthNormal&/span& &span class=&p&&(&/span& &span class=&n&&tex2D&/span& &span class=&p&&(&/span& &span class=&n&&_CameraDepthNormalsTexture&/span&&span class=&p&&,&/span& &span class=&n&&i&/span&&span class=&p&&.&/span&&span class=&n&&uv&/span& &span class=&o&&+&/span& &span class=&n&&uv_offset&/span& &span class=&p&&),&/span& &span class=&n&&sampleDepth&/span&&span class=&p&&,&/span& &span class=&n&&sampleNormal&/span& &span class=&p&&);&/span&
&span class=&n&&sampleDepth&/span& &span class=&o&&*=&/span& &span class=&n&&_ProjectionParams&/span&&span class=&p&&.&/span&&span class=&n&&z&/span&&span class=&p&&;&/span&
&span class=&k&&float&/span& &span class=&n&&diff&/span& &span class=&o&&=&/span&
&span class=&n&&saturate&/span&&span class=&p&&(&/span& &span class=&n&&randomDepth&/span& &span class=&o&&-&/span& &span class=&n&&sampleDepth&/span& &span class=&p&&);&/span&
&span class=&k&&if&/span& &span class=&p&&(&/span& &span class=&n&&diff&/span& &span class=&o&&&&/span& &span class=&n&&_ZDiff&/span& &span class=&p&&)&/span&
&span class=&n&&occlusionAmount&/span& &span class=&o&&+=&/span& &span class=&n&&pow&/span& &span class=&p&&(&/span&&span class=&mi&&1&/span& &span class=&o&&-&/span& &span class=&n&&diff&/span&&span class=&p&&,&/span& &span class=&n&&_Attenuation&/span&&span class=&p&&);&/span&
&/code&&/pre&&/div&&p&
到此我们发现了一个问题: 上面求得的AO结果非常不理想. 图中有非常明显的条带状阴影, 给人的感觉像是在图上轻轻地抹了一层均匀的&b&&i&&u&油漆&/u&&/i&&/b&. 产生这种现象的原因很简单 - &b&为了满足实时渲染的性能要求, 我们必须限制采样点的数目. &/b&&/p&&p&
但是, 对于这种现象我们有一个Trick ---- 可以引入&b&噪声&/b&, 将每个采样点以原点法线方向为旋转轴旋转随机的角度. 这样的新采样点会变得极其不规则, 更加离散化. &b&将低频的条纹转化成高频的噪声. &/b&&/p&&div class=&highlight&&&pre&&code class=&language-glsl&&&span&&/span&&span class=&n&&half3&/span& &span class=&n&&randomVector&/span& &span class=&o&&=&/span& &span class=&n&&tex2D&/span& &span class=&p&&(&/span& &span class=&n&&_RandomTexture&/span&&span class=&p&&,&/span& &span class=&n&&i&/span&&span class=&p&&.&/span&&span class=&n&&uv_random&/span& &span class=&p&&).&/span&&span class=&n&&xyz&/span& &span class=&o&&*&/span& &span class=&mf&&2.0&/span& &span class=&o&&-&/span& &span class=&mf&&1.0&/span&&span class=&p&&;&/span&
&span class=&n&&half3&/span& &span class=&n&&randomDirection&/span& &span class=&o&&=&/span& &span class=&n&&reflect&/span& &span class=&p&&(&/span& &span class=&n&&RandomSample&/span&&span class=&p&&[&/span& &span class=&n&&ii&/span& &span class=&p&&],&/span& &span class=&n&&randomVector&/span& &span class=&p&&);&/span&
&/code&&/pre&&/div&&p&&figure&&img src=&https://pic4.zhimg.com/v2-985dfe06f533bc25ee3ce3_b.jpg& data-rawwidth=&2880& data-rawheight=&1800& class=&origin_image zh-lightbox-thumb& width=&2880& data-original=&https://pic4.zhimg.com/v2-985dfe06f533bc25ee3ce3_r.jpg&&&/figure&上图为引入随机噪声后的采样结果. 我们发现&油漆&变成了&&b&&i&&u&沙子&/u&&/i&&/b&&. &/p&&br&&p&&b&2. 模糊/滤波&/b&&/p&&blockquote&&p&&i&&油漆&好还是&沙子&好? &/i&&/p&&p&&i&都不好! &/i&&/p&&/blockquote&&p&
&油漆&显得平淡无奇, &沙子&让人眼花缭乱. 中国人讲究中庸之道, 也就是说 ---- &b&我们需要一个&中频&的AO! &/b&&/p&&p&
在此介绍两种方法. 第一种方法是直接模糊. 比较常用的是高斯模糊. 关于高斯模糊的资料有很多, 本文不再赘述. &/p&&p&
第二种方法在采样原理上和高斯模糊别无二致, 只是采样系数由静态变为动态: 原点与采样点的UV坐标距离, 法线和深度关系共同决定采样系数, 距离越远采样系数越小, 法线和深度的差距越大则采样系数也越大. 这样的模糊使得结果更加趋近于中频, 进一步减弱了闪烁(Flickering)的效果. &/p&&br&&p&3. 与Color Buffer混合. &/p&&p&
一般加入Gamma Correction使得阴影更有层次感, 即最终结果为: &/p&&div class=&highlight&&&pre&&code class=&language-glsl&&&span&&/span&&span class=&n&&tex2D&/span& &span class=&p&&(&/span& &span class=&n&&_MainTex&/span&&span class=&p&&,&/span& &span class=&n&&i&/span&&span class=&p&&.&/span&&span class=&n&&uv&/span& &span class=&p&&)&/span& &span class=&o&&*&/span& &span class=&n&&pow&/span& &span class=&p&&(&/span& &span class=&p&&(&/span& &span class=&mi&&1&/span& &span class=&o&&-&/span& &span class=&n&&occlusion&/span& &span class=&p&&),&/span& &span class=&mf&&2.2&/span& &span class=&p&&);&/span&
&/code&&/pre&&/div&&figure&&img src=&https://pic1.zhimg.com/v2-e2a74d972de2e725fa22b2a_b.jpg& data-rawwidth=&1336& data-rawheight=&835& class=&origin_image zh-lightbox-thumb& width=&1336& data-original=&https://pic1.zhimg.com/v2-e2a74d972de2e725fa22b2a_r.jpg&&&/figure&&p&
上图为SSAO处理后的最终结果. &/p&&br&&h2&SSAO的问题与优化策略&/h2&&p&
SSAO技术的基本原理已经介绍完了, 下面我们来谈谈SSAO可能遇到的问题, 以及相应的解决方案: &/p&&p&&b&1. 采样块的问题&/b&&/p&&p&上文的SSAO实现方案其实是假定了使用Deferred Rendering, 深度和法线都可以非常容易得获取到, 因此我们的半球形采样块可以沿着顶点的法线方向摆放. 但是如果获取法线比较困难, 我们可以将半球形退化成球形, 这也正是2007年&i&Crysis&/i&中SSAO的实现方案. &/p&&p&&figure&&img src=&https://pic2.zhimg.com/v2-ee4a82aa0d9fc507c413_b.jpg& data-rawwidth=&352& data-rawheight=&184& class=&content_image& width=&352&&&/figure&
如上图所示, 采样块的摆放与法线无关, 采样点遍布整个球形中. 这种方法的效果自然不如半球形采样块. &/p&&br&&p&&b&2. 重复计算的问题&/b&&/p&&p&
SSAO最为耗时的操作是模拟多个采样点并计算其AO贡献值, 因此我们应该想办法避免重复计算, 尽量使用以前的结果. 这里可以使用&b&Reverse Reprojection&/b&(反向二次投影), 保存上一帧的AO计算信息, 使得当前帧中相对上一帧没有变化的点可以利用旧的AO信息, 避免重复计算. 这种方式称为SSAO with Temporal Coherence(&b&时间相干性&/b&), 简称为&b&&u&TSSAO&/u&&/b&. 具体的实现方式将在下文中进行阐述. &/p&&br&&p&&b&3. 滤波与精确计算之间的矛盾&/b&&/p&&p&
这也是一个Trade Off ---- 反正运算结果都是要套用滤波来过滤掉噪点, 那么最开始计算的时候就可以想办法在保证质量不受太大影响的前提下, 尽量提升效率. 举一个例子: &/p&&blockquote&假设有两个面饼师傅, 第一个师傅的工作是揉出来5个直径为1.2cm的面球, 第二个师傅的工作是把这5个面球放在一起拍成一个面饼. &/blockquote&&p&
我们不讨论这种工作方式是否合理, 只是在此情况下第一个师傅确实不用对1.2cm吹毛求疵, 只要差不多就行了. &/p&&p&
明白了这个道理, 就会发现可以}

我要回帖

更多关于 全自动抢红包神器2017 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信