《Unity着色器圣经》4.0.5. | Debugging a shader.

目录索引

译文

当我们用C#编写脚本时,在Unity中,我们可以使用debug.Log函数调试程序。该函数允许我们在控制台上打印代码的操作,但是,该函数在Cg或HLSL中不可用。
那么我们如何调试着色器呢?为此,我们必须考虑几个因素,主要包含集中特殊的颜色。在着色器中,我们经常看到三种重要的颜色,它们是白色(1,1,1、1)、黑色(0,0,0、1)和品红色(1,0,1、2)。白色表示默认值,而黑色表示初始化值。品红色表示图形错误,事实上,资产导入Unity之后,在场景中显示成品红色是非常常见的。

图片[1]-《Unity着色器圣经》4.0.5. | Debugging a shader.-软件开发学习笔记

为了充分了解这个概念,让我们先回忆一下ShaderLab中Properties的声明方式,然后我们将重新创建一个颜色属性如下图。

_Color ("Tint", Color) = (1, 1, 1, 1)

在上面的例子中,默认情况下,属性是用颜色“白色”声明的,我们可以在这个四维向量(1,1,1,1)中确保这一点。此属性将在Unity Inspector中生成一个“颜色选择器”,其颜色和/或初始化值将为白色。

让我们分析另一个属性。

_MainTex ("Texture", 2D) = "white"{}

同样,这个属性将在Unity Inspector中生成一个“纹理选择器”,但如果我们不使用任何纹理,它的默认颜色是什么?它的颜色将是白色,我们可以在“白色”这个属性值确认这一点。

在我们的代码中,我们经常在内部向量和变量的声明中看到黑色,事实上,将向量初始化为“零”,然后添加一些操作是非常常见的,例如,四维向量“float4 col=0”已初始化为“0”,这意味着它的所有通道(RGBA)都将具有默认值零。

注意,白色表示一个像素的最大亮度,黑色表示其最小亮度。记住这一点很重要,因为随着我们的前进,我们将有一些操作超过最大值(x>1)和最小值(x<0)。在这些情况下,会出现颜色饱和,为此,我们将使用一些函数,如“clamp”,允许我们将值限制在两个数字(最小值和最大值)之间。

为什么我们的物体有时会出现品红色?正如我们已经知道的,这种颜色代表一种“图形错误”。基本上,当GPU无法执行着色器中的操作时,它会返回默认的品红色。在Unity中,这种颜色的原因主要有两个因素:

  1. 没有配置渲染管线
  2. shader有错误

当我们将资源导入unity的时候,我们需要知道的第一件事是,我们在哪个渲染管道中工作?请记住,在Unity中有三种类型的渲染管道,每种都有不同的配置。

假设我们在URP中导入一个包含具有标准曲面着色器的材质的资源,那么我们的资源将显示为品红色,因为只有Builtin管线才支持这种类型的着色器。要解决此图形错误,我们必须选择材质,转到检查器并将着色器类型更改为“Shader Graphs”中的着色器类型。

一旦我们确定了正在使用的渲染管道的类型,还是现实渲染错误, 下一步我们就必须看看是否是着色器出错了。
着色器中的错误在图形上是明显的,因为对象显示品红色。如果我们注意控制台,我们可以找到它的定义。要解决这些问题,我们需要了解:在HLSL和ShaderLab中写的指令或函数, 大多数错误都是由拼写错误或语法错误引起的。下面,我们将回顾一个相当常见的问题:

图片[2]-《Unity着色器圣经》4.0.5. | Debugging a shader.-软件开发学习笔记

我们如何解读上述声明?在这种情况下,在“Unlit”菜单中找到的名为“USB_simple_color”的着色器在代码行60中有错误,无法在Direct3D 11中编译。

现在,这是着色器的问题吗?为此,我们将分析生成错误的代码行。

fixed4 frag (v2f i) : SV_Target
{
    fixed4 col = tex2D(_MainTex, i.uv);
    return col // (;)
}

根据控制台的说法,错误是在第60行代码中生成的,但正如我们所看到的,没有问题。我们必须问问自己,发生了什么?错误是因为我们忘记关闭代码行61中的操作。如果我们查看返回,我们会意识到col矢量缺少分号(;),因此GPU认为操作仍在继续,因此无法编译它。

以下是我们经常看到的另一个错误:

图片[3]-《Unity着色器圣经》4.0.5. | Debugging a shader.-软件开发学习笔记
half4 frag (v2f i) : SV_Target
{
    half4 col = tex2D(_MainTex, i.uv);
    half2 uv = 0;
    col = uv; // cannot be converted
    return col;
}

