畅小游入驻牛客啦,请大家多多关照~
图形引擎实战:GPU随机数的生成 经验分享
今天和大家分享一下在工作之中的一些感悟。本人于1年前从学生成为了引擎开发工作师。通过身份的转变也发现了一些处事的不同之处,在工作之前,无论是学习还是做学术研究往往只注重于局部而忽略了全局。然而局部最优并不等于全局最优。接下来通过一个案例的分享来阐述。
我们在进行效果编写的时候,在Shader之中往往需要随机数,特别是需要实现类似信号传输不稳定效果的情况。实现这个目前特别简单粗暴的方法有两个:一是应用脚本生成随机数,二是应用噪声纹理来实现。但使用脚本会有性能问题,要尽量使用GPU直接生成随机数,而噪声纹理又会占用额外的纹理通道,该角色shader中纹理数量已经较多,而且项目显存占用也急需优化,所以在实现这个效果时候要尽量避免使用这两种方法。
具体实现方法,目前冯女神和网络上其它地方已经有很多的分享,在这里我提出一种很粗略的实现方法。我们知道,时间贯穿着我们的世界,所有事物都有频率,在这样的思维之下,我们是不是可以通过对于频率域的一些定义而实现一些空间域上的效果。主要应用傅里叶级数来实现,可以通过多种级数的混合来实现一种近似的随机数(其实是伪随机中的伪随机)。以两种级数为例,如图3所示。
在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所示:
其中红色、黄色和蓝色的线分别代表应用脚本传递数据、应用噪声图和应用傅里叶级数的方法的渲染效率。可以发现,傅里叶级数的方法的帧率优于脚本传递的方法,劣于应用噪声图的方法,但可以减少纹理通道的占用和避免显存的开销,算是在时间与空间之间找到了一个平衡。
参考文献:
[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