具体的烘焙细节参考: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);
}
……