這個坑你遇到過嗎——烘焙自發光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);
    }
    ……
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章