【Unity Shader】(1)兰伯特模型 逐顶点光照 和 逐像素光照 分别实现 漫反射光照模型

使用逐顶点光照在unityShader中实现漫反射效果

  • 漫反射公式——兰伯特模型

    首先需要了解基本光照模型中,漫反射(Diffuse)的

    兰伯特模型
    【Unity Shader】(1)兰伯特模型 逐顶点光照 和 逐像素光照 分别实现 漫反射光照模型_第1张图片
    兰伯特模型 共有4个参数

  • 入射光线的颜色和强度—— C light

  • 材质的漫反射系数—— M diffuse

  • 表面法线—— n

  • 光源方向—— I

为了避免 n 和 I 的点积为负值,我们需要使用max来操作。但在Unity Shader中,我们可以使用 saturate(x)函数达到相同的效果。

其中,x可以是操作的标量或矢量,即float、float2、float3等类型
saturate会把传进来的x截取在[0,1]的范围内,如果x是一个矢量,那么就会对它的每一个分量进行截取操作。

  • 光照原理

在宏观上,渲染可以分为一下两个:
1、决定像素是否可见;
2、决定像素的光照计算。

在这一片博客,我们主要探讨第二点——光照的计算。

  • 部分疑问?

计算光照的公式有很多,我们使用的是兰伯特模型,但是如何理解其中的变量值?为什么会有阴影的部分?为什么有些部分的颜色与其他部分不同?

  • Q:我们探讨为什么有些光亮的颜色不同:
    A:在Unity之中,假设一个平行光源带来的每条光线间隔为 d ,那么如果是正午,也就是平行光源正向下照射,那么我们可以轻易知道,此时找到物体表面的光线间隔其实也是为 d 的。但是如果光线不是正下直射,而是有点倾斜角度(清晨或黄昏时),那么如果平行光带来的光线间隔仍为 d 时,照到物体上的间距其实已经不是 d 了,因为在光线数量有限的Unity中,发生了角度的偏移。下图可以更直观的展示这个结论:
    【Unity Shader】(1)兰伯特模型 逐顶点光照 和 逐像素光照 分别实现 漫反射光照模型_第2张图片

  • Q:兰伯特公式是如何在Shader中工作的?
    A:在上图中,cosθ可以使用 光源方向 l 和表面法线 n点积求得。而兰伯特模型中,尾部的部分,就是 光源方向 与 表面法线 点积。结合下图可以更轻易的了解:

【Unity Shader】(1)兰伯特模型 逐顶点光照 和 逐像素光照 分别实现 漫反射光照模型_第3张图片
(图片取自知乎@俊铭)

根据上图,可以分为右上角的三个情况。再结合兰伯特公式,最终可以作为权重来控制颜色的输出。当点积的值小于0时,直接颜色权重变为0,(因为要控制在[ 0 , 1]的区间内)最终导致颜色为0,阴影的产生。



代码开始:

  • 逐顶点光照

1. 创建一个空场景(只有摄像机和平行光),删除该场景中的天空盒。

2. 新建一个材质,命名为Mat_Diffuse

3. 新建一个UnityShader,命名为Sha_DIffuse并将该Shader赋值给Mat_Diffuse

4. 在场景中新建一个胶囊体,将Mat_Diffuse赋予该物体。


5. 保存,开始编辑Shader代码:

①删除第3步新建的Shader里的默认代码。
②为了控制该Shader的颜色,我们需要在Properties中添加漫反射颜色
Properties{
   
	_Diffuse ( "Diffuse", Color) = (1,1,1,1)
}

(这里更加类似于 C# 脚本的 Public Color _Diffuse;


③在SubShader之中定义Pass语义块。在Pass的一开始就指名该Pass的光照模式:
SubShader{
   
	Pass{
   
		Tags {
   "LightMode"="ForwardBase"}
	}
}

只有正确定义了LightMode,我们才可以在后续得到内置的光照变量。



④声明vertex和fragment着色器 并 包含Lightint.cginc
#pragma vertex vert
#pragma 

你可能感兴趣的:(Shader,TA,untiy,着色器,技术美术,Unity,Shader,TA)