《Unity着色器圣经》3.1.6 | 渲染类型标签

目录索引

译文

根据 Unity 官方文档(ShaderLab:向子着色器分配标签 – Unity 手册)所描述的,

使用渲染类型标签可以覆盖 Shader 对象的行为。

这是什么意思?意思是通过这个标签,我们就可以在子着色器中从一种状态切换到另一种状态,为所有符合给定类型的材质添加效果。

为了演示这个功能,我们至少需要两个着色器:

  1. 用来替换的着色器(我们希望在运行时添加的颜色或效果)
  2. 要被替换的着色器(分配给材质的着色器)

语法如下所示:

Tags { "RenderType"="type" }

类似于队列标签,渲染类型标签也有不同的预设,我们可以根据实际需要进行选择:

  • Opaque. 默认情况
  • Transparent.
  • TransparentCutout.
  • Background.
  • Overlay.
  • TreeOpaque.
  • TreeTransparentCutout.
  • TreeBillboard.
  • Grass.
  • GrassBillboard.

“不透明(Opaque)”是我们创建新着色器时默认设置的。同样,Unity 中的大多数内置着色器也是设置成不透明的,因为它们没有透明度配置。不过,我们根据我们想要实现的效果自由更改这一标签。

为了直观地理解这个概念,让我们在项目中做这么几件事:

  1. 在场景中创建几个 3D 物体。
  2. 新建一个名为 USBReplacementController 的C#脚本。
  3. 新建一个名为 USB_replacement_shader 的着色器。
  4. 最后,新建一个名为 USB_replaced_mat 的材质。

我们将会用 Camera.SetReplacementShader 方法给USB_replaced_mat 材质动态分配着色器。材质的着色器必须有和替换着色器相同的渲染类型标签,才能执行该功能。

让我们给 USB_replaced_mat 材质先分配 Mobile/Unlit 着色器,这个内置的着色器的“渲染类型”标签是“不透明”。因此,USB_ replacement_shader着色器必须满足同样的渲染类型才能执行接下来的操作。

图片[1]-《Unity着色器圣经》3.1.6 | 渲染类型标签-软件开发学习笔记
Fig. 3.1.6a. 无光照着色器(支持光照贴图)被分配给了 USB_replaced_mat 材质

USBReplacementController 脚本需要作为组件直接添加在Camera上。只要着色器们的渲染类型相同,这个脚本就会负责用新的着色器替换着色器。

using System.Collections; 
using System.Collections.Generic; 
using UnityEngine; 
[ExecuteInEditMode] public class USBReplacementController : MonoBehaviour 
{ 
    // replacement shader 
    public Shader m_replacementShader; 
    private void OnEnable() 
    { 
        if(m_replacementShader != null) 
        {
            // 相机会用新着色器替换场景中所有渲染类型相匹配的着色器
            GetComponent<Camera>().SetReplacementShader( m_replacementShader, "RenderType"); 
        } 
    } 
    private void OnDisable() 
    { 
        // 重置回默认着色器
        GetComponent<Camera>().ResetReplacementShader();
    } 
}

值得一提的是我们在类前定义了 [ExecuteInEditMode] 属性。这个属性允许我们在编辑模式下预览变更。

我们将 USB_replacement_shader 着色器设置成用于替换的着色器。

我们已经知道的是,每次新建着色器时,渲染类型都被默认设置为了“不透明”。因此,USB_replacement_shader 将会替换掉我们之前分配给材质的无光照着色器。

为了更明白的展示“替换”的操作,让我们在 USB_ replacement_shader 着色器的片元着色器里做点小手脚,把输出颜色乘以红色:

fixed4 frag (v2f i) : SV_Target 
{ 
    fixed4 col = tex2D(_MainTex, i.uv); 
    // add a red color 
    fixed4 red = fixed4(1, 0, 0, 1); 
    return col * red; 
}

我们必须确保 USB_replacement_shader 着色器作为变量被赋到 USBReplacementController 脚本里:

图片[2]-《Unity着色器圣经》3.1.6 | 渲染类型标签-软件开发学习笔记
Fig. 3.1.6b. 将 USBReplacementController 添加到相机上

另外,我们之前在场景中创建的几个3D物体需要使用 USB_replaced_mat 材质。

图片[3]-《Unity着色器圣经》3.1.6 | 渲染类型标签-软件开发学习笔记
Fig. 3.1.6c. USB_replaced_mat 材质被添加到了立方体、面和球体上

因为 USBReplacementController 类包含了 OnEnable 和 OnDisable 两个函数,所以我们在勾选与取消勾选该脚本时,就能看到内置的无光照着色器是如何在编辑模式下被替换为 USB_replacement_shader 着色器(颜色变红)的了。

