Unity Shader study notes - basic structure

Unity provides 5 templates of Unity Shader for us to choose from:

        Standard Surface Shader: A surface shader template containing the standard lighting model will be generated.

        Unlit Shader: Will generate a basic vertex/fragment shader that does not include lighting (but includes fog effects).

        Image Effect Shader: Provides a basic template for us to achieve various screen post-processing effects.

        Compute Shader: A special Shader file will be generated. This type of Shader is designed to use the parallelism of the GPU to perform some calculations that are not related to the conventional rendering pipeline.

        Ray Tracing Shader: A ray tracing shader will be created.


        The basic structure of a Unity Shader is as follows:

Shader "ShaderName"
{
    Properties
    {
        //所需的各种属性
    }
    SubShader
    {   
        //显卡A使用的子着色器
        //真正意义上的Shader代码会出现在这里
        //表面着色器(Surface Shader)或者
        //顶点/片元着色器(Vertex/Fragment Shader)或者
        //固定函数着色器(Fixed Function Shader)
    }
    SubShader
    {   
        //显卡B使用的子着色器
        //和上一个SubShader类似 
    }
    Fallback "VertexLit"
}

        Through the shadername in the first line of code, you can find the corresponding shader material in the Unity window, such as:

Shader "Unlit/FirstShader"


         The Properties semantic block contains a series of properties that will appear in the material panel:

    Properties
    {
        Name("display name", PropertyType) = DefaultValue
        Name("display name", PropertyType) = DefaultValue
    }

         Name is the name of each property, and the names of these properties in Unity usually start with an underscore.

        displayname is the displayed name, which is the name that appears on the material panel.

        PropertyType is the property type. In addition, we also need to formulate a default value for each attribute, namely DefaultValue.

         The following code gives an example showing all attribute types:

    Properties
    {
        //Name("display name", PropertyType) = DefaultValue
        _Int("Int", Int) = 1
        _Float("Float",Float) = 1.5
        _Range("Range",Range(0.0, 5.0)) = 3.0

        _Color("Color",Color) = (1, 1, 1, 1)
        _Vector("Vector",Vector) = (2, 3, 6, 1)

        _2D("2D",2D) = ""{}
        _Cube ("Cube",Cube) = "white" {}
        _3D("3D",3D) = "black"{}
    }

        Then we can see the corresponding display in the material panel:


         SubShader semantic block: Each Unity Shader file can contain multiple SubShaders, but there must be at least one. When Unity needs to load this Unity Shader, it will scan all SubShaders and select the first one that can run on the target platform. If it is not supported, it will use the Unity Shader specified by Fallback semantics.

        The main function of this semantic is to display different pictures on different graphics cards, use shaders with lower computational complexity on older graphics cards, and use shaders with higher computational complexity on advanced graphics cards to provide better performance. screen.

SubShader
    {
        //可选的
        [Tags]
        
        //可选的
        [RenderSetup]

        Pass
        {
            //Other Passes
        }
}

        A series of Pass and optional state (RenderSetup) and label (Tags) settings are defined in SubShader. Each Pass defines a complete rendering process, but if the number of Passes is too large, the rendering performance will decrease.

        Status setting: After setting, it will be applied to all Passes. If you want to render separately, you can set the above settings separately in the Pass semantic block.

         Label: A label is a key-value pair whose key and value are both string types. These key-value pairs are the bridge between the SubShader and the rendering engine, which tells the Unity rendering engine how and when to render this object. Labels can only be implemented in SubShader, not declared in the Pass block.

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


        Pass semantic block:

Pass
{
    [Name]
    //此处的Tags和上面SubShader的Tags是不一样的
    [Tags]
    [RenderSetup]
    //Other code
}

        We can define the name of the Pass, and then call the Pass in other Unity Shaders through this name.

//声明Pass名称
Name "MyPassName"

//在其他Unity Shader中调用
UsePass "FirstShader/MYPASSNAME"


        Fallback instruction: It is used to tell Unity that if all the above-mentioned SubShaders cannot run on this graphics card, then use this lowest-level Shader. It will also affect the projection of shadows, and the built-in Shader used by Fallback contains such a general Pass.

//调用最低级的Unity Shader的名字
Fallback "name"
//或者关闭Fallback,即使跑不了所有的SubShader也不管他
Fallback Off

Pass
{
    //嵌套CG/HLSL语言
	CGPROGRAM
    //指定顶点阶段函数为vert
	#pragma vertex vert
    //指定片元阶段函数为frag
	#pragma fragment frag
 
    //引入Unity中的函数库
	#include "UnityCG.cginc"
 
    //顶点阶段输入的信息,这里指定了输入的有顶点的位置信息
	struct appdata
	{
        //可以把 float4 理解为一个长度等于4的 float 数组,用 xyzw 或者 rgba 来取它的每一个元素值
        //POSITION 是这个字段的语义,它的意思是指明这个字段传入的是顶点位置信息。
		float4 vertex : POSITION;
	};
 
    //是片元阶段输入的信息,也是顶点阶段输出的信息
	struct v2f
	{
        //SV_POSITION 指定了顶点的位置是经过顶点坐标空间变换过的,直接进行光栅化处理。
		float4 vertex : SV_POSITION;
	};
 
    //这个声明通常和Properties语句块里的属性相对应
	float4 _TintColor;
 
    //vert函数输入的是appdata结构体,输出的是v2f结构体,这里个函数里只做了一件事,就是转换顶点空间并返回。
	v2f vert(appdata v)
	{
		v2f o;
		o.vertex = UnityObjectToClipPos(v.vertex);
		return o;
	}
 
    //frag函数输入的是v2f结构体,输出的是一个颜色值,这个颜色值是我们在Properties里声明的。
	float4 frag(v2f i) : SV_Target
	{
		return _TintColor;
	}
	ENDCG
}

Guess you like

Origin blog.csdn.net/weixin_45081191/article/details/129164954