shader总结六

来源:互联网 发布:辽宁北方频道网络直播 编辑:程序博客网 时间:2024/06/04 00:46

参考蛮牛教育,学习下就行了,别转载了


对于法线贴图的制作原理:

取得一张纹理,假设是256*256大小,计算相邻的两个像素的插值,上下像素的插值和左右像素的插值,对于灰度图像来说,pixel像素颜色值rgb三个值都是一样的,任取一个就行,为了把两个像素的插值表达成一个深度信息,因此把插值放在了z坐标上,写出2个向量,然后做出法线,法线是左右插值的向量和上下插值的向量的叉积,得到垂直于该平面的法向量,再把法向量从(-1,1)映射到颜色值(0,1)上,写一个c#脚本


tex0为输入贴图纹理,tex1为输出法线纹理


在蛮牛里讲的切线空间的法线贴图的做法:
如何通过顶点来得到切线空间下的三个坐标轴?先找到顶点的法线,在找到顶点的切线,根据切线和法线叉积(cross)来取得第三个坐标轴。构造空间转换矩阵rotation,将这三个向量合成一个3*3矩阵,该矩阵乘以世界空间下入射光得到切线空间下光方向,

在片元函数中UnpackNormal函数来获取对应像素的法向值然后N和L点积得到光的颜色



对于会渲染一个重要的平行光。如果场景中有点光源的时候,就没有效果了,可以加个pass通道,lightmode为forwardAdd下面加上同样的代码发现加上点光源有输出加上平行光没有效果,原因是没有加blend因此全是输出第二个pass的光了,所以第二个pass加上即可混合两个的光

对于点光源的线性衰减,可以这样做,取得光源到物体的距离,距离越远,就衰减越大



立方体采样(cube采样):

应用:一个茶壶,它通过立方体采样实现对周围的环境进行映射,这是ssmpler2D全部改成了samplerCube,在unity中TextTure Type选择Cubemap

思想:立方体采样,不再是对2d纹理的采样,而是一个三维空间下的采样,通过相机到顶点的向量(调用WorldSpaceViewDir函数也行)和顶点的法线来求得反射向量

我们看到最后把反射的光映射到纹理上从片元函数返回出去,因为立方体采样我们看到的物体上的颜色是它反射光的颜色



在一个pass中blend zero one 表示当前的输出为0之前的pass输出为1,因此当前的pass无作用


blend参数介绍:

Blend zero one:显示背景的RGB部分,无Alpha透明通道处理

Blend one  zero:  显示贴图的RGB部分,无Alpha透明通道处理

Blend one  one:贴图和背景叠加,无Alpha透明通道处理

Blend SrcAlpha  zero:仅仅显示贴图,贴图含Alpha透明通道处理。但是贴图中的透明部分,黑色部分没有颜色来显示,因为源颜色乘以alpha值0,为0;而混合目标的颜色乘以zero 0,也是0。所以透明部分显示的颜色为(0,0,0)

Blend SrcAlpha  OneMinusSrcAlpha:最终颜色 = 源颜色 * 源透明值 + 目标颜色*(1 - 源透明值)

最常用的透明混合方式。贴图alpha值高的部分,显示得实,而混合的背景很淡。而alpha值高的部分,贴图显示得淡,而背景现实得实。


如何实现这种超级赛亚人表面包裹一层气盾和物体表面泛光效果?


可以进行多pass混合的方式,比如用一个pass做当前的渲染,用另一个pass沿着当前顶点的法线做一个扩展

我们可以看到第一个pass的blend用的oneminussrealpha,也即和另外的pass透明度混合,在第一个pass中把物体的顶点外扩一下,也即顶点+=法线*0.2,让顶点扩一层后计算的光颜色为为顶点的法线和相机到顶点向量的点积,这样外层的颜色为向外衰减(里面亮外面黑),效果如下:


可以看到颜色也会变黑,我们希望把透明度向外衰减,颜色不变因此,效果如下

                           

如果没有第二个pass直接把1和3pass混合,效果如下


我们希望效果是最上面的,外层是向外衰减,内层是向内衰减而不是内层向外衰减,

可以加上第二个pass进行blend减法,让第一个pass外层泛光内层镂空的状态。第二个pass中使用效果如下


那么改成乘法,效果如下:

         


第三个pass的blend用的oneminussrealpha,也即和另外的pass透明度混合,没有把顶点外扩,也即用的内层顶点,颜色为

saturate(dot(N,V))很小,1减去后很大说明颜色和透明度是向内衰减的(外面亮里面黑),也即实现内层这样的效果:







Mesh:网格

由三角形组成。由一个数组存储,前3个元素表示第一个三角形的顶点,然后依次表示第2个、第三个

Mesh Filter: 网格过滤器

指定mesh(物体的几何形状)

Mesh renderer:网格渲染器

网格渲染器从网格过滤器中获得几何体的形状然后进行渲染。


对于一个汽车材质的物体如果要想知道物体的长度和高度,可以写一个脚本,由于汽车里面包含三个部分,每个部分的的属性是这样的,


把脚本挂在汽车父物体上面,在脚本中这样来写,将三个部件拖动到脚本中,找到每个组件的mesh组件里面的每个顶点,用一个vector3数组来保存,遍历数组每个元素求得最大值和最小值,这里只粘贴出了一个部件的做法,另外2个一样的做法


如果我们在update函数中让mesh中每个顶点每隔一段时间绕y轴旋转一定度数,在uptate函数中这样写,把脚本拖动到汽车的最顶级的物体上



让汽车呈现左右颜色呈插值独立的不同颜色



中间的值Center是在面板中拖动的,让顶点减去汽车坐标中间值取绝对值单位化,让它乘以一个变化率,返回从主颜色到副颜色以一个变量插值变化的颜色,因此返回的是lerp

但是图片中没有光照效果,第一种方式采用以前的加入光照的方法,第二种是创建一个surface shader然后再加入颜色的融合,那么创建一个表面着色器,然后默认已经指定了金属感和光泽



然后将已经写好的顶点片元着色器的代码的内容添加到表面着色器当中



这样就有光照了