图片[4]-《Unity着色器圣经》3.1.6 | 渲染类型标签-软件开发学习笔记
Fig. 3.1.6d. USB_replacement_shader 着色器替换了内置的无光照着色器

原文对照

According to the official documentation in Unity,

Use the RenderType tag to overwrite the behavior of a shader

What does the above statement mean? Basically, with this Tag, we can change from one state to another in the SubShader, adding an effect on any material that matches a given Type.

To carry out its function, we need at least two shaders:

  1. A replacement one (color or effect that we want to add at run time)
  2. And another to be replaced (shader assigned to the material)

Its syntax is as follows:

Tags { "RenderType"="type" }

Like the Queue Tags, RenderType has different configurable values that vary depending on the task we want to perform. Among them, we can find.

  • Opaque. Default.
  • Transparent.
  • TransparentCutout.
  • Background.
  • Overlay.
  • TreeOpaque.
  • TreeTransparentCutout.
  • TreeBillboard.
  • Grass.
  • GrassBillboard.

By default, the “Opaque” type is set every time we create a new shader. Likewise, most of the built-in shaders in Unity are assigned with this value, since they do not have a configuration for transparencies. However, we can freely change this category; everything will depend on the effect we apply to a match.

To understand the concept thoroughly, we will do the following. In our project,

  1. We will make sure to create some 3D objects in the scene.
  2. We will generate a C# script that we will call USBReplacementController.
  3. Then we will create a shader that we will call USB_replacement_shader.
  4. Finally, we will add a material that we will call USB_replaced_mat.

We will assign a shader over the material USB_replaced_mat dynamically using the Camera.SetReplacementShader. The material shader must have a Tag RenderType equal to the replacement shader to perform the function.

To exemplify, we will assign the Mobile/Unlit shader to USB_replaced_mat. This built-in shader has a Tag of type “RenderType” equal to “Opaque.” Therefore, the shader USB_ replacement_shader must match the same RenderType for the operation to be carried out.

图片[1]-《Unity着色器圣经》3.1.6 | 渲染类型标签-软件开发学习笔记
Fig. 3.1.6a. Unlit shader (Supports Lightmap) has been assigned over the material USB_replaced_mat

The USBReplacementController script must be assigned directly to the camera as a component. This controller will be in charge of replacing a shader with a replacement one, as long as they have the same configuration in the RenderType.

using System.Collections; 
using System.Collections.Generic; 
using UnityEngine; 
[ExecuteInEditMode] public class USBReplacementController : MonoBehaviour 
{ 
    // replacement shader 
    public Shader m_replacementShader; 
    private void OnEnable() 
    { 
        if(m_replacementShader != null) 
        {
            // the camera will replace all the shaders in the scene with the replacement one the “RenderType” configuration must match in both shader 
            GetComponent<Camera>().SetReplacementShader( m_replacementShader, "RenderType"); 
        } 
    } 
    private void OnDisable() 
    { 
        // let's reset the default shader 
        GetComponent<Camera>().ResetReplacementShader();
    } 
}

It is worth mentioning that we have defined the [ExecuteInEditMode] function over the class. This property will allow us to preview changes in edit mode.

We will use USB_replacement_shader as a replacement shader.

As we already know, every time we create a new shader, it configures its RenderType equal to “Opaque”. Consequently, USB_replacement_shader may replace the Unlit shader we previously assigned to the material.

To preview the changes clearly, we will go to the fragment shader stage of USB_ replacement_shader and add a red color, which we will multiply by the output color.

fixed4 frag (v2f i) : SV_Target 
{ 
    fixed4 col = tex2D(_MainTex, i.uv); 
    // add a red color 
    fixed4 red = fixed4(1, 0, 0, 1); 
    return col * red; 
}

We must make sure to include USB_replacement_shader in the Shader type replacement variable found in the USBReplacementController script.

图片[2]-《Unity着色器圣经》3.1.6 | 渲染类型标签-软件开发学习笔记
Fig. 3.1.6b. The USBReplacementController has been assigned to the camera

And in addition, those objects that we added previously in the scene must have the material USB_replaced_mat.

图片[3]-《Unity着色器圣经》3.1.6 | 渲染类型标签-软件开发学习笔记
Fig. 3.1.6c. The material USB_replaced_mat has been assigned to 3D objects; to a Quad, a Cube and a Sphere

Since the USBReplacementController class has included the OnEnable and OnDisable functions, if we activate or deactivate the script, we can see how the built-in shader Unlit is replaced by USB_replacement_shader in edit mode, applying a red color in the rendering.

图片[4]-《Unity着色器圣经》3.1.6 | 渲染类型标签-软件开发学习笔记
Fig. 3.1.6d. The USB_replacement_shader has replaced the built-in shader, Unlit in the final rendering
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容