Unity Shader入门教程(二) :实现顶点和片元着色器之间的通信
程序员文章站
2022-03-30 13:45:13
...
这篇文章将介绍Pass{}内的代码的编写。我们先看如下Unity Shader代码:(此文部分采自《unity shader入门精要》)
关于顶点着色器和片元着色器不懂的学习可以自行搜索概念的意思,这里就不介绍了。
Shader "Custom/myTest" {
SubShader {
Pass{
CGPROGRAM
//申明顶点着色器函数
#pragma vertex vert
//申明片元着色器函数
#pragma fragment frag
//使用一个结构体来定义顶点着色器的输入
struct a2v{
//POSITION语义告诉Unity,用模型空间的顶点坐标填充vertex变量
float4 vertex : POSITION;
//NORMAL语义告诉Unity,用模型空间的法向量方向填充normal变量
float3 normal : NORMAL;
//TEXCOORD0语义告诉Unity,用模型的第一套纹理坐标填充texcoord变量
float4 texcoord : TEXCOORD0;
};
//如果没有自定义的结构体,则可写成float4 vert(float4 v : POSITION) : SV_POSITION
float4 vert(a2v v) : SV_POSITION{
//使用v.vertex来访问模型空间的顶点坐标
return UnityObjectToClipPos(v.vertex);
}
float4 frag() : SV_Target{
return fixed4(1.0, 1.0, 1.0, 1.0); //fixed4(r, g, b, a),取值范围为[0,1]
}
ENDCG
}
}
FallBack "Diffuse"
}
其中POSITION、NORMAL等大写的语义代表CG/HLSL语义,告诉GPU以怎样的方式进行渲染。该代码就表示了顶点/片元着色器以怎样的方式进行渲染。然而在实践中,我们往往希望从顶点着色器输出一些数据,例如把模型的法线、纹理坐标等传递给片元着色器,这就需要再定义一个新的结构体。修改后代码如下:
Shader "Custom/myTest" {
SubShader {
Pass{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
struct a2v{
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
};
//使用一个结构体来定义顶点着色器的输出
struct v2f{
//SV_POSITION语义告诉Unity,pos里面包含了顶点在裁切空间中的位置信息
float4 pos : SV_POSITION;
//COLOR0语义可以用于存储颜色信息
fixed3 color : COLOR0;
};
v2f vert(a2v v){
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
//v.normal包含了顶点的法线方向,其分量范围在[-1.0,1.0]
//下面的代码把分量范围映射到了[0.0, 1.0]
//存储到o.color中传递给片元着色器
o.color = v.normal * 0.5 + fixed3(0.5, 0.5, 0.5);
return o;
}
fixed4 frag(v2f i) : SV_Target{
//将插值后的i.color显示到屏幕上
return fixed4(i.color, 1.0);
}
ENDCG
}
}
FallBack "Diffuse"
}
在上面代码中,顶点着色器的输出结构中,必须包含一个变量,它的语义是SV_POSITION。否则,渲染器将无法得到裁切空间中的顶点坐标,也就无法将顶点渲染到屏幕上。COLOR0语义中的数据则可以由用户自己定义,但一般是存储颜色。
上一篇: Java通过Spring配置发送QQ邮件