0、Halftone(半色调)是什么
直观的描述就是修拉的画,用“点”的方式来完成画面。
当印刷设备通常只能以有限数量的墨水颜色时,halftone通过调整图像中不同区域的点的大小和密度,来创造出一种灰度或颜色过渡的效果。
一、绘制圆点矩阵
这一部分比较抽象,但是很有意思!
1. 屏幕UV *深度
屏幕uv两个坐标轴的数据都为(0,1),可以模拟为黑白关系,如图所示。
让UV乘上其模型在场景中的深度,可以使得物体深度变化时,屏幕纹理会随着物体等比例缩放。
2. 放大倍数UV,并取小数
放大UV可以使得UV范围变大,通过用frac 取小数,可以让纹理在模型上重复出现。这里取小数的目的是将放大后的uv每一块都映射到0-1的范围内。
例如放大3倍,如下图所示,u、v两个坐标轴的值都扩大了三倍,最后就能有9个纹理(3x3=9)。
3. 📌重新映射并取长度(Length)
我们可以将其中一块拿出来作为示例,将其坐标的(0,1)的范围remap到(-0.5, 0.5),也就是将坐标轴原点移动到了每一块的中心位置。再取长度,长度的计算公式为:根号 x方+y方,所以可以得到,越接近坐标原点的位置颜色越黑(值越接近0),越向外扩散值越大越白,这样就利用程序模拟出了绘制圆点的效果。
此时编译出来的效果:
二、调子融合
前面的步骤是将圆点矩阵平铺到了物体上,那么如何让其根据物体本身的黑白关系来分布这些圆点呢?
1. (半)兰伯特 打基础
首先还是需要用到兰伯特或版兰伯特,得到最基础的明暗关系的数据,有需要的话再乘一个投影。
兰伯特在这儿:Unity Shader学习(二) ShaderForge - 兰伯特光照模型
2. 📌Power
想要将物体的黑白关系融入,我们得想办法如何处理数据将黑白关系区分出来。这里用到的方法是:以圆点矩阵为底数,兰伯特黑白关系为指数,power。
如下图,可以观察一下不同指数的幂函数分布。
我们知道圆点矩阵的数据都分布于(0,1),所以只看x变量位于(0,1)的部分即可。可以看出,当指数为负数时,任意值都大于1;当指数大于1时,会使得黑的地方更黑。结合这两点,可以将原本的黑白关系的范围跨越正负数进行映射,就能够得到我们想要的效果。
这里将 半兰伯特的黑白关系(0,1) 映射到了(-0.5,2),之后进行power得到由下图的效果,可以自行调整参数。
3. 四舍五入
这时候想要的大致效果已经出来了,但是圆点的边缘还不够清晰,所以采用了Round进行四舍五入,得到一个非黑即白的效果。