本篇用一个案例来讲述vf着色器的基础。
案例 1.0
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader "ShaderLearning/1_SimpleShader"{
Properties{
}
SubShader{
Tags{
}
pass{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
//顶点着色器代码,它是逐顶点执行得
//POSITION / SV_POSITION 都是 CG/HLSL中得语义。负责告诉系统输入值和输出值
//POSITION把模型顶点坐标填充到 v 中输入系统
//SV_POSITION告诉 unity 输出得是 裁剪空间中得顶点坐标
//如果没有这些 语义 的话, 渲染起完全不知道输入输出是什么
float4 vert(float4 v:POSITION) : SV_POSITION{
return UnityObjectToClipPos(v); //将模型的顶点坐标转换成裁剪坐标
}
//SV_TARGET是系统值,表示该函数返回的是用于下一个阶段OutPut Merger的颜色值
fixed4 frag():SV_TARGET{
return fixed4(1,1,0,0); //返回一个自定义的颜色值
}
ENDCG
}
}
Fallback "VertexLit"
}
结果
将此shader赋予材质球,结果将是给材质球染上一层黄色。
到此为止,一个最基础不过的vf着色器就写好了。接下来,我们逐渐丰富器内容。
案例2.0
要想呈现效果更丰富,那么得获取到一些数据,然后加以修改才行。
在CGPROGRAM下,我们要定义一些要获取的数据类型:
//定义输入顶点着色器阶段的数据类型
//a : application v : vertex
//我们知道,渲染流水线分为3个阶段:应用阶段,几何阶段(包含顶点着色器),光栅化阶段(包含片元着色器)
//a2v意即将数据从应用阶段传到顶点着色器中
struct a2v{
//语义的作用:
float4 vertex:POSITION; //用模型空间的顶点坐标填充
float3 normal:NORMAL; //用模型空间的法线方向填充
float4 texcoord:TEXCOORD; //用模型的第一套纹理坐标填充
//此外还有有一些其他的语义:TANGENT,COLOR,TEXCOORD1-3 等等。
//详情:https://msdn.microsoft.com/en-us/library/windows/desktop/bb509647.aspx
//那么,这些语义的数据从哪里获得呢?
//在unity中,他们是由使用该材质的Mesh Render提供的。在每帧调用DC的时候,该组件会把它负责渲染的模型数据发送给unity shader
};
//顶点着色器 和 片元着色器 之间的通信
//此结构体定义由顶点着色器传入片元着色器的数据结构
struct v2f{
//SV_POSITION告诉unity , pos里包含了顶点在裁剪空间中的位置信息。
float4 pos : SV_POSITION;
//COLOR0语义可以用于存储颜色信息
fixed3 color : COLOR0;
};
然后在顶点着色器、片元着色器阶段处理这些数据:
//因为要返回的数据类型已经在v2f中定义,所以此时要把SV_POSITION删除
v2f vert(a2v v) {
v2f o;
//将模型的顶点坐标转换成裁剪坐标
o.pos = UnityObjectToClipPos(v.vertex);
//v.normal包含顶点的法线方向,其分量范围在【-1,1】
//通过下列公式,将值映射在【0,1】,使得颜色更加明亮
o.color = v.normal * 0.5 + fixed3(0.5,0.5,0.5);
return o;
}
//SV_TARGET是系统值,表示该函数返回的是用于下一个阶段OutPut Merger的颜色值
fixed4 frag(v2f i):SV_TARGET{
return fixed4(i.color,1); //返回一个颜色插值
}
结果
这样就能使材质按照其法线值来染上相应的颜色。
案例3.0
到目前为止,我们只是获取模型上的顶点数据来进行修改呈现,接下来我们通过获取外部数据来修改呈现效果。
Properties{
_Color("Color Tint",Color) = (1,1,1,1)
}
pass{
...
fixed4 _Color;
...
fixed4 frag(v2f i):SV_TARGET{
fixed3 c = i.color;
//使用_Color来控制输出颜色
c *= _Color.rgb;
return fixed4(c,1); //返回一个颜色插值
}
...
}
结果
这就能够在材质面板中,调节参数,来控制显示结果
网友评论