目录索引
译文
为了测试由 Shader Graph 构建的着色器,我们接下来将使用 URP。
我们将从安装 Shader Graph 包开始,从 Unity 的项目界面创建无光照 Shader Graph(路径:Create/Shader/Universal Render Pipeline)。
接着,创建一个名为 USB_simple_color_SG 的 Shader Graph,就像我们在第 3.0.1 小节中创建第一个着色器 USB_simple_color 进行学习那样。两个着色器所实现的功能相同,只不过现在我们是通过节点而不是代码进行编写的。
创建完成之后,我们发现新建的 Shader Graph 文件以“.shadergraph”而非先前的“.shader”为后缀名,它的文件图标也和我们之前创建的着色器有所不同。
需要注意的是,类似于我们之前编写的 ShaderLab 着色器,我们也可以在检查器中修改 Shader Graph 的路径。
通常新建 Shader Graph 着色器,其默认路径在 Shader Graphs 下。如果我们想要修改路径,我们可以直接在 Blackboard 中进行修改(位于着色器名称下方,如下图所示)。
![图片[1]-《Unity着色器圣经》9.0.4 | 我们的第一个Shader Graph-软件开发学习笔记](https://gamedevfan.cn/wp-content/uploads/2025/05/image-120-1024x401.jpeg)
上面的操作与我们在“.shader”后缀的文件中修改路径是一样的。
Shader "Shader Graphs/USB_simple_color_SG"
{
Properties { ... }
SubShader { ... }
}
![图片[2]-《Unity着色器圣经》9.0.4 | 我们的第一个Shader Graph-软件开发学习笔记](https://gamedevfan.cn/wp-content/uploads/2025/05/image-119-1024x401.jpeg)
正如我们在先前的章节中所学习的,每次我们创建无光照着色器时,Unity会自动添加一个名为 _MainTex 的纹理,但 Shader Graph 并不会这么做。通常在我们新建 Shader Graph 时,Blackboard的属性是空的,我们需要根据自己的需求自行添加每一个属性。
双击打开我们刚才创建的 USB_simple_color_SG 着色器。在 ShaderLab 中,属性是添加在属性(Properties)语义块中的;而在 Shader Graph 中,我们通过左侧 Blackboard 面板中的“加号”按钮创建属性。
![图片[3]-《Unity着色器圣经》9.0.4 | 我们的第一个Shader Graph-软件开发学习笔记](https://gamedevfan.cn/wp-content/uploads/2025/05/image-118-1024x556.jpeg)
在开始连连看之前,我们先简单介绍一下 Shader Graph 中顶点/片元着色器的工作原理。
在顶点着色器中有三个预定义的输入节点:Position(3)、Normal(3) 和 Tangent(3),对应于顶点输入结构体中的 POSITION[n]、 NORMAL[n] 和 TANGENT[n] 语义。
![图片[4]-《Unity着色器圣经》9.0.4 | 我们的第一个Shader Graph-软件开发学习笔记](https://gamedevfan.cn/wp-content/uploads/2025/05/image-117-1024x397.jpeg)
括号里的数字指的是所拥有的维数,因此 Position(3) 等于模型空间中的 Position.xyz。
为什么 Shader Graph 的 Position 只有三维但 Cg / HLSL 中有四维呢?
第四个维度,通常写作 W 或 A ,在多数情况下为 0 或 1。当 W 分量等于 1 时代表空间中的“点”;当 W 分量等于 0 时代表空间中的向量。
因此,我们可以得出这样的结论:某个顶点的位置是 float4(X,Y,Z,1)、法线是 float4(X,Y,Z,0)、切线是 float4(X,Y,Z,0)(切线和法线都是空间中的一个方向,因此 W 分量为0)。
绝大多数 Shader Graph 中的函数都和以“.shader”结尾的 HLSL 代码存在对应关系。
在开始连连看之前,我们需要在 Blackboard 中创建两个属性:一个名为 _Color 的颜色类型属性和一个名为 _MainTex 的 Texture2D 类型属性。
![图片[5]-《Unity着色器圣经》9.0.4 | 我们的第一个Shader Graph-软件开发学习笔记](https://gamedevfan.cn/wp-content/uploads/2025/05/image-116-1024x398.jpeg)
有一个经常问的问题是:_Color 和 _MainTex 的默认值是什么?
当我们在 ShaderLab 中声明属性时,我们可以直接定义它的默认值(例如 (1, 1, 1, 1), “white”),然而在 Shader Graph 中则不然。_Color的默认值是黑色 (0, 0, 0, 1)的,我们可以在图检查器(Graph Inspector)面板下的节点设置(Node Setting)选项卡中修改属性的默认值(Default),如下图所示。
![图片[6]-《Unity着色器圣经》9.0.4 | 我们的第一个Shader Graph-软件开发学习笔记](https://gamedevfan.cn/wp-content/uploads/2025/05/image-115-1024x437.jpeg)
_MainTex 属性也是如此,在图检查器(Graph Inspector)面板下的节点设置(Node Setting)选项卡中我们可以选择它的模式(Mode),默认设置为白色。
在 ShaderLab 代码中,如果我们想要在程序中使用属性语义块中的属性,就需要在 CGPROGRAM 语义块中声明它们的连接变量。
这一步在 Shader Graph 不同,我们需要做的是将属性从 Blackboard 拖拽到连线界面中。
![图片[7]-《Unity着色器圣经》9.0.4 | 我们的第一个Shader Graph-软件开发学习笔记](https://gamedevfan.cn/wp-content/uploads/2025/05/image-114-1024x393.jpeg)
在第一章的第 3.2.7 小节中,我们在声明纹理时还要声明对应的采样器(sample)并用 tex2D 函数采样。这一操作在 Shader Graph 中对应于 Sample Texture 2D 节点,如果我们想要创建这个节点,可以按照以下方法:
- 在连线界面按空格键,输入需要的节点名称,寻找所要的节点(Sample Texture 2D)
- 右键,选择“创建节点(Create Node)”,找到我们需要的节点
要使 Texture2D 类型的纹理与 Sample Texture 2D 节点配合使用,我们需要做的就是将 _MainTex 属性与 Sample Texture 2D 中的 Texture(T2) 输入相连接,如下图所示。
![图片[8]-《Unity着色器圣经》9.0.4 | 我们的第一个Shader Graph-软件开发学习笔记](https://gamedevfan.cn/wp-content/uploads/2025/05/image-113-1024x397.jpeg)
这一操作等同于创建一个四维向量 col,并将纹理 _MainTex 和 uv 坐标输入 tex2D 函数,并将结果传给它(float4 col = tex2D(_MainTex, i.uv))。
如果我们想改变纹理的色调,只需将 2D Sample Texture 节点的 RGBA 输出乘以 _Color 属性即可。这样,当颜色为黑色时,纹理将变为黑色;当颜色为白色时,纹理将变为默认颜色。
![图片[9]-《Unity着色器圣经》9.0.4 | 我们的第一个Shader Graph-软件开发学习笔记](https://gamedevfan.cn/wp-content/uploads/2025/05/image-112-1024x398.jpeg)
要将两个节点相乘,我们可以在界面中创建一个乘法(Multiply)节点,并将两个节点的值作为节点输入。最后,将乘法节点的输出连接到片元着色器中的 Base Color。操作完成后,我们需要点击 Shader Graph 界面左上方的“保存资产(Svae Asset)”按钮来保存着色器。
![图片[10]-《Unity着色器圣经》9.0.4 | 我们的第一个Shader Graph-软件开发学习笔记](https://gamedevfan.cn/wp-content/uploads/2025/05/image-111-1024x396.jpeg)
我们必须考虑的一点是,Base Color 对应的是最终输入着色器的 RGB 颜色,是片元着色器阶段中发生的操作的一部分。这意味着最终的颜色输出(如颜色 + Alpha + 混合)将等同于“.shader”中的 SV_Target 语义。
下一节我们将学习如何在 Shader Graph 中加入更多操作。
原文对照
To test our shaders, we will work with Universal RP.
We will start our adventure by going to the Unity Project window and creating an Unlit Shader Graph, located by the following route: Create / Shader / Universal Render Pipeline. Please note: this route will only be visible if we have the Shader Graph package included in our project.
Next, we will recreate in Shader Graph the USB_simple_color shader that we started in section 3.0.1. To do this, we will name this new shader USB_simple_color_SG since it will have the same characteristics, although now being created through nodes instead of code.
At first glance, the first difference we see between both programs is that the first one has a “.shader” extension, while the second has “.shadergraph”. Likewise, the presentation icon in each case has a graphic variation that is used to differentiate its nature.
It should be noted that, as in previous programs, in Shader Graph we can also modify the path in the Inspector.
By default, all the shaders that we create with this interface will be saved in the Shader Graphs path, however, if we want to modify their destination, we can do it directly from the access to the path which is found in the Blackboard, under the name of the shader.
![图片[1]-《Unity着色器圣经》9.0.4 | 我们的第一个Shader Graph-软件开发学习笔记](https://gamedevfan.cn/wp-content/uploads/2025/05/image-120-1024x401.jpeg)
The above operation is the equivalent to changing the path of a program with the “.shader” extension.
Shader "Shader Graphs/USB_simple_color_SG"
{
Properties { ... }
SubShader { ... }
}
![图片[2]-《Unity着色器圣经》9.0.4 | 我们的第一个Shader Graph-软件开发学习笔记](https://gamedevfan.cn/wp-content/uploads/2025/05/image-119-1024x401.jpeg)
As we could see in previous sections, every time we created an Unlit Shader, Unity added a default property corresponding to a texture called _MainTex. Shader Graph cannot do this. When we start the interface, the Blackboard, where properties are added, is empty by default. This means that we will have to add each property to the shader independently.
Open the shader USB_simple_color_SG by double-clicking on it. As we already know, in ShaderLab, the properties are added within the Properties’ field via code, however, in Shader Graph they are added from the Blackboard by pressing the plus button on the panel, which is on the left side of the interface.
![图片[3]-《Unity着色器圣经》9.0.4 | 我们的第一个Shader Graph-软件开发学习笔记](https://gamedevfan.cn/wp-content/uploads/2025/05/image-118-1024x556.jpeg)
Before starting, we will make a small introduction to the vertex/fragment shader stage to understand how it works with this interface.
As we can see, in the vertex shader stage there are three defined inputs which are: Position(3), Normal(3), Tangent(3), as in a Cg or HLSL shader. These inputs refer to the semantics that we can use in the vertex input, this means that Position(3) equals POSITION[n], Normal(3) equals NORMAL[n] and Tangent(3) equals TANGENT[n].
![图片[4]-《Unity着色器圣经》9.0.4 | 我们的第一个Shader Graph-软件开发学习笔记](https://gamedevfan.cn/wp-content/uploads/2025/05/image-117-1024x397.jpeg)
The value that precedes such inputs refers to the number of dimensions that it possesses, therefore Position(3) equals Position.xyz in object-space.
Why has Shader Graph got three dimensions but Cg or HLSL up to four?
Recall that the fourth dimension of a vector corresponds to its W component, which, in most cases, is “one or zero”. When W equals one, it means that the vector corresponds to a position in space or a point. Whereas, when W equals “zero” the vector corresponds to a direction in space.
Considering the above explanation, we can conclude that, if the input Position had four coordinates, then these would be, e.g., float4(X, Y, Z, 1) and for the Normals float4(X, Y, Z, 0), likewise for the Tangents that also correspond to a direction in space.
It is essential to understand this analogy since most of the functions, applications and properties in Shader Graph are based on the structure of a “.shader” in HLSL.
To start our program, the first thing we will do is go to the Blackboard and create two properties: a color type, which we will call _Color, and a Texture2D type; which we will call _MainTex.
![图片[5]-《Unity着色器圣经》9.0.4 | 我们的第一个Shader Graph-软件开发学习笔记](https://gamedevfan.cn/wp-content/uploads/2025/05/image-116-1024x398.jpeg)
A question that frequently arises is, what is the default color of our property _Color or even _MainTex?
When we declare a property in ShaderLab we can define its tonality by its value (e.g. (1, 1, 1, 1), “white”), however, in Shader Graph it is different. By default, our property _Color is black (0, 0, 0, 1), this can be corroborated by going to the Graph Inspector; Node Settings tab. If we look at the “Default” property, we will see that it is set to black.
![图片[6]-《Unity着色器圣经》9.0.4 | 我们的第一个Shader Graph-软件开发学习笔记](https://gamedevfan.cn/wp-content/uploads/2025/05/image-115-1024x437.jpeg)
We can select a different color by pressing the tonality bar (black bar) to change the color. For _MainTex it is exactly the same, within the Graph Inspector; Node Settings tab, we can select its “Mode”, which equals “white” by default.
To generate communication between the ShaderLab properties and our program, we must create connection variables within the CGPROGRAM field.
This process is different in Shader Graph. What we must do is drag the properties that we have in the Blackboard to the node area.
![图片[7]-《Unity着色器圣经》9.0.4 | 我们的第一个Shader Graph-软件开发学习笔记](https://gamedevfan.cn/wp-content/uploads/2025/05/image-114-1024x393.jpeg)
As we saw in chapter I, section 3.2.7, we must generate a sample for a texture to be projected onto an object. For this, there is the Sample Texture 2D node, which fulfills the function of tex2D. If we want to work with this node, we can do two actions:
1. Press the “space bar” on the node area and write the name of the node we are looking for; which in this case would be “Sample Texture 2D”, 2. Or right-click, select the Create Node option and find the node we want to work with.
All we have to do for the Texture2D type texture to work in conjunction with the Sample Texture 2D node, is to connect the output of the _MainTex property with the Texture(T2) type input, which is included in the Sample Texture 2D.
![图片[8]-《Unity着色器圣经》9.0.4 | 我们的第一个Shader Graph-软件开发学习笔记](https://gamedevfan.cn/wp-content/uploads/2025/05/image-113-1024x397.jpeg)
This operation is equivalent to creating a four-dimensional vector and passing both the texture and the uv coordinates input to it (e.g. float4 col = tex2D(_MainTex, i.uv)).
If we want to change the tint of the texture, all we have to do is multiply the 2D Sample Texture RGBA output by the _Color property output. In this way, when the color is black, the texture will be black, and when the color is white, the texture will be its default color.
![图片[9]-《Unity着色器圣经》9.0.4 | 我们的第一个Shader Graph-软件开发学习笔记](https://gamedevfan.cn/wp-content/uploads/2025/05/image-112-1024x398.jpeg)
To multiply both nodes, we must simply bring the Multiply node and pass both values as input. Finally, the color output (factor) of the previous operation must be connected to the Base Color found in the fragment shader stage. Once the operation is complete, we must save our shader by pressing the Save Asset button that is located at the top left of the Shader Graph interface.
![图片[10]-《Unity着色器圣经》9.0.4 | 我们的第一个Shader Graph-软件开发学习笔记](https://gamedevfan.cn/wp-content/uploads/2025/05/image-111-1024x396.jpeg)
Something we must consider is that the Base Color is an input that corresponds to the final RGB color of our shader and is part of the operations that are occurring within the fragment shader stage. This means that the final color output (e.g. color + alpha + blending) would equal the SV_Target semantics that we can find in a “.shader”.
Later we will see in detail how to add more operations in Shader Graph.
暂无评论内容