Shader Graph 7.5.1

一、关于Shader Graph

Shader Graph使您可以直观地构建着色器。你无需编写代码,就可以在图框架中创建和连接节点。

Shader Graph可通过Unity版本2018.1及更高版本中的Package Manger窗口获得。如果您安装了诸如通用渲染管道(URP)或高清渲染管道(HDRP)之类的可编程渲染管道(SRP),Unity会在您的项目中自动安装Shader Graph。

注意:Shader Graph软件包与URP和HDRP兼容,但与内置渲染器不兼容。

Unity Engine 2018.x上的Shader Graph软件包版本为预览版,不接受错误修复和功能维护。要使用受支持的Shader Graph版本,请使用Unity Engine 2019.1或更高版本。

二、Shader Graph入门

Shader Graph仅与可编程渲染管道(SRP)兼容,即高清晰度渲染管道(HDRP)和通用渲染管道(URP)。这两个SRP在Unity 2018.1和更高版本中可用。旧版内置渲染管道不支持Shader Graph。

HDRP和URP软件包随附了Shader Graph。当您将两个SRP添加到项目中时,Unity会自动安装Shader Graph。

有关设置SRP的更多信息,请参阅HDRP入门URP入门

1.创建新的Shader Graph

配置SRP之后,可以创建新的Shader Graph。右键单击项目窗口,在上下文菜单中找到Create > Shader,然后选择所需的Shader Graph类型。

Unity当前支持以下图形类型:

  • PBR Graph
  • Sub Graph
  • Unlit Graph

如果您在项目中使用HDRP,则还可以使用以下特定于HDRP的图形类型:

  • Decal Graph
  • Fabric Graph
  • Hair Graph
  • Lit Graph
  • StackLit Graph
  • Unlit Graph

双击新创建的Shader Graph,在Shader Graph窗口中将其打开。

> Shader Graph窗口

Shader Graph窗口由主节点(Master Node),主预览(Main Preview)和黑板(Blackboard)组成。

  • Master Node

确定着色器输出的最终连接。

  • Main Preview

预览当前着色器输出的区域。在这里,您可以旋转、缩放对象。您还可以更改预览着色器的基本网格。

  • Blackboard

在单个收集的视图中包含着色器所有属性的区域。使用黑板来添加,删除,重命名和重新排序属性。

2.我的第一个Shader Graph

在开始之前,请确保正确设置了项目,并且图形正确加载。

> 创建新节点

使用Create Node菜单创建新节点。有两种打开菜单的方法:

  1. 右键单击,然后从上下文菜单中选择Create Node。
  2. 按空格键。

在菜单中,您可以在搜索栏中键入以查找特定节点,或浏览库中的所有节点。在此示例中,我们将创建一个Color节点。首先,在Create Node菜单的搜索栏中键入Color。然后,单击Color,按Enter以创建Color节点。

> 连接节点

要构建图形,您需要将节点连接在一起。为此,请单击一个节点的输出插槽,然后将该连接拖到另一个节点的输入插槽中。

首先将颜色节点连接到我们的主节点的Albedo插槽。

> 更改节点输出

请注意,该连接更新了主预览,并且主预览中的3D对象现在为黑色,这是在颜色节点中指定的颜色。您可以单击该节点中的颜色栏,然后使用颜色选择器更改颜色。您在节点上进行的任何更改都会实时更新主预览中的对象。

例如,如果选择蓝色,则3D对象将立即反映此更改。

> 保存图形

目前,Shader Graph不会自动保存。有两种保存更改的方法:

  1. 单击窗口左上角的Save Asset按钮。
  2. 关闭图形的时候,如果Unity检测到任何未保存的更改,则会显示一个弹出窗口,并询问您是否要保存这些更改。

> 创建材质

保存图形后,使用Shader创建新的材质。创建新材质并为其指定Shader Graph着色器的过程与常规着色器相同。在主菜单或项目视图上下文菜单中,选择Assets > Create > Material。选择刚创建的材料。在其Inspector窗口中,选择Shader下拉菜单,单击Shader Graph,然后选择要应用于材质的Shader。

您也可以右键单击Shader Graph着色器,然后选择Create > Material。此方法会自动将该Shader Graph着色器分配给新创建的材质。

> 将材质放到场景中

将材质拖放到场景中的对象上。或者,在对象的Inspector窗口中,找到Mesh Renderer > Materials,然后将材质应用到Element。

> 使用属性来编辑图形

您还可以使用属性来更改着色器的外观。属性是在材质的Inspector窗口中可见的选项,这些选项使其他人无需打开Shader Graph即可更改着色器中的设置。

要创建新属性,请使用黑板右上角的添加(+)按钮,然后选择要创建的属性的类型。在此示例中,我们将选择Color。

选项描述
Property Button要更改属性的名称,请在黑板上右键单击该按钮,选择Rename,然后输入一个新的属性名称。要删除该属性,请右键单击该按钮,然后选择Delete。
Exposed启用此复选框可使该属性在材质的Inspector窗口中可见。
Reference在C#脚本中显示的属性名称。要更改参考名称,请输入新字符串。
Default属性的默认值。
Mode属性的模式。每个属性都有不同的模式。对于颜色,您可以选择Default或HDR。
Precision属性的默认精度。
Hybrid Instanced一种实验功能,使用混合DOTS渲染器时可以实例化此属性。

有两种方法可以引用图形中的属性:

  1. 将属性从黑板拖到图形上。
  2. 右键单击并选择Create Node。该属性在Properties类别中列出。

保存图形,然后返回到材质的Inspector窗口。该属性现在显示在Inspector窗口中。您对Inspector窗口中的属性所做的任何更改都会影响使用此材质的所有对象。

3.Shader Graph窗口

Shader Graph窗口包含用于使用Shader Graph系统创建着色器的工作空间。要打开Shader Graph窗口,必须首先创建一个Shader Graph。
Shader Graph窗口包含各种单独的元素,例如黑板、内部检查器和主预览。这些元素可以在工作空间内移动。缩放Shader Graph窗口时,它们将自动锚定到最近的角。

  • 标题栏
选项描述
Save Asset保存图形以更新Shader Graph。
Show In Project在项目窗口中突出显示Shader Graph。
Precision提供下拉菜单以选择图形的精度模式。
Check Out如果启用了版本控制,则将从源代码控制提供程序中检出Shader Graph。
Color Mode提供下拉菜单为图形选择颜色模式。
Blackboard切换黑板的可见性。
Main Preview切换主预览的可见性。

  • 工作空间

在工作区中可以创建节点网络。您可以通过按住Alt和鼠标左键来平移导航工作区,通过滚动鼠标中键来缩放导航工作区。

您可以按住鼠标左键并拖动以选择带有选取框的多个节点。还有各种快捷键可用于改善工作流程。

快捷键WindowsOSX描述
CutCtrl + XCommand + X将选定的节点剪切到剪贴板
CopyCtrl + CCommand + C将选定的节点复制到剪贴板
PasteCtrl + VCommand + V将节点粘贴到剪贴板中
FocusFF将工作区集中在所有或选定节点上
Create Node空格键空格键打开创建节点菜单

  • 上下文菜单

在工作区中右键单击将打开一个上下文菜单。请注意,右键单击工作区中的某个节点将打开该节点而不是工作区的上下文菜单。

选项描述
Create Node打开创建节点菜单
Cut将选定的节点剪切到剪贴板
Copy将选定的节点复制到剪贴板
Paste将节点粘贴到剪贴板中
Delete删除选定的节点
Duplicate复制所选节点
Collapse Previews折叠所有节点上的预览
Expand Previews扩展所有节点上的预览

> Blackboard

黑板上列出了可在图形中使用的属性和关键字。在这里,您可以定义一系列的属性和关键字类型,以及相应的名称,属性和默认值。您还可以向使用着色器的材质公开属性和关键字。

要更改Shader Graph的路径,请在黑板上双击其路径字段,然后输入新路径。 Unity编辑器使用Shader Graph路径在材质检查器的Shader下拉菜单中列出相应的Shader Graph。同样,您可以更改Sub Graph的路径字段。编辑器使用Sub Graph路径在Create Node菜单中列出相应的Sub Graph。

您可以在Shader Graph窗口中的任意位置移动黑板。即使您调整窗口的大小,它与最近的角始终保持相同的距离。

要创建新的属性或关键字,请单击黑板标题栏上的添加(+)按钮,然后选择属性或关键字类型。

要重新排序黑板上列出的项目,请拖放它们。要删除项目,请使用Windows上的Delete键,或使用OS X上的Command + Backspace组合键。要重命名项目,请双击其名称,然后输入新名称。将属性和关键字从黑板拖到图形上以创建相应的节点。

> Main Preview

主预览在活动的渲染管道上显示着色器的表示。它实时更新,并自动更新以显示您在Shader Graph中所做的任何更改。 Main Preview的标题栏显示当前着色器的名称。

可以将主预览移动到Shader Graph窗口中的任何位置,并将自动随该窗口的最近角移动。

