{
  "schemaVersion": "0.11.0",
  "canonical": "https://www.pystone.net/notes/unity-shader-shaderlab-syntax/",
  "atlas": "https://www.pystone.net/?node=unity-shader-shaderlab-syntax#knowledge-atlas",
  "markdown": "https://www.pystone.net/notes/unity-shader-shaderlab-syntax.md",
  "context": "https://www.pystone.net/notes/unity-shader-shaderlab-syntax.context.json",
  "knowledgeVersion": "224c990773de.5fa8af6e39fa",
  "build": {
    "siteCommit": "224c990773de166d23a886306577dd90379529ce",
    "notesCommit": "5fa8af6e39fa3891d1b9b4832bfa6c4e0ecaaf0a",
    "builtAt": "1970-01-01T00:00:00.000Z",
    "version": "224c990773de.5fa8af6e39fa"
  },
  "id": "note:unity-shader-shaderlab-syntax",
  "slug": "unity-shader-shaderlab-syntax",
  "title": "【Unity Shader】ShaderLab语法",
  "type": "note",
  "visibility": "public",
  "idStability": "rename-stable",
  "author": {
    "name": "Perrin Yong",
    "profile": "https://www.pystone.net/profile/"
  },
  "publisher": {
    "name": "Perrin Yong",
    "profile": "https://www.pystone.net/profile/"
  },
  "aliases": [],
  "summary": "【Unity Shader】ShaderLab语法",
  "contentRole": "unspecified",
  "isMoc": false,
  "mocRecognition": "none",
  "generated": false,
  "attribution": "unspecified",
  "domain": "10-计算机、信息技术与工程",
  "tags": [],
  "mocs": [],
  "contentHash": "26c4161011addd441a33cb9a58cfe13a773a01a92fef772ee3c833e33ca03f97",
  "assets": [],
  "headings": [
    {
      "depth": 1,
      "text": "【Unity Shader】ShaderLab语法",
      "anchor": "unity-shadershaderlab语法",
      "citation": "https://www.pystone.net/notes/unity-shader-shaderlab-syntax/#unity-shadershaderlab%E8%AF%AD%E6%B3%95"
    },
    {
      "depth": 2,
      "text": "Overview",
      "anchor": "overview",
      "citation": "https://www.pystone.net/notes/unity-shader-shaderlab-syntax/#overview"
    },
    {
      "depth": 2,
      "text": "基本结构",
      "anchor": "基本结构",
      "citation": "https://www.pystone.net/notes/unity-shader-shaderlab-syntax/#%E5%9F%BA%E6%9C%AC%E7%BB%93%E6%9E%84"
    },
    {
      "depth": 3,
      "text": "SubShader",
      "anchor": "subshader",
      "citation": "https://www.pystone.net/notes/unity-shader-shaderlab-syntax/#subshader"
    },
    {
      "depth": 3,
      "text": "Pass",
      "anchor": "pass",
      "citation": "https://www.pystone.net/notes/unity-shader-shaderlab-syntax/#pass"
    },
    {
      "depth": 4,
      "text": "tags",
      "anchor": "tags",
      "citation": "https://www.pystone.net/notes/unity-shader-shaderlab-syntax/#tags"
    },
    {
      "depth": 4,
      "text": "根据情况决定是否执行pass",
      "anchor": "根据情况决定是否执行pass",
      "citation": "https://www.pystone.net/notes/unity-shader-shaderlab-syntax/#%E6%A0%B9%E6%8D%AE%E6%83%85%E5%86%B5%E5%86%B3%E5%AE%9A%E6%98%AF%E5%90%A6%E6%89%A7%E8%A1%8Cpass"
    },
    {
      "depth": 4,
      "text": "优化建议",
      "anchor": "优化建议",
      "citation": "https://www.pystone.net/notes/unity-shader-shaderlab-syntax/#%E4%BC%98%E5%8C%96%E5%BB%BA%E8%AE%AE"
    },
    {
      "depth": 2,
      "text": "相关概念",
      "anchor": "相关概念",
      "citation": "https://www.pystone.net/notes/unity-shader-shaderlab-syntax/#%E7%9B%B8%E5%85%B3%E6%A6%82%E5%BF%B5"
    },
    {
      "depth": 3,
      "text": "shader properties",
      "anchor": "shader-properties",
      "citation": "https://www.pystone.net/notes/unity-shader-shaderlab-syntax/#shader-properties"
    },
    {
      "depth": 4,
      "text": "How property values are provided to shaders",
      "anchor": "how-property-values-are-provided-to-shaders",
      "citation": "https://www.pystone.net/notes/unity-shader-shaderlab-syntax/#how-property-values-are-provided-to-shaders"
    },
    {
      "depth": 4,
      "text": "Property attributes",
      "anchor": "property-attributes",
      "citation": "https://www.pystone.net/notes/unity-shader-shaderlab-syntax/#property-attributes"
    },
    {
      "depth": 5,
      "text": "Attributes recognized by Unity",
      "anchor": "attributes-recognized-by-unity",
      "citation": "https://www.pystone.net/notes/unity-shader-shaderlab-syntax/#attributes-recognized-by-unity"
    },
    {
      "depth": 4,
      "text": "MaterialPropertyBlock",
      "anchor": "materialpropertyblock",
      "citation": "https://www.pystone.net/notes/unity-shader-shaderlab-syntax/#materialpropertyblock"
    },
    {
      "depth": 5,
      "text": "使用原因",
      "anchor": "使用原因",
      "citation": "https://www.pystone.net/notes/unity-shader-shaderlab-syntax/#%E4%BD%BF%E7%94%A8%E5%8E%9F%E5%9B%A0"
    },
    {
      "depth": 3,
      "text": "语义（semantics）",
      "anchor": "语义semantics",
      "citation": "https://www.pystone.net/notes/unity-shader-shaderlab-syntax/#%E8%AF%AD%E4%B9%89semantics"
    },
    {
      "depth": 4,
      "text": "顶点着色器输入语义 - 应用阶段传递模型数据到顶点着色器时",
      "anchor": "顶点着色器输入语义---应用阶段传递模型数据到顶点着色器时",
      "citation": "https://www.pystone.net/notes/unity-shader-shaderlab-syntax/#%E9%A1%B6%E7%82%B9%E7%9D%80%E8%89%B2%E5%99%A8%E8%BE%93%E5%85%A5%E8%AF%AD%E4%B9%89---%E5%BA%94%E7%94%A8%E9%98%B6%E6%AE%B5%E4%BC%A0%E9%80%92%E6%A8%A1%E5%9E%8B%E6%95%B0%E6%8D%AE%E5%88%B0%E9%A1%B6%E7%82%B9%E7%9D%80%E8%89%B2%E5%99%A8%E6%97%B6"
    },
    {
      "depth": 4,
      "text": "从顶点着色器到片元着色器",
      "anchor": "从顶点着色器到片元着色器",
      "citation": "https://www.pystone.net/notes/unity-shader-shaderlab-syntax/#%E4%BB%8E%E9%A1%B6%E7%82%B9%E7%9D%80%E8%89%B2%E5%99%A8%E5%88%B0%E7%89%87%E5%85%83%E7%9D%80%E8%89%B2%E5%99%A8"
    },
    {
      "depth": 4,
      "text": "片元着色器输出语义",
      "anchor": "片元着色器输出语义",
      "citation": "https://www.pystone.net/notes/unity-shader-shaderlab-syntax/#%E7%89%87%E5%85%83%E7%9D%80%E8%89%B2%E5%99%A8%E8%BE%93%E5%87%BA%E8%AF%AD%E4%B9%89"
    },
    {
      "depth": 2,
      "text": "Ref",
      "anchor": "ref",
      "citation": "https://www.pystone.net/notes/unity-shader-shaderlab-syntax/#ref"
    }
  ],
  "claims": [],
  "outgoing": [],
  "incoming": [
    {
      "id": "note:game-graphics-and-runtime",
      "title": "游戏图形与运行时",
      "url": "https://www.pystone.net/notes/game-graphics-and-runtime/",
      "atlas": "https://www.pystone.net/?node=game-graphics-and-runtime#knowledge-atlas",
      "label": "游戏图形与运行时",
      "origin": "explicit",
      "humanReviewed": true,
      "context": "渲染基础中的“【Unity Shader】ShaderLab语法”导航项",
      "citation": "https://www.pystone.net/notes/game-graphics-and-runtime/#%E6%B8%B2%E6%9F%93%E5%9F%BA%E7%A1%80"
    }
  ],
  "contentMarkdown": "# 【Unity Shader】ShaderLab语法\n\n> 创建时间：2020/10/13 15:14\n\n  * 【Unity Shader】ShaderLab语法\n    * Overview\n    * 基本结构\n      * SubShader\n      * Pass\n        * tags\n        * 根据情况决定是否执行pass\n        * 优化建议\n    * 相关概念\n      * shader properties\n        * How property values are provided to shaders\n        * Property attributes\n          * Attributes recognized by Unity\n        * MaterialPropertyBlock\n          * 使用原因\n      * 语义（semantics）\n        * 顶点着色器输入语义 - 应用阶段传递模型数据到顶点着色器时\n        * 从顶点着色器到片元着色器\n        * 片元着色器输出语义\n    * Ref\n\n## Overview\n\nShaderLab 是 Unity 提供 的 编写 Unity Shader 的 一种 说明性 语言。 它 使用 了 一些 嵌 套在 花 括号 内部 的 语义（ syntax） 来 描述 一个 Unity Shader 文件 的 结构。 这些 结构 包含 了 许多 渲染 所需 的 数据， 例如 Properties 语句 块 中 定义 了 着色 器 所需 的 各种 属性， 这些 属性 将会 出现 在 材质 面板 中。\n\n定义 了 要 显示 一个 材质 所需 的 所有 东西， 而 不仅仅是 着色 器 代码。\n\n冯乐乐. Unity Shader入门精要（异步图书） (Kindle Locations 881-884). 人民邮电出版社. Kindle Edition.\n\n## 基本结构\n\n> ShaderlabVS 用于 Unity Shaderlab 编程的 Visual Studio 插件:\n>  <https://github.com/mollyxxl/ShaderlabVS>\n>  <https://github.com/tgjones/HlslTools>\n\n```csharp\nstring s = String.Empty;\n\n```\n\n### SubShader\n\n每个UnityShader文件可以包含多个SubShader语义块，但至少要有一个。当Unity需要加载这个UnityShader时，Unity会扫描所有的SubShader语义块，然后选择一个能够在目标平台上运行的SubShader。如果都不支持的话，Unity就会使用FallBack语义指定的UnityShader。\n\n> Unity提供这种语义的原因在于，不同的显卡具有不同的能力。例如，一些旧的显卡仅能支持一定数目的操作指令，而一些高级的显卡可以支持更多的指令数，那么我希望在旧的显卡上使用计算复杂度较低的着色器，而在高级的显卡上执行计算复杂度高的着色器，以便提供更出色的画面效果。\n\nSubShader中定义了一系列的 **Pass** 以及 **可选的标签[Tags]** 、 **状态[RenderSetup]**\n\n### Pass\n\nThe Pass block causes the geometry of a GameObject to be rendered once.\nPass的意思就是渲染一次模型\n\nShader passes interact with Unity’s rendering pipeline in several ways; for example, a Pass can indicate that it should only be used for deferred shading using the Tags command. Certain passes can also be executed multiple times on the same GameObject; for example, in forward rendering the “ForwardAdd” pass type is executed multiple times based on how many Lights are affecting the GameObject.\n\nIn the Built-in Render Pipeline, when using a Surface Shader, **how lighting is applied and which Passes of the shader are used** depends on which rendering path is used. Each pass in a shader communicates its lighting type via Pass Tags.\n\n使用内置渲染管线时，使用Surface Shader时，使用不同的渲染路径，引擎会根据pass的LightMode tags决定pass的调用顺序和执行方式。\n\n> In Forward Rendering, ForwardBase and ForwardAdd passes are used.\n>  In Deferred Shading, Deferred pass is used.\n>  In legacy Deferred Lighting, PrepassBase and PrepassFinal passes are used.\n>  In legacy Vertex Lit, Vertex, VertexLMRGBM and VertexLM passes are used.\n>  In any of the above, to render Shadows or a depth texture, ShadowCaster pass is used.\n\n**多通道渲染** \\- 就是在一个shader中有多个Pass，玩家可以根据需求设定通过哪个Pass来进行渲染，从而实现在不同的时候对使用同一个shader对同一个对象进行不同的效果处理。\n\n#### tags\n\nInside a Pass tags are used to control which role this pass has in the lighting pipeline (ambient, vertex lit, pixel lit etc.)\n标注pass在光照管线中扮演什么角色。\n\n> [Tags] 和 [RenderSetup] 也可以在Pass中声明。不同的是，SubShader中的一些标签设置是特定的。也就是说，这些标签和Pass中设置的标签是不一样的。而对于状态设置来说，其使用的语法是相同。不过在SubShader进行的设置将会用于所有的Pass。\n\n#### 根据情况决定是否执行pass\n\n引用：<https://answer.uwa4d.com/question/5da4886a743afa3d3cc90558>\n\n  1. 写两个Shader，避免冗余，把公共函数写到cginc文件里，或者使用UsePass直接指定Pass。\n\n  2. 写个宏控制Pass内部的代码开关，但drawcall省不掉，对于性能最理想的应该还是切换Shader。\n\n  3. Material.SetShaderPassEnabled：它只能通过LightMode来开关对应Pass。(SRP中可能有效)\n\n> By default, all Shader passes are enabled. This function allows a Material to treat a specific Shader pass (as indicated by LightMode pass tag) as if it does not exist in the Shader.\n\n#### 优化建议\n\n每个Pass定义一次完整的渲染流程.但是如果Pass数目过多会造成渲染性能的下降。因此，我们尽量使用数量最小的Pass。\n\n## 相关概念\n\n### shader properties\n\nShader declares Material properties in a Properties block. If you want to access some of those **properties** in a shader program, you need to declare a **Cg/HLSL variable** with the same name and a matching type.\n\n```csharp\nstring s = String.Empty;\n\n```\n```csharp\nstring s = String.Empty;\n\n```\n83  Properties | Cg/HLSL variable\n---|---\nColor, Vector | float4, half4 or fixed4\nRange, Float | float, half or fixed\nTexture | sampler2D\nCubemaps | samplerCUBE\n3D textures | sampler3D\n\n#### How property values are provided to shaders\n\n  * **Per-Renderer values** set in MaterialPropertyBlock. This is typically “per-instance” data (e.g. customized tint color for a lot of objects that all share the same material).\n\n  * Values set in the Material\nthat’s used on the rendered object.\n\n  * Global shader properties, set either by Unity rendering\ncode itself, or from your own scripts\n(e.g. Shader.SetGlobalTexture).\n\n**The order of precedence is like above: per-instance data overrides everything; then Material data is used; and finally if shader property does not exist in these two places then global property value is used. Finally, if there’s no shader property value defined anywhere, then “default” (zero for floats, black for colors, empty white texture for textures) value will be provided.**\n\n> **Color spaces and color/vector shader data**\n>  When using Linear color space, all material color properties are supplied as sRGB colors, but are converted into linear values when passed into shaders.\n\nFor example, if your Properties shader block contains a Color property called “MyColor“, then the corresponding ”MyColor” HLSL variable will get the linear color value.\n\nFor properties that are marked as Float or Vector type, no color space conversions are done by default; it is assumed that they contain non-color data. It is possible to add [Gamma] attribute for float/vector properties to indicate that they are specified in sRGB space, just like colors (see Properties).\n\n#### Property attributes\n\n```csharp\nstring s = String.Empty;\n\n```\n\nProperty前的方括号里面为Property的属性。\nThese are either attributes recognized by Unity, or they can indicate your own MaterialPropertyDrawer classes to control how they should be rendered in the material inspector.\n\n##### Attributes recognized by Unity\n\n  * [HideInInspector]\n\n  * [NoScaleOffset]\n\n  * [Normal]\n\n  * [HDR] - indicates that a texture property expects a high-dynamic range (HDR) texture.\n\n  * [Gamma] - indicates that a float/vector property is specified as sRGB value in the UI\n(just like colors are), and possibly needs conversion according to color space used. See Properties in Shader Programs.\n\n  * **[PerRendererData] - indicates that a texture property will be coming from per-renderer data in the form of a MaterialPropertyBlock. Material inspector changes the texture slot UI for these properties.**\n动态材质属性的修改\n\n> Unity queries the Texture value for this property from the renderer’s MaterialPropertyBlock, instead of from the Material.\n\n  * [MainTexture] - indicates that a property is the main texture for a Material. By default, Unity considers a texture with the property name name _MainTex as the main texture. Use this attribute if your texture has a different property name, but you want Unity to consider it the main texture. If you use this attribute more than once, Unity uses the first property and ignores subsequent ones.\n\n  * [MainColor] - indicates that a property is the main color for a Material. By default, Unity considers a color with the property name name _Color as the main color. Use this attribute if your color has a different property name, but you want Unity to consider it the main color. If you use this attribute more than once, Unity uses the first property and ignores subsequent ones.\n\n#### MaterialPropertyBlock\n\n##### 使用原因\n\n**MaterialPropertyBlock** is used by `Graphics.DrawMesh` and `Renderer.SetPropertyBlock`. Use it in situations where you want to draw multiple objects with the same material, but slightly different properties.\n\n  1. 当我们操作材质共性时，可以使用SharedMaterial属性，改变这个属性，那么所有使用此材质的物件都将会改变，而我们需要改变单一材质时，会使用Material属性，修改Material属性时其实是会生成一份材质拷贝的，即Material(Instance)。材质属性块则不存在实例化。\n\n  2. Use MaterialPropertyBlock Is faster to set properties using a MaterialPropertyBlock rather than material.SetFloat(); Material.SetColor();\n\n> 当你想让100个不同玩家同屏时，如果使用材质操作颜色属性，那么首先就存在100份材质拷贝的实例；其次，材质操作属性本身就比材质属性块操作要慢那么点，在性能优化中一毫秒的优化就是胜利，那么这里一毫秒那里一毫秒，累积起来就不得了了。\n\n### 语义（semantics）\n\n```csharp\nstring s = String.Empty;\n\n```\n\nA semantic is a **string** attached to a shader input or output that conveys information about the **intended use of a parameter**. 通过语义来表明 其“意图”。让Shader知道从哪读取输送到哪里去。表示图元数据的 **含义** （顶点的位置、法向量或者纹理信息），也表明这些图元数据 **存放的硬件资源** 。\n\n语义概念的提出和图形流水线工作机制大有关系。\n\n  * 顶点处理器的输入数据是处于模型空间的顶点数据（位置、法向量），输出的是投影坐标和光照颜色\n\n  * 片段处理器要将光照颜色做为输入\n\n在高级语言中（C/C++），数据从接口的一端流向另一端，是因为提供了数据存放的内存位置（通常是指针信息）；由于Cg 语言并不支持指针机制，且图形硬件处理过程中，数据通常暂存在寄存器中，故而在Cg 语言中，通过引入 **语义绑定（binding semantics）机制，指定数据存放的位置** ，实际上就是将输入\\输出数据和寄存器做一个映射关系（在OpenGL Cg profiles 中是这样的，但在DirectX-based Cgprofiles 中则并没有这种映射关系）。根据输入语义，图形处理器从某个寄存器取数据；然后再将处理好的数据，根据输出语义，放到指定的寄存器。\n\n#### 顶点着色器输入语义 - 应用阶段传递模型数据到顶点着色器时\n\n语义 | 描述\n---|---\nPOSITION | 模型空间中模型顶点坐标位置，通常是float4类型\nNORMAL | 顶点法线，通常是float3类型\nTANGENT | 顶点切线，通常是float3类型\nTEXCOORDn | 顶点的纹理坐标，TEXCOORD0表示第一组纹理坐标以此类推，通常是float2或float4\nCOLOR | 顶点的颜色，通常是float4或fixed4\n\n#### 从顶点着色器到片元着色器\n\n顶点着色器的输出即是片段着色器的输入，所以顶点着色器的输出必须和片段着色器的输入语义是一致的。\n\n语义 | 描述\n---|---\nSV_POSITION | 裁剪空间中顶点坐标，结构体中必须有一个用该语义修饰的变量等同于DirectX9中的POSITION,但最好使用SV_POSITION\nCOLOR0 | 通常用于修饰第一组顶点颜色，但不是必须的\nCOLOR1 | 通常用于修饰第二组顶点颜色，但不是必须的\nTEXCOORD0~TEXCOORD7 | 顶通常用于修饰纹理坐标，但不是必须的\n\n#### 片元着色器输出语义\n\n语义 | 描述\n---|---\nSV_Target | 等同于DirectX9中的COLOR，但我们最好用SV_Target。表示的是将输出数据传递给render_target（渲染目标）\nDEPTH | 片段的深度\n\n其他语义：\n\n  * SV_TargetN：多个渲染目标。\nSV_Target1、SV_Target2 等等：这些是着色器写入的附加颜色。这在“多渲染目标”渲染技术（Multiple Render Targets rendering technique, MRT）中使用。SV_Target0 等同于 SV_Target。\n\n  * SV_Depth：像素着色器深度输出\n通常情况下， 片元着色器不会覆盖 Z 缓冲区值，并使用 常规三角形栅格化中的默认值。但是， 对于某些效果，输出每个像素的自定义 Z 缓冲区深度值很有用。\n\n## Ref\n\n<https://www.lfzxb.top/unity-shader_unityshaderstudygo/>\n<https://www.cnblogs.com/nanwei/p/7193768.html>\n<https://docs.unity3d.com/Manual>\n<https://blog.uwa4d.com/archives/1983.html>\n"
}
