目标
- 在blender的球上实现Toon Shader,理解blender着色器的工作原理。
- 完全通过自己的思考,不参考任何完整的教程,可以参考官方文档。
初始工程
1. 建球,改灯光颜色。
问题1:这个Material Output我就看不懂,里面的三个节点是什么意思?
- 如果我们要解决我们现在要处理的这个目标,实际上我们只需要理解surface就行,surface代表着物体的,就是表面的颜色会呈现什么情况。
- volume代表着物体的内部,可以制作类似体积雾,烟火颗粒之类的物体。
- displacement代表表面的凹凸贴图或者法线贴图,可以制作皮肤纹理,或者皱纹之类的物体。
- 参考:https://docs.blender.org/manual/en/3.0/render/shader_nodes/output/material.html
2. 我们添加一个Diffuse Shader
- Diffuse着色器代表着漫反射着色器,是最简单的着色器之一,主要的参数就是基础颜色为和粗糙度。
- 效果大概长这样。
- (光线的颜色我调成了黄色。)
问题2:顶点着色器和片元着色器呢?BSDF是什么意思?
- 我们上一个博客了解了,我们应该通过顶点着色器和片元着色器来对物体进行着色,但是随着渲染技术的迭代,人们发现我们其实只需要控制小部分的参数就能够完美的生成各种材质,我们不应该花时间在写很复杂的着色器代码。
- 所以BSDF,也叫原理化着色器诞生了,它的作用就是通过控制少量参数完成顶点着色器和片元着色器的工作。
- 简单来说,BSDF接收外部各种信息(光照等)作为输入(在着色器中被省略),输出的是物体每个像素的RGB,我们只需要关注他的基础参数即可。
问题3:那Diffuse BSDF输出的是什么?
- 按照我的理解,Diffuse BSDF实际上输出的就是每个物体上的每个像素和对应的RGB颜色。
- 所以我们要做的就是对每个每个像素对应的RGB颜色进行操作即可。
问题3:那也就是说Material Output的Surface输入的也是[(像素,RGB)]这种感觉?
- 其实surface的鲁棒性非常好,你给他随便丢一个向量进去,它似乎也能跑出结果,例如:
- 我在blender甚至找不到单个向量,那么两个零向量相加也行,最后跑出来必然是全黑呗。
- 这样跑出来的就是全白了。
- 测试一下纯红色。
- 甚至一个单值都不会报错,所以如果你的着色器出问题了,debug其实特别麻烦,因为系统的健壮性太好了。
- 调试这个方面这个做得不如虚幻引擎好,虚幻可以实时看到数值。
3. 思考怎么样才能够实现toon的效果。
- 实际上toon就是亮的地方都是一个颜色,暗的地方都是一个颜色,我们如果能直接做一个向量的大于小于就好了,但是blender并没有提供那样的节点。
- 那我们先尝试使用greater than节点。
- 我们发现这样子应该是该像素的范数(长度)超过0.4的为亮面(值为1),暗面的值为0。
- 那这不就好办了,我直接引入一个RGB色彩,和它相乘,那么1的值全部变为那个颜色。
- 然后0的值,只要和暗面的颜色相加,就可以得到我们想要的颜色。
- 最后的结果是这样的,但总感觉有点不对,这完全失去了材质原本的颜色。
- 按理说应该是根据本身的颜色做一个暗面的降档。
- 或者是多段的明暗分界线非常明显,而并不是这样只有一个明暗分界线。
4. 重新整理思路
- 首先我们要划分多个档,例如说我们划分3个档次,一个是向量长度大于0.6的,一个是向量长度大于0.2小于0.6的,一个是向量长度小于0.2的。
- 当向量长度大于0.6,我们可以取原色,因为高光的颜色已经足够纯净。[区块1]
- 当向量长度在0.2-0.6的时候,我们把它阶梯化为3层,分别是0.2,0.4和0.6,而向量方向不变。[区块2]
- 当向量长度小于0.2的时候,我们直接赋予一个我们指定的颜色。[区块3]
4.1. 书写区块1
- 大于0.6的和原色相加。
4.2. 书写区块2
- 小于0.6的,我们通过snap把所有在0.4-0.6的值挂在0.4,所有0.2-0.4的值挂在0.2,所有0.0-0.2的挂在0。
4.3. 书写区块3
- 小于0.2的,我们自己指定颜色。
4.4. 最后相加就是结果
4.5. 渲染效果
- 是不是感觉有点那味了,如果我们一开始选用的着色器带有辉光,则效果会更好,这些留到下一个章节。
- 不知道为什么,CSDN的动图放不上来。
一些帮助学习的网站
- https://nme.babylonjs.com/