您可以通过按住鼠标左键并在主预览上拖动来旋转预览网格,并可以使用滚轮缩放它。可以通过右键单击主预览来更改预览网格。在这里,您可以从任何原始网格类型中进行选择,也可以选择一个自定义网格。

4.创建节点菜单

创建节点菜单是如何在Shader Graph中创建节点。要打开创建节点菜单,请在Shader Graph窗口中的工作区上单击鼠标右键,然后选择Create Node或按空格键。
在创建节点菜单的顶部是一个搜索栏。您可以通过在搜索字段中键入节点名称的任何部分来搜索节点。
Shader Graph中可用的所有节点均按其功能分类在创建节点菜单中列出。用户创建的任何Sub Graph也可以在Sub Graph下的创建节点菜单中找到。
在创建节点菜单中选择一个节点会将其添加到工作区。

上下文创建节点菜单

上下文创建节点菜单会过滤可用的节点,以仅显示那些使用选定边的数据类型的节点。它将列出这些节点上与该数据类型匹配的每个可用端口。

您可以通过以下方式打开上下文创建节点菜单:用鼠标左键从端口拖动边并将其释放到工作区的空白区域。

5.Sticky Notes

便笺是可以在图形视图中写入的对象。它们是等效于代码注释的图形视图,由标题和正文组成。您可以在图形中创建任意数量的便笺,并将它们用于多种目的,例如:

  • 描述图的一部分如何工作。
  • 为自己或在Unity项目中进行协作的其他人留下笔记。
  • 作为待办事项清单,其中包括以后要完成的任务。

> 使用Sticky Notes

要创建便笺,请在图形视图中的空白处上单击鼠标右键,然后在上下文菜单中单击Create Sticky Note。然后,您可以自定义内容并将内容添加到新的便笺中。您可以输入两个文本区域:

  • Title: 便笺顶部的文本区域是标题。您可以使用它来简要描述便笺中包含的信息。
  • Body:标题区域下方的较大文本区域是正文。您可以在此处编写注释的全部内容。

编辑文字

要在便笺上编辑文本,请双击文本区域。这也会选择整个文本区域,因此在编辑文本之前,请确保先移动光标。

移动和调整大小

您可以将便笺移动到图形上的任何位置。您也可以单击并拖动以手动调整便笺的大小,或者让便笺自动调整其大小以适合内容。有关如何调整便笺大小的信息,请参见下面的上下文菜单部分的适合文本。

复制

使用以下键盘快捷键可以剪切,复制,粘贴和复制便笺。

  • Copy: Ctrl+C
  • Cut: Ctrl+X
  • Paste: Ctrl+V
  • Duplicate: Ctrl+D

上下文菜单

要打开便笺的上下文菜单,请在其上的任意位置单击鼠标右键。上下文菜单中的选项如下。

选项描述
Dark Theme/Light Theme将便签的颜色主题在浅色主题和深色主题之间切换。
Text Size将文本区域中的字体大小调整为以下点值。
SmallTitle: 20, Body: 11
MediumTitle: 40, Body: 24
LargeTitle: 60, Body: 36
HugeTitle: 80, Body: 56
Fit To Text调整便签的大小,使其恰好适合文本区域。如果标题超过一行,Unity会调整便笺的大小,以使标题文本适合一行。
Delete删除您选择的便笺。
Group Selection将您选择的所有便笺分组放置。
Ungroup Selection从组中删除您选择的所有便笺。

6.Sub Graph

Sub Graph是Shader Graph的一种特殊类型,您可以从其他图内部引用。当您希望在一个图形或多个图形中多次执行相同的操作时,此功能很有用。Sub Graph与Shader Graph在三个主要方面不同:

  • 当您从另一个图内部引用子图时,子图黑板上的属性定义了子图节点的输入端口。
  • 子图具有其自己的资源类型。有关更多信息,包括有关如何制作新子图的说明,请参见子图。
  • 子图没有主节点。相反,它有一个称为输出的节点。有关更多信息,请参见输出节点。

输出节点

当您从另一个图内部引用子图时,输出节点定义子图节点的输出端口。要添加和删除端口,请使用自定义端口菜单。

子图和着色器阶段

如果子图中的一个节点指定了一个着色器阶段(例如,就像采样纹理2D节点如何指定片元着色器阶段一样),则编辑器会将整个子图锁定到该阶段。您不能将指定不同着色器阶段的任何节点连接到子图输出节点,并且编辑器将引用该图的任何子图节点锁定到该着色器阶段。

子图和关键字

您在子图中的黑板上定义的关键字的行为与常规Shader Graph中的关键字相似。当您向Shader Graph添加子图节点时,Unity也会在Shader Graph中定义该子图中的所有关键字,以便子图按预期工作。

要在Shader Graph中使用子图关键字,或在材质检查器中显示该关键字,请将其从子图复制到Shader Graph的黑板上。

7.颜色模式

Shader Graph可以在图形的节点上显示颜色,以提高可读性。此功能使用颜色模式来更改要在图形中显示的颜色。使用Shader Graph窗口右上角的Color Mode:下拉菜单可以更改颜色模式。

> 模式

名字描述
None在节点上不显示颜色。所有节点均使用默认的灰色。
Category根据节点分配的类别在其上显示颜色。请参阅下面的类别颜色。
Precision根据当前使用的精度类型在节点上显示颜色。
User Defined使您可以按节点设置显示颜色。这些是图形的自定义颜色。请参阅下面的用户定义颜色。

类别颜色

此模式根据节点的类别在节点上显示颜色。请参阅节点库以了解可用的不同类别。

下表列出了当前类别及其对应的颜色。

NameColorHex Value
Artistic#DB773B#DB773B
Channel#97D13D#97D13D
Input#CB3022#CB3022
Math#4B92F3#4B92F3
Procedural#9C4FFF#9C4FFF
Utility#AEAEAE#AEAEAE
UV#08D78B#08D78B

注意:Shader Graph中的Sub Graph节点属于Utility类别。如果选择Category模式,则所有Sub Graph都将使用Utility颜色。

精度颜色

此模式根据节点的当前精度在其上显示颜色。如果将节点设置为Inherit精度,则显示颜色将反映当前活动的精度。有关Inherit的更多信息,请参见精确模式。

下表列出了当前的精度类型及其相应的颜色。

NameColorHex Value
Half#CB3022#CB3022
Float#4B92F3#4B92F3

用户定义的颜色

此模式根据用户首选项在节点上显示颜色。在此模式下,用户为每个节点定义颜色。如果未设置自定义颜色,则节点以默认灰色显示。

要为节点设置自定义颜色,请右键单击目标节点以打开上下文菜单,然后选择Color。

选项描述
Change...弹出颜色选择器菜单,让您在节点上设置自己的自定义颜色。
Reset删除当前选择的颜色并将其设置为默认的灰色。

覆盖默认颜色

对于每个项目,您可以在“类别”和“精度”模式下覆盖预设颜色。 Unity使用.uss样式表和十六进制颜色代码来设置颜色。项目中的默认样式表为Packages / com.unity.shadergraph / Editor / Resources / Styles / ColorMode.uss。

最佳实践是创建此文件的副本以覆盖预设。在项目的Assets文件夹下,创建一个新的Editor / Resources / Styles文件夹结构,并将ColorMode.uss的副本放置在Styles文件夹中。更改此.uss文件中的十六进制颜色代码以覆盖预设,并对类别和精度模式使用您自己的自定义颜色。

8.精确模式

Shader Graph允许您设置特定的精度数据模式以在不同平台上进行优化。使用左上角的Precision下拉菜单设置整个图形的精度,或使用每个节点上的齿轮图标菜单设置图形上各个节点的精度。

> 菜单选项

NameDescription
Float将精度模式设置为Float。
Half将精度模式设置为Half
Inherit将精度模式设置为Inherit。请参见下面的精度继承。仅在节点上可用。

> 使用精度模式

可视化精度

若要通过图形显示数据精度,请使用Shader Graph窗口右上角的Color Mode。将Color Mode设置为Precision以直观地指示当前评估中每个节点使用的是Half还是Float。

图形精度

要将整个图形的精度设置为Float或Half,请使用Shader Graph窗口左上角的下拉菜单。默认情况下,新创建的节点使用此下拉菜单中设置的精度。

节点精度

要为每个节点设置唯一的精度,请使用其齿轮图标菜单。根据您在每个节点上设置的精度,精度类型在数据流过图形时向上或向下强制转换。

例如,如果将一个Half节点连接到一个Float节点,则数据将向上转换到Float。如果您随后将该Float节点连接到另一个Half节点,则数据将向下转换回Half。

精度继承

节点具有一个称为“继承”的精度选项,这使它们可以继承任何传入边的精度模式。当您将所有节点添加到图中时,默认情况下将使用继承模式。为没有任何边缘连接到其输入端口的节点设置继承选项时,它们将使用“图形精度”设置。

节点从每个输入端口读取精度。您可以将具有不同精度模式的节点连接到单个节点的输入端口。在这种情况下,结果输出是连接的节点中最高的可用精度模式。

例如,将节点D设置为继承。节点B将Half的精度传递给输入端口A。节点C将Float的精度传递给输入端口B。因此,节点D输出Float,这是节点D上输入端口中精度最高的模式。

