反射与折射
只考虑平行光,且物体表面光滑。
高光反射:光射到物体表面直接被反射出来被成为高光反射,既图中红色所画出的光线。
漫反射:光射向物体表面,折射在物体内部的光经过不断地折射,再次射出物体,此被称为漫反射,既图中地蓝色所画出的光线。
BRDF光照模型:用于模拟真实地光物理。
SSS材质:用于描述光物理,属于BRDF中次表面反射其中地一部分。
标准光照模型
该光照为直接光照,由光直接照射在物体表面,在反射到摄像机上,其中包含自发光,高光反射,漫反射,环境光(用于描述间接光照)。
间接光照
间接光照:例如在一个红色的方块和一个蓝色的小球,当光照射到方块上经反射后照射在蓝色小球上呈现红色,在被照射到的地方,月接近方块,颜色越红,此被称为间接光照。
自发光
自发光:由物体直接发光射向摄像机(自发光就等于材质颜色,本身不对周围物体造成影响,由unity中引入了全局光照之后,可以对此中影响进行模拟)。
漫反射
当光照垂直于物体表面射入时没有漫反射,漫反射的强度由光的入射角度决定,颜色由光的颜色和被照射物体的材质影响。强度可以使用入射角的cos去计算。cosθ可以使用向量的叉乘公式去计算。


向量n和向量l为单位向量。
顶点漫反射
代码简单实现,此处未计算环境光(逐顶点计算)。

环境光获取:
1 2 3
| fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
o.color = diffuse + ambient;
|
片元漫反射
代码简单实现:

二者之间的区别:
在片元着色器中的处理更加细节,二者呈现的漫反射远看没有什么区别,近看可以法线,在顶点着色器中处理的物体表面的阴影边缘可以明显看到顶点,在片元中就没有这种情况。
半兰伯特漫反射
概念:将计算公式中的点乘的结果乘上0.5加上0.5,将其范围固定到0~1之间,可以解决,前两者的阴影地方过黑的问题。
高光反射
Phong模型
计算照射到摄像机中光(紫色的向量代表)的强度和颜色。
当θ = 0度时,为最大值 1。反射的到摄像机内
当θ = 90度时,为最小值 0. 此时没有反射光进入到摄像机内
其中向量r,向量l和向量n都为单位向量。
所以最后公式为:
Blinn-Phong模型
当θ=0度时,法线向量n等于向量h。
当θ=90度时,法线向量n垂直于向量h。
Phong顶点高光反射
1 2 3 4
| fixed3 reflectDir = normalize(reflect(-worldLight, worldNom)); fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - UnityObjectToWorldDir(v.vertex)); fixed3 specular = _LightColor0.rgb * _Specular * pow(max(0, dot(reflectDir, viewDir)), _Gloss);
|
效果图:
Phong片元高光反射
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| v2f vert (appdata_base v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); fixed3 worldNormal = UnityObjectToWorldNormal(v.normal); o.worldNormal = worldNormal; o.worldPos = UnityObjectToWorldDir(v.vertex); return o; }
fixed4 frag (v2f i) : SV_Target { fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz; fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz); fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * max(0, dot(worldLightDir, normalize(i.worldNormal))); fixed3 reflectDir = normalize(reflect(-worldLightDir, i.worldNormal)); fixed3 viewDir = normalize(_WorldSpaceLightPos0.xyz - i.worldPos.xyz); fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(reflectDir, viewDir)), _Gloss);
fixed3 color = ambient + diffuse + specular; return float4(color, 1); }
|
效果图:
BlinnPhong高光反射
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| fixed4 frag (v2f i) : SV_Target { fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz; fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz); fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * max(0, dot(worldLightDir, normalize(i.worldNormal))); fixed3 viewDir = normalize(_WorldSpaceLightPos0.xyz - i.worldPos.xyz); fixed3 halfDir = normalize(worldLightDir + viewDir); fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(i.worldNormal, halfDir)), _Gloss);
fixed3 color = ambient + diffuse + specular; return float4(color, 1); }
|
该模型是将公式中reflectDir与viewDir的点积,更换成了法线和半角向量的点积。效果图如下:
unity库函数
在写shader过程中尽可能去使用unity的一个库函数,因为库函数中会进行一些判断,去避免一些不必要的麻烦。
视角坐标的获取,在获取后进行normalize,有些库函数中并不进行normalize。
1
| fixed3 viewDir = normalize(UnityWorldSpaceViewDir(UnityObjectToWorldDir(v.vertex)));
|
世界光的获取
1
| fixed3 worldLight = UnityWorldSpaceLightDir(UnityObjectToWorldDir(v.vertex));
|