在Unity中,不管什么种类的Shader,都是基于顶点片元着色器(Vertex Fragment Shader)制作的
完整案例
Shader "Hibari/VertexFragMentShader"
{
SubShader
{
pass
{
CGPROGRAM
#pragma vertex vert //声明VertexShader函数
#pragma fragment frag //声明fragmentShader函数
/*输入结构体:将数据从应用程序发送至顶点着色器*/
struct a2v
{
float4 vertex : POSITION; //传入顶点坐标
float4 normal : NORMAL; //传入顶点法向
float4 texcoord : TEXCOORD0; //传入纹理坐标
};
/*输出结构体:从顶点着色器获取数据,并输出至片元着色器*/
struct v2f
{
float4 myPosition : SV_POSITION; //从剪裁空间中获取顶点坐标
fixed3 myColor : COLOR0; //获取顶点色
};
/*定义顶点着色器函数*/
v2f vert(a2v input)
{
v2f output;
output.myPosition = UnityObjectToClipPos(input.vertex);
output.myColor = input.normal;
return output;
}
/*定义片元着色器函数*/
fixed4 frag(v2f input) : SV_Target
{
return fixed4(input.myColor, 1.0);
}
ENDCG
}
}
}
编译指令
编译指令用来告诉 着色器的函数 名字叫什么
注:虽然名字可以自定义,但通常会约定一个名字 vert:顶点着色器函数(Vertex Shader Function) frag:片元着色器函数(Fragment Shader Function)
#pragma vertex [function Name] //声明VertexShader函数
#pragma fragment [function Name] //声明fragmentShader函数
语义
在定义【变量或函数】时,后面会带一个【冒号+单词】,这个单词就是语义。
语义的作用: 在Shader编程过程中,我们需要获取渲染流水线中相关的模型数据 语义的作用就是,将【渲染流水线中相关的数据】与【函数、变量做关联】 通过变量达到读取数据和返回输出数据
//语法
Type varName : [语义] //将变量与语义做关联(表示读取)
tpye functionName() : [语义] //将返回值与语义做关联(表示输出)
typeA functionName(TypeB varName : [语义])
//将输入的参数与语义做关联,
//和返回值具有相同的功能(表示输出)
//示例
float4 vertex : POSITION;
fixed4 frag(v2f input) : SV_Target
{
return fixed(1,1,1,1);
}
顶点着色器输入输出结构体
有时候函数输入或者输出多个语义数据时,当个变量会不方便,做一个结构体会比较方便使用
a2v:应用程序输入到顶点着色器
a2v(Application To VertexShader) Application 应用程序(从cpu过来的模型数据) VertexShader 顶点着色器 将数据从应用程序中读取到顶点着色器
//示例
struct a2v
{
float4 vertex : POSITION; //传入顶点坐标
float4 normal : NORMAL; //传入顶点法向
float4 texcoord : TEXCOORD0; //传入纹理坐标
};
v2f:从顶点着色器到片元着色器
v2f(VertexShader To FragmentShader) VertexShader 顶点着色器 FragmentShader 片元着色器 将顶点数据输出到片元着色器
//示例
struct v2f
{
float4 myPosition : SV_POSITION; //从剪裁空间中获取顶点坐标
fixed3 myColor : COLOR0; //获取顶点色
};
着色器函数
顶点与片元着色器算法主要就写在这里面 vert:表示顶点着色器函数(VertexShaderFunction) frag:表示片元着色器函数(FragmentShaderFunction)
Vert:顶点着色器函数
顶点着色器函数需要从【应用程序】获取数据到【顶点着色器】,所以【函数参数a2v类型】 顶点着色器函数运算完成后,需要将数据输出到【片元着色器】,所以【返回值为v2f类型】
v2f vert(a2v input)
{
v2f output;
//修改数据
output.myPosition = UnityObjectToClipPos(input.vertex); //编辑顶点坐标
output.myColor = input.normal; //编辑顶点颜色
return output;
}
Frag:片元着色器函数
片元着色器需要从【顶点着色器】获取已经【运算完成信息】,所以【函数参数v2f类型】
注:片元着色器在运算完成后,只有一个信息(即将渲染结果保存到帧缓存) 因此不需要额外定义一个结构体,直接将函数的返回值与SV_Taregt做关联即可。
fixed4 frag(v2f input) : SV_Taregt
{
return fixed4(input.myColor, 1.0);
}