您也可以使用精度模式来设置没有输入端口的节点。这些通常是输入节点,默认情况下将其设置为继承并使用图形精度。与其他节点类似,使用每个输入节点的齿轮图标菜单来手动设置图形输入数据的精度。

当为没有连接到其输入端口的节点设置继承选项时,它们将使用“图形精度”设置。如果更改“图形精度”模式,则这些节点的精度也会更改。跟踪设置为继承的节点非常重要,因为在更改“图形精度”时,它们可能会导致转换瓶颈。

例如,如果将图形精度从Half更改为Float,但将节点B手动设置为Half,则输入到节点B的数据将从Float更改为Half,然后在节点D处再次转换回Float。

子图精度

在子图中,图形和节点的精度行为与普通图形相同。使用左上角的下拉菜单来设置图形精度,并使用每个节点上的齿轮图标菜单来为子图形中的各个节点设置节点精度。

在输出节点上为子图输出设置精度。此精度适用于子图的输出节点的所有输出端口。

对于子图输入,在子图的黑板上为每个单独的属性设置精度模式。使用继承选项的属性会使用左上角的下拉菜单继承为子图设置的图精度。

您在主图形中使用子图形节点时,子图形将确定其自身的精度。子图黑板上输入属性的精度模式继承了子图资源的子图精度。子图的输出使用输出节点的精度。您不能更改Shader Graph内子图节点的精度。

例如,将子图精度设置为Half,将图形精度设置为Float。然后将Input A和Output节点都设置为继承。子图的输入和输出端口继承了子图精度的Half,即使您将图形精度设置为Float也是如此。如果希望子图的继承行为与主图的继承行为匹配,则必须将子图精度也设置为Float。

9.自定义函数节点

Shader Graph使您可以在Unity中轻松编写自定义着色器。但是,由于我们的默认节点无法覆盖您要制作的所有内容,因此该软件包现在在节点库中带有自定义函数节点。

通过自定义函数节点,可以将自己的自定义HLSL代码注入Shader Graph中。您可以使用字符串模式将小型函数直接写入图形,也可以引用外部HLSL包含文件。您还可以使用自定义端口菜单在节点本身上定义自己的输入和输出端口。

> 如何使用

使用创建节点菜单创建自定义函数节点。默认情况下,新的自定义函数节点没有任何输入或输出端口。

使用节点右上角的齿轮图标打开“自定义端口菜单”和“自定义函数菜单”。

自定义功能菜单

选项描述
Inputs自定义端口菜单,用于定义节点的输入端口。
Outputs自定义端口菜单,用于定义节点的输出端口。
Type可以在其中设置功能类型的下拉菜单。选择File以引用外部文件,或选择String以直接向节点输入功能。
Name最终生成的代码中的自定义函数的名称。
Source引用外部HLSL包含文件的资源字段。仅在文件模式下可用。
Body您在其中输入HLSL代码的文本框。仅在字符串模式下可用。

通过字符串定义函数

如果选择字符串模式,则图形将生成着色器功能。 Name字段定义了所生成函数的名称,而Body字段定义了所生成函数的内容。参数,花括号和缩进范围会自动处理。在字符串模式下,填写Body字段时,可以使用标记$ precision而不是half或float。处理该节点时,将根据该节点的精度将其替换为正确的类型。

上面的示例生成以下函数:

void MyFun_float(float3 V3,float V1,out float Out)
{
     Out = V3 * V1 + 1/2;
}

通过文件定义功能

如果选择文件模式,则图形不会自动生成着色器功能。文件模式在最终生成的着色器中插入一个包含引用,并使用引用文件中的功能。Name字段必须与您要调用的函数的名称匹配。 Source字段包含对包含该功能的HLSL文件的引用。

在自定义函数节点上使用文件模式时,必须手动正确格式化功能。为Shader Graph创建自定义函数时要注意的一件事是精度后缀。生成的代码在函数名称后附加一个精确的后缀。您的包含文件函数还必须附加所需的精度后缀(如下面的_float所示),或包含带有_float和_half后缀的多个函数,但您的Name字段不得包含精度后缀。

文件模式允许图形中的自定义功能具有更大的灵活性。您可以在函数范围之外定义统一变量,如此处显示的矩阵所示。

您可以在同一文件中定义多个函数,然后从引用的函数中调用它们。或者,您可以引用同一文件,但使用来自不同自定义函数节点的不同功能。

您甚至可以包括包含其他功能的其他文件。

重用自定义函数节点

自定义函数节点本身是一个单节点实例。如果希望在不重新创建输入,输出和函数引用的情况下重复使用相同的自定义函数,请使用子图。子图显示在创建节点菜单中,它们允许您共享或重复使用自定义函数。

直接在子图中创建您的自定义函数,或者右键单击现有的自定义函数节点,然后选择Convert to Sub Graph。使用黑板和自定义端口菜单添加适当的输入和输出端口。此后,即使在其他子图中,您也可以根据需要多次重复使用自定义函数。

10.Shader Graph 示例

Shader Graph软件包提供了示例资源,您可以通过Package Manager下载它们。导入这些样本时,Unity会将文件放在项目的Asset文件夹中。这些文件包含一些示例,这些示例演示了如何使用Shader Graph功能。

添加示例

要将示例添加到您的项目中,请转到Window > Package Manager。在可用软件包列表中找到Shader Graph,然后选择它。在包装说明下,提供了可用示例的列表。单击要添加的示例旁边的导入到项目按钮。

Unity将导入的示例放在您的项目的Asset文件夹中的Assets>Samples> Shader Graph> [版本号]> [示例名称]下。下面的示例显示了程序模式的示例。

可用示例

以下示例当​​前可用于Shader Graph。

此资源集合展示了Shader Graph可能使用的各种程序技术。直接在您的项目中使用它们,或编辑它们以创建其他程序模式。该集合中的模式为:Bacteria细菌,Brick砖块,Dots圆点,Grid网格,Herringbone人字形,Hex Lattice六角格,Houndstooth千鸟格,Smooth Wave平滑波,Spiral螺旋,Stripes条纹,Truchet,Whirl旋转,Zig Zag锯齿形。

三、内部Shader Graph

Shader Graph Asset是Shader Graph引入的新资源类型。您可以从创建菜单的项目窗口中创建Shader Graph Asset。

为了方便起见,有一个用于PBR Graph,Unlit Graph和Sub Graph的创建菜单项。可以在着色器子菜单中找到它们。这两个主要图形选项将创建具有适当主节点的Shader Graph Asset。

可以通过双击Shader Graph Asset或在选择Shader Graph Asset时单击Inspector窗口中的Open Shader Editor来打开Shader Graph窗口。

四、Sub Graph Asset

子图资源是随Shader Graph引入的新资源类型。子图资源定义了一个子图。这与Shader Graph不同。您可以通过着色器子菜单中的Sub Graph来创建子图资源。

可以通过以下方式打开Shader Graph窗口:双击Sub Graph资源,或者在选择Sub Graph资源后单击Inspector中的Open Shader Editor。

节点

节点根据其可用端口在Shader Graph上定义输入、输出或操作。节点可以具有任意数量的输入和/或输出端口。通过将这些端口与Edge相连,可以创建Shader Graph。节点也可能具有任意数量的控件,这些是节点上没有端口的控件。

有关节点的组件,请参见:

  • 端口
  • 边缘

Shader Graph中有许多可用的节点。有关所有可用节点的完整列表,请参见节点库。

预览

一些节点在该节点上具有预览。该预览显示图形中该阶段的主要输出值。可以使用预览顶部的“折叠”按钮隐藏预览。当鼠标光标悬停在节点上时显示。您还可以通过Shader Graph窗口上的上下文菜单折叠和展开所有节点上的预览。

上下文菜单

右键单击节点将打开一个上下文菜单。该菜单包含许多可以在节点上执行的操作。请注意,当选择多个节点时,这些操作将应用于整个选择。

选项描述
Copy Shader将图形中此阶段生成的HLSL代码复制到剪贴板
Show Generated Code显示生成的代码
Disconnect All从节点上的所有端口删除所有边缘
Cut将选定的节点剪切到剪贴板
Copy将选定的节点复制到剪贴板
Paste将节点粘贴到剪贴板中
Delete删除选定的节点
Duplicate复制选定的节点
Convert To Sub-graph创建一个包含选定节点的新子图资源
Convert To Inline Node将属性节点转换为适当数据类型的常规节点
Convert To Property在适当属性类型的黑板上将节点转换为新属性
Open Documentation打开一个新的Web浏览器,进入节点库中选定的节点文档页面。

颜色模式

节点与Shader Graph窗口的颜色模式进行交互。颜色显示在节点标题栏上文本下方的节点上。有关节点可用颜色的更多信息,请参见颜色模式。

> 端口

端口定义节点上的输入或输出。将Edge连接到端口允许数据流过Shader Graph节点网络。

每个端口都有一个数据类型,该数据类型定义了可以连接哪些边缘。每个数据类型都有一个关联的颜色来标识其类型。

只能将一个Edge连接到任何输入端口,但是可以将多个Edge连接到输出端口。

