[基础] Unity Shader:法向量与光照

在现实世界中,太阳照射在物体的那一面较亮,而物体背朝太阳的那一面较暗,这就是我们要讨论的问题:如何计算一个物体各个表面的阴暗程度。

1. 法向量

法向量(normal vector) 也被称为法线(normal),它是垂直于平面的向量,在游戏中,模型的一个顶点往往会携带额外的信息,顶点法线就是其中之一。

2. 辐照度

在实时渲染中,我们通常把光源当成一个没有体积的点,用 来表示它的方向,那么,我们如何量化光呢?在光学里,我们使用辐照度(irradiance) 来量化光。在计算光照模型时,我们需要知道一个物体表面的辐照度,而物体表面往往是和 不垂直的,那么如何计算这样的表面的辐照度呢?

如上图所示,我们可以使用光源方向 和表面法线 之间的夹角 的余弦值来得到。

3. 辐照度的计算

两个向量之间的一个点积公式如下:

由此公式我们可以得出:

若我们将 规范化,也就是模长变为1,则公式又变成了:

由此可得出,辐照度可通过规范化光源向量 和规范化法向量 的点积来得到。

4. 应用于Shader

接下来,我们将理论真正地应用于Shader中,首先,我们要先规范化法向量和光源向量:

cpp 复制代码
float3 N = normalize(appData.normal); // 规范化法向量
float3 L = normalize(_WorldSpaceLightPos0); // 规范化光源向量

然后通过点积求得辐照度,为了防止点积结果为负值,我们需要将其限制在[0, 1]范围内,Cg提供了 saturate 函数恰恰可以实现这样的功能:

cpp 复制代码
float E = saturate(dot(N, L)); // 辐照度

得到辐照度后,我们就可以用物体颜色乘上辐照度了:

cpp 复制代码
outData.color = _Color.rgb * E; // 物体颜色 × 辐照度

当然,我们也可以让物体表面颜色也受到光照色的影响,不过在此之前要先引入 Lighting.cginc 文件:

cpp 复制代码
outData.color = (_Color * 0.5 + _LightColor0 * 0.5) * E; // 物体颜色混合光照色 × 辐照度

当然,我们也可以在片元着色器最后返回颜色时加上环境色 UNITY_LIGHTMODEL_AMBIENT,这样物体表面也将会受到环境色的影响:

cpp 复制代码
return inputData.color + UNITY_LIGHTMODEL_AMBIENT;

最终效果如下:

相关推荐
张老师带你学6 小时前
unity TerrainSampleAssets
科技·游戏·unity·游戏引擎·模型
亿元程序员6 小时前
亿元Cocos小游戏实战合集2.0
游戏·游戏引擎
RReality9 小时前
【Unity Shader URP】色带渐变着色(Ramp Shading)实战教程
ui·unity·游戏引擎·图形渲染
mxwin17 小时前
Unity URP 体积光与雾效 基于深度重建世界空间位置,实现体积雾与体积光
unity·游戏引擎
张老师带你学19 小时前
unity 树资源 有樱花树 buildin
科技·游戏·unity·游戏引擎·模型
魔士于安19 小时前
unity 植物 不常见 花 触手植物
游戏·unity·游戏引擎·贴图·模型
魔士于安20 小时前
unity=>传送门特效 带自由视角旋转放大 鼠标操作
前端·游戏·unity·游戏引擎·贴图·模型
南無忘码至尊21 小时前
Unity学习90天 - 第4天 - 认识物理系统基础并实现物体碰撞反弹
学习·unity·游戏引擎
南無忘码至尊21 小时前
Unity学习90天 - 第4天 - 学习预制体 Prefab + 实例化并实现按鼠标生成子弹
学习·unity·游戏引擎
魔士于安1 天前
Unity资源Toon City Pack 发电厂 工地 公园 地铁站口 银行 车 直升飞机 可动 URP
游戏·unity·游戏引擎·贴图·模型