描边

大半年前学会了描边,但是一直没时间整理,加上描边在手机上性能可以预见不咋滴,所以这块很久都没管了,趁现在有空整理一下学习的过程。

当时人比较菜,找了很多资料来看,有些描边效果不是特别满意,有些技术又理解不了。给出的描边方案大体包括以下这几种

1、画模型的时候,如果有些像素的法线跟摄像机平行则认为是边界,需换成描边色

2、剔除掉正面,沿法线放大,通过画背面的方式来画描边

3、用sobel算子计算出描边

4、先沿法线放大用描边色填充画出个模型色块来,再画模型,让模型盖在描边的色块上

5、自定义单个模型深度图,在shader中将深度图转成黑白图,这张图就能用一些姿势算出边界,然后与背景混合,边界用描边色,其他用背景色

然后以下是我当时的要求以及根据这些解决方案做出的思考和选择,首先我要求的描边,必须是严格在模型外侧,类似衣服口袋有描边这种是我不希望有的,并且我希望能自定义描边是内描边还是外描边以及描边颜色,当多个模型存在时,想要能够我指定的模型有描边。

第一种方案实现起来最简单,而且当时的我也知道怎么做,但是还是舍弃了,原因是我不相信法线,没人规定平行于摄像机的法线一定在边界,有些情况法线还会在身上。

第二个方案,当时不懂剔除掉正面是个啥操作,以及当时不懂有深度这一说,以为先画就会在后面,后画就一定在最前面,让后又不懂怎么控制渲染顺序。所以没法施行

第三个方案,sobel其实检测的是颜色变化,只要颜色强弱明显就会被认为是边界,这样就会画在人物身上,跟我的需求不符

第四个方案,这个其实一开始是我想要的效果,虽然只能是外描边,但也能接受,但奈何我当时不会控制渲染顺序

第五个方案,当时找到了UE4的材质和后处理,刚好有UE4就开起来学习了一下,最终用了这个方案。刚好还找到一个sobel算子的,顺带学会了sobel算子。然后说下流程,首先渲染一张模型的深度图,利用这张图跑一遍描边shader,在像素着色器中首先我们采样深度图的时候,将其转成只有黑白两种颜色,因为模型的深度比较小,非模型部分深度比较大,所以可以认为两个极端0和1。因为我想做外描边,所以模型部分我弄成1,非模型部分是0(如果想两个调换,用1.0去减就行了)。接着每个像素用卷积去处理周围包含自己在内的9个像素,这样非模型部分是0,原本处于非模型与模型交接处的非模型部分就变成了非0值,模型部分依旧是1。然后用这个值减去原本的01值,这样模型部分就变成0了,描边部分因为原先是非模型部分所以减完依旧是非0值。然后用这个值去画描边决定描边的透明度。如果想模糊一点就用高斯模糊的算子做卷积,最终的效果如下图所示

描边

这个方案的好处是有足够的定制手段,不过就得针对每个模型做自定义的深度图,并且渲染还都是全屏的,性能开销极大。不过颜值还是不错的,而且功能强大,甚至可以绘制被遮蔽部分,毕竟有自定义深度图和场景的深度图做比较。

描边

 

顺便记录一下sobel算子怎么用,对每个像素卷积进行计算后,得到的Gx和Gy是一个颜色,对颜色进行平方相加后开根号,大概是将xyz平方后相加再开根号吧,最后算得一个G值,用做插值,大于某个预置的用描边色,否则用背景色。