Use of Unity Shader CG property variables

1. Declare attribute variables in CG

Shader declares the opened properties through the Properties code block. If you want to access these properties in the Shader program, you need to declare it again in the CG code block.
Example:

Shader "Custom/CG Properties"
{
    Properties
    {
        _MyFloat ("Float Property", Float) = 1 // 浮点类型
        _MyRange ("Range Property", Range(0, 1)) = 0.1 // 范围类型
        _MyColor ("Color Property", Color) = (1, 1, 1, 1) // 颜色类型
        _MyVector ("Vector Property", Vector) = (0, 1, 0, 0) //向量类型
        _MyTex ("Texture Property", 2D) = "white" {} // 2D贴图类型
        _MyCube ("Cube Property", Cube) = "" {} // 立方体贴图类型
        _My3D ("3D Property", 3D) = "" {} // 3D贴图类型
    }
    SubShader
    {
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // 在CG中声明属性变量
            float _MyFloat; // 浮点类型
            float _MyRange; // 范围类型
            fixed4 _MyColor; // 颜色类型
            float4 _MyVector; //向量类型
            sampler2D _MyTex; // 2D贴图类型
            samplerCUBE _MyCube; // 立方体贴图类型
            sampler3D _My3D; // 3D贴图类型

            void vert ()
            {
            }
            void frag ()
            {
            }
            ENDCG
        }
    }
}

insert image description here

2. Use color in Shader

After declaring the attribute variable with CG, the function of modifying the color is realized.
An example is as follows:

Shader "Custom/CG Properties"
{
    Properties
    {
        _MainColor ("Main Color", Color) = (1, 1, 1, 1) // 开放颜色属性
    }
    SubShader
    {
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // 在CG中声明属性变量
            fixed4 _MainColor; // 颜色类型

            void vert (in float4 vertex:POSITION,out float4 position:SV_POSITION)
            {
            	//将顶点从模型空间变换到齐次裁切空间
            	position=UnityObjectToClipPos(vertex);
            }
            void frag (out fixed4 color:SV_TARGET)
            {
            	//调用颜色变量
            	color=_MainColor;
            }
            ENDCG
        }
    }
}

3. Use textures in Shader

After the texture map is defined in the Properties code block, it needs to be declared again in the CG code block.
The function used for problem texture sampling is:

tex2D(Texture,texcoord);
  • Texture: Represents a texture map;
  • texcoord : Indicates sampling the texture of the texture; in
    addition, CG also needs to declare an additional variable to store other information of the texture. Such as the often used tiling (Tiling) and offset (Offset) properties.
    insert image description here
    The syntax for declaring a texture variable's Tiling and Offset in CG is as follows:
float4 {TextureName}_ST;
  • TextureName: the name of the texture attribute;
  • ST: The first letter of Scale and Transform, indicating the scaling and translation of UV.

The variable declared in CG is of type float4, where xxxyyThe y components areXXX value andYYY value,zzz andwwThe w components areXXX value andYYY value.
The texture calculation formula is:
texcoord = uv ⋅ { Texture Name } . xy + { Texture Name } . zw texcoord=uv \{TextureName\}.xy+\{TextureName\}.zwtexcoord=uv{ TextureName}.xy+{ TextureName}.zw

It is important to note that when calculating texture coordinates, you must first multiply the tile value and add the offset value.
Need to cooperate with calling the tex2D() function, use texcoord to sample the texture.

A complete example:

Shader "Custom/Texture Property"
{
    Properties
    {
        _MainColor ("MainColor", Color) = (1, 1, 1, 1)
        _MainTex ("MainTex", 2D) = "white" {}   // 开放纹理属性
    }
    SubShader
    {
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            fixed4 _MainColor;
            sampler2D _MainTex;  // 声明纹理属性变量以及ST变量
            float4 _MainTex_ST;

            void vert (in float4 vertex : POSITION,in float2 uv : TEXCOORD0, out float4 position : SV_POSITION,
                    out float2 texcoord : TEXCOORD0)
            {
                position = UnityObjectToClipPos(vertex);
                // 使用公式计算纹理坐标
                texcoord = uv * _MainTex_ST.xy + _MainTex_ST.zw;
            }

            void frag (in float4 position : SV_POSITION,in float2 texcoord : TEXCOORD0,out fixed4 color : SV_TARGET)
            {
            	//调用tex2D()函数,使用texcoord对纹理_MainTex进行采样
                color = tex2D(_MainTex, texcoord) * _MainColor;
            }
            ENDCG
        }
    }
}

