实现一个简单地Shader
简单的Shader
Shader "Unlit/SimpleShader"
{
SubShader{
Pass{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
float4 vert(float4 v : POSITION) :SV_POSITION{
return mul(UNITY_MATRIX_MVP,v);
}
float4 frag() : SV_TARGET{
return fixed4(1.0,1.0,0.5f,1.0);
}
ENDCG
}
}
}
在CGPROGRAM到CGEND中间添加代码片段的编译指令和Cg代码.
#pragma vertex vert
#pragma fragment frag
告诉编译器那个函数执行顶点着色器,那个函数执行片元着色器.
float4 vert(float4 v : POSITION) :SV_POSITION{
return mul(UNITY_MATRIX_MVP,v);
}
使用顶点着色器代码,它是逐顶点进行,输入的参数包含了顶点位置,通过POSITION语义指定. 返回一个float4,它是该顶点在裁剪空间中的位置,通过SV_POSITION定义,UNITY_MATRIX_MVP是Unity内置的模型-观察-投影矩阵.
float4 frag() : SV_Target{
return fixed4(1.0,1.0,0.5f,1.0);
}
frag没有任何输入,输出一个float4,用SV_Target定义,等同于告诉渲染器,用户输出的颜色存储到一个渲染目标.
当我们需要更多的模型数据的时候,我们将为顶点着色器定义一个新的参数,这个参数将是一个结构体,结构体中包含了法线 切线 纹理坐标等诸多数据
struct a2v {
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
};
这里的a2v表示a(application) v(vertex shader),表示数据从应用阶段传递到顶点着色器中 POSITION等语义中的数据从MeshRender中传递过来,每帧调用DrawCall的时候,MeshRender将他负责渲染的数据传递给UnityShader. 在给顶点着色器传参数的时候传a2v结构体
我们声明一个结构体v2f,用于在顶点着色器和片元着色器之间进行传递数据,
struct v2f {
float4 pos : SV_POSITION;
fixed3 color : COLOR0;//COLOR0语义用于存储颜色信息
};
在顶点着色器中我们返回v2f的结构体,此结构体中包含了SV_POSITION,在顶点着色器中,我们给color值,来进行逐顶点的color插值,数值选用法线的相关值。
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;
}
在fragment中我们只用返回插值后的color
fixed4 frag(v2f i) : SV_Target{
return fixed4(i.color,1.0);
}
最终效果:
插值得到的新结果