U3D光源烘培光照贴图和light probes

注意可能会犯的错误:
1).确保模型的UV值为0-1之间(需要在import settings->model面板下勾选generate lightmap uvs复选框,单击apply按钮)。
2).注意可能会犯的错误:只有静态物体才会被传递到beast进行烘培,烘培的照明和阴影都一样,所以如果要让有某物体A的阴影投射到动态物体是上,那么记得将A设置为静态物体。
如果要让运动物体产生投射到其它物体上的阴影,那么可以增加实时光照(可以调节光照强度和阴影强度),来照明所有的物体, unity可以混合lightmaps,lightprobes照明(不包含lightmaps)和实时光照阴影的 。因此制作时候布置好bakeonly, realtime only的灯光,再进行烘培,然后将动态物体在场景中移动即可。

一、光源
方向光源是最不消耗GPU资源的。点光源的阴影较消耗GPU资源。聚光灯是较消耗GPU资源的。
Area light区域光源无法用于实时光照,只适用于光照贴图烘培。
Cookie如果是平行光或聚光灯 那么可以是2D的纹理遮罩贴图,如果是点光源那么cookie要是cubemap texture立方体纹理。

只有 平行光在forward/Vertexlit渲染模式下支持阴影,其它光源类型在player setting中设置Rendering path 为deferred模式下(4.x版本非移动平台才支持)才能支持阴影。
灯光可以设置render mode important, culling mask设置, lightmapping 光照贴图(如果是bake only灯光只用在烘培中使用,realtimeonly灯光仅实时光照使用, 所以烘培下实时照明的灯光不会进行烘培照明,实时下烘培的灯光也不会进行实时照明)。
光源颜色调节:红黄色是偏暖的下午色,shadow type是设置阴影,
光照light probe和烘培见

二、光照贴图:
光照贴图技术是用来增加静态物体光照效果的技术(使用的是autodesk的beast插件),不能用来实时的处理动态光照(动态光照需要用light probe或实时光照实现)。
确保模型的UV值为0-1之间(需要在import settings->model面板下勾选generate lightmap uvs复选框,单击apply按钮),是烘培的坑,遇到多查询下,多看下文档。否则将无法对该模型进行烘培。
lightmapping窗口:
选中 Object页签可以选择每个物体,对每个物体进行烘培的参数设置。
Bake页签是烘培方式(Single Lightmaps是简单的静态光照阴影,不能表示表面凹凸即不会考虑Bump/SpecShader类型的材质(需要表现可以使用Dual lightmaps技术不过需要摄像机指定渲染路径为deferredLighting),也不能表示动态物体的光影可以用probes解决),光照贴图质量,天空光颜色,强度,LOD高模到低模计算光照贴图,光照贴图分辨率,不同物体的烘培图的间距。
Maps页签可指定probes group的引用,光照贴图个数,贴图纹理压缩启用
烘培时候light probes也会被烘培,在unity4.0后不再需要切换平台再烘培。Bake scene按钮有下拉按钮可以选择Bake Selected对修改的部分进行烘培提高烘培效率, Bake Probes。
三、烘培结果:
1.烘培在Single Light maps情况下:
unity是根据上述设置,将场景物体和光照设置,传递给beast烘培引擎,进行烘培计算,然后输出给unity使用。烘培结果后,使用相同的场景,进行了烘培的静态物体不再使用实时灯光照明,故着色不会重叠; 动态物体,还是会受到realtime only和auto类型的灯光照明
以下是静态烘培过的物体在不同的渲染路径下,会有不同的实时光照着色表现:
在摄像机渲染路径为VetexLit下使用光照贴图后,静态物体的渲染,将会使用从一个lightmapping贴图中读取烘培的光照颜色,不使用实时光照。PC上走的是另外的VertexLMRGBM的渲染pass(或XXXLMRGBM), 移动下走的是VertexLM的pass(或XXXLM)。
在摄像机渲染路径为Forward下使用unity的默认材质的烘培过的静态物体,会继续受到realtime only的Pixel光源的照明,要改变这个情况光源修改为auto或非pixel即可。Forward路径下自定义的烘培可以在basePass中应用光照贴图(因为addtion会执行多次),在addpass中计算实时的pixel光照。
在摄像机渲染路径为Deferred下:表现和Forward一致,且打开阴影选项下,移动实时光源,所有静态和非静态物体都会投射阴影。
凹凸贴图(是对法线贴图进行扰动的灰度图,以表现更好的凹凸效果)在单光照贴图下,烘培会导致凹凸贴图丢失了,但是新版的应该不会。即使丢失了也可以通过烘培Directional lightmaps贴图而不是single lightmaps贴图,方向光照贴图会输出一个光照贴图和一个scale贴图,保存的是光照信息。