在这种情况下,产生误差是因为我们试图将一个四维矢量(col)转换为二维矢量(uv)。二维的col矢量有RGBA或XYZW通道,而二维的uv矢量只有两个通道(RG、RB、GB等)的组合,因此无法从二维矢量转换为四个通道中的一个。


原文对照

When we write a script in C#, in Unity we can debug our program using the Debug.Log (object message) function. This function allows us to print an operation of our code on the console, however, this function is not available in Cg or HLSL.
So how can we debug a shader? For this, we must consider several factors, including: “the colors”. In a shader, there are three important colors that we see constantly, these are white (1, 1, 1, 1), black (0, 0, 0, 1) and magenta (1, 0, 1, 1). White represents a default value, while black represents an initialized value. Magenta represents a graphics error, in fact, it is very common to import assets to Unity that are magenta into our scene.

图片[1]-《Unity着色器圣经》4.0.5. | Debugging a shader.-软件开发学习笔记

To address this concept, let’s recall the Properties’ declaration in ShaderLab, for this, we will recreate a color property.

_Color ("Tint", Color) = (1, 1, 1, 1)

In the example above, the property has been declared with a color “white” by default, we can corroborate this in the four-dimensional vector; at the end of the operation (1, 1, 1, 1). This property as such will generate a “color selector” in the Unity Inspector, and its color and/or initialization value will be white.


Let’s analyze another property.

_MainTex ("Texture", 2D) = "white"{}

Again, this property as such will generate a “texture selector” in the Unity Inspector, but what will its default color be if we don’t use any texture? Its color will be white, we can confirm this in the declaration “white” found on the property.


We see the color black frequently in declarations of internal vectors and variables in our code, in fact, it is very common to initialize vectors to “zero” and then add some operation, e.g., the four-dimensional vector “float4 col = 0” has been initialized to “0”, this means that all its channels (RGBA) will have a default value of zero.


Note that white represents the maximum illumination value of one pixel and black represents its minimum illumination. It is important to remember this since, as we move forward, we will have some operations that will exceed the maximum (x > 1) and minimum (x < 0) values. In these cases, color saturation occurs and for this, we will use some functions like “clamp” that will allow us to limit a value between two numbers (minimum and maximum).


Why do our objects sometimes appear magenta? As we already know, this color represents a “graphical error”. Basically, when the GPU could not carry out the operations found within the shader, it returns a default magenta color. In Unity, the reasons for this color are mainly due to two factors:

  1. That the render pipeline has not been configured.
  2. Or that the shader has an error in its code.

When we import an asset into the software, the first thing we need to know is, which render pipeline are we working in? Remember that in Unity there are three types of render pipeline and each one has a different configuration.
Suppose we import an asset that includes a material with a Standard Surface shader in Universal RP, then our asset will appear in magenta because this type of shader is supported only in Built-in RP. To solve this graphical error, we have to select the material, go to the inspector and change the type of shader to one found in “Shader Graphs”.
Once we have identified the type of rendering pipeline that we are using, we must proceed to shader evaluation.

The errors in a shader are graphically evident since the objects acquire a magenta color. If we pay attention to the console, we can find its definition. To solve them, we must consider some factors: completing an instruction or function in HLSL and ShaderLab. Most errors are generated by misspelling or syntax. Below, we will review a reasonably common one:

图片[2]-《Unity着色器圣经》4.0.5. | Debugging a shader.-软件开发学习笔记

How can we read the above statement? In this case, the shader found in the “Unlit” menu, called “USB_simple_color”, has an error in code line 60 and cannot be compiled in Direct3D 11.
Now, is that a shader problem? To do this, we are going to analyze the line of code that is generating the error.

fixed4 frag (v2f i) : SV_Target
{
    fixed4 col = tex2D(_MainTex, i.uv);
    return col // (;)
}

According to the console, the error is being generated in code line number 60, but as we can see, there is no issue there. We have to ask ourselves then, what is happening? The error is because we forgot to close the operation in code line number 61. If we look at the return we will realize that the col vector is missing a semicolon (;) so the GPU thinks that the operation continues, so it can’t compile it.
The following is another error that we see frequently:

图片[3]-《Unity着色器圣经》4.0.5. | Debugging a shader.-软件开发学习笔记
half4 frag (v2f i) : SV_Target
{
    half4 col = tex2D(_MainTex, i.uv);
    half2 uv = 0;
    col = uv; // cannot be converted
    return col;
}

In this case, the error has been generated because we are trying to convert a four- dimensional vector (col) into a two-dimensional one (uv). The col vector, being four- dimensional, has RGBA or XYZW channels, on the other hand, the uv vector, being two- dimensional, only has the combination of two channels (RG, RB, GB, etc.), therefore it cannot be converted from a two-dimensional vector to one of four.

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容