在内置渲染管线中编写表面着色器时,您需要描述表面的属性(如反照率颜色和法线),并利用__光照模型__计算光照的交互。
内置的光照模型有两种,分别是 Lambert 和 BlinnPhong,前者用于漫反射光照,后者用于镜面反射光照。Unity 使用 Lighting.cginc 文件定义这些模型(Windows: <unity 安装路径>/Data/CGIncludes/Lighting.cginc; macOS: _/Applications/Unity/Unity.app/Contents/CGIncludes/Lighting.cginc_)。
有些您可能更希望使用自定义光照模型。这时就可以用表面着色器。光照模型实际上就是符合一定规范的 Cg/HLSL 函数。
| 功能名称 | 通用渲染管线 (URP) | 高清渲染管线 (HDRP) | 自定义 SRP | 内置渲染管线 |
|---|---|---|---|---|
| 表面着色器 | 否 如需了解在 URP 中创建着色器对象的简化方法,请参阅着色器图表。 |
否 如需了解在 HDRP 中创建着色器对象的简化方法,请参阅着色器图表。 |
否 | 是 |
光照模型中包含多个以 Lighting 开头的常规函数。您可以在着色器文件中的任何位置,或其中一个被包含的文件中,声明这些函数。这些函数是:
half4 Lighting<Name> (SurfaceOutput s, UnityGI gi); 请针对_不依赖_视图方向的光照模型,在前向渲染路径中使用此函数。
half4 Lighting<Name> (SurfaceOutput s, half3 viewDir, UnityGI gi); 请针对_依赖_视图方向的光照模型,在前向渲染路径中使用此函数。
half4 Lighting<Name>_Deferred (SurfaceOutput s, UnityGI gi, out half4 outDiffuseOcclusion, out half4 outSpecSmoothness, out half4 outNormal); 对延迟着色路径使用此函数。
请注意,您无需声明所有函数。光照模型不一定会使用视图方向。同样的,如果光照模型仅在前向渲染中生效,请勿声明 _Deferred 函数。这能确保使用视图方向的着色器仅会编译到前向渲染。
声明以下函数以自定义光照贴图数据和探针的解码:
half4 Lighting<Name>_GI (SurfaceOutput s, UnityGIInput data, inout UnityGI gi);请注意,要解码 Unity 标准光照贴图和 SH 探针,您可以使用内置函数 DecodeLightmap 和 ShadeSHPerPixel;这些函数位于 Unity 内部 UnityGlobalIllumination.cginc 文件中的 UnityGI_Base 内(Windows: <unity 安装路径>/Data/CGIncludes/UnityGlobalIllumination.cginc; macOS: _/Applications/Unity/Unity.app/Contents/CGIncludes/UnityGlobalIllumination.cginc__)。
以下是使用内置 Lambert 光照模型的着色器示例:
Shader "Example/Diffuse Texture" {
Properties {
_MainTex ("Texture", 2D) = "white" {}
}
SubShader {
Tags { "RenderType" = "Opaque" }
CGPROGRAM
#pragma surface surf Lambert
struct Input {
float2 uv_MainTex;
};
sampler2D _MainTex;
void surf (Input IN, inout SurfaceOutput o) {
o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
}
ENDCG
}
Fallback "Diffuse"
}
以下是有纹理和没有纹理时的外观对比(在场景中使用一个方向光):