Version: 2023.2
How Unity loads and uses shaders
计算着色器

在运行时替换着色器

在内置渲染管线中,可以让摄像机在运行时更改用于渲染特定几何体的着色器。可以这样做以实现视觉效果,例如边缘检测。

Shader replacement is done from scripts with either the Camera.RenderWithShader or Camera.SetReplacementShader function. Both functions take a shader and a replacementTag.

It works like this: the camera renders the scene as it normally would. The objects still use their materials, but the shader they use changes:

  • If replacementTag is empty (must be an empty string not null), then all objects in the scene are rendered with the given replacement shader.
  • 如果 replacementTag 不为空,则对于将要渲染的每个对象:
    • 查询真实对象的着色器以获取标签值
    • 如果没有该标签,则不渲染对象。
    • 在替换着色器中找到一个子着色器,并且该子着色器的一个给定标签具有找到的值。如果找不到此类子着色器,则不渲染对象。
    • 现在,使用该子着色器来渲染对象。

因此,比如说,如果所有着色器都要有一个值为“Opaque”、“Transparent”、“Background”或“Overlay”的“RenderType”标签,则可编写一个替换着色器,该着色器只使用一个具有 RenderType = Solid 标签的子着色器来渲染实体对象。在替换着色器中找不到其他标签类型,因此不会渲染对象。或者您也可以为不同“RenderType”标签值编写若干子着色器。顺便提一下,所有内置 Shader 对象都设置了一个“RenderType”标签。

光照着色器替换

使用着色器替换时,将使用摄像机上配置的渲染路径来渲染场景。这意味着用于替换的着色器可以包含阴影和光照通道(您可以使用表面着色器进行着色器替换)。这对于渲染特殊效果和场景调试很有用。

内置着色器中的着色器替换标签

所有内置着色器都设置了一个“RenderType”标签,可以在使用替换着色器进行渲染时使用此标签。标签值如下:

  • __Opaque__:大部分着色器(法线自发光反射和地形着色器)。
  • __Transparent__:大部分半透明着色器(透明、粒子、字体和地形附加通道着色器)。
  • __TransparentCutout__:遮罩透明度着色器(透明镂空、两个通道植被着色器)。
  • __Background__:天空盒着色器。
  • __Overlay__:光环、光晕着色器。
  • __TreeOpaque__:地形引擎树皮。
  • __TreeTransparentCutout__:地形引擎树叶。
  • __TreeBillboard__:地形引擎公告牌树。
  • __Grass__:地形引擎草。
  • __GrassBillboard__:地形引擎公告牌草。

内置场景深度/法线纹理

摄像机内置了渲染深度或深度+法线纹理的功能(可能在某些效果中需要该功能)。请参阅摄像机深度纹理页面。请注意,在某些情况下(取决于硬件),可以使用着色器替换方法在内部渲染深度和深度+法线纹理。因此,务必在着色器中设置正确的“RenderType”标签。

代码示例

Start() 函数指定替换着色器:

void Start() {
    camera.SetReplacementShader (EffectShader, "RenderType");
}

此函数请求 EffectShader 使用 RenderType 键。对于所需的每个 RenderType,EffectShader 都有一个键/值标签。Shader 应如下所示:

Shader "EffectShader" {
     SubShader {
         Tags { "RenderType"="Opaque" }
         Pass {
             ...
         }
     }
     SubShader {
         Tags { "RenderType"="SomethingElse" }
         Pass {
             ...
         }
     }
 ...
 }

SetReplacementShader 将检查场景中的所有对象,不使用它们的普通着色器,而是使用第一个具有指定键的匹配值的子着色器。在此示例中,任何对象的着色器若具有 Rendertype=“Opaque” 标签,都将被 EffectShader 中的第一个子着色器替换,任何对象若具有 RenderType=“SomethingElse” 着色器都将使用第二个替换子着色器,以此类推。如果任何对象的着色器不具有替换着色器中指定键的匹配标签值,则不会渲染这样的对象。

How Unity loads and uses shaders
计算着色器