默认输入

每个输入端口(节点左侧的一个端口,表示它用于将数据输入到节点中)均具有默认输入。当没有边缘连接时,这显示为连接到端口的小字段。除非端口具有端口绑定,否则此字段将显示端口数据类型的输入。如果端口确实具有端口绑定,则默认输入字段可能会显示一个特殊字段,例如用于选择UV通道的下拉列表,或者仅显示一个标签以帮助您理解预期的输入,例如用于几何数据的协调空间标签。

> 自定义端口菜单

自定义端口菜单在自定义函数节点和子图输出节点上可用。此菜单使您可以添加,删除,重命名,重新排序和定义自定义输入和输出端口的类型。

如何使用

单击节点右上角的齿轮图标,以打开节点顶部的“自定义端口菜单”。要关闭菜单,请再次单击齿轮图标。使用齿轮图标打开菜单会自动取消选择任何当前选择,并选择连接到菜单的当前节点。

添加和删​​除端口

要添加端口,请单击端口列表右下角的+图标。

要删除端口,请使用左侧的汉堡包图标选择一个端口,然后单击端口列表右下角的-图标。

重命名端口

要重命名端口,请双击其文本字段并输入新名称。当前,只有以下字符对端口名称有效:A-Z,a-z,0-9,_,()和空格。如果名称包含无效字符,则会显示错误标志。

重新排序端口

要重新排序端口,请单击并按住左侧的图标,然后将端口拖到列表中所需的位置。

更改端口类型

要更改端口类型,请使用右侧的“类型”下拉菜单。有关当前有效端口类型的列表,请参见“数据类型”页面。

> 边

边定义两个端口之间的连接。边定义了数据如何通过Shader Graph节点网络流动。它们只能从输入端口连接到输出端口。

每个边都有一个数据类型,该数据类型定义了可以连接到哪些端口。每个数据类型都有一个关联的颜色来标识其类型。

您可以通过使用鼠标左键单击并从端口中拖动来创建新的边。可以使用Delete(Windows),Command + Backspace(OSX)或通过右键单击节点从上下文菜单中删除边。

您可以通过以下方式打开上下文创建节点菜单:用鼠标左键从端口拖动边缘并将其释放到工作区的空白区域。

主节点

主节点是一种特殊的节点。Shader Graph的端点定义了着色器的最终表面外观。您的Shader Graph应始终包含一个,并且只有一个为主节点。如果有可用的后端,则主节点将自动处理不同可编程渲染管道之间的着色器转换。

有关所有可用主节点的完整列表,请参见节点库中的主节点。

属性类型

属性类型可以在黑板上定义,以供在图形中使用。这些属性将显示给使用着色器的材质检查器。

每个属性都有一个关联的数据类型。有关更多信息,请参见数据类型。

> 常用参数

除了特定于其数据类型的值之外,所有属性还具有以下参数。

名称类型描述
Display NameString属性的显示名称
ExposedBoolean如果为true,则此属性将在材质检查器中公开
Reference NameString着色器内部属性使用的内部名称

注意:如果您覆盖Reference Name参数,请注意以下情况:

  • 如果您的Reference Name不是以下划线开头,则会自动添加下划线。
  • 如果您的Reference Name包含HLSL不支持的任何字符,则将其删除。
  • 您可以通过右键单击默认的Reference Name并选择Reset Reference来恢复为默认Reference Name。

1.Vector1

定义Vector 1的值。

Data TypeMode
Vector1Default、 Slider、 Integer、Enum

Default

在材质检查器中显示标量输入字段。

FieldTypeDescription
DefaultVector1属性的默认值。

Slider

在材质检查器中显示一个滑块字段。

FieldTypeDescription
DefaultVector1属性的默认值。
MinVector1滑块的最小值。
MaxVector1滑块的最大值。

Integer

在材质检查器中显示一个整数输入字段。

FieldTypeDescription
DefaultInteger属性的默认值。

Enum

在材质检查器中显示一个枚举输入字段。

2.Vector2

定义Vector 2的值。在材质检查器中显示Vector4输入字段,其中不使用z和w分量。

FieldTypeDescription
DefaultVector2属性的默认值。

3.Vector3

定义Vector3的值。在材质检查器中显示Vector4输入字段,其中不使用w分量。

FieldTypeDescription
DefaultVector3属性的默认值。

4.Vector4

定义Vector4的值。在材质检查器中显示ector4输入字段。

FieldTypeDescription
DefaultVector4属性的默认值。

5.Color

定义颜色值。

Data TypeModes
ColorDefault、HDR

Default

在材质检查器中显示SRGB颜色字段。

FieldTypeDescription
DefaultVector4属性的默认值。

HDR

在材质检查器中显示HDR颜色字段。

FieldTypeDescription
DefaultVector4属性的默认值。

6.Texture 2D

定义Texture 2D值。在材质检查器中显示“纹理”类型的对象字段。

Data TypeModes
TextureWhite、 Black、 Grey、 Bump
FieldTypeDescription
DefaultTexture属性的默认值。

7.Texture 3D

定义Texture 3D值。在材质检查器中显示“纹理3D”类型的对象字段。

FieldTypeDescription
DefaultTexture属性的默认值。

8.Texture 2D Array

定义Texture 2D Array值。在材质检查器中显示“纹理2D数组”类型的对象字段。

FieldTypeDescription
DefaultTexture属性的默认值。

9.Cubemap

定义一个Cubemap值。在材质检查器中显示“纹理”类型的对象字段。

FieldTypeDescription
DefaultCubemap属性的默认值。

10.Boolean

定义一个布尔值。在材料检查器中显示ToggleUI字段。请注意,在着色器内部,此值为Vector1。Shader Graph中的布尔类型仅用于可用性。

FieldTypeDescription
DefaultBoolean属性的默认值。

关键字

您可以使用关键字为Shader Graph创建不同的变体。根据关键字的设置和编辑器中的设置,构建管道可能会剥离这些变体。

关键字之所以有用,有很多原因,例如:

  • 创建具有可为每个Material实例打开或关闭的功能的着色器。
  • 创建具有在某些平台上行为不同的功能的着色器。
  • 根据各种条件创建可以按复杂程度缩放的着色器。

关键字有三种类型:布尔值,枚举和内置关键字。根据其类型,Unity在图形,着色器以及(可选)材质检查器中定义了一个关键字。有关关键字类型的更多信息,请参见布尔关键字,枚举关键字和内置关键字。有关这些关键字如何影响最终着色器的更多信息,请参见关于制作多个着色器程序变体的文档

在Shader Graph中,首先在黑板上定义一个关键字,然后使用关键字节点在图形中创建一个分支。

> 常用参数

尽管某些字段特定于某些类型的关键字,但所有关键字都具有以下参数。

名字类型描述
Display NameString关键字的显示名称。 Unity在引用相应关键字的节点的标题栏中显示此名称,如果公开该关键字,则在Material Inspector中显示该名称。
ExposedBoolean如果将其设置为true,则Unity在材料检查器中显示相应的关键字。如果将其设置为false,则关键字不会出现在材料检查器中。
Reference NameString着色器中关键字的内部名称。

如果覆盖Reference Name参数,请注意以下几点:
•关键字Reference Name始终使用大写字母,因此Unity会将所有小写字母转换为大写字母。
• 如果Reference Name包含HLSL不支持的任何字符,则Unity将这些字符替换为下划线。
• 右键单击Reference Name,然后选择Reset Reference以恢复为默认参考名称。
DefinitionEnum设置如何在着色器中定义关键字。

有三个可用选项。
Shader Feature: Unity在构建时会剥离未使用的着色器变体。
Multi Compile: Unity从不剥离任何着色器变体。
Predefined: 指示活动的渲染管道已经定义了此关键字,因此Shader Graph未在其生成的代码中对其进行定义。
ScopeEnum设置定义关键字的范围。

Global Keywords: 为整个项目定义关键字,并计入全局关键字限制。
Local Keywords: 仅为一个着色器定义关键字,该着色器具有自己的本地关键字限制。
使用预定义关键字时,Unity会禁用此字段。

> 布尔关键字

布尔关键字为开或关。这导致两个着色器变体。 Shader Graph将“参考名称”字段中的值用于打开状态,并自动将关闭状态定义为下划线(_)。

要在材料检查器中显示布尔关键字,其参考名称必须包含_ON后缀。例如,BOOLEAN_9451464C_ON。

类型特定的参数

除了上面列出的公共参数外,布尔关键字还具有以下附加参数。

NameTypeDescription
DefaultBoolean启用复选框以将关键字的默认状态设置为开,并禁用复选框以将其默认状态设置为关。
此复选框确定在“着色器图”生成预览时用于关键字的值。当您使用此着色器创建新材质时,它还定义了关键字的默认值。

> 枚举关键字

枚举关键字可以具有两个或多个状态,您可以在Entries(条目)列表中定义它们。如果公开枚举关键字,则其Entries列表中的“显示名称”将显示在材质检查器的下拉菜单中。

