jquave 发表于 2023-2-16 11:05

Meta Pass

本贴是学习著名的Jasper Flick 先生的CustomSRP 文章。
如果你也想要学习SRP,推荐去看他的文章。
因为间接漫反射光照会直接从表面反射出来,因此还应该受到这些表面的漫反射率的影响。Unity使用一个特殊的Meta Pass来确定给烘焙时从表面反射出来的光照,然后提供给烘焙系统,从而计算间接光照。
抽离公用属性

因为一些属性是公用的,我们干脆直接抽离到一个单独的ToonInput.hlsl文件中,让我们在Shaders文件夹下创建它,然后将ToonPass.hlsl文件中的纹理属性和UnityPerMaterial缓冲区拷贝过来。我们定义一些方法来获取这些属性,而不是直接访问缓冲区的属性。










因为我们需要在所有的Pass中访问Common.hlsl,所以我们可以直接将include common和ToonInput文件的指令放到所有Pass的外面。记得将ToonPass 文件中的重复声明删掉。


我们还要在ShadowCasterPass中也做类似的处理。上面的操作我们在Unlit.shader中也作一遍。
实现MetaPass

在Toon.shader中添加MetaPass的定义,该Pass的LightMode设置为Meta,关闭剔除功能,包含MetaPass.hlsl。


在Shaders文件夹下新建MetaPass.hlsl文件。我们需要知道表面的漫反射率,只需要顶点对象空间的位置和基础UV,在顶点函数中裁剪空间的顶点位置设为0,片元函数中通过ZERO_INITIALIZE宏把表面数据初始化为0。通过获取表面的颜色光滑度金属度来获取BRDF数据。


现在重新烘焙场景,所有的间接照明都会消失。因为我们的片元函数中返回的是0。




漫反射率

MetaPass可用于生成不同的数据,通过定义一个bool4类型的标记向量unity_MetaFragmentControl进行通信。在片元函数中进行判断,如果标记了X分量,则需要漫反射率。




这一句可以给反射光照作色,但Unity的MetaPass还需要加上粗糙度乘以一般的镜面反射率来提升效果。思路是高镜面但粗糙的材质可以传递一些间接光照。
最后通过PositivePow方法扩大反射光照,但将其限制到unity_MaxOutputValue。






现在我们得到了正确的间接光照颜色,在Lighting.hlsl文件的GetLighting方法中,也将表面的漫反射应用上。




我们可以将环境光照强度设回1.然后将方向光组件的Mode属性设置为Mixed






自发光表面

即使场景中没有照明,有些表面仍然可以发出光,它可以参与到烘焙光照贴图的计算中,从而照明周围的静态物体。
在Shader属性中添加两个属性,一个资方光纹理贴图和一个HDR自发光颜色。将颜色设为白色。


在ToonInput.hlsl文件的缓冲区中添加一个自发光颜色属性,声明一个资方光纹理属性。然后定义一个GetEmission方法,将采样的自发光纹理结果和颜色值相乘得到最终的自发光。


在ToonPass.hlsl文件的片元函数中,将自发光加到最终颜色中。


在UnlitInput.hlsl也定义这个方法,不过只需要返回基础纹理颜色


给Unlit.shader的_BaseColor技术颜色添加一个HDR的标签,使得不授光的材质也能发出非常明亮的光。


烘焙自发光

我们在Meta Pass文件的片元函数中进行判断,如果unity_MetaFragmentControl的Y分量被标记,则返回自发光的颜色,Alpha为1。


不过现在自发光的光线还不能参与烘焙光照贴图的计算中。
自发光是通过一个单独的Pass进行烘焙的,我们需要对每个材质进行烘焙自发光的设置才行。
我们在ToonShaderGUI脚本中定义一个BakedEmission方法并在OnGUI中调用,在BakedEmission方法通过调用MaterialEditor的LightmapEmissionProerty方法将自发光的GlobalIllumination属性在材质面板中暴露出来。




GlobalIllumination属性由三个选项
None。物体会自发光,但不会照亮其周围物体。
Realtime。物体自发光的光线会参与实时全局照明计算中。
Baked。物体自发光光线会参与到烘焙光照贴图的计算中。可以照亮静态物体但对动态物体无效。






烘焙透明物体

Unity的烘焙系统对透明的处理是硬编码的。他会根据材质的渲染队列来判断该材质是透明不透明还是裁切。他会将_MainTex和_Color属性的Alpha相乘,然后通过_Cutoff属性对该透明度进行裁剪。
我们将这两个属性通过HideInInspector标签使他们不在材质面板中显示。


我们要确保_MainTex,_Color 属性和_BaseMap,_BaseColor值保持一致。我们在ToonShaderGUI脚本中定义一个CopyLightMappingProperties方法。将_BaseMap,_BaseColor同步到_MainTex,_Color。



页: [1]
查看完整版本: Meta Pass