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

上一篇传送门!!!

一. Pass中的CG编译指令

在Unity Shader 中,ShaderLab语言只是起到阻止代码结构作用,而真正实现渲染效果的部分是用CG语言编写的。

1.1.编译指令

CG程序片段通过指令嵌入在Pass中,夹在指令CGPROGRAM和ENDCG之间,通常结构如下:

Pass
{
    
    
	// ...设置渲染状态...
	CGPROGAM
	//编译指令
	#pragma vertex vert
	# pragma fragment frag
	
	//CG代码
	ENDCG
}

在CG程序片段之前,通常需要先使用 #pragma声明编译指令,下面是总结出来的表格:

编译指令 作用
# pragma vertex name 定义顶点着色器的名称,通常会使用 vert
# pragma fragment name 定义片段着色器的名称,通常会使用 frag
# pragma target name 定义 Shader 要编译的目标级别,默认2.5

1.2. 着色器函数(本篇不扩展语义和结构体内容。)

下面是一个最简单的Shader代码片:

Shader "Custom/Simplest Shader"
{
    
    
	SubShader
	{
    
    
		Pass
		{
    
    
			// ...设置渲染状态...
			CGPROGAM
			//编译指令
			#pragma vertex vert //定义顶点着色器的名称
			# pragma fragment frag //定义片段着色器的名称
			//通常情况下,为了代码的可读性和易用性考虑,一般都会使用vert和frag来命名。
			
			//CG代码
			void vert (in float4 vertex : POSITION,
					out float4 position : SV_POSITION)
			{
    
    
				position = UnityObjectToClipPos(vertex);
			}
			void frag (in float4 vertex : SV_POSITION,
					out fixed4 color : SV_TARGET)
			{
    
    
				color = fixed4(1,0,0,1);
			}
			ENDCG
		}
	}
}

这是一个顶点-片段着色器(Simple Shader)。在这个Shader中只包含一Subshader中只包含一个Pass,最核心的CG程序嵌套在CGPROGAM和ENDCG之间。
在这个代码块主要是通过 顶点函数和片段函数来实现的。

1.2.A.无返回值函数

函数一般有无返回值和返回值,其中无返回值就是函数不会返回任何变量,而是通过out关键词将变量输出,上述Simple Shader中的顶点函数和片段函数使用的就是无返回值的函数,
无返回值函数的语法结构如下:

	void name (in 参数 , out 参数)
	{
		//函数体
	}

关键词解释:
1).void: 表示返回空值。
2).name:定义函数的名称,后续可以通过这个名称调用函数。
3).in:输入参数,语法:in + 数据类型 + 名称,一个函数可以有多个输入,关键词in可以省略。
4).out : 输出参数,语法为:out + 数据类型 + 名称,一个函数可以有多个输出。

v顶点函数):来看下面这段:

			void vert (in float4 vertex : POSITION, out float4 position : SV_POSITION)
			{
    
    
				position = UnityObjectToClipPos(vertex);
			}

顶点着色器输入一个float4类型的数据,名称为vertex,经过Unity内置空间变换函数UnityObjectToClipPos把模型空间坐标转换到裁切空间坐标,然后输出为float4类型的position。

in
UnityObjectToClipPos
out
顶点着色器
一个float4类型的数据=vertex
把模型空间坐标转换到裁切空间坐标
为float4类型的position

frag):来看下面这段:

扫描二维码关注公众号,回复: 15823595 查看本文章
			void frag (in float4 vertex : SV_POSITION, out fixed4 color : SV_TARGET)
			{
    
    
				color = fixed4(1,0,0,1);
			}

顶点函数输出的顶点坐标输入到片段函数之后,最终输出float4类型的数据,名称为color。在函数内color变量被赋予值为(1,0,0,1),红色。最终效果现实为红色。

in
名称
out
顶点坐标float4类型的SV_POSITION
一个float4类型的片段函数frag
color
为float4类型的数据

1.2.B.有返回值的函数

有返回值的函数不在使用out关键词输出参数,而是会在最后通过return关键词返回一个变量,语法结构是这样的:

			type name (in 参数)
			{
    
    
				//函数体
				return 返回值;
			}
数据类型 描述
fixed,fixed2,fixed3,fixed4 低精度浮点值,使用11位精度进行存储,数值区间[-2,0,2,0],用于存储颜色、标准化后的向量。
half,half2,half3,half4 中精度浮点值,使用16 位精度进行存储,数值区间为[-60000,60000]
float,float2,float3,float4 高精度浮点值,使用 32 位精度进行存储,用于存储顶点坐标、标准化的向量、纹理坐标等
struct 结构体,可以将多个变量整体进行打包

标准化向量:标准化向量指的是那些长度为1的向量,标准化向量也被称为归一化的向量或者单位向量。
下面是把Simplest Shader 中无返回值的函数改写为有返回值的函数,改写后的代码如下:

Shader "Custom/Simplest Shader"
{
    
    
	SubShader
	{
    
    
		Pass
		{
    
    
			CGPROGAM
			#pragma vertex vert //定义顶点着色器的名称
			# pragma fragment frag //定义片段着色器的名称
			//CG代码
			float4 vert (in float4 vertex : POSITION) : SV_POSITION
			{
    
    
				//返回裁切空间顶点坐标
				return UnituObjectToClipPos(vertex);
			}
			fixed4 frag (in float4 vertex : SV_POSITION) : SV_TARGET)
			{
    
    
				//返回颜色值
				return fixed4(1,0,0,1);
			}
			ENDCG
		}
	}
}

改写完后的两个Shader最终现实的效果是一样的。

1.2.C.结束 (想的美!!)

不论有没有返回值,在输入和输出的参数后面都会有一个冒号 : ,然后跟一个全是大写的关键词,这些关键词就是语义。这里解释一下,这些是CG/HLSL提供的语义,它们是用来传递数据信息的。SV的含义是系统数值(system-value),其中POSITION和SV_POSITION的区别在于应用的平台不一样,例如在索尼PS4上必须使用SV_POSITION来修饰顶点着色器的输出,否则无法正常运行。同时也欢迎读者来补充。
关于语义部分,我会放在下一篇

猜你喜欢

转载自blog.csdn.net/xukaibo111/article/details/124245118