这个坑你遇到过吗——烘焙自发光metapass的使用

具体的烘焙细节参考: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);
    }
    ……
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章