定义枚举关键字时,Shader Graph会将条目的参考后缀附加到主要参考名称,以定义每种状态。它使用{Reference} _ {ReferenceSuffix}模式定义大多数条目,但是请注意,它使用else语句选择最后一个条目,该条目被视为关闭状态。

   

类型特定的参数

除了上面列出的公共参数外,Enum关键字还具有以下附加参数。

名字类型描述
DefaultEnum从下拉菜单中选择一个条目,以确定在Shader Graph生成预览时用于关键字的值。当您使用此着色器创建新材质时,它还定义了关键字的默认值。编辑条目列表时,Shader Graph会自动更新此下拉菜单中的选项。
EntriesReorderable List该列表定义了关键字的所有状态。每个状态都有单独的显示名称和参考后缀。

Display Name:出现在黑板上的关键字和材质检查器的下拉菜单中。 Shader Graph还将此名称用于引用关键字的节点上的端口标签。
Reference Suffix: Shader Graph使用此后缀在着色器中生成关键字状态。

> 内置关键字

内置关键字始终是布尔关键字或枚举关键字,但是它们的行为略有不同。 Unity编辑器或活动的渲染管道将设置它们的值,并且您无法编辑它们。

黑板上的所有内置关键字字段均灰显,Default字段除外,您可以启用或禁用该字段以在Shader Graph预览中显示差异。您也不能在材质检查器中公开内置关键字。

数据类型

Shader Graph中有许多数据类型。节点上的每个端口都有一个关联的数据类型,该数据类型定义了可以连接到它的哪些边缘。数据类型具有用于可用性的颜色,这些颜色应用于该数据类型的端口和边缘。

某些数据类型具有关联的属性类型,用于将这些值暴露给使用着色器的材质检查器。

名字颜色描述
Vector 1浅蓝向量1或标量值
Vector 2绿色向量2的值
Vector 3黄色向量3的值
Vector 4粉色向量4的值
Dynamic Vector浅蓝请参阅下面的动态数据类型
Matrix 2蓝色矩阵2x2值
Matrix 3蓝色矩阵3x3值
Matrix 4蓝色矩阵4x4值
Dynamic Matrix蓝色请参阅下面的动态数据类型
Dynamic蓝色请参阅下面的动态数据类型
Boolean紫色布尔值。在生成的着色器中定义为float
Texture 2D红色Texture 2D资源
Texture 2D Array红色Texture 2D Array资源
Texture 3D红色Texture 3D资源
Cubemap红色立方体贴图资源
Gradient(渐变)灰色渐变值。在生成的着色器中定义为结构
SamplerState(采样器状态)灰色用于采样纹理的状态

> 升级/截断

所有向量类型都可以升级或截断以匹配任何向量类型端口。仅当所讨论的端口不是动态向量类型时,才会发生此行为。截断时,多余的通道将被简单地删除。升级时,默认值将填充所需的额外渠道。这些值为(0、0、0、1)。

> 动态数据类型

一些数据类型是动态的。这意味着使用这些数据类型的端口可以根据所连接的数据类型来更改其基础的具体数据类型。默认情况下,使用动态数据类型的节点只能具有一个具体的数据类型,这意味着一旦连接的边将其数据类型应用于该端口,该节点的所有其他动态数据类型插槽将应用相同的数据类型。

一个值得注意的例外是乘法节点,它同时允许动态矩阵和向量类型。

  • 动态向量

动态向量类型允许连接任何向量类型的边。除非最小尺寸为1,否则所有连接的边都会自动截断为具有最小尺寸的类型,在这种情况下,将提升Vector 1。

  • 动态矩阵

动态矩阵类型允许连接任何矩阵类型的边。所有连接的边都会自动截断为具有最小尺寸的类型。

  • 动态

动态类型是一种特殊情况。支持它的节点必须定义如何验证它。对于乘法节点,它允许任何向量或矩阵类型的连接,确保根据数据类型的混合应用正确的乘法。

精度类型

Shader Graph中目前有两种Precision Type。使用Precision Mode中列出的选项为每个节点定义精度类型。

名字描述
Half中精度浮点值;通常为16位(范围为–60000至+60000,精度为大约3个十进制数字)。
Half对于短矢量,方向,对象空间位置和高动态范围颜色很有用。
Float高精度浮点值;通常为32位(与常规编程语言中的浮点数相同)。
全浮点精度对于涉及复杂功能(例如三角函数,幂和幂)的世界空间位置,纹理坐标和标量计算很有用。

端口绑定

某些输入端口可能具有端口绑定。这意味着期望应该提供给端口的数据,例如法线矢量或UV。但是,端口绑定只会影响没有连接边的端口。这些端口仍具有常规数据类型,该数据类型定义可以连接哪些边。

实际上,这意味着如果没有边连接到端口,则该端口中使用的默认数据将从其端口绑定中获取。可以在下面找到端口绑定及其关联的默认选项的完整列表。

端口绑定列表

名字数据类型选件描述
BitangentVector 3顶点或片元的切线,标签描述了预期的变换空间
ColorVector 4RGBA拾色器
ColorRGBVector 3RGB拾色器
NormalVector 3顶点或片元法向矢量,标签描述了预期的变换空间
PositionVector 3顶点或片元位置,标签描述了预期的变换空间
Screen PositionVector 4Default, Raw, Center, Tiled(默认,原始,居中,平铺)
TangentVector 3顶点或片元切线矢量,标签描述了预期的变换空间
UVVector 2UV0, UV1, UV2, UV3
Vertex ColorVector 4RGBA顶点颜色值。
View DirectionVector 3顶点或片元视图方向矢量,标签描述了预期的变换空间

着色器阶段

着色器阶段是指节点或端口所属的着色器管道的一部分。例如,“顶点”或“片元”。

在Shader Graph中,每个端口都定义了着色器阶段,但通常节点上的所有端口都锁定到同一着色器阶段。由于基础着色器语言的限制,某些节点上的端口不可用。有关具有Shader Stage限制的节点,请参见节点库文档。

着色器阶段列表

Vertex每个顶点计算的运算
Fragment每个片元计算的运算

五、节点库

节点库包含有关Shader Graph中所有单个节点的文档。包括描述,端口,参数,着色器代码和示例图像。为方便起见,节点的组织与创建节点菜单中的类别相同。

分类目录

Artistic(艺术)Channel(通道)
Input(输入)Master(主节点)
Math(数学)Procedural(程序)
Utility(实用)UV
Patterns(图案)

Artistic

> Adjustment(调整)

Channel Mixer(通道混合器)

控制输入​​In的每个通道对每个输出通道的贡献量,节点上的滑块参数控制每个输入通道的贡献。切换按钮参数控制当前正在编辑哪个输出通道。滑块控件,用于编辑每个输入通道范围(介于-2和2之间)的贡献。

  • 端口
名字方向类型绑定描述
InInputVector 3None输入值
OutOutputVector 3None输出值
  • 控制项
名字类型选项描述
Toggle Button ArrayR, G, B选择要编辑的输出通道。
RSlider控制输入​​红色通道对所选输出通道的贡献。
GSlider控制输入​​绿色通道对所选输出通道的贡献。
BSlider控制输入​​蓝色通道对所选输出通道的贡献。
  • Shader Function 生成的代码示例

void Unity_ChannelMixer_float (float3 In, float3 Red, float3 Green, float3 Blue, out float3 Out)
{
    Out = float3(dot(In, Red), dot(In, Green), dot(In, Blue));
}

Contrast(对比度)

通过输入对比度的数量来调整输入In的对比度,对比度值为1将使输入保持不变,对比度值0将返回输入的中点。

  • 端口
名字方向类型绑定描述
InInputVector 3None输入值
ContrastInputVector 1None对比值
OutOutputVector 3None输出值
  • 生成的代码示例
void Unity_Contrast_float(float3 In, float Contrast, out float3 Out)
{
    float midpoint = pow(0.5, 2.2);
    Out =  (In - midpoint) * Contrast + midpoint;
}

Hue(色调)

通过输入偏移量来偏移输入In的色调,偏移量的单位可以通过参数Range设置。角度偏差在-180到180范围内。在弧度中,它是-Pi到Pi。

  •  端口
名字方向类型绑定描述
InInputVector 3None输入值
OffsetInputVector 1None抵消色调量
OutOutputVector 3None输出值
  • 控制项
名字类型选项描述
RangeDropdownDegrees、Normalized输入偏移量的单位
  • 生成的代码示例

 Degrees

void Unity_Hue_Degrees_float(float3 In, float Offset, out float3 Out)
{
    // RGB to HSV
    float4 K = float4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
    float4 P = lerp(float4(In.bg, K.wz), float4(In.gb, K.xy), step(In.b, In.g));
    float4 Q = lerp(float4(P.xyw, In.r), float4(In.r, P.yzx), step(P.x, In.r));
    float D = Q.x - min(Q.w, Q.y);
    float E = 1e-4;
    float3 hsv = float3(abs(Q.z + (Q.w - Q.y)/(6.0 * D + E)), D / (Q.x + E), Q.x);

    float hue = hsv.x + Offset / 360;
    hsv.x = (hue < 0)
            ? hue + 1
            : (hue > 1)
                ? hue - 1
                : hue;

    // HSV to RGB
    float4 K2 = float4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
    float3 P2 = abs(frac(hsv.xxx + K2.xyz) * 6.0 - K2.www);
    Out = hsv.z * lerp(K2.xxx, saturate(P2 - K2.xxx), hsv.y);
}

