US2S3L10——顶点-片元着色器传递更多参数

顶点/片元着色器传递更多参数

如果顶点/片元着色器想要传递更多参数,我们需要通过结构体进行封装,用语义修饰结构体成员变量来达到目的

注意:只有顶点/片元着色器的回调函数相关参数和返回值才需要通过语义修饰
一般的自定义函数是不需要语义的,因为我们自己调用自己的自定义函数是可以明确知道每个参数的作用的

顶点着色器获取更多数据信息

当我们在顶点着色器当中想要获取更多模型相关信息时,可以使用结构体对数据进行封装
通过对结构体中成员变量加语义的方式来定义想要获取的信息

使用结构体作为参数和返回值类型后,函数的参数和返回值就不需要再使用语义进行修饰了

我们也可以不用自己声明结构体,而使用Unity定义好的结构体,详见:结构体(UnityCG.cginc中)

假设顶点着色器需要接收来自应用阶段的更多语义的参数,如:模型空间下的顶点坐标,顶点法线,uv坐标
这时我们需要声明一个结构体,其中的成员使用对应的语义修饰,然后将其作为顶点着色器的参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#pragma vertex myVert

//从应用阶段获取对应语义数据后,传递给顶点着色器的回调函数的结构体
struct a2v
{
float4 vertex : POSITION; //顶点坐标(基于模型空间)
float3 normal : NORMAL; //顶点法线(基于模型空间)
float2 uv : TEXCOORD0; //纹理坐标(uv)
};

float4 myVert(a2v data) : SV_POSITION
{
v2f v2fData; //需要传递给片元着色器的数据
v2fData.postion = UnityObjectToClipPos(data.vertex);
v2fData.normal = data.normal; //以后学习了相关内容再去处理它,目前暂时直接赋值
v2fData.uv = data.uv; //以后学习了相关内容再去处理它,目前暂时直接赋值

return UnityObjectToClipPos(data.vertex);
}

片元着色器获取更多数据信息

当我们在片元着色器当中想要获取更多信息时,采用的方式还是**封装结构体的方式**

注意:片元着色器中获取的数据基本上都是由顶点着色器传递过来的
所以我们封装的结构体还需要作为顶点着色器的返回值类型

假设片元着色器需要接收顶点着色器的输出的裁剪空间的坐标,还需要顶点法线和uv坐标,
这时我们也需要声明一个结构体,其中的成员使用对应的语义修饰,
然后将其作为顶点着色器的返回值,片元着色器的参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#pragma vertex myVert
#pragma fragment myFrag

//从应用阶段获取对应语义数据后,传递给顶点着色器的回调函数的结构体
struct a2v
{
float4 vertex : POSITION; //顶点坐标(基于模型空间)
float3 normal : NORMAL; //顶点法线(基于模型空间)
float2 uv : TEXCOORD0; //纹理坐标(uv)
};

//从顶点着色器传递给片元着色器的结构体数据,同样这里的成员也需要用语义去进行修饰
struct v2f
{
float4 postion : SV_POSITION; //裁剪空间下的坐标
float3 normal : NORMAL; //顶点法线(基于模型空间)
float2 uv : TEXCOORD0; //纹理坐标(uv)
};

v2f myVert(a2v data)
{
v2f v2fData; //需要传递给片元着色器的数据
v2fData.postion = UnityObjectToClipPos(data.vertex);
v2fData.normal = data.normal; //以后学习了相关内容再去处理它,目前暂时直接赋值
v2fData.uv = data.uv; //以后学习了相关内容再去处理它,目前暂时直接赋值

return v2fData;
}

fixed4 myFrag(v2f data) : SV_Target
{
//得到顶点着色器传递过来的data,经过处理后输出片元颜色
return fixed4(1, 0, 0, 1);
}