基础
光照贴图存储的是入射光线,而非出射光线
- 光照贴图并非"光线入射后漫反射出去的部分",因为在计算物体上某个点的光照贴图时,并不需要物体本身的属性,只需要知道物体周围的其他物体的表面属性
- ‘光线入射后漫反射出去的部分’由Specular控制,金属的Specular约等于0,非金属的Specular约等于1
- 光照贴图的本质是irradiance map,也就是单位面积上的入射光通量,而非单位立体角
- Unity自己的光照烘焙生成exr文件,Bakery GPU Lightmapper生成hdr文件
光照贴图并非普通的贴图
光照贴图不能像 _MainTex 一样手动指定,这是因为:
- 光照贴图 被绑定到了 LightingData.asset 上,而 LighingData.asset 被绑定到了 Scene 上(打开任意场景 ->Lighting窗口 -> BakedLightmaps)
- 一个场景只能绑定一个LightingData,该文件内部的数据不能动态修改。如果要切换光照贴图,需要将两次烘焙生成的LightingData合并,融合为一个新的LightingData文件,然后绑定到场景上
- 物体的Mesh Renderer记录了 ① Lightmap Index:根据物体所在的场景,找到对应的LightingData,再根据Index锁定光照贴图;② Tiling, Offset
Color-based Transparency
- 使用场景:stained glass window
-
Unity Lightmapper uses the values of a givent exture to evaluate light transmission through the material
-
Color-based transparency is independent of the material color or albedo texture
// Properties块添加:
_TransparencyLM ("Transmissive Texture", 2D) = "white" {
}
// 然后手动指定贴图
Meta Pass
- Meta Pass不参与实时渲染,只在光照烘焙中起作用
- All of Unity’s built-in Materials have a Meta Pass, and the Standard Shadercontains a Meta pass.
- Bakery Lightmapper有自己的MetaPass(BakeryMetaPass.cginc)
- 即使不写Meta Pass,物体依然会参与光照烘焙,发出漫反射光线,并且albedo=白(即使手动指定了_MainTex和_Color),无emissive
立方体:Standard Shader,纯黑
立方体:Standard Shader,纯白
立方体:Unlit Shader,红色(对地面的漫反射GI效果同上)
- Meta Pass简单示例,
Pass
{
Name "META"
Tags {
"LightMode"="Meta"}
Cull Off
CGPROGRAM
#include "UnityStandardMeta.cginc" // 官方已经定义好了v2f_meta、vert_meta和frag_meta,可以直接使用
#pragma vertex vert_meta
#pragma fragment frag_meta2 // 也可以自定义frag_meta2
float4 frag_meta2 (v2f_meta i): SV_Target
{
UnityMetaInput o;
UNITY_INITIALIZE_OUTPUT(UnityMetaInput,o);
// fixed4 c = tex2D (_MainTex, i.uv);
o.Albedo= _Color;
// 如果想让物体在光照烘焙时,显示其他颜色,可以自定义_MetaPassColor,然后o.Albedo = _MetaPassColor;
o.Emission= Emission(i.uv.xy);
return UnityMetaFragment(o);
}
ENDCG
}
- 在光照烘焙时,Meta Pass提供albedo和emission信息,虽然MetaPass中也可以输入Metallic,Roughness等信息,但都只是对albedo和emission作修正,实际烘焙时只考虑albedo和emission,例如Unity Standard Shader - UnityStandardMeta.cginc中,利用Metallic(specColor)和Roughness来修正Albedo
-
The built-in Meta Passes do not handle spectral specular reflectance.
-
Metallic surfaces with a black (or almost black) albedo bounce very little light diffusely. Because the lightmappers handle only diffuse light transport, thismeans that you may see very little bounced light from these types of surfaces.Unity’s built-in Meta Passes account for this by providing a boosted version ofthe metal hue color instead of a physically correct albedo. This means that youget some bounce even from metallic materials. If you want a differentbehaviour, you can create a custom meta pass.
// Albedo for lightmapping should basically be diffuse color.
// But rough metals (black diffuse) still scatter quite a lot of light around, so
// wewant to take some of that into account too.
half3 UnityLightmappingAlbedo (half3 diffuse, half3 specular, half smoothness)
{
half roughness = SmoothnessToRoughness(smoothness);
half3 res = diffuse;
res += specular *roughness * 0.5;
return res;
}
float4 frag_meta (v2f_meta i) : SV_Target
{
// we'reinterested in diffuse & specular colors,
// andsurface roughness to produce final albedo.
FragmentCommonData data = UNITY_SETUP_BRDF_INPUT(i.uv);
UnityMetaInput o;
UNITY_INITIALIZE_OUTPUT(UnityMetaInput, o);
#ifdef EDITOR_VISUALIZATION
o.Albedo = data.diffColor;
o.VizUV = i.vizUV;
o.LightCoord = i.lightCoord;
#else
o.Albedo = UnityLightmappingAlbedo (data.diffColor, data.specColor, data.smoothness);
#endif
o.SpecularColor = data.specColor;
o.Emission = Emission(i.uv.xy);
return UnityMetaFragment(o);
}
Emmisive
// Properties
MyEmissionColor (" Emission Color", Color)=(1,0,0,1)
//Meta Pass内
fixed3 _MyEmissionColor;
o.Emission = _MyEmissionColor;
Inorder for emission to work, Material.globalIlluminationFlags mustbe set to MaterialGlobalIlluminationFlags.BakedEmissive.Standard shaders set this value automatically.
方法1: Inspector(Debug模式)下编辑材质的 Lightmap Flags = Baked Emissive
方法2:https://blog.csdn.net/linjf520/article/details/122191393
Material Validator
- 视口 -> Shading Mode = Material Validation,用来检查Albedo或者Specluar是否太暗或者太亮
- Material Validator基于MetaPass,这是因为Material Validator的核心逻辑在UnityMetaPass.cgnic中,因此Material Validator也需要Unity Standard Shader。如果使用自定义Shader,则需要自定义MetaPass.cgnic,自己编写Material Validator的核心逻辑
Transparency & Translucency
By default, shaders in Unity use monochrome transparency. This means that Unity uses the alpha channel of the material color or albedo texture to evaluate light transmission through the material.
Meta Pass中无法指定不透明度
“RenderType” | |
---|---|
=“Transparent” | 烘焙时的不透明度=_MainTex.a * _Color.a,_Cutoff不起作用 |
=“TransparentCutout” | 光照烘焙时,会将_MainTex.a * _Color.a作为alpha,cutoff = 1-0.5*alpha,如果cutoff > _Cutoff,则完全不透明,否则完全透明 |
_Color (“Tint”, Color) = (1,0,0,1) 不透明
_Color (“Tint”, Color) = (1,0,0,0.5) 半透明
参数设置
色彩空间
防止亮部过曝:Project Settings -> Player -> Other Settings -> Color Space = Linear
Color Space | |
---|---|
Gamma | ![]() |
Linear | ![]() |
光照贴图UV
- 对模型资产(fbx)启用‘Generate Lightmap’后,自动生成UV1,光照模型存储在UV1中
- 默认情况下,Unity按照UV1烘焙光照信息,如果模型只有UV0,并且不启用‘Generate Lightmap’,那么按照UV0烘焙光照信息
- 也可以在建模软件中展光照贴图UV,存储在UV1中
- 不要对植被模型Generate Lightmap,因为植被模型的UV0通常是所有叶子叠在一起,展成不重叠的UV1会造成Unity花费数小时!应该在SpeedTree中对植被模型展光照UV
光照贴图分辨率
切换到Baked Lightmap视图模式(或者在BakeryGPULightmapper中启用‘Show checker’)
选中场景中的模型 -> Inspector -> Mesh Renderer -> Lightmapping -> 调整Scale In Lightmap,数值越大,texel越密
如果光照贴图texel的分辨率太小,烘焙后可能出现彩色斑块:
Light Mode & Lighting Mode
官方文档
Light Mode:Light组件 -> Mode = Realtime / Mixed / Baked
Lighitng Mode:Lighting面板 -> Lighting Mode = Baked Indirect / Subtractive / Shadowmask
Lighting Mode参数只适用于场景中的Mixed Light,如果场景中只有Baked Light,那么Lighting Mode参数无效
实际烘焙的内容 | 光照通道 | 适用场景 | |
---|---|---|---|
Subtractive | direct and indirect lighting | direct real-time shadows for one Directional Light only | stylized art or low-end hardware |
Baked Indirect | baked indirect lighting | real-time direct lighting real-time shadowmaps |
mid-range hardware |
Shadowmask | baked indirect lighting | real-time direct lighting supports baked shadows for distant GameObjects (with Shadow masks) and blends them automatically with real-time shadow |
high-end or mid-range hardware |
Lightmap Parameters
官方文档
Project -> Create -> Lightmap Parameters
- LightmapParameters可以作用于物体的Mesh Renderer组件,例如某一组物体使用LightmapParametersA,另外一组物体使用LightmapParametersB
- 给不同的物体设置不同的Lightmap Parameters:Mesh Renderers -> Lightmap Parameters
- LightmapParameters也可以作用于整个场景:Lighting窗口 -> Scene -> Lightmap Parameters,并且场景中物体的Mesh Renderer组件 -> Lightmap Parameters = Scene Default Parameters(默认值)
Baked GI部分参数
参数 | 说明 |
---|---|
· Anti-aliasing Samples | 每个texel的supersamples数量 · A value of 1 disables super sampling(会得到错误的光照信息,因此不推荐) · Values between 2 and 8 provide 2x2 supersampling. The default value is 8, which removes most aliasing artifacts. · Values between 9 and 256 provide 4x4 supersampling. Use these values to remove artifacts, like jagged edges in direct lighting. This can happen when you use baked shadows. |
Pushoff | Pushes ray origins away from geometry along the normal based on the value you specify in modelling units. Unity applies this value to all baked lightmaps. It affects direct light, indirect light, and baked ambient occlusion. Adjust this setting to reduce self-occlusion and self-shadowing artifacts. |
Baked Tag | Groups specific sets of objects in atlases. As with the System Tag, the exact numeric value is not significant. Unity never puts GameObjects with different Baked Tag values in the same atlas. However, there is no guarantee that objects with the same tag end up in the same atlas because there may be too many objects with that tag to fit into one atlas. Unity会把相同的Baked Tag放在同一张光照贴图里 优化建议: · 将多个物体通过Mesh Baker合并为同一个物体,可以减少drawcall,但是前提条件是这些物体共享同一张光照贴图 · 建议将Terrain烘焙到单独的光照贴图,从而可以单独调整Terrain光照效果,而不影响到建筑物 |
Backface Tolerance | pecifies the percentage of front-facing geometry sampling ray hits a texel must have for Unity to consider it valid. This makes it possible for Unity to invalidate a texel if too many of the rays cast from it hit backfaces (e.g. if the texel is inside geometry). A value of 1.0 means that Unity considers a texel invalid when any of its rays hits a backface. If Backface Tolerance is 0.0, the lighting system rejects the texel only if it sees nothing but backfaces. If it is 1.0, the lighting system rejects the ray origin if it has even one ray that hits a backface. When a texel is invalid, Unity clones valid values from surrounding texels to prevent artifacts. Lower this value to solve lighting problems caused by backface samples. Use the Texel Validity Scene View Draw Mode to adjust this value. |
Limit Lightmap Count | · Applies a limit to the number of lightmaps that Unity can use to pack together GameObjects with the same Baked Global Illumination settings. · 如果多个物体的LightmapParameters不同,但是数值(Anti-aliasing Samples, Pushoff, Baked Tag, Backface Tolerance)相同,Unity可能会把他们打包到同一张lightmap里,Limit Lightmap Count限制了这种行为 · 如果Limit Lightmap Count=1,那么Unity最多使用1张光照贴图来合并LightmapParameters数值相同的物体 |
Encoding
Edit > Project Settings > Player > Other Settings > Lightmap Encoding
High Quality = HDR encoding
Normal Quality = RGBM encoding
Low Quality = dLDR encoding
- 光照贴图的Texture Type要设置为‘Lightmap’. Select Lightmap if you are using the Texture as a Lightmap. This option enables encoding into a specific format (RGBM or dLDR, depending on the platform) and a post-processing step on Texture data (a push-pull dilation pass).
- 在Project Settings中改变Lightmap Encdding并不会修改磁盘中的HDR文件,但是会改变内存中的HDR贴图,因为内存中已经是encoding过的了,Inspector中显示的空间占用也会发生变化:
- 磁盘上的HDR文件,用PS打开,显示为32bit
- 移动平台建议dLDR encoding(Low Quality),Compression=High Quality
- 如果在PC平台上选择Low Quality,因为PC平台不支持dLDR encoding,因此会自动转为RGBM encoding?(待确认)
HDR encoding:原始编码方式,直接采样
RGBM encoding:编码时,将multiplier写入A通道,解码时:
inline half3 DecodeLightmapRGBM (half4 data, half4 decodeInstructions)
{
// If Linear mode is not supported we can skip exponent part
#if defined(UNITY_COLORSPACE_GAMMA)
# if defined(UNITY_FORCE_LINEAR_READ_FOR_RGBM)
return (decodeInstructions.x * data.a) * sqrt(data.rgb);
# else
return (decodeInstructions.x * data.a) * data.rgb;
# endif
#else
return (decodeInstructions.x * pow(data.a, decodeInstructions.y)) * data.rgb;
#endif
}
dLDR encoding:
- used on mobile platforms by simply mapping a range of [0, 2] to [0, 1],因为映射到了[0,1],所以需要的bit更少
- Baked light intensities that are above a value of 2 will be clamped
- Some platforms store lightmaps as dLDR because their hardware compression produces poor-looking artifacts when using RGBM.
- 在解码时,输入的是fixed4,输出的是half3
- 解码时:
// Decodes doubleLDR encoded lightmaps.
inline half3 DecodeLightmapDoubleLDR( fixed4 color, half4 decodeInstructions)
{
// decodeInstructions.x contains 2.0 when gamma color space is used or pow(2.0, 2.2) = 4.59 when linear color space is used on mobile platforms
return decodeInstructions.x * color.rgb;
}
Target platform | Encoding | Compression - size (bits per pixel) |
---|---|---|
Standalone(PC, Mac, Linux) | RGBM / HDR | DXT5 / BC6H - 8 bpp |
WebGL 1.0 / 2.0 | RGBM | DXT5 - 8 bpp |
iOS ASTC [1] | dLDR / RGBM / HDR | ASTC - 3.56 bpp / ASTC - 3.56 bpp / RGB9E5 - 32 bpp |
iOS PVRTC | dLDR / RGBM / HDR | PVRTC RGB - 4 bpp / ETC2 RGBA - 8 bpp / RGB9E5 - 32 bpp |
tvOS | dLDR / RGBM / HDR | ASTC - 3.56 bpp / ASTC - 3.56 bpp / RGB9E5 - 32 bpp |
Android ASTC [2] | dLDR / RGBM / HDR | ASTC - 3.56 bpp / ASTC - 3.56 bpp / ASTC HDR - 3.56 bpp |
Android ETC2 | dLDR / RGBM / HDR | ETC2 RGB - 4 bpp / ETC2 RGBA - 8 bpp / ASTC HDR - 3.56 bpp |
Android ETC | dLDR / RGBM / HDR | ETC1 RGB - 4 bpp / ETC2 RGBA - 8 bpp / ASTC HDR - 3.56 bpp |
[1]: The texture compression format used for lightmaps on iOS depends on the Texture compression format setting in the Player Settings.
[2]: The texture compression format used for lightmaps on Android depends on Player Settings and Build Settings. See Texture compression settings for more details on how these settings interact. Encoding和Compression一一对应
Trouble Shooting
彩色/白色条纹
通常发生在两个物体的交界处:
查看Lightmap:
解决方法:Lightmapping Settings -> 调大Padding,默认情况下Padding=2,而白边正好占用两个texel,Padding指不同模型的光照贴图在Atlas中的间距
如果条纹发生在模型内部,那么调大padding无效,下面的解决方法二选一
1)建模软件中手动将相邻的面分离
2)FBX资产 -> Model -> 启用‘Generate Lightmap UVs’ -> 调大PackMargin(例如10)-> Apply,如果模型中的一条边是锐边,那么它两侧的面,在UV1中,被padding隔开
间接光照过暗
调亮光源(例如Directional Light),会导致直接光照过曝,细节丢失:
调高光源的Indirect Multiplier,会导致角落处,由于光线多次反弹,积累了过多的亮度,因此建议优先调整Lightmapping的Albedo Boost
Albedo Boost:Intensify the albedo of materials, draw the albedo value towards white for indirect light computation
如果纹理本身就是纯白(1,1,1),那么Albedo Boost=1和=10没有任何区别
参数 | |
---|---|
Albedo Boost=1 Indirect Intensity=1 |
![]() |
Albedo Boost=10 Indirect Intensity=1 |
![]() |
Albedo Boost=1 Indirect Intensity=5 |
![]() |
Albedo Boost=5 Indirect Intensity=5 |
![]() |