Normalized

void Unity_Hue_Normalized_float(float3 In, float Offset, out float3 Out)
{
    // RGB to HSV
    float4 K = float4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
    float4 P = lerp(float4(In.bg, K.wz), float4(In.gb, K.xy), step(In.b, In.g));
    float4 Q = lerp(float4(P.xyw, In.r), float4(In.r, P.yzx), step(P.x, In.r));
    float D = Q.x - min(Q.w, Q.y);
    float E = 1e-4;
    float3 hsv = float3(abs(Q.z + (Q.w - Q.y)/(6.0 * D + E)), D / (Q.x + E), Q.x);

    float hue = hsv.x + Offset;
    hsv.x = (hue < 0)
            ? hue + 1
            : (hue > 1)
                ? hue - 1
                : hue;

    // HSV to RGB
    float4 K2 = float4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
    float3 P2 = abs(frac(hsv.xxx + K2.xyz) * 6.0 - K2.www);
    Out = hsv.z * lerp(K2.xxx, saturate(P2 - K2.xxx), hsv.y);
}

Invert Colors(反转颜色)

在每个通道的基础上反转输入In的颜色,该节点假定所有输入值都在0-1的范围内。

  • 端口
名字方向类型绑定描述
InInputDynamic VectorNone输入值
OutOutputDynamic VectorNone输出值
  • 控制项
名字类型选项描述
RedToggleTrue、 False如果True,红色通道反转。
GreenToggleTrue、False如果True,绿色通道反转。如果输入向量尺寸小于2,则禁用。
BlueToggleTrue、 False如果True,蓝色通道反转。如果输入向量尺寸小于3,则禁用。
AlphaToggleTrue、 False如果True,Alpha通道倒置。如果输入向量尺寸小于4,则禁用。
  •  生成的代码示例
void Unity_InvertColors_float(float In, float InvertColors, out float Out)
{
    Out = abs(InvertColors - In);
}

Replace Color(更换颜色)

将输入In中的值替换为输入From至输入To的值,输入范围(Range)可用于在输入从到替换周围定义更大范围的值。输入模糊(Fuzziness)可用于柔化选区周围的边缘,类似于抗锯齿。

  • 端口
名字方向类型绑定描述
InInputVector 3None输入值
FromInputVector 3Color颜色替换
ToInputVector 3Color颜色替换
RangeInputVector 1None从输入From替换此范围内的颜色
FuzzinessInputVector 1None柔化选区周围的边缘
OutOutputVector 3None输出值
  • 生成的代码示例 
void Unity_ReplaceColor_float(float3 In, float3 From, float3 To, float Range, out float3 Out, float Fuzziness)
{
    float Distance = distance(From, In);
    Out = lerp(To, In, saturate((Distance - Range) / max(Fuzziness, 1e-5f)));
}

Saturation(饱和度)

通过输入饱和度的数量来调整输入In的饱和度,饱和度值为1时,输入将保持不变。饱和度值为0将使输入完全失去饱和。

  • 端口
名字方向类型绑定描述
InInputVector 3None输入值
SaturationInputVector 1None饱和度值
OutOutputVector 3None输出值
  • 生成的代码示例
void Unity_Saturation_float(float3 In, float Saturation, out float3 Out)
{
    float luma = dot(In, float3(0.2126729, 0.7151522, 0.0721750));
    Out =  luma.xxx + Saturation.xxx * (In - luma.xxx);
}

White Balance(白色平衡)

分别通过输入Temperature和Tint的数量来调整输入In的Temperature和Tint,Temperature具有将值移向黄色或蓝色的效果。Tint具有变粉红色或绿色的效果。

  • 端口
NameDirectionTypeBindingDescription
InInputVector 3None输入值
TemperatureInputVector 1None温度偏移值
TintInputVector 1None着色偏移值
OutOutputVector 3None输出值
  • 生成的代码示例
void Unity_WhiteBalance_float(float3 In, float Temperature, float Tint, out float3 Out)
{
        // Range ~[-1.67;1.67] works best
        float t1 = Temperature * 10 / 6;
        float t2 = Tint * 10 / 6;

        // Get the CIE xy chromaticity of the reference white point.
        // Note: 0.31271 = x value on the D65 white point
        float x = 0.31271 - t1 * (t1 < 0 ? 0.1 : 0.05);
        float standardIlluminantY = 2.87 * x - 3 * x * x - 0.27509507;
        float y = standardIlluminantY + t2 * 0.05;

        // Calculate the coefficients in the LMS space.
        float3 w1 = float3(0.949237, 1.03542, 1.08728); // D65 white point

        // CIExyToLMS
        float Y = 1;
        float X = Y * x / y;
        float Z = Y * (1 - x - y) / y;
        float L = 0.7328 * X + 0.4296 * Y - 0.1624 * Z;
        float M = -0.7036 * X + 1.6975 * Y + 0.0061 * Z;
        float S = 0.0030 * X + 0.0136 * Y + 0.9834 * Z;
        float3 w2 = float3(L, M, S);

        float3 balance = float3(w1.x / w2.x, w1.y / w2.y, w1.z / w2.z);

        float3x3 LIN_2_LMS_MAT = {
        3.90405e-1, 5.49941e-1, 8.92632e-3,
        7.08416e-2, 9.63172e-1, 1.35775e-3,
        2.31082e-2, 1.28021e-1, 9.36245e-1
    };

        float3x3 LMS_2_LIN_MAT = {
        2.85847e+0, -1.62879e+0, -2.48910e-2,
        -2.10182e-1,  1.15820e+0,  3.24281e-4,
        -4.18120e-2, -1.18169e-1,  1.06867e+0
    };

    float3 lms = mul(LIN_2_LMS_MAT, In);
    lms *= balance;
    Out = mul(LMS_2_LIN_MAT, lms);
}

> Blend(混合)

Blend(混合)

使用参数Mode定义的混合模式将输入Blend的值混合到输入Base上,混合的强度由输入不透明度定义。不透明度值为0时,将不变地返回输入Base。

  • 端口
名字方向类型绑定描述
BaseInputDynamic VectorNone基本层值
BlendInputDynamic VectorNone混合层值
OpacityInputVector 1None混合强度
OutOutputDynamic VectorNone输出值
  •  控制项
名字类型选项描述
ModeDropdownBurn, Darken, Difference, Dodge, Divide, Exclusion, HardLight, HardMix, Lighten, LinearBurn, LinearDodge, LinearLight, LinearLightAddSub, Multiply, Negation, Overlay, PinLight, Screen, SoftLight, Subtract, VividLight, Overwrite混合模式应用
  •  生成的代码示例

Burn(燃烧)

void Unity_Blend_Burn_float4(float4 Base, float4 Blend, float Opacity, out float4 Out)
{
    Out =  1.0 - (1.0 - Blend)/Base;
    Out = lerp(Base, Out, Opacity);
}

 Darken(变暗)

void Unity_Blend_Darken_float4(float4 Base, float4 Blend, float Opacity, out float4 Out)
{
    Out = min(Blend, Base);
    Out = lerp(Base, Out, Opacity);
}

Difference(差异)

void Unity_Blend_Difference_float4(float4 Base, float4 Blend, float Opacity, out float4 Out)
{
    Out = abs(Blend - Base);
    Out = lerp(Base, Out, Opacity);
}

Dodge(躲闪)

void Unity_Blend_Dodge_float4(float4 Base, float4 Blend, float Opacity, out float4 Out)
{
    Out = Base / (1.0 - Blend);
    Out = lerp(Base, Out, Opacity);
}

Divide(分裂)

void Unity_Blend_Divide_float4(float4 Base, float4 Blend, float Opacity, out float4 Out)
{
    Out = Base / (Blend + 0.000000000001);
    Out = lerp(Base, Out, Opacity);
}

Exclusion(排除)

void Unity_Blend_Exclusion_float4(float4 Base, float4 Blend, float Opacity, out float4 Out)
{
    Out = Blend + Base - (2.0 * Blend * Base);
    Out = lerp(Base, Out, Opacity);
}

HardLight(强光)

void Unity_Blend_HardLight_float4(float4 Base, float4 Blend, float Opacity, out float4 Out)
{
    float4 result1 = 1.0 - 2.0 * (1.0 - Base) * (1.0 - Blend);
    float4 result2 = 2.0 * Base * Blend;
    float4 zeroOrOne = step(Blend, 0.5);
    Out = result2 * zeroOrOne + (1 - zeroOrOne) * result1;
    Out = lerp(Base, Out, Opacity);
}

HardMix(硬混合)

void Unity_Blend_HardMix_float4(float4 Base, float4 Blend, float Opacity, out float4 Out)
{
    Out = step(1 - Base, Blend);
    Out = lerp(Base, Out, Opacity);
}

Lighten(减轻)

