游戏引擎中的常用资源用什么类型指针类型转换

主流的同步方案有两种:帧同步和CS同步。&br&正好这两天在整理这块的东西,就一并分享一下!也希望能够得到一些讨论的机会。&br&&br&看到评论,补充一个观点:&i&&u&&b&CS和帧同步其实各有有优缺点,并不是某一项方案一定能够取代另一项方案,当游戏类型对实时性要求很高时(比如,实时格斗、体育竞技类游戏(NBA2K)),帧同步可能就是唯一的方案了。&/b&&/u&&/i&&br&&br&&br&&br&以下是正式答案&br&&p&&b&概念定义:&/b&&br&&/p&&br&&b&1 ArenaServer&/b&&br&&br&&ul&&li&战斗核心逻辑及数据所在&/li&&li&不关心表现&/li&&li&由客户端的输入驱动运行&/li&&li&CS同步架构里,这个部分是在服务器的&/li&&li&帧同步架构里,这个部分是在客户端的。&/li&&/ul&&br&&br&&b&2 ArenaServer[预表现层]&/b&&br&&br&&ul&&li&战斗的预表现层,一定在客户端&/li&&li&对于一些需要本地预表现的逻辑,如行走。需要先在这里模拟实现。&/li&&li&ArenaServer的真实数据反馈到预表现层后,会修改本地数据。&/li&&li&ArenaClient只知道预表现层,并不知道真正的ArenaServer的存在。&/li&&li&所以,当游戏要改变同步方案时,Client层并不需要修改。&/li&&/ul&&br&&br&&b&3 ArenaClient:ArenaInput+ArenaRender &/b&&br&&br&&ul&&li&负责客户端输入和渲染&/li&&li&只与预表现层交互。&/li&&/ul&&br&&b&4 FrameServer&/b&&br&&ul&&li&以每秒30次(假设)的频率,收集各个客户端上报上来的ClientInput。&/li&&li&组装为FrameInput,广播给各个客户端。&/li&&li&即为帧同步的服务器所有逻辑&/li&&/ul&&img data-rawwidth=&611& data-rawheight=&710& src=&/a58b8ba96f844b3e8f124ad0aae496aa_b.jpeg& class=&origin_image zh-lightbox-thumb& width=&611& data-original=&/a58b8ba96f844b3e8f124ad0aae496aa_r.jpeg&&&br&&img data-rawwidth=&618& data-rawheight=&799& src=&/520e56f5c710d014dc778_b.jpeg& class=&origin_image zh-lightbox-thumb& width=&618& data-original=&/520e56f5c710d014dc778_r.jpeg&&&br&&br&&br&&img data-rawwidth=&1410& data-rawheight=&694& src=&/8a63be2a3c4fb_b.jpeg& class=&origin_image zh-lightbox-thumb& width=&1410& data-original=&/8a63be2a3c4fb_r.jpeg&&&br&&br&=======一早上都在画这三个图,最后求个赞~~~=======
主流的同步方案有两种:帧同步和CS同步。 正好这两天在整理这块的东西,就一并分享一下!也希望能够得到一些讨论的机会。 看到评论,补充一个观点:CS和帧同步其实各有有优缺点,并不是某一项方案一定能够取代另一项方案,当游戏类型对实时性要求很高时(比…
&img src=&/50/v2-9a2b7d5714_b.jpg& data-rawwidth=&851& data-rawheight=&315& class=&origin_image zh-lightbox-thumb& width=&851& data-original=&/50/v2-9a2b7d5714_r.jpg&&&p&就在近期的Unite Europe 2017 中,有两个talk比较有意思,分别是The AAA graphics of Spellsouls: achieving 60FPS on mobile 和 The&br&Real-time VFX of Spellsouls,恰好最近在做一些优化方面的工作,就一起学习了一下。&/p&&p&&br&&/p&&p&游戏官方介绍说是一个Moba类的卡牌,但个人感觉就是3D版的炉石?下面是几个截图。&/p&&p&&br&&/p&&img src=&/50/v2-a1a09fbbaa2d_b.jpg& data-rawwidth=&1251& data-rawheight=&657& class=&origin_image zh-lightbox-thumb& width=&1251& data-original=&/50/v2-a1a09fbbaa2d_r.jpg&&&p&&br&&/p&&p&&br&&/p&&img src=&/50/v2-912faeb817a2cc3b7daeeec7d847a2f9_b.jpg& data-rawwidth=&1256& data-rawheight=&655& class=&origin_image zh-lightbox-thumb& width=&1256& data-original=&/50/v2-912faeb817a2cc3b7daeeec7d847a2f9_r.jpg&&&p&&br&&/p&&p&&br&&/p&&p&作为一个图形程序,目标有两个:&/p&&p&&br&&/p&&p&AAA级别的画质&/p&&p&支持尽可能多的移动设备&/p&&p&&br&&/p&&p&所面临的挑战&/p&&p&&br&&/p&&img src=&/50/v2-020af72fcdf16d5e152a_b.jpg& data-rawwidth=&1147& data-rawheight=&609& class=&origin_image zh-lightbox-thumb& width=&1147& data-original=&/50/v2-020af72fcdf16d5e152a_r.jpg&&&p&&br&&/p&&p&&br&&/p&&p&首先是如何基于PBR Shading打造一种真实暗黑风格,然后是Shader的变种,接着是对性能的优化,最低设备支持到iphone4s,最后是动态画质调整。&/p&&p&&br&&/p&&img src=&/50/v2-04ac0d1366_b.jpg& data-rawwidth=&1134& data-rawheight=&604& class=&origin_image zh-lightbox-thumb& width=&1134& data-original=&/50/v2-04ac0d1366_r.jpg&&&p&&br&&/p&&p&PBR Shading之多对性能消耗很大,是因为其光照模型非常的复杂,这个代价对于大部分的低端设备还是不太现实的,我们对PBR做了一些深入研究之后,决定还是走Blinn-Phong这一套,采用的是近似的方法来处理。&/p&&p&通过和美术同学的通力合作,我们得到了一些不错的效果,而且在移动平台,由于屏幕尺寸很小,所以和真实的PBR差别并不是很大。&/p&&p&&br&&/p&&p&&br&&/p&&img src=&/50/v2-a571cccbeac_b.jpg& data-rawwidth=&1125& data-rawheight=&587& class=&origin_image zh-lightbox-thumb& width=&1125& data-original=&/50/v2-a571cccbeac_r.jpg&&&p&&br&&/p&&p&当一提到PBR的时候,你可能第一时间会反应出一个模型拥有不同的质感,比如皮革,金属,木头等等。我们最初就用了Roughness和Metalness来处理,但是我们发现这还不够,原因有两点,对于Roughness和Metalness的计算非常消耗性能,另一个原因是我们的游戏是一个魔幻类的游戏,有时候又不想那么真。最终我们添加了一张新的Reflectivity贴图,这样计算cubemap的反射就非常简单了。&/p&&p&&br&&/p&&p&对于环境光对角色的影响,采用的是分级的Cubemap&/p&&p&&br&&/p&&img src=&/50/v2-5525a56aff9c9dede71e484_b.jpg& data-rawwidth=&1116& data-rawheight=&594& class=&origin_image zh-lightbox-thumb& width=&1116& data-original=&/50/v2-5525a56aff9c9dede71e484_r.jpg&&&p&&br&&/p&&p&同时我们对CubeMap进行了HDR的处理,让暗的地方更暗,亮的地方更亮,这样最终效果会更好一些。&/p&&p&&br&&/p&&p&接下来要说的是&/p&&p&&br&&/p&&img src=&/50/v2-efefcf4103ffd54d0ec7feb_b.jpg& data-rawwidth=&1138& data-rawheight=&599& class=&origin_image zh-lightbox-thumb& width=&1138& data-original=&/50/v2-efefcf4103ffd54d0ec7feb_r.jpg&&&p&&br&&/p&&p&对于动态阴影,我们首先考虑的是Unity自带的阴影系统,他可以适用于很多场合,FPS,TPS等等,但是我们只有俯视角的操作,所以我们实现了自己的基于PCF的阴影系统,比Unity自带的影子系统更快一些,而且可以精准的控制,你们如果要自己来处理阴影的话,最好先考虑下基于自己的游戏能不能做的比Unity更好,同时有没有时间去处理,我们对这两个问题的回答都是yes,所以我们这样做了。&/p&&p&&br&&/p&&p&可以注意到场景中的动态阴影和地面烘培的静态阴影可以完美地Blend,这更加符合真实世界的表现。技术上,对于Lightmap,rgb三个通道用来表示光照的,阴影Bake在alpha 通道里面,最终和动态阴影Blend。&/p&&p&&br&&/p&&p&我们采用的VRay来进行光照的烘培,这是设计师和技术共同的抉择,从技术方面我们可以实现很酷的阴影,美术方面他们可以在Max里面控制烘培的效果,品质也会更高。&/p&&p&&br&&/p&&p&接下来是动态的光照&/p&&p&&br&&/p&&img src=&/50/v2-a8fe0e0cadf5fbfa42a679a_b.jpg& data-rawwidth=&1119& data-rawheight=&577& class=&origin_image zh-lightbox-thumb& width=&1119& data-original=&/50/v2-a8fe0e0cadf5fbfa42a679a_r.jpg&&&p&&br&&/p&&p&我们没有去做Defered rendering,因为这在移动平台上不太现实,而用forward的方式渲染的时候,对于多个光源的情况,需要通过多个Pass来渲染,这也很 expensive,所以我们做了几个不同的shader来处理0个灯光,1个灯光,2个灯光,3个灯光,4个灯光的情况,按照设备的性能来使用对应的shader。&/p&&p&&br&&/p&&p&对于每一个材质我们都可以在编辑器上定义一些渲染状态,&/p&&p&&br&&/p&&img src=&/50/v2-b51eada2510_b.jpg& data-rawwidth=&1113& data-rawheight=&591& class=&origin_image zh-lightbox-thumb& width=&1113& data-original=&/50/v2-b51eada2510_r.jpg&&&p&&br&&/p&&p&为了给设计师充分的空间,我们的Shader通常写得非常复杂&/p&&p&&br&&/p&&img src=&/50/v2-0db6fb2b12bc97d0225fee16_b.jpg& data-rawwidth=&1137& data-rawheight=&587& class=&origin_image zh-lightbox-thumb& width=&1137& data-original=&/50/v2-0db6fb2b12bc97d0225fee16_r.jpg&&&p&&br&&/p&&p&遇到了三个问题&/p&&p&&br&&/p&&img src=&/50/v2-cbde_b.jpg& data-rawwidth=&1131& data-rawheight=&599& class=&origin_image zh-lightbox-thumb& width=&1131& data-original=&/50/v2-cbde_r.jpg&&&p&&br&&/p&&p&分析了一大堆之后,决定自己动手撸一个Variant system&/p&&p&&br&&/p&&img src=&/50/v2-43c5f4f8e1cb172840df_b.jpg& data-rawwidth=&1130& data-rawheight=&581& class=&origin_image zh-lightbox-thumb& width=&1130& data-original=&/50/v2-43c5f4f8e1cb172840df_r.jpg&&&p&&br&&/p&&p&听起来很炫酷,但其实很简单,一共分为两个部分&/p&&p&&br&&/p&&img src=&/50/v2-a8c57def6_b.jpg& data-rawwidth=&1138& data-rawheight=&574& class=&origin_image zh-lightbox-thumb& width=&1138& data-original=&/50/v2-a8c57def6_r.jpg&&&p&&br&&/p&&p&还优化了构建的速度&/p&&p&&br&&/p&&img src=&/50/v2-9e4eef27bf7e0af817e250_b.jpg& data-rawwidth=&1131& data-rawheight=&593& class=&origin_image zh-lightbox-thumb& width=&1131& data-original=&/50/v2-9e4eef27bf7e0af817e250_r.jpg&&&p&&br&&/p&&p&重点,CPU和GPU的优化!我们实际上需要优化的东西有三点,帧率,电量,发热&/p&&p&&br&&/p&&img src=&/50/v2-35ecc27c5ce8b37785decbc6a24531a4_b.jpg& data-rawwidth=&1123& data-rawheight=&594& class=&origin_image zh-lightbox-thumb& width=&1123& data-original=&/50/v2-35ecc27c5ce8b37785decbc6a24531a4_r.jpg&&&p&&br&&/p&&p&做优化的时候,一定要同时考虑三者。首先讲GPU的优化&/p&&p&&br&&/p&&img src=&/50/v2-527c73d7bc485c7defbc223_b.jpg& data-rawwidth=&1122& data-rawheight=&599& class=&origin_image zh-lightbox-thumb& width=&1122& data-original=&/50/v2-527c73d7bc485c7defbc223_r.jpg&&&p&&br&&/p&&p&可以用Adreno Profiler截帧,然后实时改shader生效,这样就解决了重新编译之痛。&/p&&p&&br&&/p&&p&不过Adreno Profiler看到的shader很难看懂,一个trick就是你可以用Unity Editor编译出来的shader直接贴在这里,也可以立即生效。&/p&&p&&br&&/p&&p&在Adreno Profiler还可以看到shader里面指令数量,指令数量越多,消耗肯定就越高&/p&&p&&br&&/p&&img src=&/50/v2-ec1881155cad2ca15bfaa66c75fb50e5_b.jpg& data-rawwidth=&1126& data-rawheight=&584& class=&origin_image zh-lightbox-thumb& width=&1126& data-original=&/50/v2-ec1881155cad2ca15bfaa66c75fb50e5_r.jpg&&&p&&br&&/p&&p&下图中的抖动是因为移动设备的过热保护造成的。下面是很容易踩到的坑,希望你们别踩到了。&/p&&p&&br&&/p&&img src=&/50/v2-ad43e1285fdf_b.jpg& data-rawwidth=&1125& data-rawheight=&598& class=&origin_image zh-lightbox-thumb& width=&1125& data-original=&/50/v2-ad43e1285fdf_r.jpg&&&p&&br&&/p&&p&1. 不要在develop mode来衡量fps,虽然在develop mod可以用来做profiling和找性能瓶颈,但是你所面对的游戏和你的最终用户所面对的游戏是不一样的,很多地方代码消耗都不一样,最不济也是在release版本下在屏幕上放个fps统计。&/p&&p&2. 因为移动设备对于过热会有降频保护,所以在测试的时候,很可能会因为性能波动而造成fps波动,多疑参考第三点&/p&&p&3. 把目标帧率拔高一些作为优化目标,这样在发布的时候帧率恢复到正常帧率就不会出问题了,比如我们在优化60fps的时候是将目标帧率锁定在80的。&/p&&p&&br&&/p&&p&&br&&/p&&p&对于Shader的优化主要是两个点,减少指令数,小心No-ops.&/p&&p&&br&&/p&&img src=&/50/v2-de065f2afd5b65c883a6d_b.jpg& data-rawwidth=&1136& data-rawheight=&599& class=&origin_image zh-lightbox-thumb& width=&1136& data-original=&/50/v2-de065f2afd5b65c883a6d_r.jpg&&&p&&br&&/p&&p&当年我们在做自己的GPU Skinning,下面是一条最简单的蒙皮计算&/p&&p&&br&&/p&&img src=&/50/v2-d2e49f6c3d_b.jpg& data-rawwidth=&835& data-rawheight=&58& class=&origin_image zh-lightbox-thumb& width=&835& data-original=&/50/v2-d2e49f6c3d_r.jpg&&&p&&br&&/p&&p&性能和预期差别太大了,我们在Profiler里面显示有250条No-ops,。结果我们换成下面的形式&/p&&p&&br&&/p&&p&&br&&/p&&img src=&/50/v2-ca3d793ebe5e774cb8837_b.jpg& data-rawwidth=&1029& data-rawheight=&140& class=&origin_image zh-lightbox-thumb& width=&1029& data-original=&/50/v2-ca3d793ebe5e774cb8837_r.jpg&&&p&&br&&/p&&p&快了20%!&/p&&p&&br&&/p&&p&最后一个是用half来替代float,这个在shader里面可以提速很多。不要用fix类型,很多移动GPU是不支持fix的,这些GPU会把fix转成half。&/p&&p&&br&&/p&&img src=&/50/v2-b3ad8ee1794eafafbbf8_b.jpg& data-rawwidth=&1132& data-rawheight=&602& class=&origin_image zh-lightbox-thumb& width=&1132& data-original=&/50/v2-b3ad8ee1794eafafbbf8_r.jpg&&&p&&br&&/p&&p&下一个优化是最简单的优化,缩放分辨率。&/p&&p&对于现在的一些移动设备,分辨率已经大到变态了。比如一些1440p,相对于1080p,gpu要多渲染75%的像素,移动GPU对于填充率是非常敏感的,所以比较好的方案是渲染1080p的图像,然后放大到1440p,在移动平台上通常是发现不了的。&/p&&p&&br&&/p&&img src=&/50/v2-04d879a1f5b06a223ccfb8_b.jpg& data-rawwidth=&744& data-rawheight=&398& class=&origin_image zh-lightbox-thumb& width=&744& data-original=&/50/v2-04d879a1f5b06a223ccfb8_r.jpg&&&p&&br&&/p&&p&缩放的方案也有硬件实现方案和软件实现方案。&/p&&p&&br&&/p&&p&对于现在的移动设备,MSAA是基本免费的(貌似5.6才支持?)。&/p&&p&&br&&/p&&p&由于fillrate对于移动GPU来说很容易变成性能瓶颈,所以下面要说的帧率杀手就是,overdraw。&/p&&p&&br&&/p&&p&Overdraw主要是由于半透明物体的渲染引起的,因为每渲染一个半透明物体,就要很framebuff里面已存在的pixel做blend。不过很难凭人眼去判断overdraw的程度,所以我们做了一个检查overdraw的工具,这些设计师就可以一键检查自己制作的特效是否合格。这个工具免费share给大家。&/p&&p&&br&&/p&&img src=&/50/v2-e2b6d4ca729d_b.jpg& data-rawwidth=&1135& data-rawheight=&595& class=&origin_image zh-lightbox-thumb& width=&1135& data-original=&/50/v2-e2b6d4ca729d_r.jpg&&&p&&br&&/p&&p&上面的都是GPU方面的优化,下面要说一下CPU方面的优化,主要的优化方法我们都尝试了,这里要说的主要是两个方面。&/p&&p&第一,预加载和对象池。首先要说明的一点,io是非常耗时的,所以对于资源最好是采用一些预加载,&/p&&p&包括实例化对象和warm up shader.&/p&&p&关于shader的Warm up,我们的做法是在loading阶段在看不到的地方用所有材质去渲染一个quad。&/p&&p&&br&&/p&&img src=&/50/v2-a5dcfd355e6f_b.jpg& data-rawwidth=&1128& data-rawheight=&590& class=&origin_image zh-lightbox-thumb& width=&1128& data-original=&/50/v2-a5dcfd355e6f_r.jpg&&&p&&br&&/p&&p&第二个点是逻辑Update和渲染Update分离。&/p&&p&我们将逻辑Update用更慢的速度Update,每秒20次,帧与帧之间的结果想办法用插值来处理,相比于每秒60次的update 快了200%。&/p&&p&&br&&/p&&img src=&/50/v2-cef38cc348dee89c834a41_b.jpg& data-rawwidth=&1116& data-rawheight=&592& class=&origin_image zh-lightbox-thumb& width=&1116& data-original=&/50/v2-cef38cc348dee89c834a41_r.jpg&&&p&&br&&/p&&p&最后聊一下画质分级。&/p&&p&主要是跟据GPU来进行画质分级的,不同画质对应着不同的特性。&/p&&p&&br&&/p&&img src=&/50/v2-e31b7e0a17c6fd1c6fd639_b.jpg& data-rawwidth=&1116& data-rawheight=&577& class=&origin_image zh-lightbox-thumb& width=&1116& data-original=&/50/v2-e31b7e0a17c6fd1c6fd639_r.jpg&&&p&&br&&/p&&p&测试方面,我们开发了一个真机上的工具,用来开关这些特性&/p&&p&&br&&/p&&img src=&/50/v2-4c4a4fa3044c15dbfe0d5cf0cc394562_b.jpg& data-rawwidth=&1124& data-rawheight=&620& class=&origin_image zh-lightbox-thumb& width=&1124& data-original=&/50/v2-4c4a4fa3044c15dbfe0d5cf0cc394562_r.jpg&&&p&&br&&/p&&p&这样就可以很快地对设备进行分级了。&/p&&p&&br&&/p&&p&&b&关于游戏的特效也专门有一个talk,这里也简单整理一下。&/b&&/p&&p&&br&&/p&&p&从制作的流程上看,分别有下面三个阶段&/p&&p&&br&&/p&&img src=&/50/v2-f430f8d42ace8d9ea771c63_b.jpg& data-rawwidth=&1114& data-rawheight=&621& class=&origin_image zh-lightbox-thumb& width=&1114& data-original=&/50/v2-f430f8d42ace8d9ea771c63_r.jpg&&&p&&br&&/p&&p&Art通常是创意阶段,给游戏的风格指明方向后面的两个阶段都是以Art为基础和目标。为了给游戏制作独一无二的特效,肯定是需要TECH作为支撑,最后我们需要就是一条打磨得非常完美的流水线,能够让每个人都能够在流水线上发挥自己的才华。&/p&&p&&br&&/p&&p&首先是Art,在设计方向,我们首先需要表达出gameplay想要表达的意思,让玩家能够理解&/p&&p&&br&&/p&&img src=&/50/v2-cd5d468f1eed68_b.jpg& data-rawwidth=&1060& data-rawheight=&564& class=&origin_image zh-lightbox-thumb& width=&1060& data-original=&/50/v2-cd5d468f1eed68_r.jpg&&&p&&br&&/p&&p&&br&&/p&&img src=&/50/v2-7f952af554df88a437019efb2d4e452b_b.jpg& data-rawwidth=&1143& data-rawheight=&643& class=&origin_image zh-lightbox-thumb& width=&1143& data-original=&/50/v2-7f952af554df88a437019efb2d4e452b_r.jpg&&&p&&br&&/p&&p&我们想在保持尽量真实的情况下又有一些风格化&/p&&p&&br&&/p&&p&下面是制作贴图的一些建议&/p&&p&&br&&/p&&img src=&/50/v2-9dec9e74f208694fdfc880a7596fd86d_b.jpg& data-rawwidth=&1149& data-rawheight=&646& class=&origin_image zh-lightbox-thumb& width=&1149& data-original=&/50/v2-9dec9e74f208694fdfc880a7596fd86d_r.jpg&&&p&&br&&/p&&p&下面是动画制作的一些建议。&/p&&p&&br&&/p&&img src=&/50/v2-dedd4ecbed5b9cba2f22ea_b.jpg& data-rawwidth=&1143& data-rawheight=&629& class=&origin_image zh-lightbox-thumb& width=&1143& data-original=&/50/v2-dedd4ecbed5b9cba2f22ea_r.jpg&&&p&&br&&/p&&p&没怎么听懂…&/p&&p&&br&&/p&&p&接下来讲Tech。&/p&&p&通常特效其实是一种折衷,因为设计师总有各种天马行空的想法,但是技术上不一定能实现。实际上技术就是让美术发挥无限的可能性,特别是在移动平台。作为特效设计师,我一直认为在工具和打磨流水线上的投资是值得的。&/p&&p&&br&&/p&&p&我们自定义了作为特效的Shader&/p&&p&&br&&/p&&img src=&/50/v2-54a71da0066abadb1fb33a_b.jpg& data-rawwidth=&747& data-rawheight=&408& class=&origin_image zh-lightbox-thumb& width=&747& data-original=&/50/v2-54a71da0066abadb1fb33a_r.jpg&&&p&&br&&/p&&p&上面有很多特性开关。&/p&&p&&br&&/p&&p&自定义颜色的几种方法&/p&&p&&br&&/p&&img src=&/50/v2-c5e97df4cdd335fd042e2cae3a167a62_b.jpg& data-rawwidth=&1140& data-rawheight=&636& class=&origin_image zh-lightbox-thumb& width=&1140& data-original=&/50/v2-c5e97df4cdd335fd042e2cae3a167a62_r.jpg&&&p&&br&&/p&&p&&br&&/p&&p&可以在shader里面定义很多Color变量,中间做插值渐变,也可以用LUT,,通常推荐用LUT,这样会更灵活,而且对设计师也更加友好,设计师可以用别的图片编辑软件来编辑这张LUT,或者在Unity做一个托渐变的工具也不错。&/p&&p&一张贴图的通道分布&/p&&p&&br&&/p&&img src=&/50/v2-6a34ad499ea2ec01e5375_b.jpg& data-rawwidth=&1128& data-rawheight=&642& class=&origin_image zh-lightbox-thumb& width=&1128& data-original=&/50/v2-6a34ad499ea2ec01e5375_r.jpg&&&p&&br&&/p&&p&减法运算&/p&&p&&br&&/p&&img src=&/50/v2-d005f959bcc3eafb7f1446_b.jpg& data-rawwidth=&1047& data-rawheight=&638& class=&origin_image zh-lightbox-thumb& width=&1047& data-original=&/50/v2-d005f959bcc3eafb7f1446_r.jpg&&&p&&br&&/p&&p&用第二张贴图来控制alpha值,获得更复杂的效果。右边的火焰只用了一个dc就实现,他是由一个sprite sheet和一张alpha mask组成。&/p&&p&&br&&/p&&img src=&/50/v2-f30f9e675660dbde_b.jpg& data-rawwidth=&1025& data-rawheight=&469& class=&origin_image zh-lightbox-thumb& width=&1025& data-original=&/50/v2-f30f9e675660dbde_r.jpg&&&p&&br&&/p&&p&还有裁剪方式与混合模式上效果的变化&/p&&p&&br&&/p&&img src=&/50/v2-5ce3e2b348fb0d8bca7218_b.jpg& data-rawwidth=&1149& data-rawheight=&640& class=&origin_image zh-lightbox-thumb& width=&1149& data-original=&/50/v2-5ce3e2b348fb0d8bca7218_r.jpg&&&p&&br&&/p&&p&在优化方面,主要要优化的有亮点,DC和overdraw,后者更加要注意&/p&&p&&br&&/p&&img src=&/50/v2-43b22c5c74c1b36832adfed_b.jpg& data-rawwidth=&1142& data-rawheight=&635& class=&origin_image zh-lightbox-thumb& width=&1142& data-original=&/50/v2-43b22c5c74c1b36832adfed_r.jpg&&&p&&br&&/p&&p&&br&&/p&&p&对于不同的设备做了LOD,像Glow和Bloom这种后期效果我们基本都是用一些fake的方法去模拟。&/p&&p&&br&&/p&&p&最后是Pipeline&/p&&p&首先是概念设计&/p&&p&&br&&/p&&img src=&/50/v2-fb1fce333b32f_b.jpg& data-rawwidth=&1142& data-rawheight=&644& class=&origin_image zh-lightbox-thumb& width=&1142& data-original=&/50/v2-fb1fce333b32f_r.jpg&&&p&&br&&/p&&p&&br&&/p&&p&我们的特效基本都是基于Mesh制作,可以说我们的特效,90%都是在Mesh上做一些贴图的动画,由于我们的摄像机是固定的,所以我们很多时候都可以采用一些treat的做法。&/p&&p&&br&&/p&&p&重点讲下Morph target,Wiki里面的解释&/p&&p&&br&&/p&&p&&b&Morph target&br&animation&/b&, &b&per-vertex animation&/b&, &b&shape interpolation&/b&, or &b&blend shapes&/b&&a href=&/?target=https%3A//en.wikipedia.org/wiki/Morph_target_animation%23cite_note-Liu-2006-1& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&[1]&i class=&icon-external&&&/i&&/a& is a method of 3D &a href=&/?target=https%3A//en.wikipedia.org/wiki/3D_computer_graphics& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&computer animation&i class=&icon-external&&&/i&&/a& used together with techniques such as &a href=&/?target=https%3A//en.wikipedia.org/wiki/Skeletal_animation& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&skeletal animation&i class=&icon-external&&&/i&&/a&. In a morph target animation, a &deformed& version&br&of a mesh is stored as a series of &a href=&/?target=https%3A//en.wikipedia.org/wiki/Vertex_%28geometry%29& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&vertex&i class=&icon-external&&&/i&&/a& positions. In&br&each &a href=&/?target=https%3A//en.wikipedia.org/wiki/Key_frame& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&key frame&i class=&icon-external&&&/i&&/a& of an&br&animation, the vertices are then &a href=&/?target=https%3A//en.wikipedia.org/wiki/Interpolation& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&interpolated&i class=&icon-external&&&/i&&/a& between these stored positions.&/p&&p&对于变形的mesh,我们通常都使用Marph target这种方法,它很节省性能,这个冰块生长的动画就只使用了5个Morph target就搞定了。&/p&&p&&br&&/p&&img src=&/50/v2-bccf65d1ec3372cdc3c41_b.jpg& data-rawwidth=&1163& data-rawheight=&634& class=&origin_image zh-lightbox-thumb& width=&1163& data-original=&/50/v2-bccf65d1ec3372cdc3c41_r.jpg&&&p&&br&&/p&&p&当实在需要用骨骼的时候,我们通常会限制在10根骨骼以下,每个顶点最多只受两个骨骼影响。&/p&&p&对于贴图,我们是像下面这样分类的。&/p&&p&&br&&/p&&img src=&/50/v2-36cd38170f5aad25f66d_b.jpg& data-rawwidth=&757& data-rawheight=&421& class=&origin_image zh-lightbox-thumb& width=&757& data-original=&/50/v2-36cd38170f5aad25f66d_r.jpg&&&p&&br&&/p&&p&只有在用其它方法完成不了的时候,才使用sprite sheet,比如说闪电或者一些很特别烟。&/p&&p&&br&&/p&&p&在绘制贴图的时候,我们出了手绘,用PS去绘制,还尝试了用Substance基于procedual的方式去制作一些贴图,我觉得它简直是上天赐予给特效设计师的礼物!可能在初期需要付出一些学习成本,但当你逐渐掌握的时候,迭代的效率简直Crazy。&/p&&p&&br&&/p&&p&我们还使用了AE,MAX,Phoenix等工具。&/p&&p&&br&&/p&&p&然后是粒子系统&/p&&p&&br&&/p&&img src=&/50/v2-af4cfcd75d131_b.jpg& data-rawwidth=&1128& data-rawheight=&637& class=&origin_image zh-lightbox-thumb& width=&1128& data-original=&/50/v2-af4cfcd75d131_r.jpg&&&p&&br&&/p&&p&我们不会把粒子作为一个特效的主体,而只是把它作为一些调料加载特效里面,不过对于一些很依赖随机性的东西,我们只能用粒子系统去做,不过要遵循一定的约束。&/p&&p&&br&&/p&&p&最终在整合的时候,我们使用的是Unity的Animation system.&/p&&p&&br&&/p&&img src=&/50/v2-abaa1fff4d4a_b.jpg& data-rawwidth=&1172& data-rawheight=&641& class=&origin_image zh-lightbox-thumb& width=&1172& data-original=&/50/v2-abaa1fff4d4a_r.jpg&&&p&&br&&/p&&p&特效的每一个阶段都是一个Animation clip,通过时间来触发状态的切换,通过Layer来对特效进行分层。我们基本不使用Animationd的transition而是直接跳转,因为很多东西没法Blend。&/p&&p&&br&&/p&&p&最后举了一个特效的例子&/p&&p&&br&&/p&&img src=&/50/v2-c5a47c20bdb9db9731075fd_b.jpg& data-rawwidth=&740& data-rawheight=&409& class=&origin_image zh-lightbox-thumb& width=&740& data-original=&/50/v2-c5a47c20bdb9db9731075fd_r.jpg&&&p&&br&&/p&&p&完全没有用到粒子系统.&/p&&p&&br&&/p&&p&&b&Link&/b&&/p&&p&&a href=&/?target=https%3A///watch%3Fv%3DYZWKdw03Gls& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Unite Europe 2017 - The Real-time VFX of Spellsouls&i class=&icon-external&&&/i&&/a& \&/p&&p&&a href=&/?target=https%3A///watch%3Fv%3DvJZcbscZ4-o%26t%3D2979s& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Unite Europe 2017 - The AAA graphics of Spellsouls: achieving 60FPS on mobile&i class=&icon-external&&&/i&&/a&&/p&&p&&/p&&p&&/p&
就在近期的Unite Europe 2017 中,有两个talk比较有意思,分别是The AAA graphics of Spellsouls: achieving 60FPS on mobile 和 The Real-time VFX of Spellsouls,恰好最近在做一些优化方面的工作,就一起学习了一下。 游戏官方介绍说是一个Moba类的卡牌…
&img src=&/50/v2-1ce745e4fce5fb_b.jpg& data-rawwidth=&1000& data-rawheight=&419& class=&origin_image zh-lightbox-thumb& width=&1000& data-original=&/50/v2-1ce745e4fce5fb_r.jpg&&&p&在计算机图形学中,BRDF(Bidirectional Reflectance Distribution Function,双向反射分布函数)是真实感图形学中最核心的概念之一,它描述的是物体表面将光能从任何一个入射方向反射到任何一个视点方向的反射特性,即入射光线经过某个表面反射后如何在各个出射方向上分布。BRDF模型是绝大多数图形学算法中用于描述光反射现象的基本模型。&/p&&p&&br&&/p&&p&这篇文章,将专注于总结和提炼《Real-Time Rendering 3rd》(实时渲染图形学第三版)中第七章“Advanced Shading · 高级着色”的内容,并对这章中介绍BRDF的内容进行适当补充和引申,构成全文,成为一个对BRDF进行近乎系统式总结的文章。&/p&&img src=&/v2-f6fc209fbe014c13553b65d_b.jpg& data-rawwidth=&860& data-rawheight=&360& class=&origin_image zh-lightbox-thumb& width=&860& data-original=&/v2-f6fc209fbe014c13553b65d_r.jpg&&&p&
图1 基于BRDF渲染的场景图 (C)Disney 2014.《超能陆战队》&/p&&p&&br&&/p&&p&&br&&/p&&h2&一、导读&/h2&&p&&br&&/p&&p&简而言之,通过阅读这篇总结式文章,你将对BRDF的以下要点有所了解:&/p&&ul&&li&一、BRDF的前置知识 · 数学篇&/li&&ul&&li&球面坐标 Spherical Coordinate&/li&&li&立体角 Solid Angle&/li&&li&投影面积 Foreshortened Area&/li&&/ul&&li&二、BRDF前置知识 · 辐射度量学篇&/li&&ul&&li&辐射度量学基本参数表格&/li&&li&辐射通量/光通量 Radiant Flux&/li&&li&辐射强度/发光强度 Radiant Intensity&/li&&li&辐射率/光亮度 Radiance&/li&&li&辐照度/辉度 Irradiance &/li&&/ul&&li&三、BRDF的定义与理解&/li&&ul&&li&BRDF的定义式&/li&&li&BRDF的非微分形式&/li&&li&BRDF与着色方程&/li&&li&BRDF的可视化表示 &/li&&/ul&&li&四、BRDF的性质&/li&&ul&&li&亥姆霍兹光路可逆性&/li&&li&能量守恒性质&/li&&li&线性特征&/li&&/ul&&li&五、BRDF模型的分类&/li&&ul&&li&BRDF经验模型&/li&&li&数据驱动的BRDF模型&/li&&li&基于物理的BRDF模型&/li&&/ul&&li&六、基于物理的BRDF · 前置知识&/li&&ul&&li&次表面散射 Subsurface Scattering&/li&&li&菲涅尔反射 Fresnel Reflectance&/li&&li&微平面理论 Microfacet Theory&/li&&/ul&&li&七、基于物理的BRDF · 常见模型&/li&&ul&&li&Cook-Torrance BRDF模型&/li&&li&Ward BRDF模型&/li&&/ul&&li&八、BRDF与其引申&/li&&ul&&li&BSSRDF&/li&&li&SBRDF(SVBRDF)&/li&&li&BTDF与BSDF&/li&&/ul&&/ul&&p&&br&&/p&&p&&br&&/p&&p&&br&&/p&&h2&二 、BRDF前置知识· 数学篇&/h2&&p&&br&&/p&&p&&br&&/p&&p&在正式了解BRDF的概念之前,有必要先了解数学和辐射度量学相关的前置基础知识。&/p&&p&&br&&/p&&h2&2.1 球面坐标 SphericalCoordinate&/h2&&p&由于光线主要是通过方向来表达,通常用球面坐标表达它们比用笛卡尔坐标系更方便。&/p&&p&如图,球面坐标中的向量用三个元素来指定:&/p&&p&&br&&/p&&p&&br&&/p&&img src=&/v2-3a9d90a8c08cb97dd163cf57e03cdb82_b.png& data-rawwidth=&558& data-rawheight=&516& class=&origin_image zh-lightbox-thumb& width=&558& data-original=&/v2-3a9d90a8c08cb97dd163cf57e03cdb82_r.png&&&p&
图2 球面坐标&/p&&p&其中:&/p&&p&&br&&/p&&ul&&li&r表示向量的长度&/li&&li&θ表示向量和Z轴的夹角&/li&&li&Φ表示向量在x-y平面上的投影和x轴的逆时针夹角。&/li&&/ul&&p&&br&&/p&&p&&br&&/p&&h2&2.2 立体角 Solid Angle&/h2&&p&立体角描述了从原点向一个球面区域张成的视野大小,可以看成是弧度的三维扩展。&/p&&p&&br&&/p&&img src=&/v2-bec5d6cf7f8ef_b.jpg& data-rawwidth=&336& data-rawheight=&304& class=&content_image& width=&336&&&p&
图3 立体角&/p&&p&我们知道弧度是度量二维角度的量,等于角度在单位圆上对应的弧长,单位圆的周长是2π,所以整个圆对应的弧度也是2π 。立体角则是度量三维角度的量,用符号Ω表示,单位为立体弧度(也叫球面度,Steradian,简写为sr),等于立体角在单位球上对应的区域的面积(实际上也就是在任意半径的球上的面积除以半径的平方ω= s/r2 ),单位球的表面积是4π ,所以整个球面的立体角也是4π 。&/p&&p&&br&&/p&&img src=&/v2-aa49a4bd7b4_b.jpg& data-rawwidth=&245& data-rawheight=&203& class=&content_image& width=&245&&&p&
图4 立体角&/p&&p&&br&&/p&&p&立体角ω有如下微分形式:&/p&&p&&img src=&/equation?tex=d%5Comega+%3D%5Cfrac%7BdA%7D%7Br%5E%7B2%7D%7D& alt=&d\omega =\frac{dA}{r^{2}}& eeimg=&1&&&/p&&p&其中&i&dA&/i&为面积微元。而面积微元&i&dA&/i&在球面坐标系下可以写成:&/p&&p&&img src=&/equation?tex=dA%3D%28rd%5Ctheta+%29%28rsin%5Ctheta+d%5Cvarphi+%29%3Dr%5E%7B2%7Dsin%5Ctheta+d%5Ctheta+d%5Cvarphi+& alt=&dA=(rd\theta )(rsin\theta d\varphi )=r^{2}sin\theta d\theta d\varphi & eeimg=&1&&&/p&&p&&br&&/p&&p&因此:&/p&&p&&img src=&/equation?tex=d%5Comega+%3D%5Cfrac%7BdA%7D%7Br%5E%7B2%7D%7D%3Dsin%5Ctheta+d%5Ctheta+d%5Cvarphi+& alt=&d\omega =\frac{dA}{r^{2}}=sin\theta d\theta d\varphi & eeimg=&1&&&/p&&p&&br&&/p&&p&&br&&/p&&h2&2.3 投影面积 Foreshortened Area&/h2&&p&投影面积描述了一个物体表面的微小区域在某个视线方向上的可见面积。&/p&&p&对于面积微元A,则沿着与法向夹角为θ方向的A的可见面积为:&/p&&p&&img src=&/equation?tex=Area%3DAcos%5Ctheta+& alt=&Area=Acos\theta & eeimg=&1&&&/p&&p&&br&&/p&&p&&br&&/p&&img src=&/v2-ffacb5b147db_b.jpg& data-rawwidth=&828& data-rawheight=&534& class=&origin_image zh-lightbox-thumb& width=&828& data-original=&/v2-ffacb5b147db_r.jpg&&&p&
图5 投影面积&/p&&p&&br&&/p&&p&&br&&/p&&p&&br&&/p&&h2&三、BRDF前置知识· 辐射度量学篇&/h2&&p&&br&&/p&&h2&3.1 辐射度量学基本参数表格&/h2&&p&如下是截取的wiki(&a href=&/?target=https%3A//en.wikipedia.org/wiki/Radiometry& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&en.wikipedia.org/wiki/R&/span&&span class=&invisible&&adiometry&/span&&span class=&ellipsis&&&/span&&i class=&icon-external&&&/i&&/a&))上的辐射度量学国际单位制的辐射量参数表格:&/p&&img src=&/v2-cc666acd2eecbdc81d5ceff6cda67917_b.jpg& data-rawwidth=&1232& data-rawheight=&731& class=&origin_image zh-lightbox-thumb& width=&1232& data-original=&/v2-cc666acd2eecbdc81d5ceff6cda67917_r.jpg&&&p&&br&&/p&&p&下面对几个核心的基本量进行分别介绍。&/p&&p&&br&&/p&&p&&br&&/p&&h2&3.2 辐射通量/光通量 Radiant Flux&/h2&&p&辐射通量(Radiant Flux,又译作光通量,辐射功率)描述的是在单位时间穿过截面的光能,或每单位时间的辐射能量,通常用Φ来表示,单位是W,瓦特。&/p&&p&&img src=&/equation?tex=%5CPhi+%3D%5Cfrac%7BdQ%7D%7Bdt%7D& alt=&\Phi =\frac{dQ}{dt}& eeimg=&1&&&/p&&p&其中的Q表示辐射能(Radiant energy),单位是J,焦耳。&/p&&p&&br&&/p&&p&&br&&/p&&h2&3.3 辐射强度/发光强度 Radiant Intensity&/h2&&p&对一个点(比如说点光源)来说,辐射强度表示每单位立体角的辐射通量,用符号I表示,单位 &img src=&/equation?tex=W%5Ccdot+sr%5E%7B-1%7D& alt=&W\cdot sr^{-1}& eeimg=&1&& :&/p&&p&&img src=&/equation?tex=I%3D%5Cfrac%7Bd%5CPhi+%7D%7Bd%5Comega+%7D& alt=&I=\frac{d\Phi }{d\omega }& eeimg=&1&&&/p&&p&概括一下:辐射强度(Radiant intensity,又译作发光强度),表示每单位立体角的辐射通量,通常用符号I表示,单位 &img src=&/equation?tex=W%5Ccdot+sr%5E%7B-1%7D& alt=&W\cdot sr^{-1}& eeimg=&1&& ,瓦特每球面度。&/p&&p&&br&&/p&&p&&br&&/p&&p&&br&&/p&&h2&3.4 辐射率/光亮度 Radiance&/h2&&p&辐射率(Radiance,又译作光亮度,用符号L表示),表示物体表面沿某一方向的明亮程度,它等于每单位投影面积和单位立体角上的辐射通量,单位是W·sr-1·m-2,瓦特每球面度每平方米。在光学中,光源的辐射率,是描述非点光源时光源单位面积强度的物理量,定义为在指定方向上的单位立体角和垂直此方向的单位面积上的辐射通量。光亮度L也可以理解为发光程度I在表面dA上的积分。&/p&&p&一种直观的辐射率的理解方法是:将辐射率理解为物体表面的微面元所接收的来自于某方向光源的单位面积的光通量,因此截面选用垂直于该方向的截面,其面积按阴影面积技术计算。&/p&&p&&br&&/p&&p&辐射率的微分形式:&/p&&p&&img src=&/equation?tex=L%3D%5Cfrac%7Bd%5E%7B2%7D%5CPhi+%7D%7BdAcos%5Ctheta+d%5Comega+%7D& alt=&L=\frac{d^{2}\Phi }{dAcos\theta d\omega }& eeimg=&1&&&/p&&p&其中:Φ是辐射通量,单位瓦特(W);Ω是立体角,单位球面度(sr)。&/p&&p&另外需要注意的是,辐射率使用物体表面沿目标方向上的投影面积,而不是面积。&/p&&p&&br&&/p&&p&概括一下:辐射率(Radiance,又译作光亮度),表示每单位立体角每单位投影面积的辐射通量,通常用符号L表示,单位是 &img src=&/equation?tex=W%5Ccdot+sr%5E%7B-1%7D%C2%B7m%5E%7B-2%7D& alt=&W\cdot sr^{-1}·m^{-2}& eeimg=&1&& ,瓦特每球面度每平方米。&/p&&p&&br&&/p&&p&&br&&/p&&p&&br&&/p&&h2&3.5 辐照度/辉度 Irradiance&/h2&&p&辐照度(Irradiance,又译作辉度,辐射照度,用符号E表示),指入射表面的辐射通量,即单位时间内到达单位面积的辐射通量,或到达单位面积的辐射通量,也就是辐射通量对于面积的密度,&/p&&p&用符号E表示,单位 &img src=&/equation?tex=W%2Fm%5E%7B2%7D& alt=&W/m^{2}& eeimg=&1&& ,瓦特每平方米。&/p&&p&辐照度可以写成辐射率(Radiance)在入射光所形成的半球上的积分:&/p&&p&&img src=&/equation?tex=%5Cfrac%7Bd%5CPhi+%7D%7BdA%7D%3DE%3D%5Cint_%7B%5COmega%7D+%5E%7B%7D+L%28%5Comega+%29cos+%5Ctheta+d%5Comega+& alt=&\frac{d\Phi }{dA}=E=\int_{\Omega} ^{} L(\omega )cos \theta d\omega & eeimg=&1&&&/p&&p&其中,Ω是入射光所形成的半球。L(ω)是沿ω方向的光亮度。&/p&&p&&br&&/p&&p&概括一下:辐照度(Irradiance,又译作辉度,辐射照度),表示单位时间内到达单位面积的辐射通量,也就是辐射通量对于面积的密度,通常用符号E表示,单位 &img src=&/equation?tex=W+%2Fm%5E%7B2%7D& alt=&W /m^{2}& eeimg=&1&& ,瓦特每平方米。&/p&&p&&br&&/p&&p&&br&&/p&&p&&br&&/p&&p&&br&&/p&&h2&四、BRDF的定义与理解&/h2&&p&&br&&/p&&p&&br&&/p&&h2&4.1 BRDF的定义式&/h2&&p&可以将给一个表面着色的过程,理解为给定入射的光线数量和方向,计算出指定方向的出射光亮度(radiance)。,在计算机图形学领域,BRDF (Bidirectional Reflectance Distribution Function,译作双向反射分布函数 )是一个用来描述表面如何反射光线的方程。顾名思义,BRDF就是一个描述光如何从给定的两个方向(入射光方向l和出射方向v)在表面进行反射的函数。&/p&&p&BRDF的精确定义是出射辐射率的微分(differential outgoing radiance)和入射辐照度的微分(differential incoming irradiance)之比:&/p&&p&&img src=&/equation?tex=f%28l%2C+v%29+%3D+%5Cfrac%7Bd+L_%7Bo%7D+%28v%29+%7D%7Bd+E%28l%29%7D+& alt=&f(l, v) = \frac{d L_{o} (v) }{d E(l)} & eeimg=&1&&&/p&&p&要理解这个方程的含义,可以想象一个表面被一个来自围绕着角度&b&l&/b&的微立体角的入射光照亮,而这个光照效果由表面的辉度dE来决定。&/p&&p&表面会反射此入射光到很多不同的方向,在给定的任意出射方向v,光亮度dLo与辐照度dE成一个比例。而两者之间的这个取决于l和v的比例,就是BRDF。&/p&&p&&br&&/p&&img src=&/v2-93f33bc09230b59aadc38d40faaa94cf_b.jpg& data-rawwidth=&1330& data-rawheight=&635& class=&origin_image zh-lightbox-thumb& width=&1330& data-original=&/v2-93f33bc09230b59aadc38d40faaa94cf_r.jpg&&&p&
图6 BRDF图示&/p&&p&&br&&/p&&p&一个最常见的疑问是,BRDF为什么要取这样的定义。BRDF为什么被定义为辐射率(radiance)和辐照度(irradiance)之比,而不是radiance和radiance之比,或者irradiance和irradiance之比呢?&/p&&p&&br&&/p&&p&首先,我们分别重温它们的定义:&/p&&ul&&li&辐照度(Irradiance,又译作辉度,辐射照度),表示单位时间内到达单位面积的辐射通量,也就是辐射通量对于面积的密度,通常用符号E表示,单位 &img src=&/equation?tex=W%5Ccdot+m%5E%7B-2%7D& alt=&W\cdot m^{-2}& eeimg=&1&& ,瓦特每平方米。&/li&&li&辐射率(Radiance,又译作光亮度),表示每单位立体角每单位投影面积的辐射通量,通常用符号L表示,单位是 &img src=&/equation?tex=W%5Ccdot+sr%5E%7B-1%7D%C2%B7m%5E%7B-2%7D& alt=&W\cdot sr^{-1}·m^{-2}& eeimg=&1&& ,瓦特每球面度每平方米。&/li&&/ul&&p&那么,关于这个问题,我们可以这样理解:因为照射到入射点的不同方向的光,都可能从指定的反射方向出射,所以当考虑入射时,需要对面积进行积分。而辐照度irradiance正好表示单位时间内到达单位面积的辐射通量。所以BRDF函数,选取入射时的辐照度Irradiance,和出射时的辐射率Radiance,可以简单明了地描述出入射光线经过某个表面反射后如何在各个出射方向上分布。而直观来说,BRDF的值给定了入射方向和出射方向能量的相对量。&/p&&p&&br&&/p&&p&概括一下:BRDF(Bidirectional Reflectance Distribution Function,译作双向反射分布函数 ),定义为出射辐射率的微分(differential outgoing radiance)和入射辐照度的微分(differential incoming irradiance)之比,描述了入射光线经过某个表面反射后如何在各个出射方向上分布,给定了入射方向和出射方向能量的相对量,单位是 &img src=&/equation?tex=sr%5E%7B-1%7D& alt=&sr^{-1}& eeimg=&1&& ,每球面度。&/p&&p&&br&&/p&&p&&br&&/p&&h2&4.2 BRDF的非微分形式&/h2&&p&这里的讨论仅限于非区域光源,如点光源或方向光源。在这种情况下,BRDF定义可以用非微分形式表示: &/p&&p&&img src=&/equation?tex=f%28l%2C+v%29+%3D+%5Cfrac%7BL_%7Bo%7D%28v%29%7D%7B+E%28l%29%5Coverline%7Bcos%7D+%5Ctheta+_i%7D& alt=&f(l, v) = \frac{L_{o}(v)}{ E(l)\overline{cos} \theta _i}& eeimg=&1&&&/p&&p&其中:&/p&&ul&&li&EL是光源在垂直于光的方向向量L平面测量的辐照度(irradiance)。&/li&&li&Lo(v)是在视图矢量v的方向上产生的出射辐射率(radiance)。&/li&&/ul&&p&&br&&/p&&p&&br&&/p&&h2&4.3 BRDF与着色方程&/h2&&p&根据上文所了解了BRDF的定义,现在,就很容易得到BRDF是如何用n个非区域光来拟合一般的着色方程的: &/p&&p&&img src=&/equation?tex=L_o%28v%29+%3D+%5Csum_%7Bk+%3D+1%7D%5E%7Bn%7D%7Bf%28l_k%2C+v%29+%5Cotimes+E_%7BL_k%7D+cos+%5Ctheta_%7Bi_k%7D%7D+& alt=&L_o(v) = \sum_{k = 1}^{n}{f(l_k, v) \otimes E_{L_k} cos \theta_{i_k}} & eeimg=&1&&&/p&&p&其中k是每个光源的索引。使用?符号(分段向量乘法),是因为BRDF和辉度(irradiance)都是RGB向量。考虑到入射和出射方向都拥有两个自由度(通常参数化是使用两个角度:相对于表面法线的仰角θ和关于法线的旋转角度&i&φ&/i&),一般情况下,BRDF是拥有四个标量变量的函数。&/p&&p&另外,各向同性BRDFs(Isotropic BRDFs)是一个重要的特殊情况。这样的BRDF在输入和输入方向围绕表面法线变化(保持相同的相对夹角)时保持不变。所以,各向同性BRDF是关于三个标量的函数。&/p&&p&&br&&/p&&p&&br&&/p&&h2&4.4 对BRDF的可视化表示&/h2&&p&一种理解BRDF的方法就是在输入方向保持恒定的情况下对它进行可视化表示,如下图。对于给定方向的入射光来说,图中显示了出射光的能力分布:在交点附近球形部分是漫反射分量,因此出射光来任何方向上的反射概率相等。椭圆部分是一个反射波瓣(Reflectance Lobe)。它形成了镜面分量。显然,这些波瓣位于入射光的反射方向上,波瓣厚度对应反射的模糊性。根据互易原理,可以将这些相同的可视化形成认为是每个不同入射光方向对单个出射方向的贡献量大小。&/p&&img src=&/v2-30c53540adf08ae1f1f95a0_b.jpg& data-rawwidth=&1231& data-rawheight=&633& class=&origin_image zh-lightbox-thumb& width=&1231& data-original=&/v2-30c53540adf08ae1f1f95a0_r.jpg&&&p&
图7 BRDF的可视化表示&/p&&p&&br&&/p&&p&&br&&/p&&h2&五、BRDF的性质&/h2&&p&&br&&/p&&p&&br&&/p&&h2&5.1 可逆性&/h2&&p&BRDF的可逆性源自于亥姆霍兹光路可逆性(Helmholtz Recoprpcity Rule)。&/p&&p&BRDF的可逆性即,交换入射光与反射光,并不会改变BRDF的值:&/p&&p&&img src=&/equation?tex=f%28l%2Cv%29%3Df%28v%2Cl%29& alt=&f(l,v)=f(v,l)& eeimg=&1&&&/p&&p&&br&&/p&&p&&br&&/p&&h2&5.2 能量守恒性质&/h2&&p&BRDF需要遵循能量守恒定律。能量守恒定律指出:入射光的能量与出射光能量总能量应该相等。能量守恒方程如下:&/p&&p&&img src=&/equation?tex=Q_%7Bincoming%7D%3DQ_%7Breflected%7D%2BQ_%7Babsorb%7D%2BQ_%7Btransmitted%7D& alt=&Q_{incoming}=Q_{reflected}+Q_{absorb}+Q_{transmitted}& eeimg=&1&&&/p&&p&由此可知:&/p&&p&&img src=&/equation?tex=Q_%7Breflected%7D+%5Cleq+Q_%7Bincoming%7D& alt=&Q_{reflected} \leq Q_{incoming}& eeimg=&1&&&/p&&p&因此BRDF必须满足如下的积分不等式,也就是能量守恒性质:&/p&&p&&img src=&/equation?tex=%5Cforall+l%2C%5C%2C+%5Cint_%5COmega+f_%7B%5Ctext%7Br%7D%7D%28l%2Cv%29%5C%2Ccos+v+dv+%5Cle+1& alt=&\forall l,\, \int_\Omega f_{\text{r}}(l,v)\,cos v dv \le 1& eeimg=&1&&&/p&&p&&br&&/p&&p&&br&&/p&&h2&5.3 线性特征&/h2&&p&很多时候,材质往往需要多重BRDF计算以实现其反射特性。表面上某一点的全部反射辐射度可以简单地表示为各BRDF反射辐射度之和。例如,镜面漫反射即可通过多重BRDF计算加以实现。&/p&&p&&br&&/p&&p&&br&&/p&&h2&六、BRDF的模型分类&/h2&&p&&br&&/p&&p&根据BRDF的定义来直接应用,会有一些无从下手的感觉。而为了方便和高效地使用BRDF数据,大家往往将BRDF组织成为各种参数化的数值模型。&/p&&p&有各式各样的BRDF模型,如:&/p&&ul&&li&Phong (1975)&/li&&li&Blinn-Phong (1977)&/li&&li&Cook-Torrance (1981)&/li&&li&Ward (1992)&/li&&li&Oren-Nayar (1994)&/li&&li&Schlick (1994)&/li&&li&Modified-Phong (Lafortune 1994)&/li&&li&Lafortune (1997)&/li&&li&Neumann-Neumann (1999)&/li&&li&Albedo pump-up (Neumann-Neumann 1999)&/li&&li&Ashikhmin-Shirley (2000)&/li&&li&Kelemen (2001)&/li&&li&Halfway Vector Disk (Edwards 2006)&/li&&li&GGX (Walter 2007)&/li&&li&Distribution-based BRDF (Ashikmin 2007)&/li&&li&Kurt (2010)&/li&&li&etc.&/li&&/ul&&p&这些BRDF的模型可以分为如下几类:&/p&&ul&&li&经验模型(Empirical Models):使用基于实验提出的公式对BRDF做快速估计。&/li&&li&数据驱动的模型(Data-driven Models):采集真实材质表面在不同光照角度和观察角将BRDF按照实测数据建立查找表,记录在数据库中,以便于快速的查找和计算。&/li&&li&基于物理的模型(Physical-based Models):根据物体表面材料的几何以及光学属性建立反射方程,从而计算BRDF,实现极具真实感的渲染效果。&/li&&/ul&&p&&br&&/p&&p&&br&&/p&&h2&6.1 BRDF经验模型&/h2&&p&关于BRDF的经验模型,有如下几个要点:&/p&&ul&&li&经验模型提供简洁的公式以便于反射光线的快速计算。&/li&&li&经验模型不考虑材质特性,仅仅提供一个反射光的粗糙近似。&/li&&li&经验模型不一定满足物理定律,比如Helmholtz可逆性或能量守恒定律。&/li&&li&经验模型因为其简洁和高效性被广泛运用。&/li&&/ul&&p&常见的BRDF经验模型有:&/p&&ul&&li&Lambert漫反射模型&/li&&li&Phong模型&/li&&li&Blinn-Phong模型&/li&&li&快速Phong模型&/li&&li&可逆Phong模型&/li&&/ul&&p&Lambert模型,Phong模型、Blinn-Phong模型和其改进模型都是常见的光照模型,由于篇幅原因,就不展开论述了。&/p&&p&&br&&/p&&p&&br&&/p&&p&&br&&/p&&h2&6.2 数据驱动的BRDF模型&/h2&&p&数据驱动的BRDF模型可以理解为,度量一个大的BRDF材质集合,并将其记录为高维向量,利用降维的方法从这些数据中计算出一个低维模型,这样基于查表的方式,可以直接找到渲染结果,省去大量的实时计算。代表工作如:A Data-Driven Reflectance Model,ACM SIGGRAPH,2003 &a href=&/?target=http%3A//people.csail.mit.edu/wojciech/DDRM/index.html& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&people.csail.mit.edu/wo&/span&&span class=&invisible&&jciech/DDRM/index.html&/span&&span class=&ellipsis&&&/span&&i class=&icon-external&&&/i&&/a&&/p&&p&&br&&/p&&p&另外,MERL等实验室使用各类仪器测量了上多种真实材质表面在不同光照角度和观察角度下的反射数据,并记录在数据库中,如MERL BRDF Database。&/p&&img src=&/v2-eb46eba411a3437_b.jpg& data-rawwidth=&1426& data-rawheight=&1480& class=&origin_image zh-lightbox-thumb& width=&1426& data-original=&/v2-eb46eba411a3437_r.jpg&&&p&图8 一个名为“MERL 100”的BRDF数据库。其中,含50种“光滑材质”(例如金属和塑料),和50种“粗糙材质”(例如纺织物)&/p&&p&&br&&/p&&p&需要注意的是,由于这些数据由于采集自真实材质,即便渲染出来的结果很真实,但缺点是没有可供调整效果的参数,无法基于这些数据修改成想要的效果,另外部分极端角度由于仪器限制,无法获取到数据,而且采样点密集,数据量非常庞大,所以并不适合游戏等实时领域,一般可用在电影等离线渲染领域,也可以用来做图形学研究,衡量其他模型的真实程度。&/p&&p&这边提供一些数据库的链接供参考:&/p&&ul&&li&MERLBRDF Database: &a href=&/?target=http%3A///brdf/& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://www.&/span&&span class=&visible&&/brdf/&/span&&span class=&invisible&&&/span&&i class=&icon-external&&&/i&&/a&&/li&&li&MITCSAIL: &a href=&/?target=http%3A//people.csail.mit.edu/addy/research/brdf/& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&people.csail.mit.edu/ad&/span&&span class=&invisible&&dy/research/brdf/&/span&&span class=&ellipsis&&&/span&&i class=&icon-external&&&/i&&/a&&/li&&li&CAVE Database:&a href=&/?target=http%3A//www1.cs.columbia.edu/CAVE/databases/tvbrdf/about.php& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&www1.cs.columbia.edu/CA&/span&&span class=&invisible&&VE/databases/tvbrdf/about.php&/span&&span class=&ellipsis&&&/span&&i class=&icon-external&&&/i&&/a&&/li&&/ul&&p&&br&&/p&&p&&br&&/p&&h2&6.3 基于物理的BRDF模型&/h2&&p&基于物理的渲染(PBR, Physically-based rendering)是计算机图形学中用数学建模的方式模拟物体表面各种材质散射光线的属性从而渲染照片真实图片的技术,是近年来是实时渲染领域的大趋势。&/p&&p&基于物理的BRDF模型通过包含材质的各种几何及光学性质来尽可能精确的近似现实世界中的材料。而一个基于物理的BRDF要必须满足至少如下两条BRDF的特性:能量守恒、亥姆霍兹光路可逆性。&/p&&p&常见的基于物理的BRDF模型有:&/p&&ul&&li&Cook-Torrance BRDF模型&/li&&li&Ward BRDF模型&/li&&/ul&&p&下文将先介绍基于物理的BRDF常常用到到的菲涅尔反射,次表面散射和微平面理论等理论,分别概括这两种基于物理的BRDF模型。&/p&&p&&br&&/p&&p&&br&&/p&&p&&br&&/p&&h2&七、基于物理的BRDF · 前置知识&/h2&&p&&br&&/p&&p&&br&&/p&&h2&7.1 次表面散射 Subsurface Scattering&/h2&&p&在真实世界中许多物体都是半透明的,比如皮肤、玉、蜡、大理石、牛奶等。当光入射到透明或半透明材料表面时,一部分被反射,一部分被吸收,还有一部分经历透射。这些半透明的材质受到数个光源的透射,物体本身就会受到材质的厚度影响而显示出不同的透光性,光线在这些透射部分也可以互相混合、干涉。&/p&&p&次表面散射,Subsurface Scattering,简称SSS(又简称3S),就是光射入半透明材质后在内部发生散射,最后射出物体并进入视野中产生的现象,是指光从表面进入物体经过内部散射,然后又通过物体表面的其他顶点出射的光线传递过程。&/p&&img src=&/v2-c5a2ed14d4a645ea43bf8a_b.jpg& data-rawwidth=&1191& data-rawheight=&670& class=&origin_image zh-lightbox-thumb& width=&1191& data-original=&/v2-c5a2ed14d4a645ea43bf8a_r.jpg&&&p&图9 次表面散射示例1&/p&&img src=&/v2-df3f18d73a0bf579acbccba674e7d207_b.jpg& data-rawwidth=&1045& data-rawheight=&995& class=&origin_image zh-lightbox-thumb& width=&1045& data-original=&/v2-df3f18d73a0bf579acbccba674e7d207_r.jpg&&&p&图10 次表面散射示例2&/p&&p&&br&&/p&&p&又如文章开头,贴出的《超能陆战队》中大白的渲染照中,大白的白色身体,略微有些透明的感觉,就是典型的次表面散射。&/p&&p&简而言之:次表面散射,即光射入表面,在材质里散射,然后从与射入点不同的地方射出表面的一种现象。&/p&&p&&br&&/p&&img src=&/v2-520ba8bd631bdeb88e6fbf_b.jpg& data-rawwidth=&1440& data-rawheight=&414& class=&origin_image zh-lightbox-thumb& width=&1440& data-original=&/v2-520ba8bd631bdeb88e6fbf_r.jpg&&&p&图11 光与表面的相互作用。左图,可以看到次表面相互作用导致光从入口点重新射出。红色和绿色圆圈代表两个不同尺度下的像素所覆盖的区域。在右边,所有的次表面散射光都是从入口点发出的,忽略了表面之下的细节。&/p&&p&&br&&/p&&p&&br&&/p&&p&&br&&/p&&h2&7.2 菲涅尔反射 Fresnel Reflectance&/h2&&p&菲涅耳方程(Fresnel equations)是一组用于描述光在两种不同折射率的介质中传播时的反射和折射的光学方程。方程中所描述的反射被称作“菲涅耳反射”。&/p&&p&菲涅尔反射(Fresnel Reflectance)或者菲涅尔效果(Fresnel Effect),即当光入射到折射率不同的两个材质的分界面时,一部分光会被反射,而我们所看到的光线会根据我们的观察角度以不同强度反射的现象。&/p&&p&菲涅尔反射能够真实地模拟真实世界中的反射。在真实世界中,除了金属之外,其它物质均有不同程度的菲涅尔反射效果。&/p&&p&关于菲涅尔反射,一个很好的例子是一池清水。从水池上笔直看下去(也就是与法线成零度角的方向)的话,我们能够一直看到池底。而如果从接近平行于水面的方向看去的话,水池表面的高光反射会变得非常强以至于你看不到池底。&/p&&img src=&/v2-bfbd9c7b2f375b41bbed6be6dd719940_b.jpg& data-rawwidth=&4280& data-rawheight=&2843& class=&origin_image zh-lightbox-thumb& width=&4280& data-original=&/v2-bfbd9c7b2f375b41bbed6be6dd719940_r.jpg&&&p&图12 菲涅尔反射效果&/p&&p&&br&&/p&&p&简单来说,视线垂直于表面时,反射较弱,而当视线并非垂直表面时,夹角越小,反射越明显。&/p&&p&对于粗糙表面来说,在接近平行方向的高光反射也会增强但不够达到100%的强度.为何如此是因为影响菲涅尔效应的关键参数在于每个微平面的法向量和入射光线的角度,而不是宏观平面的法向量和入射光线的角度。因此我们在宏观层面看到的实际上是微平面的菲涅尔效应的一个平均结果。&/p&&p&&br&&/p&&p&根据菲涅尔反射,若你看向一个圆球,那么圆球中心的反射会较弱,而靠近边缘是反射会较强。另外需注意,这种关系也受折射率影响。&/p&&p&&br&&/p&&img src=&/v2-70e2e2f696d5d2deda71c9c_b.jpg& data-rawwidth=&1268& data-rawheight=&313& class=&origin_image zh-lightbox-thumb& width=&1268& data-original=&/v2-70e2e2f696d5d2deda71c9c_r.jpg&&&p&图13 基于菲涅尔反射,在Unreal Engine 4中实现的边缘光Shader&/p&&p&&br&&/p&&p&&br&&/p&&p&&br&&/p&&h2&7.3 微平面理论 Microfacet Theory&/h2&&p&微表面理论假设表面是由不同方向的微小细节表面,也就是微平面(microfacets)组成。每一个微小的平面都会根据它的法线方向在一个方向上反射光线。&/p&&p&表面法线朝向光源方向和视线方向中间的微表面会反射可见光。然而,不是所有的表面法线和半角法线(half normal)相等的微表面都会反射光线,因为其中有些会被遮挡,如下图所示。&/p&&img src=&/v2-a9fdba6e51eba503d7abc0fb61bd23cb_b.jpg& data-rawwidth=&1129& data-rawheight=&554& class=&origin_image zh-lightbox-thumb& width=&1129& data-original=&/v2-a9fdba6e51eba503d7abc0fb61bd23cb_r.jpg&&&p&图14 微平面理论图示&/p&&p&&br&&/p&&p&我们用法线分布函数(Normal Distribution Function,简写为NDF),D(h)来描述组成表面一点的所有微表面的法线分布概率。则可以这样理解:向NDF输入一个朝向h,NDF会返回朝向是h的微表面数占微表面总数的比例,比如有8%的微表面朝向是h,那么就有8%的微表面可能将光线反射到v方向。&/p&&img src=&/v2-48b2f332d5e0d046f0e54a_b.jpg& data-rawwidth=&1217& data-rawheight=&309& class=&origin_image zh-lightbox-thumb& width=&1217& data-original=&/v2-48b2f332d5e0d046f0e54a_r.jpg&&&p&图15 由微平面组成的表面。仅红色微平面的表面法线和半矢量h对齐,能参与从入射光线向量l到视线向量v的光线反射&/p&&p&NDF的定义式:&/p&&p&&img src=&/equation?tex=D%28h%29%3D%5Cfrac%7B%5Calpha%5E%7B2%7D%7D%7B%5Cpi%28%28n%5Ccdot+h%29%5E%7B2%7D%28%5Calpha%5E%7B2%7D-1%29%2B1%29%5E%7B2%7D%7D& alt=&D(h)=\frac{\alpha^{2}}{\pi((n\cdot h)^{2}(\alpha^{2}-1)+1)^{2}}& eeimg=&1&&&/p&&p&在微观层面上不规则的表面会造成光的漫反射。例如,模糊的反射是由于光线的散射造成的。而反射的光线并不均匀,因此我们得到的高光反射是模糊的。如下图。&/p&&p&&br&&/p&&img src=&/v2-3f791b78fcc45ab98c037f_b.jpg& data-rawwidth=&600& data-rawheight=&307& class=&origin_image zh-lightbox-thumb& width=&600& data-original=&/v2-3f791b78fcc45ab98c037f_r.jpg&&&p&&br&&/p&&p&
图16 模糊的微平面高光反射&/p&&p&&br&&/p&&p&&br&&/p&&p&&br&&/p&&h2&八、基于物理的BRDF · 常见模型&/h2&&p&&br&&/p&&p&&br&&/p&&h2&8.1 Cook-Torrance BRDF模型&/h2&&p&Cook-Torrance模型作为图形学中最早的基于物理的BRDF模型,由Cook和Torrance提出,是Torrance-Sparrow模型的一个应用版本。现今,Cook-Torrance模型已经成为基于物理着色的标准模型之一。Cook-Torrance模型将物理学中的菲涅尔反射引入了图形学,实现了比较逼真的效果。&/p&&p&Cook-Torrance微平面着色模型(Cook-Torrance microfacet
specular shading model),即Microfacet Specular BRDF,定义为:&/p&&p&&img src=&/equation?tex=f%28l%2Cv%29%3D%5Cfrac%7BF%28l%2Ch%29G%28l%2Cv%2Ch%29D%28h%29%7D%7B4%28n%5Ccdot+h%29%28n%5Ccdot+v%29%7D& alt=&f(l,v)=\frac{F(l,h)G(l,v,h)D(h)}{4(n\cdot h)(n\cdot v)}& eeimg=&1&&&/p&&p&其中:&/p&&ul&&li&F为菲涅尔反射函数( Fresnel 函数 )&/li&&li&G为阴影遮罩函数(Geometry Factor,几何因子),即未被shadow或mask的比例&/li&&li&D为法线分布函数(NDF)&/li&&/ul&&p&&br&&/p&&p&篇幅原因,就不展开论述了,若大家有兴趣,可以参考历年的SIGGRAPH Course: Physically Based Shading in Theory and Practice系列与其他相关文章。&/p&&p&如SIGGRAPH 2013 Course: Physically Based Shading in Theory and Practice:&/p&&p&&a href=&/?target=http%3A///publications/s2013-shading-course/& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&/pub&/span&&span class=&invisible&&lications/s2013-shading-course/&/span&&span class=&ellipsis&&&/span&&i class=&icon-external&&&/i&&/a&&/p&&p&具体的课程中的两篇推荐:&/p&&ol&&li&Background:Physics and Math of Shading: &a href=&/?target=http%3A///publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_slides.pdf& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&/pub&/span&&span class=&invisible&&lications/s2013-shading-course/hoffman/s2013_pbs_physics_math_slides.pdf&/span&&span class=&ellipsis&&&/span&&i class=&icon-external&&&/i&&/a&&/li&&li&Physically
Based Lighting in Call of Duty: Black Ops :&a href=&/?target=http%3A///publications/s2013-shading-course/lazarov/s2013_pbs_black_ops_2_slides_v2.pdf& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&/pub&/span&&span class=&invisible&&lications/s2013-shading-course/lazarov/s2013_pbs_black_ops_2_slides_v2.pdf&/span&&span class=&ellipsis&&&/span&&i class=&icon-external&&&/i&&/a&&/li&&/ol&&p&&br&&/p&&p&&br&&/p&&h2&8.2 Ward BRDF模型&/h2&&p&一般情况下,我们可以将BRDF分为两类:&/p&&p&各项同性(Isotropic)的BRDF &/p&&ul&&li&反射不受与给定表面法向夹角的约束&/li&&li&随机表面微结构&/li&&/ul&&p&各向异性(Anisotropic)的BRDF&/p&&ul&&li&反射比随着与某个给定的表面法向之间的夹角而变化&/li&&li&图案的表面微结构&/li&&li&金属丝,绸缎,毛发等&/li&&/ul&&p&&br&&/p&&p&Phong和Cook-Torrance BRDF模型都不能处理各项异性的效果,Ward模型却可以。&/p&&p&Ward模型由Ward于1992年提出[Measuringand Modeling Anissropic Reflection,ACM SIGGRAPH,1992]。Ward模型介绍了更一般的表面法向表达方式:通过椭圆体(ellipsoids)这种允许各向异性反射的形式来表达。&/p&&p&然而,由于没有考虑菲涅耳因子(Fresnel factor)和几何衰减因子(geometric attenuation factor),该模型更像是一种经验模型,但还是属于基于物理的BRDF模型。&/p&&p&&br&&/p&&p&各向同性的Ward模型定义为:&/p&&img src=&/v2-6517f51bea2d5d99f583c_b.jpg& data-rawwidth=&1647& data-rawheight=&185& class=&origin_image zh-lightbox-thumb& width=&1647& data-original=&/v2-6517f51bea2d5d99f583c_r.jpg&&&p&&br&&/p&&p&&br&&/p&&p&&br&&/p&&h2&九、BRDF与其引申&/h2&&p&&br&&/p&&p&有不少与BRDF类似的函数:&/p&&ul&&li&BSSRDF:Bidirectional Surface Scattering Reflectance Distribution,双向表面散反射分布函数&/li&&li&SBRDF(SVBRDF): spatially varying BRDF(spatial BRDF) 空间BRDF&/li&&li&BTDF:Bidirectional Transmittance Distribution Function 双向透射分布函数&/li&&li&BSDF : Bidirectional Scattering Distribution Function,双向散射分布函数&/li&&/ul&&p&&br&&/p&&p&下面分别进行介绍。&/p&&p&&br&&/p&&p&&br&&/p&&h2&9.1 BSSRDF&/h2&&p&BRDF只是更一般方程的一种近似,这个方程就是BSSRDF(Bidirectional scattering-surface reflectance distribution function,双向表面散反射分布函数)。BSSRDF描述了射出辐射率与入射通量之间的关系,BSSRDF函数通过把入射和出射位置作为函数的输入,从而来包含这些现象,它描述了沿入射方向从物体表面的一点到另外一点,最后顺着出射方向出去的光线的相对量。注意,这个函数还考虑了物体表面的一点到另外一点,最好顺着出射方向出去的光线相对量。注意,这个函数还考虑了物体表面不一致的情况,因为随着位置的变化,反射系数也会发生变化。在实时绘制中,物体表面上的位置可以用来获取颜色纹理、光泽度,以及凹凸纹理图等信息。&/p&&p&&br&&/p&&img src=&/v2-1a6d28d6762ccd0bf90f91e2501acd82_b.jpg& data-rawwidth=&400& data-rawheight=&300& class=&content_image& width=&400&&&p&
图17 BRDF渲染图&/p&&p&&br&&/p&&img src=&/v2-95ee8dbec39ccfbec0690_b.jpg& data-rawwidth=&400& data-rawheight=&300& class=&content_image& width=&400&&&p&
图18 BSSRDF渲染图&/p&&p&&br&&/p&&h2&9.2 SBRDF(SVBRDF)&/h2&&p&一个捕获基于空间位置BRDF变化的函数被称为空间变化的BRDF(Spatially Varying BRDF ,SVBRDF)或称空间BRDF,空间双向反射分布函数(Spatial BRDF ,SBRDF)。&/p&&p&&br&&/p&&p&&br&&/p&&h2&9.3 BTDF与BSDF&/h2&&p&即使一般的BSSRDF函数,无论其多么复杂,仍然忽略了现实世界中非常重要的一些变量,比如说光的偏振。此外,也没有处理穿过物体表面的光线传播,只是对反射情况进行了处理。为了处理光线传播的问题,对物体表面定义了两个BRDF和两个BTDF(T表示传播“Transmittance”),每侧各有一个,这样就组成了BSDF(S表示散射“Scattering”)。&/p&&img src=&/v2-cac7e3de3ed44_b.jpg& data-rawwidth=&752& data-rawheight=&750& class=&origin_image zh-lightbox-thumb& width=&752& data-original=&/v2-cac7e3de3ed44_r.jpg&&&p&图19 当用于镜面反射的BRDF和用于镜面透射的BTDF使用菲涅尔公式进行调制渲染时,得到了如真实玻璃视觉上精确的反射和透射的角度变化。来自《Physically Based Rendering, Third Edition》Figure 8.10&/p&&p&&br&&/p&&p&而在实践中,这些更复杂的函数很少使用,BRDF和SVBRDF足以胜任一般情况下表面渲染的效果。&/p&&p&&br&&/p&&p&&br&&/p&&p&&br&&/p&&h2&十、其他参考&/h2&&p&&br&&/p&&p&[1] &a href=&/?target=http%3A//graphics.stanford.edu/%7Ehenrik/images/subsurf.html& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&graphics.stanford.edu/~&/span&&span class=&invisible&&henrik/images/subsurf.html&/span&&span class=&ellipsis&&&/span&&i class=&icon-external&&&/i&&/a&&/p&&p&[2] &a href=&/?target=http%3A///lessons/3d-basic-rendering/introduction-to-shading/reflection-refraction-fresnel& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://www.&/span&&span class=&visible&&/lesso&/span&&span class=&invisible&&ns/3d-basic-rendering/introduction-to-shading/reflection-refraction-fresnel&/span&&span class=&ellipsis&&&/span&&i class=&icon-external&&&/i&&/a&&/p&&p&[3] &a href=&/?target=http%3A//wiki.nuaj.net/index.php%3Ftitle%3DBRDF& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&wiki.nuaj.net/index.php?&/span&&span class=&invisible&&title=BRDF&/span&&span class=&ellipsis&&&/span&&i class=&icon-external&&&/i&&/a& &/p&&p&[4] &a href=&/?target=https%3A///pbr-guide& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://www.&/span&&span class=&visible&&/pbr-g&/span&&span class=&invisible&&uide&/span&&span class=&ellipsis&&&/span&&i class=&icon-external&&&/i&&/a&&/p&&p&[5] &a href=&/?target=http%3A///coursestatic/course_2987.html& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://www.&/span&&span class=&visible&&/coursestati&/span&&span class=&invisible&&c/course_2987.html&/span&&span class=&ellipsis&&&/span&&i class=&icon-external&&&/i&&/a&&/p&&p&[6] &a href=&/?target=https%3A///latest/INT/Engine/Rendering/Materials/HowTo/Fresnel/index.html& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&/l&/span&&span class=&invisible&&atest/INT/Engine/Rendering/Materials/HowTo/Fresnel/index.html&/span&&span class=&ellipsis&&&/span&&i class=&icon-external&&&/i&&/a&&/p&&p&[7] &a href=&/?target=https%3A//en.wikipedia.org/wiki/Fresnel_equations& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&en.wikipedia.org/wiki/F&/span&&span class=&invisible&&resnel_equations&/span&&span class=&ellipsis&&&/span&&i class=&icon-external&&&/i&&/a&&/p&&p&[8] &a href=&/p/& class=&internal&&&span class=&invisible&&https://&/span&&span class=&visible&&/p/21&/span&&span class=&invisible&&376124&/span&&span class=&ellipsis&&&/span&&/a&&/p&&p&[9] &a href=&/?target=https%3A//en.wikipedia.org/wiki/Radiometry& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&en.wikipedia.org/wiki/R&/span&&span class=&invisible&&adiometry&/span&&span class=&ellipsis&&&/span&&i class=&icon-external&&&/i&&/a&&/p&&p&[10] Real Shading in Unreal Engine 4:&a href=&/?target=https%3A///Resources/files/2013SiggraphPresentationsNotes-.pdf& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&/R&/span&&span class=&invisible&&esources/files/2013SiggraphPresentationsNotes-.pdf&/span&&span class=&ellipsis&&&/span&&i class=&icon-external&&&/i&&/a&&/p&&p&[11] SIGGRAPH 2013 Course: Physically BasedShading in Theory and Practice:&a href=&/?target=http%3A///publications/s2013-shading-course/& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&/pub&/span&&span class=&invisible&&lications/s2013-shading-course/&/span&&span class=&ellipsis&&&/span&&i class=&icon-external&&&/i&&/a&&/p&&p&[12] Physically Based Rendering, Third Edition&/p&&p&&br&&/p&&p&The end.&/p&
在计算机图形学中,BRDF(Bidirectional Reflectance Distribution Function,双向反射分布函数)是真实感图形学中最核心的概念之一,它描述的是物体表面将光能从任何一个入射方向反射到任何一个视点方向的反射特性,即入射光线经过某个表面反射后如何在各…
&img src=&/50/v2-a0e84aa99e3ae89ad8328df09bab9ef2_b.jpg& data-rawwidth=&800& data-rawheight=&500& class=&origin_image zh-lightbox-thumb& width=&800& data-original=&/50/v2-a0e84aa99e3ae89ad8328df09bab9ef2_r.jpg&&&p&原文链接:&a href=&/?target=http%3A///archives/QA_NGUI-1.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&关于Unity中的NGUI优化,你可能遇到这些问题 - Blog&i class=&icon-external&&&/i&&/a&&/p&&p&上期我们聊到了UGUI的性能优化思路,本期我们来探秘NGUI。可能不少开发朋友会有疑惑,到底是NGUI还是UGUI的性能更好?小编在此想先表达下我的个人观点:&/p&&p&从理论上来说,没有什么依据可以证明UGUI的性能一定比NGUI更优异。在UWA的测评报告中,对于NGUI来说,主要统计UIPanel.LateUpdate\UICamera.Update\UIRect.Update和UIRect.Start;对于UGUI来说,主要统计Canvas.BuildBatch和Canvas.SendwillRenderCanvases。&/p&&p&相对于NGUI来看,UGUI确实在以下方面存在提升性能的可能:首先,5.2版本之后,Unity逐渐将一部分UGUI的计算放到子线程去做,以此来缓解主线程的压力;其次,UGUI的UIMesh生成是通过底层C++代码实现的,而NGUI只能通过在上层不断创建vertex list来进行,这样在堆内存的管理上,UGUI确实要好很多,带来的隐性收益就是GC触发次数会少很多。&/p&&p&但不能表示NGUI做出来的UI性能就一定比UGUI差,这个说法是不存在的。而且,在我们深度优化的过程中发现,NGUI同样可以达到很高的性能水准。所以,NGUI和UGUI都是很好的工具,只要把它们的特性掌握好,都可以做成性能很棒的UI界面。&/p&&h2&&strong&关键字&/strong&&/h2&&p&&strong&界面制作&/strong&&br&&strong&界面切换&/strong&&br&&strong&网格重建&/strong&&br&&strong&UICamera.Update&/strong&&br&&strong&Draw Call&/strong&&br&&strong&加载&/strong&&br&&strong&字体&/strong&&/p&&h2&&strong&一、界面制作&/strong&&/h2&&p&&strong&Q1:我用的是NGUI,本来已经打包图集了,输出时候是不是就不用理会那些原始2D Sprite图 ?粒子贴图需要Packing Tag吗?&/strong&&/p&&blockquote&&p&在NGUI中使用Atlas后,原纹理是不需要进行打包或进行其他特殊处理的,因为理论上这些资源在运行时已不再需要。粒子系统所使用的纹理并不是Sprite类型的,因此不需要设置Packing Tag。&/p&&/blockquote&&p&&strong&Q2:NGUI变形,如下图走样了,请问是不是图片压缩导致的?&/strong&&br&&/p&&img src=&/v2-83f88222edb71386cabd48fee99171fc_b.jpg& data-rawwidth=&578& data-rawheight=&192& class=&origin_image zh-lightbox-thumb& width=&578& data-original=&/v2-83f88222edb71386cabd48fee99171fc_r.jpg&&&blockquote&&p&当UI纹理在设备上的显示分辨率低于原始分辨率时,会因为出现aliasing现象,导致UI局部变形。通常对于粗线条、块状的UI图素,变形通常是不明显的,但对于细线条的UI图素,则可能非常明显。&br&通常该问题可以考虑三种方式来改善:&/p&&ol&&li&在NGUI中将UIRoot的Scaling Style设置为Flexible,这种方式的好处在于UI纹理不会因为设备分辨率的限制而降低,而缺点在于相同的UI纹理在高分辨率设备上显得比较小,而在低分辨率设备上显得比较大,从而提高了UI布局的复杂度;&/li&&li&将UI纹理的显示分辨率(Sprite的size属性)设定为高于原始分辨率,其缺点在于高分辨率设备上可能会产生模糊,但大多数情况下“模糊”相比于“走样”更不易察觉;&/li&&li&开启UI纹理的Mipmap,从而在低分辨率设备上自动切换到低Level,以“模糊”替换“走样”,但缺点在于增加了纹理的大小,因此只适用于出现了明显变形的少量UI。&/li&&/ol&&/blockquote&&p&&strong&Q3:能否在NGUI多分辨率适应方面提供一些解决方案或者思路?&/strong&&/p&&blockquote&&p&多分辨率适应涉及到以下几个方面:&/p&&ol&&li&布局。通常可以通过 NGUI 中的 Anchor 组件来实现,能够保证 UI 到屏幕上指定锚点的距离;&/li&&li&UI 背景图比例。通常我们建议将背景图的长宽比放大,以适配不同长宽比的屏幕,但要注意两边需要留空,或者保留可被裁掉的元素;&/li&&li&UI 的整体缩放。可以通过 UIRoot 组件的 Scaling Style 来统一配置。&/li&&/ol&&p&需要提醒的是,不同类型的游戏对布局的需求通常也不同,因此还是需要结合实际开发情况来做调整。&/p&&/blockquote&&p&&strong&Q4:我发现ScrollRect里有大量元素,在拖动的时候触发了很多onTransformChanged,能否提供一些优化思路?&/strong&&/p&&blockquote&&p&OnTransformChanged是UI元素在移动时触发的,所以该回调的开销是不可避免的,但一般来说该回调本身耗时并不会太高。因此,当OnTransformChanged耗时很高时,有三种方式进行优化:&/p&&ol&&li&可以先查看是否有哪个或者哪些子函数占比较高,比如,当OnTransformChanged触发了OnDimensionChanged时,耗时会明显升高,而OnDimensionChanged则是在开启了Canvas的Pixel Perfect时才会出现的。那么就可以考虑是否在拖动时暂时关闭Pixel Perfect。&/li&&li&如果主要是其自身开销造成,那么很可能就是因为移动的UI元素数量太大引起的。那么就可以从策略上减少UI元素数量,比如,做成拖动翻页的界面,一次性只需移动两页的UI元素等。&/li&&li&如果使用的是Mask组件,那么可以尝试改为Rect Mask 2D组件,同样会有性能上的提升。&/li&&/ol&&/blockquote&&p&&strong&Q5:我看到UICamera.Update()的GC调用特别高,只要我一移动就会产生2.8K的GC,看起来是NGUITools.FindInParents这个方法导致的,有没有什么可以优化的方法呢?&/strong&&/p&&img src=&/v2-1c6e3bf426aefc309ede32d2_b.png& data-rawwidth=&624& data-rawheight=&100& class=&origin_image zh-lightbox-thumb& width=&624& data-original=&/v2-1c6e3bf426aefc309ede32d2_r.png&&&img src=&/v2-cffed573ebe34_b.png& data-rawwidth=&653& data-rawheight=&120& class=&origin_image zh-lightbox-thumb& width=&653& data-original=&/v2-cffed573ebe34_r.png&&&br&&blockquote&&p&在 Editor 下,当调用GetComponent() 且 T组件并不在当前的GameObject 上时,确实会出现GC Alloc,但这在发布后是不会出现的,因此建议在真机上做一个验证。这是因为在Editor下,Unity的MissingComponentException实现所致,在出现以上情况时,Unity 并不是直接返回一个 NULL,而是返回一个代理 Object用来储存一些相关信息,在后续被访问时可以给出更详细的报错信息。&/p&&/blockquote&&h2&&strong&二、网格重建&/strong&&/h2&&p&&strong&Q1:我用NGUI开发,因为角色名字导致重建,使得UIPanel.LateUpdate的CPU占用很高。如果将它们分离到多个UIPanel里,是否这个开销会相对小一些?&/strong&&/p&&blockquote&&p&将较多的动态UI元素分组放在不同的UIPanel中确实是UWA比较推荐的方式,一方面可以降低重建的概率,某些分组中可能没有UI元素发生变化,从而不会进行重建;另一方面可以降低重建的开销。通过分组,可以将每个UIPanel所产生的Mesh控制在较小的范围内,从而控制其重建的开销(通常重建的开销会因Mesh的增大而明显升高,且不是线性的关系)。虽然这种做法会产生额外的DrawCall,但DrawCall的开销与网格重建相比通常都非常小。&/p&&/blockquote&&p&&strong&Q2:我的UWA报告中看到几乎每次切换场景都会有UIPanel.LateUpdate()这个函数的堆内存开销,请问说明了什么问题,我是否还能优化?&/strong&&br&&img src=&/v2-f4a782b7af86ccd1a20fa55e9f8909c4_b.png& data-rawwidth=&1107& data-rawheight=&369& class=&origin_image zh-lightbox-thumb& width=&1107& data-original=&/v2-f4a782b7af86ccd1a20fa55e9f8909c4_r.png&&&br&&/p&&blockquote&&p&UIPanel.LateUpdate持续分配较大量的堆内存,说明UI界面在制作上存在以下问题:&/p&&ol&&li&Panel中Widgets数量过多,且存在频繁的变动,导致UIPanel需要进行大量的网格重建;&/li&&li&动静态UI元素没有分离;&/li&&li&建议研发团队对UI界面的制作进行进一步检测,尽可能将静态UI元素和动态UI元素分开,存放于不同的Panel下。同时,对于不同频率的动态元素也建议存放于不同的Panel中。&/li&&/ol&&/blockquote&&p&&strong&Q3:UWA建议“尽可能将静态UI元素和频繁变化的动态UI元素分开,存放于不同的Panel下。同时,对于不同频率的动态元素也建议存放于不同的Panel中。”那么请问,如果把特效放在Panel里面,需要把特效拆到动态的里面吗?&/strong&&/p&&blockquote&&p&通常特效是指粒子系统,而粒子系统的渲染和UI是独立的,仅能通过Render Order来改变两者的渲染顺序,而粒子系统的变化并不会引起UI部分的重建,因此特效的放置并没有特殊的要求。&/p&&/blockquote&&h2&&strong&三、界面切换&/strong&&/h2&&p&&strong&Q1:请问这个GameObject.Active的开销怎么这么高?Activate会产生堆内存分配吗?&/strong&&br&&img src=&/v2-1dbfbf4b814f_b.png& data-rawwidth=&442& data-rawheight=&69& class=&origin_image zh-lightbox-thumb& width=&442& data-original=&/v2-1dbfbf4b814f_r.png&&&/p&&blockquote&&p&这个是PC上的鼠标交互事件造成的,是UI界面的Active操作,所以触发了各种相关的OnEnable调用,研发团队可以在Profiler中进行进一步定位,查看根源。&br&一般来说,GameObject的Activate操作本身是不会产生堆内存分配,但它引发的各种底层类的OnEnable会产生堆内存的分配。开发团队可以参考这里加深理

我要回帖

更多关于 指针类型转换 的文章

 

随机推荐