找回密码
 立即注册
查看: 350|回复: 0

Meta Pass

[复制链接]
发表于 2023-2-16 11:05 | 显示全部楼层 |阅读模式
本贴是学习著名的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。



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-9-21 11:18 , Processed in 0.093242 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表