欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Unity Shader入门教程(二) :实现顶点和片元着色器之间的通信

程序员文章站 2022-03-30 13:45:13
...

这篇文章将介绍Pass{}内的代码的编写。我们先看如下Unity Shader代码:(此文部分采自《unity shader入门精要》)

关于顶点着色器和片元着色器不懂的学习可以自行搜索概念的意思,这里就不介绍了。

Shader "Custom/myTest" {
	SubShader {
		Pass{
			CGPROGRAM

                        //申明顶点着色器函数
			#pragma vertex vert
                        //申明片元着色器函数
			#pragma fragment frag

			//使用一个结构体来定义顶点着色器的输入
			struct a2v{
				//POSITION语义告诉Unity,用模型空间的顶点坐标填充vertex变量
				float4 vertex : POSITION;
				//NORMAL语义告诉Unity,用模型空间的法向量方向填充normal变量
				float3 normal : NORMAL;
				//TEXCOORD0语义告诉Unity,用模型的第一套纹理坐标填充texcoord变量
				float4 texcoord : TEXCOORD0;
			};

			//如果没有自定义的结构体,则可写成float4 vert(float4 v : POSITION) : SV_POSITION
			float4 vert(a2v v) : SV_POSITION{
				//使用v.vertex来访问模型空间的顶点坐标
				return UnityObjectToClipPos(v.vertex);
			}

			float4 frag() : SV_Target{
				return fixed4(1.0, 1.0, 1.0, 1.0);   //fixed4(r, g, b, a),取值范围为[0,1]
			}

			ENDCG
		}
	}
	FallBack "Diffuse"
}

其中POSITION、NORMAL等大写的语义代表CG/HLSL语义,告诉GPU以怎样的方式进行渲染。该代码就表示了顶点/片元着色器以怎样的方式进行渲染。然而在实践中,我们往往希望从顶点着色器输出一些数据,例如把模型的法线、纹理坐标等传递给片元着色器,这就需要再定义一个新的结构体。修改后代码如下:

Shader "Custom/myTest" {
	SubShader {
		Pass{
			CGPROGRAM

			#pragma vertex vert
			#pragma fragment frag

			struct a2v{
				float4 vertex : POSITION;
				float3 normal : NORMAL;
				float4 texcoord : TEXCOORD0;
			};

			//使用一个结构体来定义顶点着色器的输出
			struct v2f{
				//SV_POSITION语义告诉Unity,pos里面包含了顶点在裁切空间中的位置信息
				float4 pos : SV_POSITION;
				//COLOR0语义可以用于存储颜色信息
				fixed3 color : COLOR0;
			};

			v2f vert(a2v v){
				v2f o;
				o.pos = UnityObjectToClipPos(v.vertex);
				//v.normal包含了顶点的法线方向,其分量范围在[-1.0,1.0]
				//下面的代码把分量范围映射到了[0.0, 1.0]
				//存储到o.color中传递给片元着色器
				o.color = v.normal * 0.5 + fixed3(0.5, 0.5, 0.5);
				
				return o;
			}

			fixed4 frag(v2f i) : SV_Target{
				//将插值后的i.color显示到屏幕上
				return fixed4(i.color, 1.0);
			}

			ENDCG
		}
	}
	FallBack "Diffuse"
}

在上面代码中,顶点着色器的输出结构中,必须包含一个变量,它的语义是SV_POSITION。否则,渲染器将无法得到裁切空间中的顶点坐标,也就无法将顶点渲染到屏幕上。COLOR0语义中的数据则可以由用户自己定义,但一般是存储颜色。

相关标签: Shader