自定义shader,支持对烘培过的物体进行额外的光照着色示例:
Shader "Tut/Lighting/LightMapping/Lab_1/VertexLMRGBM" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
_Color ("Base Color", Color) =(1,1,1,1)
}
SubShader {
// 没有使用烘培,静态物体会走这里的pass,需要实时光照计算。
pass{
Tags{ "LightMode"="Vertex"}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"

uniform float4 _Color;

struct vertOut{
float4 pos:SV_POSITION;
float4 color:COLOR;
};
vertOut vert(appdata_base v)
{
float3 c=ShadeVertexLights(v.vertex,v.normal);
vertOut o;
o.pos=mul(UNITY_MATRIX_MVP,v.vertex);
o.color=_Color*float4(c,1);
return o;
}
float4 frag(vertOut i):COLOR
{
return i.color;
}
ENDCG
}//end pass
// 使用了烘培的静态物体,渲染使用下面的pass,这里不需要实时光照计算(如果自己硬要加上去也可以的),但是需要DecodeLightmap 得到烘培颜色附加到物体上。
Pass {
// Blend One Zero
Tags{"LightMode"="VertexLMRGBM"}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
float4 _MainTex_ST;
sampler2D unity_Lightmap;
float4 unity_LightmapST;

struct appdata {
float4 vertex : POSITION;
float2 texcoord : TEXCOORD0;
float2 texcoord1: TEXCOORD1;
};
struct v2f {
float4 pos : SV_POSITION;
float2 txuv : TEXCOORD0;
float2 lmuv : TEXCOORD1;
};
v2f vert (appdata v) {
v2f o;
o.pos = mul( UNITY_MATRIX_MVP, v.vertex );
o.txuv = TRANSFORM_TEX(v.texcoord.xy,_MainTex);
o.lmuv = v.texcoord1.xy * unity_LightmapST.xy + unity_LightmapST.zw;
return o;
}
half4 frag( v2f i ) : COLOR {
half4 col = tex2D(_MainTex, i.txuv.xy);
half4 lm = tex2D(unity_Lightmap, i.lmuv.xy);
col.rgb = col.rgb * DecodeLightmap(lm);
return col;
}
ENDCG
}
}
}

2.烘培在Dual lightmaps情况下:
GI( Global Illumination)是全局光照, 包括了直接光照和间接光照。
会生成far,near的光照贴图。far包含了直射光和间接光部分,near只包含了间接光。
在工程的Quality setting设置里面调整ShdowDistance,那么物体距离摄像机超过ShdowDistance值的部分将采用far的光照贴图,小于ShdowDistance值的物体将间接光照来自光照贴图,直接光照来自实时光照计算。这样对于近处的物体即可以得到间接光照,可以表现动态光源的变化,例如玩家头顶的电筒。
上述原则只对在摄像机渲染路径为Deferred下生效,在Forward和vertexlit下会直接使用far部分的光照贴图。如果在Forwar下启用也是可以的,就是shader使用surface后添加dualforward关键字,烘培之前选定use in forward rend就可以和deferred一样调整ShdowDistance来支持近处物体的GI加实时照明了。
例如:
Shader "Tut/Lighting/LightMapping/Lab_5/DualForward" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
#pragma surface surf Lambert dualforward
sampler2D _MainTex;
struct Input {
float2 uv_MainTex;
};

void surf (Input IN, inout SurfaceOutput o) {
half4 c = tex2D (_MainTex, IN.uv_MainTex);
o.Albedo = c.rgb;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}
四、Light Probes用预先计算的光照探针颜色对动态物体光照插值:
Light Probes的原理是在 场景空间中放置一些采样点,收集周围的明暗信息,然后对动态对象邻近的几个采样点进行插值运算,并将插值结果作用于动态对象上。插值运算并不会消耗太多的性能,从而实现了动态游戏对象和静态场景的实时融合效果。
1.新建一个空对象,挂载rendering->Light probe group组件,增加采样点用Add probe即可为场景添加probe采样点。正常设置烘培的灯光和场景物体,进行烘培时候可以在lightmapping->maps页签查看 light probe的引用。
2.进行正常的场景烘培操作。
3.在场景中添加物体,对物体的网格材质,选择Use Light Probes,移动该物体,就可以得到动态物体的光照效果。