void Unity_Blend_Lighten_float4(float4 Base, float4 Blend, float Opacity, out float4 Out)
{
    Out = max(Blend, Base);
    Out = lerp(Base, Out, Opacity);
}

LinearBurn(线性燃烧)

void Unity_Blend_LinearBurn_float4(float4 Base, float4 Blend, float Opacity, out float4 Out)
{
    Out = Base + Blend - 1.0;
    Out = lerp(Base, Out, Opacity);
}

LinearDodge(线性躲闪)

void Unity_Blend_LinearDodge_float4(float4 Base, float4 Blend, float Opacity, out float4 Out)
{
    Out = Base + Blend;
    Out = lerp(Base, Out, Opacity);
}

LinearLight(线性光)

void Unity_Blend_LinearLight_float4(float4 Base, float4 Blend, float Opacity, out float4 Out)
{
    Out = Blend < 0.5 ? max(Base + (2 * Blend) - 1, 0) : min(Base + 2 * (Blend - 0.5), 1);
    Out = lerp(Base, Out, Opacity);
}

LinearLightAddSub

void Unity_Blend_LinearLightAddSub_float4(float4 Base, float4 Blend, float Opacity, out float4 Out)
{
    Out = Blend + 2.0 * Base - 1.0;
    Out = lerp(Base, Out, Opacity);
}

Multiply(乘)

void Unity_Blend_Multiply_float4(float4 Base, float4 Blend, float Opacity, out float4 Out)
{
    Out = Base * Blend;
    Out = lerp(Base, Out, Opacity);
}

Negation(否定)

void Unity_Blend_Negation_float4(float4 Base, float4 Blend, float Opacity, out float4 Out)
{
    Out = 1.0 - abs(1.0 - Blend - Base);
    Out = lerp(Base, Out, Opacity);
}

Overlay(覆盖)

void Unity_Blend_Overlay_float4(float4 Base, float4 Blend, float Opacity, out float4 Out)
{
    float4 result1 = 1.0 - 2.0 * (1.0 - Base) * (1.0 - Blend);
    float4 result2 = 2.0 * Base * Blend;
    float4 zeroOrOne = step(Base, 0.5);
    Out = result2 * zeroOrOne + (1 - zeroOrOne) * result1;
    Out = lerp(Base, Out, Opacity);
}

PinLight(针灯)

void Unity_Blend_PinLight_float4(float4 Base, float4 Blend, float Opacity, out float4 Out)
{
    float4 check = step (0.5, Blend);
    float4 result1 = check * max(2.0 * (Base - 0.5), Blend);
    Out = result1 + (1.0 - check) * min(2.0 * Base, Blend);
    Out = lerp(Base, Out, Opacity);
}

Screen(屏幕)

void Unity_Blend_Screen_float4(float4 Base, float4 Blend, float Opacity, out float4 Out)
{
    Out = 1.0 - (1.0 - Blend) * (1.0 - Base);
    Out = lerp(Base, Out, Opacity);
}

SoftLight(柔光)

void Unity_Blend_SoftLight_float4(float4 Base, float4 Blend, float Opacity, out float4 Out)
{
    float4 result1 = 2.0 * Base * Blend + Base * Base * (1.0 - 2.0 * Blend);
    float4 result2 = sqrt(Base) * (2.0 * Blend - 1.0) + 2.0 * Base * (1.0 - Blend);
    float4 zeroOrOne = step(0.5, Blend);
    Out = result2 * zeroOrOne + (1 - zeroOrOne) * result1;
    Out = lerp(Base, Out, Opacity);
}

Subtract(减去)

void Unity_Blend_Subtract_float4(float4 Base, float4 Blend, float Opacity, out float4 Out)
{
    Out = Base - Blend;
    Out = lerp(Base, Out, Opacity);
}

VividLight(生动光)

void Unity_Blend_VividLight_float4(float4 Base, float4 Blend, float Opacity, out float4 Out)
{
    float4 result1 = 1.0 - (1.0 - Blend) / (2.0 * Base);
    float4 result2 = Blend / (2.0 * (1.0 - Base));
    float4 zeroOrOne = step(0.5, Base);
    Out = result2 * zeroOrOne + (1 - zeroOrOne) * result1;
    Out = lerp(Base, Out, Opacity);
}

Overwrite(重写)

void Unity_Blend_Overwrite_float4(float4 Base, float4 Blend, float Opacity, out float4 Out)
{
    Out = lerp(Base, Blend, Opacity);
}

> Filter(过滤)

Dither(抖动)

抖动是一种有意的噪声形式,用于随机化量化误差,它用于防止大规模图案,例如图像中的色带。抖动节点在屏幕空间中应用抖动,以确保图案的均匀分布。可以通过将另一个节点连接到输入屏幕位置来进行调整。

该节点通常用作主节点上Alpha剪辑阈值的输入,以使不透明对象具有透明外观。这对于创建看起来透明但具有渲染为不透明(例如写作深度和/或延迟渲染)的优点很有用。

  • 端口
名字方向类型绑定描述
InInputDynamic VectorNone输入值
Screen PositionInputVector 4Screen Position用于应用抖动模式的坐标
OutOutputDynamic VectorNone输出值
  • 生成的代码示例
void Unity_Dither_float4(float4 In, float4 ScreenPosition, out float4 Out)
{
    float2 uv = ScreenPosition.xy * _ScreenParams.xy;
    float DITHER_THRESHOLDS[16] =
    {
        1.0 / 17.0,  9.0 / 17.0,  3.0 / 17.0, 11.0 / 17.0,
        13.0 / 17.0,  5.0 / 17.0, 15.0 / 17.0,  7.0 / 17.0,
        4.0 / 17.0, 12.0 / 17.0,  2.0 / 17.0, 10.0 / 17.0,
        16.0 / 17.0,  8.0 / 17.0, 14.0 / 17.0,  6.0 / 17.0
    };
    uint index = (uint(uv.x) % 4) * 4 + uint(uv.y) % 4;
    Out = In - DITHER_THRESHOLDS[index];
}

> Mask(遮罩)

Channel Mask(通道遮罩)

在下拉通道中选择的通道上屏蔽输入In的值,输出与输入向量长度相同的向量,但所选通道设置为0。下拉通道中可用的通道通道表示输入In中存在的通道数量。

  • 端口
名字方向类型绑定描述
InInputDynamic VectorNone输入值
OutOutputDynamic VectorNone输出值
  •  控制项
名字类型选项描述
ChannelsMask DropdownNothing、Everything、Red选择任意数量的要掩盖的通道
  •  生成的代码示例
void Unity_ChannelMask_RedGreen_float4(float4 In, out float4 Out)
{
    Out = float4(0, 0, In.b, In.a);
}

Color Mask(颜色遮罩)

根据输入In中等于输入蒙版颜色的值创建一个蒙版,输入范围可用于在输入“蒙版颜色”周围定义更大范围的值,以创建蒙版。此范围内的颜色将返回1,否则该节点将返回0。输入模糊可用于柔化选区周围的边缘,类似于抗锯齿。

  • 端口
名字方向类型绑定描述
InInputVector 3None输入值
Mask ColorInputVector 3Color遮罩使用的颜色
RangeInputVector 1None从输入蒙版颜色中选择此范围内的颜色
FuzzinessInputVector 1None选择周围的羽毛边缘,较高的值会导致选择蒙版变软
OutOutputVector 1None输出遮罩值
  •  生成的代码示例
void Unity_ColorMask_float(float3 In, float3 MaskColor, float Range, float Fuzziness, out float4 Out)
{
    float Distance = distance(MaskColor, In);
    Out = saturate(1 - (Distance - Range) / max(Fuzziness, 1e-5));
}

> Normal(正常)

Normal Blend

将由输入A和B定义的两个法线贴图混合在一起,对结果进行规范化以创建有效的法线贴图。

  • 端口
名字方向类型绑定描述
AInputVector 3None第一输入值
BInputVector 3None第二输入值
OutOutputVector 3None输出值
  • 控制项
名字类型选项描述
ModeDropdownDefault、Reoriented(重定向)S选择用于混合的方法
  • 生成的代码示例

 Default

void Unity_NormalBlend_float(float3 A, float3 B, out float3 Out)
{
    Out = normalize(float3(A.rg + B.rg, A.b * B.b));
}

Reoriented

void Unity_NormalBlend_Reoriented_float(float3 A, float3 B, out float3 Out)
{
    float3 t = A.xyz + float3(0.0, 0.0, 1.0);
    float3 u = B.xyz * float3(-1.0, -1.0, 1.0);
    Out = (t / t.z) * dot(t, u) - u;
}

Normal From Height

 根据输入Input定义的高度值创建法线贴图。

  • 端口
名字方向类型描述
InInputVector 1输入高度值
OutOutputVector 3输出值
  • 控制项
名字类型选项描述
Output SpaceDropdownTangent、 World设置输出法线的坐标空间。
  • 生成的代码示例

 Tangent

