Unity 5.4已经进入到Beta阶段,其中的一个突出功能是光照探头代理体(LPPV)。在这里将会向大家介绍什么是LPPV,并且通过一些小实验来演示它是如何进行工作的。
LPPV是一个可以为无法使用烘焙光照贴图的大型动态物体提供更多光照信息的组件,想象一下蒙皮网格或者粒子系统。是的,接受烘焙光照信息的粒子系统,太棒了!
LPPV组件从属于光探头组。这个组件位于 Component -> Rendering -> Light Probe Proxy Volume下,默认情况下,这个组件看起来是如下:
![](https://i-blog.csdnimg.cn/blog_migrate/0dab866db6285d7f14624b79dd0c7a82.png)
这个组件你需要添加到诸如网格甚至光照探头组这样的游戏对象中。那些要应用上LPPV的游戏对象需要具有MeshRenderer或者Renderer组件,并且将Light Probes属性设置为“Use Proxy Volume”。
![](https://i-blog.csdnimg.cn/blog_migrate/1049914b789b74c237983e6e8fc0ab03.png)
你可以通过设置Proxy Volume Override选项来使用其它GameObject上的LPPV组件,只需拖放这个GameObject到每一个你想要使用它的Renderer组件的属性域里面。
例如:如果你将LPPV组件添加到光照探头组对象中,那么你就可以通过Proxy Volume Override属性在所有Renderer组件中共享它:
![](https://i-blog.csdnimg.cn/blog_migrate/64c6d0ef75bb2d185a74401531bd2398.png)
设置包围盒:包围盒的设置有以下三个选项:- 自动局部- 自动全局- 自定义
自动局部:这是默认的属性设置 – 包围盒会在局部空间内计算,插值光探头位置将在这个包围盒内产生。包围盒计算包括了当前以及其下所有层级的将Light Probes属性设置为Use Proxy Volume的Renderer组件,自动全局也是一样的方式。
![](https://i-blog.csdnimg.cn/blog_migrate/0dab866db6285d7f14624b79dd0c7a82.png)
自动全局:将会计算世界坐标轴对齐的包围盒。自动全局以及自动局部选项应该与Proxy Volume Override属性联合使用在其它的Renderer组件上。另外你可以通过将同一个LPPV组件设置到层级的父节点来使这个层级下的所有GameObject使用这个LPPV组件。
这个模式与自动局部的区别在于在自动局部模式下,当从一个父GameObject下的多层级GameObject使用同一个LPPV组件时包围盒计算会更加耗时,但是计算出来的包围盒尺寸会更小,这就意味着光照数据会更加紧凑。
自定义:该模式使你可以自己在UI中编辑包围盒,修改Inspector窗口中的尺寸以及起始点或者使用工具来在场景视图中编辑。包围盒在游戏对象的局部空间中指定。在这种情况下你需要确定所有的Renderer组件所在的GameObject在LPPV的包围盒内。
![](https://i-blog.csdnimg.cn/blog_migrate/78b86e76cfc04854c251f73283af57f8.png)
设置分辨率/密度:在设置完成包围盒后,下面你需要考虑代理体的密度和分辨率。要实现这个在分辨率模式下有两个选项:
自动:这是默认的属性设置 – 为密度设置一个值,例如每单位的探头数量。每单位的探头数量在X,Y以及Z轴上计算,所以(探头数量)是由包围盒的尺寸决定的。
自定义:通过下拉菜单来设置X,Y以及Z轴上的分辨率值。值从1开始以2的乘方递增直到32.你最多可以有32x32x32 个插值探头
![](https://i-blog.csdnimg.cn/blog_migrate/49203cd4ffa5368d9f08bf91ae77d4ed.jpeg)
在使用LPPV时性能度量的考虑:请记住每个64个插值光探头的批量的插值计算需要大概0.15毫秒的CPU时间(i7 – 4G赫兹)(使用Profiler观察)。光探头插值计算是多线程的,任何小于或等于64个插值光照探头将不会是多线程的,将只在主线程中运行。
使用Unity的内置Profiler,在Timeline视图下你可以看到主线程上的BlendLightProbesJob,如果你将插值光探头数量增加到超过64个,你将同样在工作线程中看到BlendLightProbesJob:
![](https://i-blog.csdnimg.cn/blog_migrate/34c6f2464dfb1a664ee51d9091273bf2.jpeg)
当只有一个批次的64个插值光探头的时候将只会运行在主线程上,当有多个批次(大于64)的时候将会安排在主线程上运行一个,其它的运行到工作线程上,但是这个行为只针对单个LPPV。如果你有多个LPPV,并且每个拥有少于64个插值光探头的话,那么他们都会运行在主线程上。
硬件需求:该组件需要至少支持Shader Model 4的图形硬件以及相应的API支持,包括支持32位浮点格式以及线性过滤的3D纹理。
使用ShadeSHPerPixel的粒子系统着色器的范例:标准着色器支持这个特性。如果你想将其添加到一个自定义着色器中,使用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
// Don’t forget to specify the target
#pragma target 3.0
#include "UnityCG.cginc"
// You have to 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
}
}
}
}
有关UnIty 5.4中光照探头代理体的新功能就介绍到这里,更多相关的技术文章请访问Unity中文官方社区!