Unity中做一颗小星球
在知乎上看见一篇文章据说是技术美术面试题,大概就是做出如下图效果:
感觉很有意思,所以在Unity中实现了一下,写这篇文章复述一下思路,也是复习一下,水平真的有限(不是谦虚),欢迎指导!
源文件奉上:
制作环境是Unity 2020.1.3,使用的是通用管线URP。
首先确定想要实现的效果,观察这张图,这是个星球,所以一定转起来~,另外就是这个图中得星球有一圈很明显的边缘光,这个应该可以通过视线方向和法线方向点乘来实现。而且这个球的表面是很有立体感的,也就是有深度,于是想到可以用视差贴图实现这一效果,关于视差贴图请移步这位大佬的文章,各种表面凹凸技术总结的非常棒:
不知道是不是其中内容没有标明出处的原因,被审核了,不过连接先放这,也许以后审核通过了呢。上面这个链接中的很多内容貌似是出自于下面这个地方的:
其次就是喷射出来的这些光线,很像GodRay效果,关于该效果可以参见这位大佬的文章:
这里使用的是在后期处理中像素进行径向模糊的方法来实现这一效果。
还有,在这个球的表面看起来似乎具有一定的流动性,于是决定使用一张flow map来实现这一效果。
首先制作这个球所需的贴图,一张颜色贴图、一张用于视差效果的深度贴图和一张flow map,贴图使用的是SD制作,这样在制作颜色贴图的过程中其他两张贴图也就顺势做出来了,而且方便后期修改,贴图长这样:
颜色、深度、Flow Map
然后开始逐一实现效果:
首先是旋转,恩…… uv.x += _Time.x*旋转速度,就这样……
然后是边缘光:pow(max(0, 1-dot(视线方向, 法线方向)), 边缘光范围)* 边缘光强度* 贴图颜色*叠加颜色。
视差贴图,关于视差贴图的实现参见上面链接中的视差遮蔽映射(Parallax Occlusion Mapping)。
GodRay体积光,由于使用的是URP环境,与传统的自定义后期方法有一定的区别(OnRenderImage无法使用),需要自己写一个ScriptableRendererFeature才行,可以通过参考官方实例来学习如何编写ScriptableRendererFeature:
其中核心还是Blit函数。写一个后处理shader,第一个Pass用来实现像素的径向偏移复制,思路如下:
通过ScriptableRendererFeature获取观察空间中球体中心坐标位置,则当前像素的偏移方向为:当前片元的UV - 球体中心坐标位置.xy,使用一个循环沿着这个方向不断复制像素,就做出了如下效果:
然后根据像素偏移的次数做衰减,这里的衰减为:当前像素颜色 *= pow(0到1的可控变量,像素偏移次数),做了衰减之后的效果:
现在的所有颜色的像素都在发光,而我希望只有亮度超过某一阈值的像素才能发光,而乘以一个step(阈值,当前像素)的方法太过生硬,经尝试发现乘以一个smoothstep(0,可控变量,当前像素)效果比较好,效果如下:
可以看到现在的问题就是像素偏移距离过大并且偏移次数少的情况下会出现这种断层,要解决这个问题,首先减少像素偏移距离,增多像素偏移次数,然后对结果进行高斯模糊处理。
另写两个Pass用于处理高斯模糊,一般情况下可以对原图像使用一个如下图所示5x5的卷积核进行卷积处理:
该图出自冯乐乐的Unity Shader入门精要,强烈推荐购买此书,亚马逊电子书好像才三十多块钱
但是一次处理25个像素太繁琐,于是可以简化成两个一维高斯核,如上图所示,先横向处理一遍所有像素,再纵向处理一遍所有像素,也就是需要些两个pass,一个用于横向处理一个用于纵向处理。经过高斯模糊处理后的图像如下:
最后写一个pass用于原图和这张体积光图进行叠加,直接Blend One One就完事了~
流动处理,关于这个流动大概有那么一丁点流动的意思就可以了,所以用flowmap对原UV进行了一些扭曲,uv -= normalize(流动方向.xy) * 扭曲强度。关于用于水体的flowMap的使用方法参见这位巨佬的文章:
最后使用URP自带的后处理进行一个Bloom处理,完事~ 牛逼
页:
[1]