light Probes 光照探头的布置技巧: 1)在光照变化处多布置探头,不用担心内存和性能开销 2)不要将所有探头布置到一个平面上 3)在运动角色或物体到达处布置探头,非达到处不用布置探头
通过代码改变探针强度示例(一般不需要,移动物体就行,除非实时改变天气), 代码也可以改变物体绑定的探针的位置(通过render组件下的anchored overide属性,一般不需要):
using UnityEngine;
using System.Collections;
using System;
//[ExecuteInEditMode]
public class _LightProbe_Lab_1 : MonoBehaviour {
public Transform actor;
public float posx;
public float factor;
public Rect[] rects;
public string[] labels;
public Rect[] rectL;
public GUISkin skin;
//
public float[] m_BaseCoefficients;
public float[] m_Coefficients;
// Use this for initialization
void Start () {
// 一般拷贝一份原始的,避免修改了得不到原始烘培的probe coefficients数据。
m_BaseCoefficients = new float[LightmapSettings.lightProbes.coefficients.Length];
Array.Copy(LightmapSettings.lightProbes.coefficients, m_BaseCoefficients, LightmapSettings.lightProbes.coefficients.Length);

m_Coefficients = new float[LightmapSettings.lightProbes.coefficients.Length];
}
// Update is called once per frame
void Update () {
actor.position = new Vector3(posx, actor.position.y, actor.position.z);
for (int i=0;i<m_BaseCoefficients.Length;i++)
{
m_Coefficients[i] = m_BaseCoefficients[i] *factor;
}
LightmapSettings.lightProbes.coefficients = m_Coefficients;
/*也可以改变某个通道:
for (int i = 0; i < m_BaseCoefficients.Length/3; i++)
{
m_Coefficients[i*3] = m_BaseCoefficients[i*3] * factor1;
m_Coefficients[i*3+1] = m_BaseCoefficients[i*3+1] * factor2;
m_Coefficients[i*3 + 2] = m_BaseCoefficients[i*3 + 2] * factor3;
}
LightmapSettings.lightProbes.coefficients = m_Coefficients;
*/
}
void OnGUI()
{
GUI.skin = skin;
for (int i = 0; i < rectL.Length; i++)
{
GUI.Label(rectL[i], labels[i]);
}
posx = GUI.HorizontalSlider(rects[0], posx, -4.2f, 4.2f);
factor = GUI.HorizontalSlider(rects[1], factor, 0f, 2f);
}
}
//探针光照着色,可以使用ShadeSH9 在CPU中将探针数据插值好传递好GPU中(应该是Unity引擎内的存储变量如unity_SHAr等),Shader都是CPU加载,引擎处理后再Load指令到GPU端的。
Shader "Tut/Lighting/LightProbes/Lab_8/adjustableSHSurf" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
_SHfactor("SH factor",float)=1.0
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
#pragma surface surf Lambert noambient vertex:vert
sampler2D _MainTex;
float _SHfactor;

struct Input {
float2 uv_MainTex;
float3 shLight;
};
void vert (inout appdata_full v, out Input o) {
float3 worldN = mul (_Object2World,float4( SCALED_NORMAL,0)).xyz;
o.shLight = ShadeSH9 (float4 (worldN, 1.0));
o.uv_MainTex=v.texcoord.xy;
}
void surf (Input IN, inout SurfaceOutput o) {
half4 c = tex2D (_MainTex, IN.uv_MainTex);
o.Albedo = c.rgb;
o.Emission=o.Albedo*IN.shLight*_SHfactor;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}

// normal should be normalized, w=1.0
half3 ShadeSH9 (half4 normal)
{
half3 x1, x2, x3;
// Linear + constant polynomial terms
x1.r = dot(unity_SHAr,normal);
x1.g = dot(unity_SHAg,normal);
x1.b = dot(unity_SHAb,normal);
// 4 of the quadratic polynomials
half4 vB = normal.xyzz * normal.yzzx;
x2.r = dot(unity_SHBr,vB);
x2.g = dot(unity_SHBg,vB);
x2.b = dot(unity_SHBb,vB);
// Final quadratic polynomial
float vC = normal.x*normal.x - normal.y*normal.y;
x3 = unity_SHC.rgb * vC;
return x1 + x2 + x3;
}

五、烘培的性能优化
在Baked选项卡下修改resolution可以减少输出lightmapping的大小,通过修改某静态物体的Scale in Lightmap也可以减少lightmapping大小。而且要对输出的Lightmapping选择compress以减少大小。



  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值