Unity Shader编程之-模拟Highlighting S
2017-06-13 本文已影响1009人
元宇宙云课堂
用过Highlighting System插件的童鞋都知道,该款可以给物体轮廓外发光高亮特效,那么本篇文章我们来动手学习下自己实现,下面开始正文。
1.边缘光方法(Rim Light):Unity官方教程里有例子,其中核心是这两句代码:
half rim = 1.0 – saturate(dot (normalize(IN.viewDir), IN.worldNormal));o.Emission = _RimColor.rgb * pow (rim, _RimPower);IN.viewDir是当前视角向量,IN.worldNormal是物体的法线。dot是计算视角和法线的点积,等于视角和法线夹角的cos值,如下图:
![[unity Shader 着色器]给物体边缘加高光轮廓的办法,付Demo(增加一组算法) - 踏浪星空 - 踏浪的编程小屋](http://game.ceeger.com/forum/attachment/Mon_1208/2_6507_9714b4303c8bae9.jpg)
Cos的值域是1-0,1-cos就成了0-1,在夹角90度时达到最大值,正好用来模拟侧光的强度(与视角成90度的部分光线最强,就是边缘光了)把这个值的变化率用一个pow函数(rim的_rimPower次方)进行放大,就能强化边缘发亮的效果。比较一下:
![[unity Shader 着色器]给物体边缘加高光轮廓的办法,付Demo(增加一组算法) - 踏浪星空 - 踏浪的编程小屋](http://game.ceeger.com/forum/attachment/Mon_1208/2_6507_128472121c95416.jpg)
没有经过Pow放大变化率的边缘光,cos函数的变化是比较平缓的,造成大片区域被染色。
![[unity Shader 着色器]给物体边缘加高光轮廓的办法,付Demo(增加一组算法) - 踏浪星空 - 踏浪的编程小屋](http://game.ceeger.com/forum/attachment/Mon_1208/2_6507_06e8734d3ee4796.jpg)
经过Pow函数放大变化率,就有了边缘发亮的效果。这个图大致体现了放大前后变化率的曲线:
![[unity Shader 着色器]给物体边缘加高光轮廓的办法,付Demo(增加一组算法) - 踏浪星空 - 踏浪的编程小屋](http://game.ceeger.com/forum/attachment/Mon_1209/2_6507_e568dc69151d411.jpg)
这种边缘光在复杂几何形体的时候效果还是不错的。
![[unity Shader 着色器]给物体边缘加高光轮廓的办法,付Demo(增加一组算法) - 踏浪星空 - 踏浪的编程小屋](http://game.ceeger.com/forum/attachment/Mon_1208/2_6507_bc3aefdbb1a1240.jpg)
![[unity Shader 着色器]给物体边缘加高光轮廓的办法,付Demo(增加一组算法) - 踏浪星空 - 踏浪的编程小屋](http://game.ceeger.com/forum/attachment/Mon_1208/2_6507_b5ebe0e3eb98943.jpg)
但是在平直的物体上,边缘光就不见了
![[unity Shader 着色器]给物体边缘加高光轮廓的办法,付Demo(增加一组算法) - 踏浪星空 - 踏浪的编程小屋](http://game.ceeger.com/forum/attachment/Mon_1208/2_6507_f3e23cdd618132e.jpg)
到了方形物体,几乎很难看见了
![[unity Shader 着色器]给物体边缘加高光轮廓的办法,付Demo(增加一组算法) - 踏浪星空 - 踏浪的编程小屋](http://game.ceeger.com/forum/attachment/Mon_1208/2_6507_171fbfcd8277db2.jpg)
很好理解,正方形每个面法线都是一个方向的,没法体现出变化和轮廓了。另外这种方法在描绘凹的几何体时,凹的部分(包括法线贴图造成的凹凸)的边缘也都会被画出来,并不是真正意义上的边缘轮廓,就是一种侧光效果。该方法的好处是简单,只要把官方的shader改写,加上计算边缘光的几句,就能实现。要显示的时候动态切换shader就可以。基本不需要代码干预,效率高。
2.单个物体轮廓渲染方法这个方法实现比较复杂,只能介绍大致思路:1.把要渲染轮廓的物体放在一个单独的层里2.在层里设置一个disable的摄像机,culling mask是渲染物体所在层。3.主摄像机保持culling mask是everything4.生成1个renderTexture5.把那个disable的辅助摄像机用RenderWithShader方法,指定一个单色渲染的shader(只需要轮廓,不需要光照计算)渲染物体的轮廓到一个renderTexture6.继续用单色Shader,用Unity自带Blur类似的方法,把物体轮廓图上下左右移动几个像素,叠加在一起,得到一个比原来轮廓大,边缘模糊的轮廓图,存到一个临时renderTexture7.把大的轮廓图和原始轮廓图叠加,把中间清晰轮廓部分消除掉,就能得到一个完整带透明度的轮廓图。8.在主摄像机的OnRenderImage里,把这个透明轮廓图和主摄像机渲染的图像进行alpha混合,就能产生一个完整并且不被遮挡的轮廓效果了。效果如图:
![[unity Shader 着色器]给物体边缘加高光轮廓的办法,付Demo(增加一组算法) - 踏浪星空 - 踏浪的编程小屋](http://game.ceeger.com/forum/attachment/Mon_1208/2_6507_3f1f7c186b23a19.jpg)
明显效果比侧光好多了。不过这种方法开销比较大,而且需要很多代码的支持。
附上一个小Demo,包含了上述两种方法。鼠标可以控制镜头平移、旋转、缩放。鼠标划过物体显示侧光效果,点击物体显示清晰轮廓效果,再次点击效果消除。
![[unity Shader 着色器]给物体边缘加高光轮廓的办法,付Demo(增加一组算法) - 踏浪星空 - 踏浪的编程小屋](http://game.ceeger.com/forum/attachment/thumb/Mon_1208/2_6507_5aa10ef2f637a6d.jpg)
![[unity Shader 着色器]给物体边缘加高光轮廓的办法,付Demo(增加一组算法) - 踏浪星空 - 踏浪的编程小屋](http://game.ceeger.com/forum/attachment/thumb/Mon_1208/2_6507_205b1b1ade13187.jpg)
![[unity Shader 着色器]给物体边缘加高光轮廓的办法,付Demo(增加一组算法) - 踏浪星空 - 踏浪的编程小屋](http://game.ceeger.com/forum/attachment/Mon_1208/2_6507_487322d0ae522f0.jpg)
![[unity Shader 着色器]给物体边缘加高光轮廓的办法,付Demo(增加一组算法) - 踏浪星空 - 踏浪的编程小屋](http://game.ceeger.com/forum/attachment/Mon_1208/2_6507_57bafef8ed416a1.jpg)
变换成细线 绿色
![[unity Shader 着色器]给物体边缘加高光轮廓的办法,付Demo(增加一组算法) - 踏浪星空 - 踏浪的编程小屋](http://game.ceeger.com/forum/attachment/Mon_1208/2_6507_4725d5e28f188a5.jpg)
![[unity Shader 着色器]给物体边缘加高光轮廓的办法,付Demo(增加一组算法) - 踏浪星空 - 踏浪的编程小屋](http://game.ceeger.com/forum/attachment/thumb/Mon_1209/2_6507_ac530d8039d141c.jpg)
多次模糊再裁剪的算法,边缘光滑,模型的锯齿在边缘线被光滑了,开销略大
![[unity Shader 着色器]给物体边缘加高光轮廓的办法,付Demo(增加一组算法) - 踏浪星空 - 踏浪的编程小屋](http://game.ceeger.com/forum/attachment/thumb/Mon_1209/2_6507_6e82d816dd6925f.jpg)
一次同时模糊、裁剪算法,边缘较模糊,锯齿也被等比放大,但开销较省。根据需要使用。总体上因为是全屏效果,与被渲染物体数量无关,所以基本上显示轮廓物体的多少不会影响效率。附件里包含两种方法的代码和shader。RimLight方法一个shader就能对应一种材质效果,不需要代码支持。后一种方法需要代码加shader,类似官方的Image Effect效果。
下面是下载地址
链接: http://pan.baidu.com/s/1c0CRKjA
密码: vasp