原文链接:光照探测器代理区块组件
光照探测器代理区块(LPPV)组件允许为不能使用烘焙光照贴图的大型动态GameObject(比如大型的例子系统或者skinned meshes)使用更多的光照信息。
默认情况下,光照探测器渲染使用场景中周围的光照探测器插值成一个光照探测器来获取光照。因此GameObject的表面环境光照是一样的。光照因为使用了球谐函数有旋转渐变,但是缺少空间渐变。这在大型GameObject或者粒子系统上很明显。GameObject使用锚点出的光照覆盖表面,and if the GameObject straddles a lighting gradient, GameObject的一部分可能显示不正确。
光照探测器代理区块组件在区块边界内部生成一个内插光照探测器的3D格网。可以在组件的UI指定格网的分辨率。内插的光照探测器球谐函数系数被上传到3D纹理。包含球谐函数系数的3D纹理在渲染时进行采样,计算散射环境光的分量。这样可以为探测器照明的GameObject增加空间渐变。
标准着色器支持这个功能。使用ShadeSHPerPixel函数为自定义着色器增加这个功能。查看本页底部的粒子系统采样着色器代码示例了解如何实现这个函数。
何时使用这个组件
Unity的大多数渲染组件包含光照探测器。光照探测器有3个选项:
- Off:渲染器不会使用任何插值的光照探测器。
- Blend Probes(默认值):渲染器使用一个内插的光照探测器。
- Use Proxy Volume:渲染器使用内插光照探测器的3D格网。
将Light Probes属性设置为Use Proxy Volume时,GameObject必须附加一个Light Probe Proxy Volume(LPPV)组件。 可以在GameObject上增加一个LPPV组件,或者使用Proxy Volume Override属性从另外一个GameObject借用LPPV组件。如果Unity在当前GameObject或者Proxy Volume Override GameObject属性中找不到LPPV组件,在渲染器的底部会显示一条报警记录。
例子
一个使用光照探测器代理组件渲染简单格网的例子
在上面的场景中,地面上有两个发光材质的平面。注意:
- 使用LPPV组件时,环境光在几何体的表面的改变。在几何体的两边分辨使用内插光照探测器制造单色。
- 几何体没有使用静态光照贴图,球体代表内插的光照探测器。它们是Gizmo Renderer的一部分。
如何使用这个组件
内插光照探测器3D格网生成的区域受Bounding Box Mode属性影响。
这些是三个可选的选项:
Bounding Box Mode | Function |
---|---|
Automatic Local(default value) | 计算一个局部空间的边界框。在边界框内部内插的位置上生成光照探测器。如果GameObject没有渲染组件,会生成一个默认的边界框。计算的边界框将包裹当前的渲染器,并且将继承关系后面的所有有光照探测器属性的渲染器设置为Use Proxy Volume。 |
Automatic World | 计算一个包裹当前渲染器的边界框,并且将继承关系后面的所有有光照探测器属性的渲染器设置为Use Proxy Volume。边界框与世界范围对齐。 |
Custom | 使用自定义的边界框。边界框在GameObject的局部空间指定。可以使用边界框编辑功能。可以在UI上修改Size和Origin来手动编辑边界区块。 |
Automatic Local和Automatic World之间最大的区别是,对于Automatic Local,当一个大量继承的GameObject与一个父GameObject使用相同的LPPV组件时,边界框的计算更消耗资源。但是生成的边界框可能会更小,也就是光照数据更紧凑。
边界区块内内插光照探测器的数量受Proxy Volume Resolution属性影响。这个属性有两个参数:
- Automatic(默认值):每个坐标轴上的分辨率,使用设置的每单元区域内插光照探测器数量以及边界框的大小来计算。
- Custom:允许没每个坐标轴设置不同的分辨率(如下图)
注意:每个坐标轴最终的分辨率必须时2的指数,并且分辨率的最大值时32。
Probe Position Mode指定一个内插光照探测器在cell内的相对位置。在有些内插的光照探测器穿过了墙壁或其他几何体而导致光照泄露时,可以使用这个选项。下面的例子在2D视图使用4*4的格网分辨率显示了Cell Corner和Cell Center的区别。
图片对比
- 一个使用标准着色器的简单格网渲染器
使用光照探测器代理区块(分辨率:4*1*1)
没有使用光照探测器代理区块 - 一个使用标准着色器的Skinned Mesh Renderer:
使用光照探测器代理区块(分辨率:2*2*2)
没有使用光照探测器代理区块
使用ShadeSHPerPixel函数的粒子系统采样着色器
Shader "Particles/AdditiveLPPV" {
Properties {
_MainTex ("Particle Texture", 2D) = "white" {}
_TintColor ("Tint Color", Color) = (0.5,0.5,0.5,0.5)
}
Category {
Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }
Blend SrcAlpha One
ColorMask RGB
Cull Off Lighting Off ZWrite Off
SubShader {
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_particles
#pragma multi_compile_fog
// Specify the target
#pragma target 3.0
#include "UnityCG.cginc"
// You must include this header to have access to ShadeSHPerPixel
#include "UnityStandardUtils.cginc"
fixed4 _TintColor;
sampler2D _MainTex;
struct appdata_t {
float4 vertex : POSITION;
float3 normal : NORMAL;
fixed4 color : COLOR;
float2 texcoord : TEXCOORD0;
};
struct v2f {
float4 vertex : SV_POSITION;
fixed4 color : COLOR;
float2 texcoord : TEXCOORD0;
UNITY_FOG_COORDS(1)
float3 worldPos : TEXCOORD2;
float3 worldNormal : TEXCOORD3;
};
float4 _MainTex_ST;
v2f vert (appdata_t v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.worldNormal = UnityObjectToWorldNormal(v.normal);
o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
o.color = v.color;
o.texcoord = TRANSFORM_TEX(v.texcoord,_MainTex);
UNITY_TRANSFER_FOG(o,o.vertex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
half3 currentAmbient = half3(0, 0, 0);
half3 ambient = ShadeSHPerPixel(i.worldNormal, currentAmbient, i.worldPos);
fixed4 col = _TintColor * i.color * tex2D(_MainTex, i.texcoord);
col.xyz += ambient;
UNITY_APPLY_FOG_COLOR(i.fogCoord, col, fixed4(0,0,0,0)); // fog towards black due to our blend mode
return col;
}
ENDCG
}
}
}
}
硬件要求
这个组件至少需要Shader Model 4图像硬件和API支持,包括32位浮点数的3D纹理和线性过滤的支持。
场景需要使用Light Probe Group组件包含光照探测器才能正常工作。如果有一个条件不满足,渲染器或光照探测器代理区块组件属性窗口会显示一条警告。