Shader笔记_002简单顶点/片元着色器扩展
< 返回列表时间: 2020-05-14来源:OSCHINA
参考<<shader入门精要>>第五章
一、如何获取其他模型数据
在001里介绍了通过POSITION获取顶点位置坐标,如果想的到更多的模型数据,比如我们想要得到模型上每个顶点的纹理坐标和法线方向
PS:我们可以通过纹理坐标来访问纹理 法线坐标一般用来计算光照
因此我们需要给顶点着色器定义一个新的参数·这个参数将不是一个简单的数据类型
而是一个结构体 Shader "Customer/SimpleShader003"{ SubShader{ Pass{ CGPROGRAM #pragma vertex vert #pragma fragment frag struct a2v{ float4 vertex: POSITION; float3 normal:NORMAL; float4 texcoord:TEXCOORD0; }; float4 vert(a2v v): SV_POSITION{ return mul(UNITY_MATRIX_MVP,v.vertex); } fixed4 frag(): SV_Target{ return fixed4(1.0,1.0,1.0,1.0); } ENDCG } } }
在上面的代码中 声明的结构体a2v 他包含了顶点着色器需要的模型数据
在a2v的定义中,我们用到了更多的UNITY支持的语义,如
NORMAL 和TEXCOORD0,当他们作为顶点着色器的输入时都是有特定含义的
因为UNITY会根据这些语义来填充这个结构体,对于顶点着色器的输出,UNITY
支持的语义有POSITION,TANGENT,NORMAL,TEXCOORD0,TEXCOORD1,TEXCOORD2
TEXCOORD3,COLOR等。
为了使用一个自定义的结构体,我们必须使用如下格式
struct name{
Type Name:Semantic;
Type Name:Semantic;
......
};
a表示应用 v表示顶点着色器 a2v的意义就是从应用阶段传递到顶点着色器中
那么填充到POSITION,TANGENT,NORMAL的语义里的数据酒究竟是从哪里来的呢?
在UNITY中,它们是由使用该材质的MeshRender组件提供的。
在每帧调用DRAW CALL的时候,MeshRender组件会把他负责渲染的模型的数据发送给UNITY SHADER,
我们知道,一个模型通常包含了一组三角面片。(我们不知道啊QAQ)
每个三角面片由三个顶点构成,而每个顶点又包含了一些数据,例如顶点位置、发现坐标、顶点颜色等等
通过上面的方法,我们就可以在顶点着色器中访问顶点的这些模型数据。
二、顶点、片元着色器之间如何相互通信
我们在实际开发的过程中,往往希望从顶点着色器输出一些数据,例如把模型的法线纹理坐标等传递给片元着色器
这就涉及到了顶点着色器和片元着色器之间的通信
为此我们需要新建一个结构体.修改后代码如下 Shader "Customer/SimpleShader004"{ SubShader{ Pass{ CGPROGRAM #pragma vertex vert #pragma fragment frag struct a2v{ float4 vertex:POSITION; float3 normal:NORMAL; float4 texcoord:TEXCOORD0; }; //使用一个结构体来定义顶点着色器的输出 struct v2f{ float4 pos :SV_POSITION; fixed3 color:COLOR0; }; v2f vert(a2v v):SV_POSITION{ v2f o; o.pos = mul(UNITY_MATRIX_MVP,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 } } }
在上面的代码中,我们声明了一个新的结构体v2f
v2f中也需要指定每个变量的语义,在本例中我们定义了SV_POSITION和COLOR0,顶点着色器的输出结构中,必须包含SV_POSITION,否则无法获取
裁剪空间的顶点坐标,COLOR0则由用户自己定义,一般是用来存颜色,例如逐顶点的漫反射颜色等,类似语义还有COLOR1
至此我们完成了从顶点着色器往片元着色器传递数据,顶点着色器是逐顶点的,片元着色器是逐片元的,因此片元着色器的输入实际是把顶点着色器的输出进行插值的结果
二、如何使用属性
unityshader和材质密不可分,shader提供了一些可以设置的参数来调试材质的效果,这些参数需要写在properties语义块里面
比如我们现在有一个新的需求,需要在面板上显示一个颜色拾取器,为此需要修改上面的代码 Shader "Customer/SimpleShader004"{ Properties{ //声明一个color类型的属性 _Color("Color Tint",Color) = (1.0,1.0,1.0,1.0) } SubShader{ Pass{ CGPROGRAM #pragma vertex vert #pragma fragment frag fixed4 _Color; struct a2v{ float4 vertex:POSITION; float3 normal:NORMAL; float4 texcoord:TEXCOORD0; }; struct v2f{ float4 pos:SV_POSITION; float3 color:COLOR0; }; v2f vert(a2v v) :SV_POSITION{ v2f o; o.pos = mul(UNITY_MATRIX_MVP,v.vertex); o.color = v.color*0.5+fixed3(0.5,0.5,0.5); return o; } fixed4 frag(v2f i):SV_Target{ fixed3 = i.color; c *=_Color.rgb; return fixed4(c,1.0); } ENDCG } } }
在上面的语句里我们定义了一个color,(1.0,1.0,1.0,1.0)代表的是白色
为了在CG代码里面访问他,我们还需要提前自己定义一个新变量 ,该变量名必须和属性里的变量名一致
ShaderLab中变量和CG类型中变量对应的关系如下所示

有时 CG变量前会有一个 uniform 关键字
uniform fixed4 _Color; 该关键字在CG里是用来修饰变量,仅仅提供该变量初始值的是如何指定和存储的相关信息,UNITY SHADER里该关键字可以省略。












热门排行