一、Indirect Bake Mode
- 烘焙的时候,会把环境光也烘焙进去
静态物体
Light 的模式设置
Realtime
- 纯实时光计算,不会有任何信息烘焙进 lightmap
Mixed
- 间接光(indirect)烘焙到 lightmap
- 直接光 direct 实时计算
- 间接光(indirect)烘焙到 lightmap
Baked
直接光信息和间接光信息都烘焙到 lightmap 中
不会有任何实时光计算
静态物体通过光照贴图获取间接光信息
shader 中采样
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/EntityLighting.hlsl" #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/ImageBasedLighting.hlsl" //Lightmap TEXTURE2D(unity_Lightmap); SAMPLER(samplerunity_Lightmap); // lightMapUV 计算,使用第二套 UV // float2 lightMapUV : TEXCOORD1; // output.lightMapUV = input.lightMapUV * unity_LightmapST.xy + unity_LightmapST.zw; float3 SamplerLightMap(float2 lightMapUV) { #if defined(LIGHTMAP_ON) return SampleSingleLightmap( TEXTURE2D_ARGS(unity_Lightmap, samplerunity_Lightmap),lightMapUV, float4(1.0,1.0,0.0,0.0), #if defined(UNITY_LIGHTMAP_FULL_HDR) false, #else true, #endif float4(LIGHTMAP_HDR_MULTIPLIER, LIGHTMAP_HDR_EXPONENT, 0.0, 0.0) ); #else return 0.0; #endif }
动态物体
动态物体可以通过 LightProbe 来获取间接光,较长的物体可以通过 LPPV 方式进行获取 lightProbe
通过摆放 LightProbe,可以将间接光信息烘焙到 LightProbe 中。LightProbe 数据通过球谐函数传入
- 不使用 LPPV
- 使用 LPPV
LightProbe 和 LPPV 使用方式
- 管线
SortingSettings sortingSettings = new SortingSettings(_camera)
{
criteria = SortingCriteria.CommonOpaque
};
DrawingSettings drawingSettings = new DrawingSettings(UnlitShaderTagId, sortingSettings)
{
enableDynamicBatching = useDynamicBatching,
enableInstancing = useGPUInstancing,
perObjectData =
PerObjectData.ReflectionProbes | //启用反射探针
PerObjectData.Lightmaps | PerObjectData.ShadowMask | //启用光照贴图、ShadowMask贴图
PerObjectData.LightProbe | PerObjectData.OcclusionProbe | //启用 LightProbe、OcclusionProbe
PerObjectData.LightProbeProxyVolume | PerObjectData.OcclusionProbeProxyVolume | //启用对应 LPPV 模式
};
drawingSettings.SetShaderPassName(1, LitShaderTagId);
FilteringSettings filteringSettings = new FilteringSettings(RenderQueueRange.opaque, renderingLayerMask: (uint) renderingLayerMask);
_context.DrawRenderers(_cullingResults, ref drawingSettings, ref filteringSettings);
_context.DrawSkybox(_camera);
if (_useColorTexture || _useDepthTexture)
{
CopyAttachments();
}
sortingSettings.criteria = SortingCriteria.CommonTransparent;
drawingSettings.sortingSettings = sortingSettings;
filteringSettings.renderQueueRange = RenderQueueRange.transparent;
_context.DrawRenderers(_cullingResults, ref drawingSettings, ref filteringSettings);
- shader
//需要使用宏定义,静态物体会开启 LIGHTMAP_ON
#pragma multi_compile _ LIGHTMAP_ON
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/EntityLighting.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/ImageBasedLighting.hlsl"
// LightProbe 的球谐函数参数
float4 unity_SHAr;
float4 unity_SHAg;
float4 unity_SHAb;
float4 unity_SHBr;
float4 unity_SHBg;
float4 unity_SHBb;
float4 unity_SHC;
//LPPV
//LightProbeProxyVolume 和 OcclusionProbeProxyVolume 使用同一个数据结构
// 如果使用了 LPPV, unity_ProbeVolumeParams.x 为 1
float4 unity_ProbeVolumeParams;
float4x4 unity_ProbeVolumeWorldToObject;
float4 unity_ProbeVolumeSizeInv;
float4 unity_ProbeVolumeMin;
//LPPV
TEXTURE3D_FLOAT(unity_ProbeVolumeSH);
SAMPLER(samplerunity_ProbeVolumeSH);
float3 SampleLightProbe (Surface surfaceWS)
{
#if defined(LIGHTMAP_ON)
return 0.0;
#else
if (unity_ProbeVolumeParams.x)
{
return SampleProbeVolumeSH4(
TEXTURE3D_ARGS(unity_ProbeVolumeSH, samplerunity_ProbeVolumeSH),
surfaceWS.position, surfaceWS.normal,
unity_ProbeVolumeWorldToObject,
unity_ProbeVolumeParams.y, unity_ProbeVolumeParams.z,
unity_ProbeVolumeMin.xyz, unity_ProbeVolumeSizeInv.xyz
);
}
else
{
float4 coefficients[7];
coefficients[0] = unity_SHAr;
coefficients[1] = unity_SHAg;
coefficients[2] = unity_SHAb;
coefficients[3] = unity_SHBr;
coefficients[4] = unity_SHBg;
coefficients[5] = unity_SHBb;
coefficients[6] = unity_SHC;
return max(0.0, SampleSH9(coefficients, surfaceWS.normal));
}
#endif
}
Unity 烘焙的硬编码
Unity 烘焙使用硬编码 _MainTex、Color、_Cutoff 来进行计算 alpha 的
Unity 根据材质球的渲染队列来判断使用哪种方式进行计算 alpha
- 支持的半透明烘焙,材质球渲染队列为:Transparent & 3000
- 支持的 Clip 烘焙,材质球渲染队列为: AlphaTest & 2450
- 正常不透明的烘焙,材质球渲染队列为:Opaque & 2000
Directional Mode
https://catlikecoding.com/unity/tutorials/rendering/part-16/
正常烘焙的间接光信息是没有法线计算的,所以没有凹凸效果,细节效果Unity 支持 Dominant Direction 模式