void Unity_NormalFromHeight_Tangent(float In, out float3 Out)
{
    float3 worldDirivativeX = ddx(Position * 100);
    float3 worldDirivativeY = ddy(Position * 100);
    float3 crossX = cross(TangentMatrix[2].xyz, worldDirivativeX);
    float3 crossY = cross(TangentMatrix[2].xyz, worldDirivativeY);
    float3 d = abs(dot(crossY, worldDirivativeX));
    float3 inToNormal = ((((In + ddx(In)) - In) * crossY) + (((In + ddy(In)) - In) * crossX)) * sign(d);
    inToNormal.y *= -1.0;
    Out = normalize((d * TangentMatrix[2].xyz) - inToNormal);
    Out = TransformWorldToTangent(Out, TangentMatrix);
}

World

void Unity_NormalFromHeight_World(float In, out float3 Out)
{
    float3 worldDirivativeX = ddx(Position * 100);
    float3 worldDirivativeY = ddy(Position * 100);
    float3 crossX = cross(TangentMatrix[2].xyz, worldDirivativeX);
    float3 crossY = cross(TangentMatrix[2].xyz, worldDirivativeY);
    float3 d = abs(dot(crossY, worldDirivativeX));
    float3 inToNormal = ((((In + ddx(In)) - In) * crossY) + (((In + ddy(In)) - In) * crossX)) * sign(d);
    inToNormal.y *= -1.0;
    Out = normalize((d * TangentMatrix[2].xyz) - inToNormal);
}

Normal From Texture

 将由输入Texture定义的高度图转换为法线图。 UV值和采样器状态可以分别通过输入UV和采样器定义。如果这些端口上没有任何连接,它们将使用输入中的默认值。有关更多信息,请参见端口绑定。

可以通过输入“偏移”和“强度”来定义创建的法线贴图的强度,其中“偏移”定义法线详图的最大距离,“强度”充当结果的乘数。

  • 端口
名字方向类型绑定描述
TextureInputTextureNone高度图
UVInputVector 2UV纹理坐标
SamplerInputSampler StateNone纹理采样器
OffsetInputVector 1None抵消样本数量
StrengthInputVector 1None力量倍增
OutOutputVector 3None输出值
  • 生成的代码示例
void Unity_NormalFromTexture_float(Texture texture, SamplerState Sampler, float2 UV, float Offset, float Strength, out float3 Out)
{
    Offset = pow(Offset, 3) * 0.1;
    float2 offsetU = float2(UV.x + Offset, UV.y);
    float2 offsetV = float2(UV.x, UV.y + Offset);
    float normalSample = Texture.Sample(Sampler, UV);
    float uSample = Texture.Sample(Sampler, offsetU);
    float vSample = Texture.Sample(Sampler, offsetV);
    float3 va = float3(1, 0, (uSample - normalSample) * Strength);
    float3 vb = float3(0, 1, (vSample - normalSample) * Strength);
    Out = normalize(cross(va, vb));
}

Normal Reconstruct Z

 使用输入In中给定的X值和Y值,为生成的法线贴图得出正确的Z值。

  • 端口
名字方向类型描述
InInputVector 2正常的X和Y值
OutOutputVector 3输出值
  • 生成的代码示例
void Unity_NormalReconstructZ_float(float2 In, out float3 Out)
{
    float reconstructZ = sqrt(1.0 - saturate(dot(In.xy, In.xy)));
    float3 normalVector = float3(In.x, In.y, reconstructZ);
    Out = normalize(normalVector);
}

Normal Strength

 通过输入强度的数量来调整由输入In定义的法线贴图的强度。强度值1将返回不变的输入。强度值0将返回空白的法线贴图。

  • 端口
名字方向类型绑定描述
InInputVector 3None输入值
StrengthInputVector 1None强度值
OutOutputVector 3None输出值
  • 生成的代码示例
void Unity_NormalStrength_float(float3 In, float Strength, out float3 Out)
{
    Out = {precision}3(In.rg * Strength, lerp(1, In.b, saturate(Strength)));
}

Normal Unpack

解压缩由输入In定义的法线贴图。该节点用于对采样为默认纹理的纹理进行解压缩,该纹理在其“纹理导入设置”中定义为“法线贴图”。

请注意,在大多数情况下,此节点是不必要的,因为当使用Sample Texture 2D或Triplanar节点采样法线贴图时,应通过将其Type参数设置为Normal来采样法线贴图。

  • 端口
名字方向类型绑定描述
InInputVector 4None输入值
OutOutputVector 3None输出值
  •  控制项
名字类型选项描述
SpaceDropdownTangent、Object设置输入法线的坐标空间。
  • 生成的代码示例

Tangent

void Unity_NormalUnpack_float(float4 In, out float3 Out)
{
    Out = UnpackNormalmapRGorAG(In);
}

 Object

void Unity_NormalUnpackRGB_float(float4 In, out float3 Out)
{
    Out = UnpackNormalmapRGB(In);
}

> Utility(效用)

Colorspace Conversion

返回将输入In的值从一个色彩空间转换为另一色彩空间的结果。从节点转换到的空间由节点上的下拉列表的值定义。

  • 端口
名字方向类型描述
InInputVector 3输入值
OutOutputVector 3输出值
  •  控制项
名字类型选项描述
FromDropdownRGB, Linear, HSV选择要转换的色彩空间
ToDropdownRGB, Linear, HSV选择要转换为的色彩空间
  •  生成的代码示例

RGB > RGB

void Unity_ColorspaceConversion_RGB_RGB_float(float3 In, out float3 Out)
{
    Out =  In;
}

RGB > Linear

void Unity_ColorspaceConversion_RGB_Linear_float(float3 In, out float3 Out)
{
    float3 linearRGBLo = In / 12.92;
    float3 linearRGBHi = pow(max(abs((In + 0.055) / 1.055), 1.192092896e-07), float3(2.4, 2.4, 2.4));
    Out = float3(In <= 0.04045) ? linearRGBLo : linearRGBHi;
}

RGB > HSV

void Unity_ColorspaceConversion_RGB_HSV_float(float3 In, out float3 Out)
{
    float4 K = float4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
    float4 P = lerp(float4(In.bg, K.wz), float4(In.gb, K.xy), step(In.b, In.g));
    float4 Q = lerp(float4(P.xyw, In.r), float4(In.r, P.yzx), step(P.x, In.r));
    float D = Q.x - min(Q.w, Q.y);
    float  E = 1e-10;
    Out = float3(abs(Q.z + (Q.w - Q.y)/(6.0 * D + E)), D / (Q.x + E), Q.x);
}

Linear > RGB

void Unity_ColorspaceConversion_Linear_RGB_float(float3 In, out float3 Out)
{
    float3 sRGBLo = In * 12.92;
    float3 sRGBHi = (pow(max(abs(In), 1.192092896e-07), float3(1.0 / 2.4, 1.0 / 2.4, 1.0 / 2.4)) * 1.055) - 0.055;
    Out = float3(In <= 0.0031308) ? sRGBLo : sRGBHi;
}

Linear > Linear

void Unity_ColorspaceConversion_Linear_Linear_float(float3 In, out float3 Out)
{
    Out = In;
}

Linear > HSV

void Unity_ColorspaceConversion_Linear_HSV_float(float3 In, out float3 Out)
{
    float3 sRGBLo = In * 12.92;
    float3 sRGBHi = (pow(max(abs(In), 1.192092896e-07), float3(1.0 / 2.4, 1.0 / 2.4, 1.0 / 2.4)) * 1.055) - 0.055;
    float3 Linear = float3(In <= 0.0031308) ? sRGBLo : sRGBHi;
    float4 K = float4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
    float4 P = lerp(float4(Linear.bg, K.wz), float4(Linear.gb, K.xy), step(Linear.b, Linear.g));
    float4 Q = lerp(float4(P.xyw, Linear.r), float4(Linear.r, P.yzx), step(P.x, Linear.r));
    float D = Q.x - min(Q.w, Q.y);
    float  E = 1e-10;
    Out = float3(abs(Q.z + (Q.w - Q.y)/(6.0 * D + E)), D / (Q.x + E), Q.x);
}

HSV > RGB

void Unity_ColorspaceConversion_HSV_RGB_float(float3 In, out float3 Out)
{
    float4 K = float4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
    float3 P = abs(frac(In.xxx + K.xyz) * 6.0 - K.www);
    Out = In.z * lerp(K.xxx, saturate(P - K.xxx), In.y);
}

HSV > Linear

void Unity_ColorspaceConversion_HSV_Linear_float(float3 In, out float3 Out)
{
    float4 K = float4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
    float3 P = abs(frac(In.xxx + K.xyz) * 6.0 - K.www);
    float3 RGB = In.z * lerp(K.xxx, saturate(P - K.xxx), In.y);
    float3 linearRGBLo = RGB / 12.92;
    float3 linearRGBHi = pow(max(abs((RGB + 0.055) / 1.055), 1.192092896e-07), float3(2.4, 2.4, 2.4));
    Out = float3(RGB <= 0.04045) ? linearRGBLo : linearRGBHi;
}

HSV > HSV

void Unity_ColorspaceConversion_HSV_HSV_float(float3 In, out float3 Out)
{
    Out = In;
}

Channel(通道)

待续......

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Kevin_Erics

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值