如何将自发光和漫反射添加到烘焙贴图中
在https://blog.csdn.net/wodownload2/article/details/94431040
一节中,我们只是简单的进行光照贴图的采样。
https://blog.csdn.net/u012871784/article/details/81179432
但是这个教程的局限性太大了
下面我们要考虑的首要问题就是如何将自发光和漫反射光加入到烘焙贴图中,以至于能够影响间接,实现gi效果。
之前的shader不变,还是保持:
Shader "MyShader/SampleLightmap"
{
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile _ LIGHTMAP_ON
#include"Lighting.cginc"
struct VertexData
{
float4 pos:POSITION;
float2 uv:TEXCOORD0;
float2 uv1:TEXCOORD1;
};
struct V2F
{
float4 pos:SV_POSITION;
float2 uv:TEXCOORD0;
#if defined(LIGHTMAP_ON)
float2 uv1:TEXCOORD1;
#endif
};
V2F vert(VertexData v)
{
V2F res;
res.pos = UnityObjectToClipPos(v.pos);
res.uv = v.uv;
#if defined(LIGHTMAP_ON)
res.uv1 = v.uv1 * unity_LightmapST.xy + unity_LightmapST.zw;
#endif
return res;
}
fixed4 frag(V2F i) :SV_TARGET
{
fixed4 col = fixed4(1,0,0,1);
#if defined(LIGHTMAP_ON)
col.rgb = DecodeLightmap(UNITY_SAMPLE_TEX2D(unity_Lightmap, i.uv1));
#endif
return col;
}
ENDCG
}
}
}
这个shader的效果只是在有烘焙贴图的时候采样烘焙贴图,无烘焙的时候默认给颜色红色(1,0,0,0,1)。
下面我们就要再编写一个通道,其LightMode=“Meta”,这样就能够将自发光和漫反射添加到烘焙结果中去了。
如下所示:
Shader "MyShader/SampleLightmap"
{
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile _ LIGHTMAP_ON
#include"Lighting.cginc"
struct VertexData
{
float4 pos:POSITION;
float2 uv:TEXCOORD0;
float2 uv1:TEXCOORD1;
};
struct V2F
{
float4 pos:SV_POSITION;
float2 uv:TEXCOORD0;
#if defined(LIGHTMAP_ON)
float2 uv1:TEXCOORD1;
#endif
};
V2F vert(VertexData v)
{
V2F res;
res.pos = UnityObjectToClipPos(v.pos);
res.uv = v.uv;
#if defined(LIGHTMAP_ON)
res.uv1 = v.uv1 * unity_LightmapST.xy + unity_LightmapST.zw;
#endif
return res;
}
fixed4 frag(V2F i) :SV_TARGET
{
fixed4 col = fixed4(1,0,0,1);
#if defined(LIGHTMAP_ON)
col.rgb = DecodeLightmap(UNITY_SAMPLE_TEX2D(unity_Lightmap, i.uv1));
#endif
return col;
}
ENDCG
}
Pass
{
Tags{ "LightMode" = "Meta" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityStandardInput.cginc"
#include "UnityMetaPass.cginc"
struct V2F
{
float4 pos:SV_POSITION;
float4 uv:TEXCOORD0;
};
V2F vert(VertexInput v)
{
V2F o;
o.pos = UnityMetaVertexPosition(v.vertex, v.uv1.xy, v.uv2.xy, unity_LightmapST, unity_DynamicLightmapST);
o.uv = TexCoords(v);
return o;
}
fixed4 frag(V2F i) :SV_TARGET
{
UnityMetaInput o;
UNITY_INITIALIZE_OUTPUT(UnityMetaInput, o);
o.Albedo = fixed3(1, 1, 0); //这里只是将漫反射添加到烘焙贴图中去
return UnityMetaFragment(o);
}
ENDCG
}
}
}
几点说明:
1、meta的pass中,在计算uv的时候需要注意,由于是在光照贴图空间所以需要这么写。
2、UnityMetaInput中包含的分量,可以参考:UnityMetaPass.cginc
struct UnityMetaInput
{
half3 Albedo;
half3 Emission;
half3 SpecularColor;
};
包含了三个量:漫反射、自发光、镜面光
3、UnityMetaFragment函数也在UnityMetaPass.cginc中,可以参考下。
经过上面的编写之后,将所有的物件的材质指定我们的shader进行渲染,烘焙之前为默认红色、烘焙之后:
看到没有有间接光的效果了,并且这个黄色使我们加入的漫反射的颜色。
如果我们换为绿色:
fixed4 frag(V2F i) :SV_TARGET
{
UnityMetaInput o;
UNITY_INITIALIZE_OUTPUT(UnityMetaInput, o);
o.Albedo = fixed3(0, 1, 0);
return UnityMetaFragment(o);
}
则其烘焙之后的结果为:
可以看到也是符合我们预期的。
我们也可以将自发光也加入进去:
fixed4 frag(V2F i) :SV_TARGET
{
UnityMetaInput o;
UNITY_INITIALIZE_OUTPUT(UnityMetaInput, o);
o.Albedo = fixed3(1, 0, 0);
o.Emission = fixed3(0, 1, 0);
return UnityMetaFragment(o);
}
这里漫反射为红色,自发光为绿色,最后应该得到黄色的间接光效果:
测试结果正确。有些时候你可能遇到,unity没有将这些自发光和漫反射光加入到烘焙贴图中去,是因为,需要设置:
foreach (Material m in editor.targets) {
m.globalIlluminationFlags =
MaterialGlobalIlluminationFlags.BakedEmissive;
}
这个就需要自定义shader的gui,遍历材质球,将其自发光的加入到烘焙中去即可。
此部分可参看:https://catlikecoding.com/unity/tutorials/rendering/part-16/的3.5节即可。