在研究通过HDRP中自带的Decal Projector Component组件来实现贴花效果的过程中,遇到了一些需要理解的地方,以下列出一些关键步骤来说明贴花过程中的细节问题。
DBufferRender 阶段
1. 根据渲染管线中贴画的设置决定是否要使用四张RenderTexture作为渲染目标。
2. 设置当前渲染目标并clear,使这些纹理有一个初始默认颜色(60至75行)。
3. 设置最终的渲染目标为RTIDs数组(78行),其中对应的纹理即是 _DBufferTexture0, 即是 _DBufferTexture1 和 即是 _DBufferTexture2(此处只用到三张纹理),可通过查看CreateBuffers方法中得知这三张纹理对应的名称是DBuffer0,DBuffer1 和 DBuffer2,和FrameDebug中显示的信息相对应。
4. 把m_HTile这张图设置为可以在shader中被写入(80行)。同时需要在shader中声明对应的可读写格式Texture,该声明在ShaderVariablesDecal.hlsl文件中,同时每个Decal都会执行到的frag函数(在ShaderPassDBuffer.hlsl文件中)中, 对_DecalHTile进行写入操作,写入的数据记录了是否需要对Decal进行 基础颜色,法线以及法线遮罩计算的flag标记。最后的判断在 LitDecalData.hlsl 文件中的 ApplyDecalToSurfaceData 方法中进行。
5. 再把 m_HTile设置到名称为 "_DecalHTileTexture" 的图,
GBuffer 阶段
1. frag方法在 ShaderPassGBuffer.hlsl 文件中,通过获取当前surfacedata和贴画的surfacedata,通过计算把贴花的baseColor,normalWS,ambientOcclusion等属性应用到当前画面上。
2. 在获取贴花surfacedata时用_DecalHTileTexture中的数据给 HTileMask 字段赋值。HTileMask 字段在应用贴花数据到当前画面时作flag位判断用。
Enable Decal 的控制
使用HDRenderPipeline/Lit 时可以在inspector面板通过勾选 Enable Decal 选项来设置是否使用decal效果,接下来简要说一下代码中是怎么通过这个选项来控制是否显示贴画的。
"HDRenderPipeline/Lit" 这个shader使用了自定义的inspector面板显示方式,通过一个叫 LitGUI的类来实现,
而 Enable Decal 这个选项在 LitGUI的父类即BaseLitGUI中定义,
其对应的ShaderProperty是 "_SupportDecals",
根据是否含有该属性以及该属性的值来设置名为 "_DISABLE_DECALS" 的 shader_feature,
在最后混合decal数据和当前表面数据时有两个判断条件来控制是否可以混合,即 HAVE_DECALS 宏和 _EnableDecals变量,其中 HAVE_DECALS 宏的定义就和 _DISABLE_DECALS 有关,
至此可以搞清楚在材质球的Inspector面板中控制的 "Enable Decal" 选项在shader中控制的是 HAVE_DECALS 这个宏。
_EnableDecals 的控制
下面理清下 _EnableDecals 变量是从哪里控制的。全局查找 "_EnableDecals" 关键字发现在 DBufferManaget.cs 中通过SetGlobalInt方式来设置该属性值,
enableDecals变量是DBufferManager类的成员变量,在HDRenderPipeline.cs中的Render方法中被设置
可以看出控制条件是 hdCamera.frameSettings.enableDecals,看名称应该是摄像机相关的一些设置。
回到Unity界面中,查看摄像机的Rendering Path设置,如果是 Use Graphics Settings,则找到当前使用的RenderPipeline物体,设置其 Rendering Passes 展开菜单中的 Decals 选项;如果是 Rendering Path 设置是Custom,那么直接在当前Inspector的Rendering Passes展开中找到Decals选项。这两处Decals的设置对应着代码中的 hdCamera.frameSettings.enableDecals 值。
总结:
1. DBufferRender阶段写入_DecalHTile纹理,存储decal可以影响哪些表面数据的flag标志位。
2. 把_DecalHTile纹理对应的RenderTexture设置给_DecalHTileTexture纹理。
3. GBuffer阶段读取_DecalHTileTexture纹理,根据其值去对把decal属性和当前表面属性进行混合(baseColor,normalWS,ambientOcclusion 或 specularColor,metallic)。
4. 材质球Inspector面板上的 Enable Decal 选项控制Shader中的 HAVE_DECALS 宏。
5. 摄像机Rendering Path设置中的Decals选项控制Shader中的_EnableDecals变量。