梳理 Unity Shader 的基本结构(学)

0x00 写在前面

 

之前一直在阅读 The Book of Shaders 一书,为什么会开始写 Unity Shader 呢?一方面,因为该书目前尚未完结,写下此文时已阅读到该书的最新章节;另一方面,也需要通过一些实践来检验以及巩固所学的知识。Unity 引擎提供的环境正好是一个不错的媒介。

 

本文没有完整可运行的 Shader 代码,只是简单梳理一下 Unity Shader 的基本结构,为之后学习做铺垫。

 

0x01 基本框架

 

一段 Unity Shader 的基本结构如下:

Shader "Path/ShaderName"{        Properties    {
    }
        SubShader    {        [Tags]        [RenderSetup]        Pass        {            Name "PassName"            [Tags]            [RenderSetup]                                }            }        Fallback "OtherShaderName" }

 

0x02 名字

 

Path/ShaderName 决定该 Shader 在选择面板上所处的位置,很像文件的全路径。例如,Shader "Path0/Path1/CustomShader" 将位于 Path0 → Path1 → CustomShader:

 

 

0x03 属性

 

Properties 括号中定义的属性将在材质面板上展示,可以方便地进行调节。

Properties{    Name("Display Name", Type) = DefaultValue    }

 

定义一个属性,就像在 C 语言中定义一个变量一样,只是格式稍有不同。在上面的代码中,Name 是属性的名字,Display Name 是用于展示在材质面板上的名字,Type 是属性的类型,DefaultValue 是属性的默认值。ps:其中 Name 常常以下划线开头,例如 _PropertiesName。

 

下面列出一些常用的属性:

 

数字

_Number0("Number 0", Range(-2.0, 2.0)) = 0.0_Number1("Number 1", Float) = 0.618_Number2("Number 2", Int) = 3

 

其中,Range 将在面板上展示一个滑动条,它的两个参数依次表示可以滑动的最小值和最大值。Float 是浮点数,Int 是整数。

 

 

颜色和向量

_Color("Color", Color) = (1, 1, 1, 1)_Vector("Vector", Vector) = (1, 1, 1, 1)

 

颜色 Color 的四个值分别表示 RGBA,在面板上将会展示修改按钮以及吸取按钮。向量 Vector 为四维向量,在面板上展示为 XYZW 四个格子。

 

 

纹理

_2DTexture("2D Texture", 2D) = "defaulttexture" {}_Cube("Cube", Cube) = "defaulttexture" {}_3DTexture("3D Texture", 3D) = "defaulttexture" {}

 

2D 表示 2D 纹理贴图,Cube 表示立方体贴图,3D 表示 3D 纹理贴图。它们都有 Tiling 和 Offset。

 

 

在 Properties 中定义的属性可以在 SubShader 的代码块中使用,只需要在相应的地方定义与这些属性 名字相同、类型匹配 的变量即可。SubShader 中的类型与 Properties 中的稍有不同,下面列出两者对应的匹配关系:

 

  • Color 和 Vector 可对应 float4、half4、fixed4

  • Range 和 Float 可对应 float、half、fixed

  • 2D 对应 sampler2D

  • Cube 对应 samplerCUBE

  • 3D 对应 sampler3D

 

SubShader 代码中,有的属性也可以不在 Properties 中定义,两者都可以在运行时通过 C# 脚本动态地进行修改(如,使用方法 Material.SetFloat 修改浮点属性)。两者的区别是,定义在 Properties 中的属性在修改后将会被保存,而不在 Properties 中的属性则不会。

 

0x04 SubShader

 

每个 Unity Shader 中都可以包含多个 SubShader,当 Unity 展示一个 Mesh 时,将会从这些 SubShader 中找到第一个可以运行的来运行。因为不同的硬件对 Shader 的支持不同,这里可以理解为

 

0x05 Tags

 

Tags 是 kv 结构,用来指定 Shader 怎样以及何时渲染对象。

 

Tags { "TagName1" = "Value1" "TagName2" = "Value2" }

 

关于 Tags 的详细说明可以查看:ShaderLab: SubShader Tags 。

 

0X06 RenderSetup

 

RenderSetup 用来设置显卡的渲染状态。比如,设置剔除模式。

 

Cull Back | Front | Off

 

关于渲染状态的详细设置可以查看:ShaderLab: Pass 。

 

0x07 Pass

 

在 SubShader 中指定的 RenderSetup 将会应用到所有 Pass 中,我们也可以在 Pass 中单独指定。Pass 中的 Tags 与 SubShader 中的有所不同 ,主要用于控制该 Pass 中的环境光、顶点照明等,详见:ShaderLab: Pass Tags 。

Pass{    Name "PassName"     [Tags]    [RenderSetup]        }

 

当用 Name 为 Pass 指定名字后,可以在其它地方复用这个 Pass。其中,Pass 名需要大写。用法如下:

 

UsePass "ShaderName/PASSNAME"

 

一个 SubShader 中可以有多个 Pass,这些 Pass 将会被依次执行。

 

0x08 Fallback

 

如果所有 SubShader 都无法使用时,将会尝试使用 Fallback 指定的着色器。如:

 

Fallback "Diffuse"

 

0X09 总结

 

本文简单梳理了一下 Unity Shader 的基本结构,因为了解不深,部分内容只能粗略带过。这些内容在以后有需要时会再深入研究。

 

最后,再回顾一下 Unity Shader 的基本结构吧:

 

  • 每个 Shader 都需要定义名字,格式为:

    Shader "Path/ShaderName" {}。

  • 在 Shader 的括号中,如果有需要,我们可以在 Properties 语义块中定义材质的属性。

  • 每个 Shader 都包含多个子着色器 SubShader。

    使用多个 SubShader 是因为不同的硬件对 Shader 的支持有所不同。

    当实例运行时,引擎会帮我们找到第一个可以运行的 SubShader 来运行。

    当所有的 SubShader 都不能运行时,则使用 Fallback 指定的 Shader。

  • 每个 SubShader 包含多个 Pass,每个 Pass 表示一个渲染流程。

    因为有的效果需要几个渲染才能表现出来,这时候就需要使用多个 Pass 了。

  • SubShader 和 Pass 都可以通过一些语义 (Tags 和 RenderType) 来设置渲染状态,Pass 还可以通过:

    Name "PassName" 来指定 Pass 的名字。

 

参考资料:

 

  • [1] Shaders Overview

  • [2] Unity Shader入门精要

Unity3D游戏开发精华教程干货推荐搜索

shader

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值