shader使用
//宏定义
#pragma multi_compile _ DIRLIGHTMAP_COMBINED // 启用 DirectionalMode
#pragma multi_compile _ LIGHTMAP_ON
//贴图名字
#define LIGHTMAP_NAME unity_Lightmap
#define LIGHTMAP_INDIRECTION_NAME unity_LightmapInd //DirectionalLightmap 贴图名称
//使用 SampleLightmap 中的分子
#if defined(LIGHTMAP_ON) && defined(DIRLIGHTMAP_COMBINED)
diffuseLighting = SampleDirectionalLightmap(TEXTURE2D_LIGHTMAP_ARGS(LIGHTMAP_NAME, LIGHTMAP_SAMPLER_NAME),
TEXTURE2D_LIGHTMAP_ARGS(LIGHTMAP_INDIRECTION_NAME, LIGHTMAP_SAMPLER_NAME),
LIGHTMAP_SAMPLE_EXTRA_ARGS, transformCoords, normalWS, encodedLightmap, decodeInstructions);
#elif defined(LIGHTMAP_ON)
diffuseLighting = SampleSingleLightmap(TEXTURE2D_LIGHTMAP_ARGS(LIGHTMAP_NAME, LIGHTMAP_SAMPLER_NAME), LIGHTMAP_SAMPLE_EXTRA_ARGS, transformCoords, encodedLightmap, decodeInstructions);
#endif
//具体方法
//directional Lightmap 存储的不是单位向量的灯光方向
//通过使用半兰伯特计算,来模拟表面受到多个光照后的效果
void SampleDirectionalLightmap(TEXTURE2D_LIGHTMAP_PARAM(lightmapTex, lightmapSampler), TEXTURE2D_LIGHTMAP_PARAM(lightmapDirTex, lightmapDirSampler), LIGHTMAP_EXTRA_ARGS, float4 transform,
float3 normalWS, float3 backNormalWS, bool encodedLightmap, real4 decodeInstructions, inout real3 bakeDiffuseLighting, inout real3 backBakeDiffuseLighting)
{
// In directional mode Enlighten bakes dominant light direction
// in a way, that using it for half Lambert and then dividing by a "rebalancing coefficient"
// gives a result close to plain diffuse response lightmaps, but normalmapped.
// Note that dir is not unit length on purpose. Its length is "directionality", like
// for the directional specular lightmaps.
// transform is scale and bias
uv = uv * transform.xy + transform.zw;
real4 direction = SAMPLE_TEXTURE2D_LIGHTMAP(lightmapDirTex, lightmapDirSampler, LIGHTMAP_EXTRA_ARGS_USE);
// Remark: baked lightmap is RGBM for now, dynamic lightmap is RGB9E5
real3 illuminance = real3(0.0, 0.0, 0.0);
if (encodedLightmap)
{
real4 encodedIlluminance = SAMPLE_TEXTURE2D_LIGHTMAP(lightmapTex, lightmapSampler, LIGHTMAP_EXTRA_ARGS_USE).rgba;
illuminance = DecodeLightmap(encodedIlluminance, decodeInstructions);
}
else
{
illuminance = SAMPLE_TEXTURE2D_LIGHTMAP(lightmapTex, lightmapSampler, LIGHTMAP_EXTRA_ARGS_USE).rgb;
}
real halfLambert = dot(normalWS, direction.xyz - 0.5) + 0.5;
bakeDiffuseLighting += illuminance * halfLambert / max(1e-4, direction.w);
real backHalfLambert = dot(backNormalWS, direction.xyz - 0.5) + 0.5;
backBakeDiffuseLighting += illuminance * backHalfLambert / max(1e-4, direction.w);
}

Bakery 支持烘焙更多 Directional 方式

问题
光照探针是如何存储数据的,如何存储自定义数据?
unity_OneOverOutputBoost,unity_MaxOutputValue