具體的烘焙細節參考:https://catlikecoding.com/unity/tutorials/custom-srp/baked-light/
強烈推薦這個網址,寫的非常的詳盡。
下面是講下,自己在烘焙自發光時,遇到的一些坑。
1、是否將lightmode設置爲meta了呢?
2、是否將材質的globalIlluminationFlags的自發光配置設置了呢?
3、是否明白其中unity_MetaFragmentControl的x和y分量代表的意義呢?
4、烘焙自發光,是否一定需要些其他pass呢?
5、烘焙的時候,頂點着色器和片元着色器如何寫呢?
6、在頂點着色器中,使用 return mul(UNITY_MATRIX_VP, float4(vertex.xyz, 1.0)); //注意這裏是vp矩陣,不是MVP矩陣,否則會出現烘焙錯誤的問題。
分別一一回答:
1、是否將lightmode設置爲meta了呢?
這個我遇到的坑是,把lightmode設置在了SubShader,導致一直烘焙不出來。
正確的寫法是:
不要讓SubShader的Tags影響到meta pass了。
2、是否將材質的globalIlluminationFlags的自發光配置設置了呢?
這個要寫一個材質UI編輯器,讓其globalIlluminationFlags設置自發光烘焙。
editor.LightmapEmissionProperty();的意思是讓材質屬性面板出現了設置項:
這個一定要讓其設置爲Bake模式,才能烘焙自發光。
3、是否明白其中unity_MetaFragmentControl的x和y分量代表的意義呢?
unity_MetaFragmentControl是unity給我們提供的變量。使用的時候,聲明下即可。
其中x分量代表的是,代表的是,代表的是,重要的事情說明三遍:代表的是,烘焙表面漫反射對其他物體的影響,也就是讓物體表面漫反射的顏色,參與gi。
其中y分量代表的是,讓物體的自發光,自發光,自發光,參與gi。
ok,如果你勾選了,Global Illumination,則烘焙是自發光,否則是烘焙了,物體表面反射顏色。
4、烘焙自發光,是否一定需要些其他pass呢?
烘焙自發光,或者說烘焙的時候,除了必要的meta pass,還需要其他的嗎?答案是不需要。在烘焙的時候,unity只檢測物體身上的材質球,是否有meta pass,甚至你將物體的其他pass都刪除都可以。但是物體不要隱藏哦。
比如這裏,srp中的畫的是CustomLit,這裏我改爲CustomLit2,但是C#的管線中沒改,此時場景看不到任何物體,但是依然能烘焙出來光照貼圖。
所以,烘焙的時候,只需要metapass,物體是active狀態,並且是參與gi的,就能烘焙出來。
5、烘焙的時候,頂點着色器和片元着色器如何寫呢?
頂點着色器:
可以參考:UnityMetaPass.cginc,這個是unity的builtin_shaders-2019.2.1f1的shader,可以在官網下載。
float4 UnityMetaVertexPosition(float4 vertex, float2 uv1, float2 uv2, float4 lightmapST, float4 dynlightmapST)
{
#if !defined(EDITOR_VISUALIZATION)
if (unity_MetaVertexControl.x) //使用靜態光照
{
vertex.xy = uv1 * lightmapST.xy + lightmapST.zw;
// OpenGL right now needs to actually use incoming vertex position,
// so use it in a very dummy way
vertex.z = vertex.z > 0 ? 1.0e-4f : 0.0f;
}
if (unity_MetaVertexControl.y) //使用動態光照
{
vertex.xy = uv2 * dynlightmapST.xy + dynlightmapST.zw;
// OpenGL right now needs to actually use incoming vertex position,
// so use it in a very dummy way
vertex.z = vertex.z > 0 ? 1.0e-4f : 0.0f;
}
return mul(UNITY_MATRIX_VP, float4(vertex.xyz, 1.0)); //注意這裏是vp矩陣,不是MVP矩陣,否則會出現烘焙錯誤的問題
#else
return UnityObjectToClipPos(vertex);
#endif
}
片段着色器:也可參考UnityMetaPass.cginc的片段着色器:UnityMetaFragment
也可以自己寫,如下:
float4 MetaPassFragment (Varyings input) : SV_TARGET {
float4 base = GetBase(input.baseUV);
Surface surface;
ZERO_INITIALIZE(Surface, surface);
surface.color = base.rgb;
surface.metallic = GetMetallic(input.baseUV);
surface.smoothness = GetSmoothness(input.baseUV);
BRDF brdf = GetBRDF(surface);
float4 meta = 0.0;
if (unity_MetaFragmentControl.x) //表面反射顏色
{
meta = float4(brdf.diffuse, 1.0);
meta.rgb += brdf.specular * brdf.roughness * 0.5;
meta.rgb = min(PositivePow(meta.rgb, unity_OneOverOutputBoost), unity_MaxOutputValue);
}
else if (unity_MetaFragmentControl.y) //自發光顏色
{
meta = float4(GetEmission(input.baseUV), 1.0);
}
return meta; //否則返回0
}
unity自身的meta的片段着色器爲:
half4 UnityMetaFragment (UnityMetaInput IN)
{
half4 res = 0;
#if !defined(EDITOR_VISUALIZATION)
if (unity_MetaFragmentControl.x)
{
res = half4(IN.Albedo,1);
// d3d9 shader compiler doesn't like NaNs and infinity.
unity_OneOverOutputBoost = saturate(unity_OneOverOutputBoost);
// Apply Albedo Boost from LightmapSettings.
res.rgb = clamp(pow(res.rgb, unity_OneOverOutputBoost), 0, unity_MaxOutputValue);
}
if (unity_MetaFragmentControl.y)
{
half3 emission;
if (unity_UseLinearSpace)
emission = IN.Emission;
else
emission = GammaToLinearSpace(IN.Emission);
res = half4(emission, 1.0);
}
……