Unity Shader:(四)从0到1动手写一个调色板Shader
0. 先写一个嘿简单的Shader
1 Shader "Test/SimpleShader" 2 { 3 SubShader 4 { 5 Pass 6 { 7 CGPROGRAM 8 #pragma vertex vert //代表顶点着色器的函数名 9 #pragma fragment frag //代表片元着色器的函数名 10 float4 vert(float4 v:POSITION) :SV_POSITION //加粗部分是CG里的语义,是固定的 11 { 12 return UnityObjectToClipPos(v); 13 } 14 fixed4 frag() : SV_Target 15 { 16 return fixed4(1.0,1.0,1.0,1.0); //代表的Color,(1,1,1)是白色,(0,0,0)是黑色 17 } 18 ENDCG 19 } 20 } 21 }
要定义更多的数据就要用到结构体了,来看看怎么写吧。
1 Shader "Test/SimpleShader" 2 { 3 SubShader 4 { 5 Pass 6 { 7 CGPROGRAM 8 #pragma vertex vert 9 #pragma fragment frag 10 11 //使用结构体来定义顶点着色器的输入 12 struct a2v 13 { 14 float4 vertex:POSITION; //用模型空间的顶点坐标填充vertex 15 float3 normal:NORMAL; //用模型空间的法线方向填充normal 16 float4 texcoord:TEXCOORD0; //用模型的第一套纹理填充texcoord 17 }; 18 float4 vert(a2v v) :SV_POSITION //注意传参是结构体参数 19 { 20 return UnityObjectToClipPos (v.vertex); 21 } 22 fixed4 frag() : SV_Target 23 { 24 return fixed4(1.0,1.0,1.0,1.0); 25 } 26 ENDCG 27 } 28 } 29 }
现在做一个颜色渐变的小球吧!!!需要把顶点着色器的信息传给片元着色器,那么就要定义一个结构体struct v2f 和方法v2f vert(a2v v) 来接收顶点着色器的输出。然后把返回值传给片元着色器fixed4 frag(v2f i): SV_Target
Shader "Test/SimpleShader" { SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag //使用结构体来定义顶点着色器的输入 struct a2v { float4 vertex:POSITION; //用模型空间的顶点坐标填充vertex float3 normal:NORMAL; //用模型空间的法线方向填充normal float4 texcoord:TEXCOORD0; //用模型的第一套纹理填充texcoord }; struct v2f { float4 pos:POSITION; fixed3 color : COLOR0; }; v2f vert(a2v v) { v2f o; o.pos = UnityObjectToClipPos(v.vertex); o.color = v.normal*0.5 + fixed3(0.5, 0.5, 0.5); return o; } fixed4 frag(v2f i) : SV_Target { return fixed4(i.color,1.0); } ENDCG } } }
效果图:
哎呀再前进一步!在材质面板显示一个颜色拾取器方便控制颜色。
根据前面介绍的,我们可以通过定义一个颜色属性,来显示到材质面板。再把这个属性赋值给片元着色器。下面加粗部分是新增加的代码。
1 Shader "Test/SimpleShader" 2 { 3 Properties{ _Color("Pick Color",Color)=(1.0,1.0,1.0,1.0)} 4 SubShader 5 { 6 Pass 7 { 8 CGPROGRAM 9 #pragma vertex vert 10 #pragma fragment frag 11 12 fixed4 _Color; 13 14 //使用结构体来定义顶点着色器的输入 15 struct a2v 16 { 17 float4 vertex:POSITION; //用模型空间的顶点坐标填充vertex 18 float3 normal:NORMAL; //用模型空间的法线方向填充normal 19 float4 texcoord:TEXCOORD0; //用模型的第一套纹理填充texcoord 20 }; 21 struct v2f 22 { 23 float4 pos:POSITION; 24 fixed3 color : COLOR0; 25 }; 26 27 v2f vert(a2v v) 28 { 29 v2f o; 30 o.pos = UnityObjectToClipPos(v.vertex); 31 o.color = v.normal*0.5 + fixed3(0.5, 0.5, 0.5); 32 return o; 33 } 34 fixed4 frag(v2f i) : SV_Target 35 { 36 fixed3 c = i.color; 37 c *= _Color.rgb; //这里是*,就是叠加这个效果 38 return fixed4(c,1.0); 39 } 40 ENDCG 41 } 42 } 43 }
效果图:可以看得出来是叠加效果。
下一节我们再介绍语义,调式,优化。