畅小游入驻牛客啦,请大家多多关照~

Hello,各位牛客的小伙伴们大家好呀~
  这是一个不寻常的日子,我宣布:“畅小游正式入驻牛客啦!”

  今后,小游会在此账号定期分享搜狐畅游相关内容,包括但不限于技术文章分享、求职秘籍、畅游文化、工作环境大揭秘等内容,对畅游感兴趣的同学点个关注再走呀~

  初来乍到,还请多多关照啦,今天为大家带来的内容是来自 搜狐畅游-引擎部  的文章~


图形引擎实战:GPU随机数的生成 经验分享

  今天和大家分享一下在工作之中的一些感悟。本人于1年前从学生成为了引擎开发工作师。通过身份的转变也发现了一些处事的不同之处,在工作之前,无论是学习还是做学术研究往往只注重于局部而忽略了全局。然而局部最优并不等于全局最优。接下来通过一个案例的分享来阐述。

图1《泰坦陨落2》中的幻影模拟效果

  为了实现美术对于图1中出现的人物角色的类似全息扫描的效果,对实现的方法进行了研究。其实这个效果的本质为平行的扫描线,不过这个扫描线之间的距离并不是均匀分布于角色上的。想要使其不均匀那就需要应用随机数,下面针对随机数的生成进行讨论。

  我们在进行效果编写的时候,在Shader之中往往需要随机数,特别是需要实现类似信号传输不稳定效果的情况。实现这个目前特别简单粗暴的方法有两个:一是应用脚本生成随机数,二是应用噪声纹理来实现。但使用脚本会有性能问题,要尽量使用GPU直接生成随机数,而噪声纹理又会占用额外的纹理通道,该角色shader中纹理数量已经较多,而且项目显存占用也急需优化,所以在实现这个效果时候要尽量避免使用这两种方法。

图2 Shader实现随机数的两种方式

  具体实现方法,目前冯女神和网络上其它地方已经有很多的分享,在这里我提出一种很粗略的实现方法。我们知道,时间贯穿着我们的世界,所有事物都有频率,在这样的思维之下,我们是不是可以通过对于频率域的一些定义而实现一些空间域上的效果。主要应用傅里叶级数来实现,可以通过多种级数的混合来实现一种近似的随机数(其实是伪随机中的伪随机)。以两种级数为例,如图3所示。

图3 两种傅里叶级数[1][2]


  以锯齿波的结果作为自变量代入方波之中,最终就会得到随机的结果。不过在实际应用时,不用一定要按照正常的条条框框来进行,有的时候,出现BUG也可能会有意想不到的效果。这种随机方案在实现具体某个物体上的效果时,可以在整个物体上,也就是全局上发挥作用,随机的效果可以尽可能的避免突变的情况。具体如下:

  在Shader之中可以这样写。通过这个过程计算出来的数,就是一种近似的随机数。其中的取值范围可以根据需要自行制定。

  half SawWave = (2 / PI) * (-sin(_Time.y) + sin(2 * _Time.y) / 2 - sin(3 * _Time.y) / 3 + sin(4 * _Time.y) / 4);

  half CubeWaveAns = (4 / PI) * (sin(SawWave) + sin(3 * SawWave) / 3 + sin(5 * SawWave) / 5 + sin(7 * SawWave) / 7);

  下面对于上述三种方案进行性能分析。首先是控制变量,仅将全息效果中随机数生成部分进行替换。在渲染分辨率相同的情况下均提取6000帧的帧率。实验结果如图4所示:

 图4 三种随机数生成方案的帧率比较

  其中红色、黄色和蓝色的线分别代表应用脚本传递数据、应用噪声图和应用傅里叶级数的方法的渲染效率。可以发现,傅里叶级数的方法的帧率优于脚本传递的方法,劣于应用噪声图的方法,但可以减少纹理通道的占用和避免显存的开销,算是在时间与空间之间找到了一个平衡。

  最后,对于全局状态的认知方面,在对新功能开发或对功能进行维护的时候,首先要厘清的问题是,用比较通俗的话来说就是“有啥,没啥,啥是啥,啥能干啥,啥和啥有啥关系,啥在啥时因为啥变成啥样,啥在啥时因为啥把啥变成啥样”。经过了这样的分析才会对于要做的事有清楚的认知。这也是在求学阶段老师对我的教导。本文旨在分享工作以来对于事物认知态度的变化,以及一点点技术的分享,仅供参考。(文:Don)


参考文献:

[1]方波傅里叶级数. https://en.wikipedia.org/wiki/File:Fourier_series_square_wave_circles_animation.gif

[2]锯齿波傅里叶级数.https://en.wikipedia.org/wiki/File:Fourier_series_sawtooth_wave_circles_animation.gif


欢迎加入搜狐畅游引擎部!

感兴趣的同学可以在官网投递简历:

双手奉上内推码:NTAI1kh



全部评论

相关推荐

12-04 16:18
已编辑
东华理工大学 前端工程师
面试官全程关摄像头1.自我介绍一下2.React和Vue哪个更熟悉一点3.你在之前那段实习经历中有没有什么技术性的突破(我只是实习了44天工作28天,我把我能说的都说了)4.你封装的哪个表单组件支不支持动态传值5.自己在实习阶段Vue3项目封装过hook吗6.hook有什么作用7.Vue2和Vue3的响应式区别(我说一个是proxy是拦截所有的底层操作,Object.defineProperty本身就是一个底层操作,有些东西拦截不了,比如数组的一些操作还有等等,面试官就说实在要拦截能不能拦截????我心想肯定不行呀,他的底层机制就不允许吧)8.pinia和vuex的区别(这个回答不出来是我太久没用了)9.pinia和zustand的区别,怎么选(直接给我干懵了)(我说react能用pinia吗  他说要用的话也可以)10.渲染一万条数据,怎么解决页面卡顿问题(我说分页、监听滚轮动态加载,纯数据展示好像还可以用canvas画)(估计是没说虚拟表单,感觉不满意)11.type和interface的区别12.ts的泛型有哪些作用(我就说了一个结构相同但是类型不同的时候可以用,比如请求响应的接口,每次的data不同,这里能用一个泛型,他问我还有什么)13.你项目用的是React,如果让你再写一遍你会选择什么14.pnpm、npm、yarn的区别15.dependencies和devdependencies的区别总而言之太久没面试了,上一段实习的面试js问了很多。结果这次js一点没问,网络方面也没考,表现得很一般,但是知道自己的问题了  好好准备,等待明天的影石360和周四的腾讯了  加油!!!
解zj:大三的第一段面试居然是这样的结局
查看15道真题和解析
点赞 评论 收藏
分享
评论
2
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务