Shader编写通常会遇到语义
1 float4 vert(float4:POSITION):SV_POSITION 2 { 3 return mul(UNITY_MATRIX_MVP,v); 4 }
POSITION与SV_POSITION都是Cg/HLSL中的语义,是不可省略的。
float4:POSITION就是将模型的顶点坐标作为vert()的参数。
有时候顶点处理函数vert()需要更多的参数,这时候就用到了结构体作为输入。
1 struct input_data 2 { 3 float4 vertex : POSITION;//模型顶点坐标 4 float4 texcoord : TEXCOORD0;//材质的第几套纹理坐标 5 }; 6 float4 vert(input_data m):SV_POSITION 7 { 8 return mul(UNITY_MATRIX_MVP,m.vertex); 9 }
当然也可以采用结构体来进行输出。
1 Shader "Custom/red" { 2 SubShader { 3 Pass{ 4 CGPROGRAM 5 // Physically based Standard lighting model, and enable shadows on all light types 6 #pragma vertex vert 7 #pragma fragment frag 8 9 struct input_data 10 { 11 float4 vertex : POSITION;//模型顶点坐标 12 float3 normal:NORMAL;//法线,凑结构体数用的,实际没用 13 float4 texcoord : TEXCOORD0;//材质的第几套纹理坐标,凑结构体数用的,实际没用 14 }; 15 16 struct output_data 17 { 18 float4 pos: SV_POSITION;//SV_POSITION语义告诉Unity,pos里包含了顶点在裁剪空间的位置信息 19 fixed3 color : COLOR0; 20 }; 21 22 output_data vert(input_data i) 23 { 24 output_data o; 25 o.pos=mul(UNITY_MATRIX_MVP,i.vertex); 26 o.color=fixed3(1.0,0,0); 27 return o; 28 } 29 30 fixed4 frag(output_data m):SV_Target//将颜色显示在屏幕上,SV_Target表示把输出的数据当做颜色存储到渲染目标中,用COLOR也可以 31 { 32 return fixed4(m.color,1);//输出红色 33 } 34 ENDCG 35 } 36 } 37 }
由上述代码可以看出vert的输出结构体被输出到frag函数中了。
仔细一想,这些结构体只有输入的结构体比较重要,与外部数据息息相关。input_data接收了模型的顶点位置,法线和贴图坐标。把这些宝贵信息送给顶点着色器函数vert();
而自定义的输出结构体其实和外界数据就没什么关系,顶多作为数据的存储载体,给片段着色器提供数据罢了,标上语义也就是个形式,注意语义还是要写的,虽然没啥意义。
但是SV_POSITION是个例外,顶点着色器的输出结构体中必须包含它,否则渲染器将无法得到裁剪空间中的顶点坐标,也就无法把顶点渲染到屏幕上。毕竟顶点着色器顶点
着色器,如果输出的连顶点坐标都没了,它还有啥意义。
frag()片段着色器后面跟着的那个SV_Target就是我们所弄出来的数据到底要输出什么,改变模型的什么。这里是输出颜色,其实COLOR也可以。
注意以上为了便于理解才写成input_data,output_data.实际书写时,一般把input_data书写为appdata,output_data书写为v2f(vert to frag)