[Shader Overview] Understanding shaders is a must-read for beginners with simple examples.

A brief summary of Shader:

1. Shader's position in the programmable rendering pipeline is the vertex shader and the fragment shader. These two parts are highly programmable.

2. Unity's ShaderLab is Unity's unique shader programming language. It is a layer of encapsulation of Cg/HLSL/ and was born to simplify programming.

3. Shader script is closely related to Material, and works together with Material on GameObject.

4. Unity's shaders include two types, one is the surface shader and the other is the vertex/fragment shader. The surface shader is actually a higher-level encapsulation of the vertex/fragment shader. It is simple and easy to use, but at the same time sacrifices the flexibility of control. It should be noted that the "vertex shader" and "fragment shader" of the vertex/fragment shader are written in the same shader file. The reason why the two discontinuous processes can be put together is because Unity performs the processing for the user. encapsulated.

5. A Shader can have multiple SubShaders, but there must be at least one SubShader.

6. A SubShader can have multiple Passes, and multiple Passes can achieve more complex effects.

Shader structure:

The shader structure includes: declaration, properties, SubShader, status settings, tags, Pass, and Fallback.

1 Statement: For example, shader "Custom/MyShader" { } where "Custom/" represents the file path and "MyShader" represents the name of this Shader

2 Properties: For example, Properties{ _Int("Int", Int) = 2 } where _Int is the variable name in the Shader script, "Int" is the variable name displayed on the Inspector, Int is the attribute of the variable, = is the The default value of this variable.

In addition to the Int type, there are also Float, Range (min, max), Color, Vector, 2D, Cube, and 3D. It should be noted that the attribute statements of 2D, Cube, and 3D are:

_2D("2D", 2D) = "white" {}, where "white" is the system's built-in texture. In addition to "white", there are also "black", "gray", and "bump".

3 SubShader: SubShader includes Pass module, status setting module and label module. Shader can contain multiple SubShaders. Each SubShader has a different rendering level. During the rendering process, the most appropriate SubShader code block will be selected for execution.

4 State setting: ShaderLab provides instructions for setting the rendering state. Common status settings are:

Cull Back | Cull Front | Cull Off: Culling mode: Culling back/front/turn off culling;

ZTest Less Greater | ZTest LEqual | ZTest GEqual | ZTest Equal | ZTest NotEqual | ZTest Always: Judgment conditions for depth testing;

ZWrite On | ZWrite Off: Turn on/off depth test;

Blend SrcFactor DstFactor: Turn on and set the blending mode;

5 Tag: It is a key-value pair, used to describe the rendering method of the object, in the form of Tags{ "Queue" = "Transfparent" }. Common Tags are:

"Queue" = "Transparent": Control the rendering order;

"RenderType" = "Opaque": Classifies shaders and can be used for shader replacement functions;

"DisableBatching" = "True": Problems may occur when using vertex animation in model space. Specify whether the SubShader can be batched;

"ForceNoShadowCasting" = "True" : Whether this SubShader will cast shadows;

"IgnorProject" = "True": Indicates whether the object is not affected by Projector, often used for translucent objects;

"CanUseSpriteAtlas" = "True": When this SubShader is used for sprites, it should be set to "False";

"PreviewType" = "Plane": Specifies the shape in which the material panel should preview the model, usually spherical.

6 Pass: Pass can include naming, tags, and rendering settings. You can use the UsePass command to call the Pass in other Shaders.

7 FallBack: When all SubShaders in the shader do not meet the current operating environment, FallBack will be executed. It tells Unity to use a specific Shader to perform rendering. Of course, it can also be turned off and no Shader rendering is used. For example: FallBack Off / FallBack "Name".

Original link: ShaderLab syntax of Unity Shader_PresleyGo's blog-CSDN blog


Shaders are divided into two categories:

  1. Vertex Shader (3D graphics are composed of triangular patches. Vertex Shader calculates the vertices on each triangular patch and prepares for final pixel rendering).
  2. Pixel Shader, as the name suggests, is a series of algorithms that calculate lighting and color in pixels. Several different graphics APIs have their own Shader languages. In DirectX, the vertex shader is called Vertex Shader, and the pixel shader is called Pixel Shader; in OpenGL, the vertex shader is also called Vertex Shader, but the pixel shader is called Fragment Shader, which is what we Often referred to as fragment Shader or fragment Shader.

To put it bluntly, Shader is actually a piece of code. The function of this code is to tell the GPU how to draw the color of each vertex of the model and ultimately the color of each pixel.

Shader programming language:

Since Shader is a piece of code, it must be written in a language. Currently, there are three mainstream languages:

  1. OpenGL Shading Language based on OpenGL, referred to as GLSL.
  2. High Level Shading Language based on DirectX, referred to as HLSL.
  3. There is also NVIDIA's C for Graphic, referred to as CG language.

Shader’s transparency channel:

//transparent

Tags { "Queue" = "Transparent" "RenderType" = "Transparent" }
LOD 100

ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha

//opaque

Tags { "RenderType"="Opaque" }

LOD 100

The location is as follows

for example