Under normal circumstances, texture resources need to be used according to this process. Unless it can be determined that a certain texture resource will never use Tiling and Offset, the declaration of the ST variable of the resource can be omitted, and its texture coordinates will not be calculated.

      void vert (in float4 vertex : POSITION,in float2 uv : TEXCOORD0, out float4 position : SV_POSITION,
                    out float2 texcoord : TEXCOORD0)
            {
                position = UnityObjectToClipPos(vertex);
                // 使用公式计算纹理坐标
                texcoord = uv;
            }

4. Use Cubemaps in Shaders

A cube map is a cube box composed of six directions: front, back, left, right, up, down, and six directions. It can also be converted from a panorama in Unity, and is usually used for environmental reflections.
The function used for cubemap sampling is:

texCUBE(Cube,r);
  • Cube: Represents a cube map;
  • r : Represents the reflection direction of the line of sight direction on the surface of the object;

Cube can directly declare this attribute variable in CG, and then get it directly, while rrThe acquisition of r is more complicated:
an example of the reflection vector on the surface of the object:
insert image description here

Assume that the direction from the camera to the vertex is vv of the sight vectorv , the direction reflected from the surface of the object is the reflection vectorrrr , the normal vector of the surface of the object isnnn , and these vectors have been normalized.

reflection vector rrThe formula for calculating r is :
r = 2 { v + [ ( − v ) ⋅ n ] n } − v = 2 [ ( − v ) ⋅ n ] n + vr=2\{v+[(-v) n] n\}-v=2[(-v)·n]n+vr=2 { v+[ ( v ) n]n}v=2 [ ( v ) n]n+v

  • vvv : The direction the camera points to the vertex is the line of sight vector;
  • n nn : the normal vector of the surface of the object;

A full cubemap example:

Shader "Unlit/Cubemap Property"
{
    Properties
    {
        _MainTex ("Main Tex", 2D) = "white" {}
        _MainColor("Main Color",Color)=(1,1,1,1)
        //添加Cubemap属性和反射强度
        _Cubemap("Cubemap",Cube)=""{}
        _Reflection("Reeflection",Range(0,1))=0
    }
    SubShader
    {
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
           
           sampler2D _MainTex;
           float4 _MainTex_ST;
           fixed4 _MainColor;

           //声明Cubemap和反射属性变量
           samplerCUBE _Cubemap;
           fixed _Reflection;


            void vert (in float4 vertex:POSITION,
            in float3 normal:NORMAL,
            in float4 uv : TEXCOORD0,
            out float4 position : SV_POSITION,
            out float4 worldPos : TEXCOORD0,
            out float3 worldNormal : TEXCOORD1,
            out float2 texcoord : TEXCOORD2)
            {
               position=UnityObjectToClipPos(vertex);
               //将顶点坐标变换到世界空间
               worldPos=mul(unity_ObjectToWorld,vertex);
               //将法线向量变换到世界空间
               worldNormal=mul(normal,(float3x3)unity_WorldToObject);
               worldNormal=normalize(worldNormal);

               texcoord=uv*_MainTex_ST.xy+_MainTex_ST.zw;
            }

            void frag (in float4 position:SV_POSITION,
            in float4 worldPos:TEXCOORD0,
            in float3 worldNormal:TEXCOORD1,
            in float2 texcoord:TEXCOORD2,
            out fixed4 color:SV_TARGET) 
            {
               fixed4 main=tex2D(_MainTex,texcoord)*_MainColor;
               //计算世界空间中从摄像机指向顶点的方向向量
               float3 viewDir=worldPos.xyz-_WorldSpaceCameraPos;
               viewDir=normalize(viewDir);
               //套用公式计算反射向量
               float3 refDir=2*dot(-viewDir,worldNormal)*worldNormal+viewDir;
               refDir=normalize(refDir);
               //对Cubemap采样
               fixed4 reflection=texCUBE(_Cubemap,refDir);
               //使用_Reflection对颜色和反射进行线性插值计算
               color=lerp(main,reflection,_Reflection);
            }
            ENDCG
        }
    }
}

Guess you like

Origin blog.csdn.net/qq_40120946/article/details/122116535