关于光照的知识补充
一、为什么逐片元着色器比逐顶点着色器更加平滑
- 在顶点着色器和片元着色器之间还存在其他流程(裁剪、屏幕映射、三角形设置、三角形遍历···),也就是说顶点着色器回调函数中返回的数据,还会在这些中间流程中进行处理,再传递给片元着色器
- 在顶点着色器中进行了颜色相关计算时,我们只是计算了模型顶点位置的颜色信息,这些数据在渲染管线中传递时,会在光栅化阶段的片元着色器之前对三角形围着的片元颜色进行插值运算,再传递给片元着色器 也就是说顶点之间的片元颜色信息,其实并不是使用该位置的相关信息计算而来,而是粗暴的插值运算,计算颜色的平均值
- 片元着色器中传入的参数结构虽然和顶点着色器返回的一样,但是里面的数据是不同的,片元着色器中传入的参数,都是为每一个片元进行专门插值后的结果 也就是说,在片元着色器进行颜色相关计算时,能够为每一个像素点,基于它的信息进行相关的颜色计算
二、内置光照计算相关函数
1.作用
内置文件"UnityCG.cginc"中提供的,帮助我们进行数学相关的计算和转换
2.常用的相关函数
| 函数 | 传入值 | 返回值 | 注意事项 |
|---|---|---|---|
| float3 WorldSpaceViewDir(float4 v) | 传入模型空间下的顶点位置 | 返回世界空间下该点到摄像机的方向 | \ |
| float3 UnityWorldSpaceViewDir(float4 v) | 传入世界空间下的顶点位置 | 返回世界空间下该点到摄像机的方向 | \ |
| float3 ObjSpaceViewDir(float4 v) | 传入模型空间下的顶点位置 | 返回模型空间下该点到摄像机的方向 | \ |
| float3 WorldSpaceLightDir(float4 v) | 传入模型空间下的顶点位置 | 返回世界空间下该点到光源的方向 | 仅用于向前渲染,没有归一化 |
| float3 UnityWorldSpaceLightDir(float4 v) | 传入世界空间下的顶点位置 | 返回世界空间下该点到光源的方向 | 仅用于向前渲染,没有归一化 |
| float3 ObjSpceLightDir(float4 v) | 传入模型空间下的顶点位置 | 返回模型空间下该点到光源的方向 | 仅用于向前渲染,没有归一化 |
| float3 UnityObjectToWorldNormal(float3 normal) | 传入模型空间下的法线 | 返回世界空间下的法线 | \ |
| float3 UnityObjectToWorldDir(float3 dir) | 传入模型空间下的方向向量 | 返回世界坐标下的方向向量 | \ |
| float3 UnityWorldToObjectDir(float3 dir) | 传入世界空间下的方向向量 | 返回模型坐标下的方向向量 | \ |
| float3 UnityObjectToClipPos(float4 v) | 传入模型空间下的顶点位置 | 返回裁剪坐标下的顶点位置 | \ |
三、关于光照方向的计算
1.模拟定向光源
直接得到_WorldSpaceLightPos0 作为光照方向 表示光线是平行的,而不是特定点发出的 一般用于模拟太阳光的效果,而不是特定点发射 一般模拟太阳光效果 采用这种方式
2.模拟点光源
用光照位置_WorldSpaceLightPos0 减去 顶点坐标 表示光线是从特定点发射的,并朝着顶点方向 一般定点光源 采用这种方式
四、修改凹凸系数的计算方式,让法线系数不影响光照
直接让 法线 * 凹凸系数的计算方式 会直接影响光照模型的计算
为了凹凸系数不影响光照效果 有一种专门的算法 但这种算法不是基于真实的物理规律 只是实现看起来"正常的效果"
- 只让法线中的 xy 乘以凹凸系数 tangentNormal.xy *= _BumpScale;
- 保证法线向量为单位向量(让法线不会为 0,而是趋于顶点法线) x² + y² + z² = 1 => z = 根号下( 1 - (x² + y²)) => tangentNormal.z = sqrt( 1 - saturate(dot(tangentNormal.xy,tangentNormal.xy))); 注释: saturate 为[0,1] 的夹紧函数