CFBC684BYYEHY(1Y7D1~AQB.png

Rendering:

image.png

 Simple flame Shader special effects:

// 定义一个自定义的水纹Shader 
Shader "Custom/WaterRipple" {
    // 定义所需属性
    Properties {
        _MainTex ("Texture", 2D) = "white" {}
        _BumpMap("Normal Map", 2D) = "bump" {}
        _RippleCenter("Ripple Center", Vector) = (0.5,0.5,0,0)
        _RippleSize("Ripple Size", Range(0,1)) = 0.05
        _RippleSpeed("Ripple Speed", Range(0,1)) = 0.1
    }

    SubShader {
        Tags {"Queue"="Transparent" "RenderType"="Opaque" }
        LOD 200

        Pass {
            CGPROGRAM
            // 定义顶点着色器函数
            #pragma vertex vert
            // 定义片元着色器函数
            #pragma fragment frag
            // 引入UnityCG.cginc库
            #include "UnityCG.cginc"

            // 定义输入顶点数据结构体
            struct appdata {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
                float2 uv : TEXCOORD0;
            };

            // 定义输出顶点数据结构体
            struct v2f {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
                float3 worldPos : TEXCOORD1;
                float3 worldNormal : TEXCOORD2;
            };

            // 定义纹理采样器
            sampler2D _MainTex;
            sampler2D _BumpMap;
            float4 _RippleCenter;
            float _RippleSize;
            float _RippleSpeed;

            // 定义顶点着色器函数
            v2f vert (appdata v) {
                v2f o;
                // 位置转换为裁剪空间坐标
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                // 保存世界空间中的位置和法线信息
                o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
                o.worldNormal = UnityObjectToWorldNormal(v.normal);
                return o;
            }

            // 定义片元着色器函数
            float4 frag (v2f i) : SV_Target {
                float2 uv = i.uv;
                float4 color = tex2D(_MainTex, uv);

                // 采样法线图
                float4 bump = tex2D(_BumpMap, uv);
                // 根据法线图计算出法线信息
                float2 normalMap = (bump.xy  2.0 - 1.0)  _RippleSize;
                // 计算片元到波纹中心的距离
                float dist = distance(i.worldPos.xy, _RippleCenter.xy);
                // 根据距离计算出波纹的大小
                normalMap = pow(saturate((_RippleSize - dist) / _RippleSize), 2);
                // 根据当前片元的位置和波纹中心的位置计算出角度
                float angle = atan2(i.worldPos.y - _RippleCenter.y, i.worldPos.x - _RippleCenter.x);
                // 加入时间偏移量和角度因素
                float timeOffset = _Time.y  _RippleSpeed + angle / (2  3.14159265359);
                // 计算纹理坐标偏移
                uv += normalMap  sin(timeOffset)  0.025;

                // 采样新的纹理颜色
                color = tex2D(_MainTex, uv);

                return color;
            }
            ENDCG
        }
    }
    // 备选Shader
    FallBack "Diffuse"
}

Simple water ripple effects:

// 定义一个自定义的水纹Shader 
Shader "Custom/WaterRipple" {
    // 定义所需属性
    Properties {
        _MainTex ("Texture", 2D) = "white" {}
        _BumpMap("Normal Map", 2D) = "bump" {}
        _RippleCenter("Ripple Center", Vector) = (0.5,0.5,0,0)
        _RippleSize("Ripple Size", Range(0,1)) = 0.05
        _RippleSpeed("Ripple Speed", Range(0,1)) = 0.1
    }

    SubShader {
        Tags {"Queue"="Transparent" "RenderType"="Opaque" }
        LOD 200

        Pass {
            CGPROGRAM
            // 定义顶点着色器函数
            #pragma vertex vert
            // 定义片元着色器函数
            #pragma fragment frag
            // 引入UnityCG.cginc库
            #include "UnityCG.cginc"

            // 定义输入顶点数据结构体
            struct appdata {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
                float2 uv : TEXCOORD0;
            };

            // 定义输出顶点数据结构体
            struct v2f {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
                float3 worldPos : TEXCOORD1;
                float3 worldNormal : TEXCOORD2;
            };

            // 定义纹理采样器
            sampler2D _MainTex;
            sampler2D _BumpMap;
            float4 _RippleCenter;
            float _RippleSize;
            float _RippleSpeed;

            // 定义顶点着色器函数
            v2f vert (appdata v) {
                v2f o;
                // 位置转换为裁剪空间坐标
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                // 保存世界空间中的位置和法线信息
                o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
                o.worldNormal = UnityObjectToWorldNormal(v.normal);
                return o;
            }

            // 定义片元着色器函数
            float4 frag (v2f i) : SV_Target {
                float2 uv = i.uv;
                float4 color = tex2D(_MainTex, uv);

                // 采样法线图
                float4 bump = tex2D(_BumpMap, uv);
                // 根据法线图计算出法线信息
                float2 normalMap = (bump.xy  2.0 - 1.0)  _RippleSize;
                // 计算片元到波纹中心的距离
                float dist = distance(i.worldPos.xy, _RippleCenter.xy);
                // 根据距离计算出波纹的大小
                normalMap = pow(saturate((_RippleSize - dist) / _RippleSize), 2);
                // 根据当前片元的位置和波纹中心的位置计算出角度
                float angle = atan2(i.worldPos.y - _RippleCenter.y, i.worldPos.x - _RippleCenter.x);
                // 加入时间偏移量和角度因素
                float timeOffset = _Time.y  _RippleSpeed + angle / (2  3.14159265359);
                // 计算纹理坐标偏移
                uv += normalMap  sin(timeOffset)  0.025;

                // 采样新的纹理颜色
                color = tex2D(_MainTex, uv);

                return color;
            }
            ENDCG
        }
    }
    // 备选Shader
    FallBack "Diffuse"
}

Guess you like

Origin blog.csdn.net/m0_74022070/article/details/131758375