US5L13——表面着色器实现顶点膨胀

表面着色器中处理顶点的方法

在编译指令中:#pragma surface 表面函数名 光照模型 可选额外参数
可选额外参数中添加:vertex:自定义函数名
函数格式:void 自定义函数名(inout appdata_full v)

实现顶点膨胀效果

直接复用之前表面着色器使用发现贴图的代码,在此基础上进行修改,代码详见:US5L12——表面着色器使用法线贴图

  1. 加入顶点碰撞控制参数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Properties
    {
    _Color("Color", Color) = (1, 1, 1, 1)
    _MainTex("Albedo (RGB)", 2D) = "white"{}
    _BumpMap("BumpMap", 2D) = ""{}
    _Emission("Emission", Color) = (0, 0, 0, 0) // 自发光
    _Metallic("Metallic", Range(0, 1)) = 0 // 金属度
    _Smoothness("Smoothness", Range(0, 1)) = 0 // 光滑度
    _Expansion("Expansion", Float) = 0 // 顶点膨胀程度
    }
  2. 在编译指令中加入顶点处理函数

    1
    #pragma surface surf Standard fullforwardshadows vertex:vert
  3. 自定义顶点处理函数

  4. 在自定义顶点处理函数中对顶点进行偏移

    1
    2
    3
    4
    5
    void vert(inout appdata_full v)
    {
    // 让顶点坐标沿其发现方向向外扩充
    v.vertex.xyz += v.normal * _Expansion;
    }

完整 Shader 代码如下:

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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
Shader "TeachShader/Lesson140"
{
Properties
{
_Color("Color", Color) = (1, 1, 1, 1)
_MainTex("Albedo (RGB)", 2D) = "white"{}
_BumpMap("BumpMap", 2D) = ""{}
_Emission("Emission", Color) = (0, 0, 0, 0) // 自发光
_Metallic("Metallic", Range(0, 1)) = 0 // 金属度
_Smoothness("Smoothness", Range(0, 1)) = 0 // 光滑度
_Expansion("Expansion", Float) = 0 // 顶点膨胀程度
}
SubShader
{
Tags { "RenderType"="Opaque" }

CGPROGRAM
#pragma surface surf Standard fullforwardshadows vertex:vert
#pragma target 3.0

fixed4 _Color;
sampler2D _MainTex;
sampler2D _BumpMap;
fixed4 _Emission;
fixed _Metallic;
fixed _Smoothness;
float _Expansion; // 顶点膨胀程度

struct Input
{
float2 uv_MainTex;
float2 uv_BumpMap;
};

void vert(inout appdata_full v)
{
// 让顶点坐标沿其发现方向向外扩充
v.vertex.xyz += v.normal * _Expansion;
}

void surf (Input IN, inout SurfaceOutputStandard o)
{
fixed4 texColor = tex2D(_MainTex, IN.uv_MainTex);
o.Albedo = texColor.rgb; // 漫反射颜色
o.Alpha = texColor.a * _Color.a; // 透明度
o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap)); // 得到切线空间下的法线
o.Emission = _Emission.rgb; // 自发光颜色
o.Metallic = _Metallic; // 金属度
o.Smoothness = _Smoothness; // 光滑度
}

ENDCG
}
FallBack "Diffuse"
}

显示效果(膨胀程度0.4):

image

表面着色器使用最终颜色处理函数

可选额外参数中添加:finalcolor:自定义函数名​,
即可自定义最终颜色处理函数,函数格式为:void 自定义函数名(Input IN, SurfaceOutput... o, inout fixed4 color)
其中,第二个参数的结构体类型与表面函数的第二个参数的结构体类型一致

假设要让外部属性 Color​ 叠加在最终颜色上:

1
2
3
4
5
6
7
8
9
10
#pragma surface surf Standard fullforwardshadows vertex:vert finalcolor:finalColorProcess
#pragma target 3.0

fixed4 _Color;

void finalColorProcess(Input IN, SurfaceOutputStandard o, inout fixed4 color)
{
// 将颜色叠加到最终颜色上
color *= _Color;
}

显示效果(叠加红色):

image

完整 Shader 代码如下:

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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
Shader "TeachShader/Lesson140"
{
Properties
{
_Color("Color", Color) = (1, 1, 1, 1)
_MainTex("Albedo (RGB)", 2D) = "white"{}
_BumpMap("BumpMap", 2D) = ""{}
_Emission("Emission", Color) = (0, 0, 0, 0) // 自发光
_Metallic("Metallic", Range(0, 1)) = 0 // 金属度
_Smoothness("Smoothness", Range(0, 1)) = 0 // 光滑度
_Expansion("Expansion", Float) = 0 // 顶点膨胀程度
}
SubShader
{
Tags { "RenderType"="Opaque" }

CGPROGRAM
#pragma surface surf Standard fullforwardshadows vertex:vert finalcolor:finalColorProcess
#pragma target 3.0

fixed4 _Color;
sampler2D _MainTex;
sampler2D _BumpMap;
fixed4 _Emission;
fixed _Metallic;
fixed _Smoothness;
float _Expansion; // 顶点膨胀程度

struct Input
{
float2 uv_MainTex;
float2 uv_BumpMap;
};

void vert(inout appdata_full v)
{
// 让顶点坐标沿其发现方向向外扩充
v.vertex.xyz += v.normal * _Expansion;
}

void surf (Input IN, inout SurfaceOutputStandard o)
{
fixed4 texColor = tex2D(_MainTex, IN.uv_MainTex);
o.Albedo = texColor.rgb; // 漫反射颜色
o.Alpha = texColor.a * _Color.a; // 透明度
o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap)); // 得到切线空间下的法线
o.Emission = _Emission.rgb; // 自发光颜色
o.Metallic = _Metallic; // 金属度
o.Smoothness = _Smoothness; // 光滑度
}

void finalColorProcess(Input IN, SurfaceOutputStandard o, inout fixed4 color)
{
// 将外部属性颜色叠加到最终颜色上
color *= _Color;
}

ENDCG
}
FallBack "Diffuse"
}