【Unity Shader 中Pass相关介绍_第三篇】

故事的开始在上一篇!!!

1.1.在CG中调用属性变量

Shader通过Properties代码块声明开放出来的属性,如果想访问这些属性,需要在CG代码块中再次进行声明,它的语法格式为:

		type name;
		//type为变量的类型,name为属性变量的名称。

提示:
必须在函数调用属性之前对其进行声明,否则编译会失败。
下面是在这一篇中介绍到的属性,在CG中全部在声明一遍,代码块如下:

Shader "Unlit/在CG中调用属性变量"
{
    
    
    Properties
    {
    
    
        //下面是可能会出现的 Properties 的结构
        _2D("2D", 2D) = "" {
    
    }											//2D贴图类型
        _Color("Color",Color) = (1,1,1,1)								//颜色类型
        _Value("Value",Range(0,10)) = 2.5								//范围类型
        _Float("Float",Float) = 0										//浮点类型
        _Vector("Vector",Vector) = (0,0,0,0)							//向量类型
        _Cube("Cube",Cube) = "" {
    
    }										//立方体贴图类型
        _3D("3D",3D) = "" {
    
    }											//3D贴图类型
        //_name("display name" , type) = "defaulttexture"				//_属性名CG代码块方便调用(“在面板中显示的” , 属性类型) = 初始化默认值

    }
    SubShader
    {
    
    
        Pass
        {
    
    
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            
            //在CG中声明属性变量
			sampler2D _2D												//2D贴图类型
			float4 _Color												//颜色类型
			float _Value												//范围类型
			float _Float												//浮点类型
			float4 _Vector												//向量类型
			samplerCUBE _Cube											//立方体贴图类型
			sampler3D _3D												//3D贴图类型

            void vert()
            {
    
    
            }

            void frag()
            {
    
    
            }
            
		ENDCG
        }
    }
}

下面是开放属性与CG属性变量的对应关系:

语义 描述
float,Range 浮点和范围类型的属性,根据精度可以使用float,half或者fixed
Color,Vector 颜色和向量类的属性,可以使用float4,half4或fixed4声明,其中颜色使用低精度的fixed4声明可以减少性能消耗
2D 2D纹理贴图属性,使用sampler2D声明
cube 立方体贴图属性,使用samplerCUBE声明
3D 3D纹理贴图属性,使用sampler3D声明

1.2.实现更改颜色

先小试一下,其他的大多都差不多,需要多练习就熟悉了。下面对颜色属性,在CG中重新声明属性变量,实现更改颜色功能。

Shader "Unlit/实现更改颜色"
{
    
    
    Properties
    {
    
    
        //开放颜色属性
        _Color("Color",Color) = (1,1,1,1)	//颜色类型,默认值为(1,1,1,1)=白色
    }
    SubShader
    {
    
    
        Pass
        {
    
    
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

			float4 _Color;		//在CG中以float4类型再次声明
			
            void vert(in float4 vertex : POSITION,
            		out float4 position : SV_POSITION)
            {
    
    
            	position = UnityObjectToClipPos(vertex);
            }

            void frag(out float4 color : SV_TARGET)		//在第一篇中解释了,为啥片段着色器可以直邮输出?
            {
    
    
            	//调用颜色变量_Color
            	Color = _Color;		//在片段着色器中直接使用变量_Color输出颜色,无返回值。
            }
		ENDCG
        }
    }
}

1.3.实现使用贴图(启用纹理的变量的Tiling和Offset的语法细则)

上面通过声明实现自由更改颜色。接下来实现使用纹理贴图。
在Properties代码块别定义之后,还需要在CG代码块中再次声明。但是与其他属性不同的是,CG还需要额外声明一个变量用于储存贴图的其他信息。如下面的图:

下面是Tiling和Offset属性:
在这里插入图片描述
平铺(Tiling)和偏移(Offset)属性,额外声明的变量就是为了储存这些信息。
在CG中,声明一个纹理的变量的Tiling和Offset的语法结构如下:
float4{TextureName}_ST;
其中TextureName是纹理属性的名称
ST:Scale和Transform的首字母,表示UV的缩放和平移。
x和y分量分别为Tiling的X值和Y值
z和w分量分别为Offset的Z值和W值
纹理坐标的计算公式为:
texcoord = uv * {TextureName}. xy + {TextureName}.zw
注意:公式先乘以平铺再加偏移值。初中的加减乘除运算规则是先乘除再加减,这样记住就可以了。有兴趣的可以看一下背后推导的过程,这里不扩充。

直接上代码,注释里会说的很清楚。

Shader "Unlit/实现使用贴图"
{
    
    
    Properties
    {
    
    
        //开放颜色属性
        _MainTex("MainTex", 2D) = "white" {
    
    }							//2D贴图类型
        _MainColor("MainColor",Color) = (1,1,1,1)						//颜色类型
        //Properties开放的名称为_MainTex的纹理属性,默认值为白色。
        							//当然这里也可以写成这样,比较灵活,他们要声明的属性是一个类型。
        							//_2D("2D", 2D) = "white" {}//2D贴图类型
        							//_Color("Color",Color) = (1,1,1,1)	//颜色类型

    }
    SubShader
    {
    
    
        Pass
        {
    
    
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag//这三行在第一篇里有详细说明。

			float4 _MainColor;		//在CG中以float4类型再次声明
			//声明纹理属性变量以及ST变量
			sampler2D _MainTex;
			float4 _MainColor_ST;
			
            void vert(in float4 vertex : POSITION,in float2 uv : TEXCOORD0,
            		out float4 position : SV_POSITION,out float2 texcoord : TEXCOORD0)
            {
    
    
				//下面这个“UnityObjectToClipPos”是unity5.6以后的写法,unity5.6以前的写法是“UNITY_MATRIX_MVP”
            	position = UnityObjectToClipPos(vertex);
            	//使用公式计算纹理坐标
            	texcoord = uv * _MainColor_ST.xy + _MainColor_ST.zw;
            	//如果用不到平铺(Tiling)和偏移(Offset)属性效果,那么可以省略对纹理资源ST变量的声明,同时不再计算其纹理坐标。
            	//则公式可以写成这样:
            	//				texcoord = uv;
            	//也就是UV坐标输入到顶点函数之后无需计算平铺和偏移,而是直接输出。
            	//片段函数void frag()获取到UV坐标之后直接对纹理进行采样。
            }
			//来到了片段着色器
            void frag(in float4 position : SV_POSITION,in float2 texcoord : TEXCOORD0,
            		out float4 color : SV_TARGET)
            {
    
    
            	Color = tex2D(_MainTex,texcoord) * _MainColor;
            }
		ENDCG
        }
    }
}

Pass介绍的第三篇了,是时候介绍 具体的 多一点的 结构体,着色器通常需要输入和输出参数,为了使代码编写更加方便,并且看起了整洁,所以有了这样的一个数据类型——结构体

猜你喜欢

转载自blog.csdn.net/xukaibo111/article/details/124333866
今日推荐