第10.3章:3D力场着色器

力场着色器是科幻游戏中的核心视觉特效,用于表现能量护盾、防护罩、磁场等科技元素。本章将深入探讨各种力场效果的实现技术。

🎯 学习目标

  • 理解力场视觉效果的原理- 掌握球形、六边形网格力场实现
  • 学会冲击波和能量传播效果
  • 理解3D空间中的力场交互

💡 力场效果原理

视觉特征分析

力场具有以下特征�?

1
2
3
4
5
6
// 力场关键要素
1. 透明�?- 半透明能量�?2. 网格模式 - 六边形或方形网格
3. 边缘增强 - 菲涅尔反�?4. 冲击反应 - 局部激活效�?5. 能量流动 - 动态扰�?```

### 效果组成

基础几何 �?网格模式 �?菲涅�?�?冲击检�?�?能量动画
�? �? �? �? �? sphere hexagon fresnel impact pulse

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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133

## 🔧 基础力场实现

### 1. 球形能量护盾

```glsl
CCEffect %{
techniques:
- name: sphere-force-field
passes:
- vert: force-field-vs:vert
frag: force-field-fs:frag
blendState:
targets:
- blend: true
blendSrc: src_alpha
blendDst: one_minus_src_alpha
rasterizerState:
cullMode: none
properties: &props
shieldColor: { value: [0.2, 0.8, 1.0, 1.0], editor: { type: color } }
gridScale: { value: 20.0, range: [5.0, 100.0] }
gridThickness: { value: 0.05, range: [0.01, 0.2] }
energySpeed: { value: 2.0, range: [0.0, 10.0] }
fresnel_power: { value: 2.0, range: [0.1, 5.0] }
fresnel_intensity:{ value: 1.5, range: [0.0, 3.0] }
transparency: { value: 0.3, range: [0.0, 1.0] }
noiseTexture: { value: white }
pulseIntensity: { value: 1.0, range: [0.0, 3.0] }
}%

CCProgram force-field-vs %{
precision highp float;
#include <cc-global>
#include <cc-local>

in vec3 a_position;
in vec3 a_normal;
in vec2 a_texCoord;

out vec3 v_worldPos;
out vec3 v_worldNormal;
out vec2 v_uv;
out vec3 v_spherePos;

vec4 vert() {
vec4 worldPos = cc_matWorld * vec4(a_position, 1);
v_worldPos = worldPos.xyz;
v_worldNormal = normalize((cc_matWorldIT * vec4(a_normal, 0)).xyz);
v_uv = a_texCoord;

// 球面坐标计算
v_spherePos = normalize(a_position);

return cc_matViewProj * worldPos;
}
}%

CCProgram force-field-fs %{
precision highp float;
#include <cc-global>
#include <cc-environment>

uniform sampler2D noiseTexture;
uniform vec4 shieldColor;
uniform float gridScale;
uniform float gridThickness;
uniform float energySpeed;
uniform float fresnel_power;
uniform float fresnel_intensity;
uniform float transparency;
uniform float pulseIntensity;

in vec3 v_worldPos;
in vec3 v_worldNormal;
in vec2 v_uv;
in vec3 v_spherePos;

// 六边形网格函�? float hexagonGrid(vec2 uv) {
// 转换为六边形坐标�? vec2 s = vec2(1.0, 1.732) * gridScale;
vec2 r = vec2(1.0, 0.5);

vec2 h = r * uv.y;
vec2 a = mod(uv * s - h, s) - s * 0.5;
vec2 b = mod(uv * s - h - s * 0.5, s) - s * 0.5;

vec2 gv = dot(a, a) < dot(b, b) ? a : b;
float d = length(gv);

return smoothstep(gridThickness, gridThickness + 0.01, d);
}

vec4 frag() {
vec3 normal = normalize(v_worldNormal);
vec3 viewDir = normalize(cc_cameraPos.xyz - v_worldPos);

// 球面UV映射
float phi = atan(v_spherePos.z, v_spherePos.x);
float theta = acos(v_spherePos.y);
vec2 sphereUV = vec2(phi / 6.28318 + 0.5, theta / 3.14159);

// 时间偏移的噪声采�? vec2 noiseUV = sphereUV + cc_time.x * energySpeed * 0.1;
vec4 noise = texture(noiseTexture, noiseUV);

// 六边形网�? vec2 gridUV = sphereUV + noise.rg * 0.05;
float hexGrid = hexagonGrid(gridUV);

// 菲涅尔反�? float fresnel = 1.0 - max(0.0, dot(normal, viewDir));
fresnel = pow(fresnel, fresnel_power) * fresnel_intensity;

// 能量脉冲
float pulse = sin(cc_time.x * energySpeed * 2.0) * 0.3 + 0.7;
pulse += noise.b * 0.3;

// 合成护盾效果
vec3 shieldFinal = shieldColor.rgb;

// 网格发光
shieldFinal += shieldColor.rgb * (1.0 - hexGrid) * 0.5 * pulse;

// 边缘发光
shieldFinal += shieldColor.rgb * fresnel;

// 噪声能量�? shieldFinal += shieldColor.rgb * noise.r * 0.3 * pulse;

// 最终透明�? float finalAlpha = transparency;
finalAlpha += (1.0 - hexGrid) * 0.2 * pulse;
finalAlpha += fresnel * 0.4;
finalAlpha *= pulseIntensity;

return vec4(shieldFinal, finalAlpha);
}
}%

2. 冲击反应力场

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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
CCEffect %{
techniques:
- name: impact-force-field
passes:
- vert: impact-vs:vert
frag: impact-fs:frag
blendState:
targets:
- blend: true
blendSrc: src_alpha
blendDst: one
properties: &props
shieldColor: { value: [1.0, 0.4, 0.2, 1.0], editor: { type: color } }
impactPosition: { value: [0.0, 0.0, 0.0], editor: { type: vec3 } }
impactRadius: { value: 2.0, range: [0.1, 10.0] }
impactIntensity: { value: 3.0, range: [0.0, 10.0] }
waveSpeed: { value: 5.0, range: [1.0, 20.0] }
rippleCount: { value: 5.0, range: [1.0, 20.0] }
gridScale: { value: 15.0, range: [5.0, 50.0] }
distortionScale: { value: 0.1, range: [0.0, 0.5] }
noiseTexture: { value: white }
baseTransparency: { value: 0.2, range: [0.0, 1.0] }
}%

CCProgram impact-vs %{
precision highp float;
#include <cc-global>
#include <cc-local>

in vec3 a_position;
in vec3 a_normal;
in vec2 a_texCoord;

out vec3 v_worldPos;
out vec3 v_worldNormal;
out vec2 v_uv;

vec4 vert() {
vec4 worldPos = cc_matWorld * vec4(a_position, 1);
v_worldPos = worldPos.xyz;
v_worldNormal = normalize((cc_matWorldIT * vec4(a_normal, 0)).xyz);
v_uv = a_texCoord;

return cc_matViewProj * worldPos;
}
}%

CCProgram impact-fs %{
precision highp float;
#include <cc-global>
#include <cc-environment>

uniform sampler2D noiseTexture;
uniform vec4 shieldColor;
uniform vec3 impactPosition;
uniform float impactRadius;
uniform float impactIntensity;
uniform float waveSpeed;
uniform float rippleCount;
uniform float gridScale;
uniform float distortionScale;
uniform float baseTransparency;

in vec3 v_worldPos;
in vec3 v_worldNormal;
in vec2 v_uv;

vec4 frag() {
vec3 normal = normalize(v_worldNormal);
vec3 viewDir = normalize(cc_cameraPos.xyz - v_worldPos);

// 冲击点距�? float distanceToImpact = length(v_worldPos - impactPosition);

// 冲击波计�? float wave = sin((distanceToImpact - cc_time.x * waveSpeed) * rippleCount);
wave = wave * 0.5 + 0.5;

// 冲击衰减
float impactFade = 1.0 - smoothstep(0.0, impactRadius, distanceToImpact);
float impactEffect = wave * impactFade * impactIntensity;

// 扭曲效果
vec2 distortedUV = v_uv + normal.xy * impactEffect * distortionScale;
vec4 noise = texture(noiseTexture, distortedUV + cc_time.x * 0.1);

// 网格模式
vec2 gridUV = distortedUV * gridScale;
vec2 grid = abs(fract(gridUV) - 0.5) / fwidth(gridUV);
float gridLines = min(grid.x, grid.y);
gridLines = 1.0 - min(gridLines, 1.0);

// 菲涅尔反�? float fresnel = 1.0 - max(0.0, dot(normal, viewDir));
fresnel = pow(fresnel, 2.0);

// 合成效果
vec3 shieldFinal = shieldColor.rgb * baseTransparency;

// 冲击波发�? shieldFinal += shieldColor.rgb * impactEffect;

// 网格激�? shieldFinal += shieldColor.rgb * gridLines * (1.0 + impactEffect);

// 边缘增强
shieldFinal += shieldColor.rgb * fresnel * (1.0 + impactEffect * 0.5);

// 噪声扰动
shieldFinal += shieldColor.rgb * noise.r * impactEffect * 0.5;

// 最终透明�? float finalAlpha = baseTransparency;
finalAlpha += impactEffect * 0.7;
finalAlpha += gridLines * 0.3;
finalAlpha += fresnel * 0.4;

return vec4(shieldFinal, finalAlpha);
}
}%

3. 磁场力线效果

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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
CCEffect %{
techniques:
- name: magnetic-field
passes:
- vert: magnetic-vs:vert
frag: magnetic-fs:frag
blendState:
targets:
- blend: true
blendSrc: src_alpha
blendDst: one_minus_src_alpha
properties: &props
fieldColor: { value: [0.8, 0.2, 1.0, 1.0], editor: { type: color } }
magnetCenter1: { value: [2.0, 0.0, 0.0], editor: { type: vec3 } }
magnetCenter2: { value: [-2.0, 0.0, 0.0], editor: { type: vec3 } }
fieldStrength: { value: 2.0, range: [0.1, 10.0] }
lineThickness: { value: 0.02, range: [0.005, 0.1] }
flowSpeed: { value: 3.0, range: [0.0, 10.0] }
density: { value: 20.0, range: [5.0, 100.0] }
noiseTexture: { value: white }
transparency: { value: 0.6, range: [0.0, 1.0] }
}%

CCProgram magnetic-vs %{
precision highp float;
#include <cc-global>
#include <cc-local>

in vec3 a_position;
in vec3 a_normal;
in vec2 a_texCoord;

out vec3 v_worldPos;
out vec3 v_worldNormal;
out vec2 v_uv;

vec4 vert() {
vec4 worldPos = cc_matWorld * vec4(a_position, 1);
v_worldPos = worldPos.xyz;
v_worldNormal = normalize((cc_matWorldIT * vec4(a_normal, 0)).xyz);
v_uv = a_texCoord;

return cc_matViewProj * worldPos;
}
}%

CCProgram magnetic-fs %{
precision highp float;
#include <cc-global>
#include <cc-environment>

uniform sampler2D noiseTexture;
uniform vec4 fieldColor;
uniform vec3 magnetCenter1;
uniform vec3 magnetCenter2;
uniform float fieldStrength;
uniform float lineThickness;
uniform float flowSpeed;
uniform float density;
uniform float transparency;

in vec3 v_worldPos;
in vec3 v_worldNormal;
in vec2 v_uv;

// 磁场线计�? vec3 magneticField(vec3 pos) {
vec3 field1 = (pos - magnetCenter1) / pow(length(pos - magnetCenter1), 3.0);
vec3 field2 = -(pos - magnetCenter2) / pow(length(pos - magnetCenter2), 3.0);
return fieldStrength * (field1 + field2);
}

vec4 frag() {
vec3 normal = normalize(v_worldNormal);
vec3 viewDir = normalize(cc_cameraPos.xyz - v_worldPos);

// 计算磁场方向
vec3 fieldVector = magneticField(v_worldPos);
vec3 fieldDirection = normalize(fieldVector);
float fieldMagnitude = length(fieldVector);

// 沿磁场线的坐�? float fieldLinePos = dot(v_worldPos, fieldDirection);

// 垂直于磁场线的距�? vec3 perpendicular = v_worldPos - fieldLinePos * fieldDirection;
float perpDistance = length(perpendicular);

// 磁场线强�? float lineIntensity = 1.0 - smoothstep(0.0, lineThickness, perpDistance);
lineIntensity *= fieldMagnitude;

// 流动效果
float flow = sin((fieldLinePos + cc_time.x * flowSpeed) * density);
flow = flow * 0.5 + 0.5;

// 噪声扰动
vec4 noise = texture(noiseTexture, v_uv + cc_time.x * 0.1);
lineIntensity *= (noise.r * 0.5 + 0.5);

// 菲涅尔反�? float fresnel = 1.0 - max(0.0, dot(normal, viewDir));
fresnel = pow(fresnel, 2.0);

// 合成磁场效果
vec3 fieldFinal = fieldColor.rgb * lineIntensity * flow;
fieldFinal += fieldColor.rgb * fresnel * 0.5;

// 最终透明�? float finalAlpha = transparency * lineIntensity * flow;
finalAlpha += fresnel * 0.3;

return vec4(fieldFinal, finalAlpha);
}
}%

🎨 高级力场特效

1. 多层防护系统

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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
CCEffect %{
techniques:
- name: multi-layer-shield
passes:
- vert: multi-shield-vs:vert
frag: multi-shield-fs:frag
blendState:
targets:
- blend: true
blendSrc: src_alpha
blendDst: one_minus_src_alpha
properties: &props
layer1Color: { value: [0.2, 0.8, 1.0, 1.0], editor: { type: color } }
layer2Color: { value: [1.0, 0.6, 0.2, 1.0], editor: { type: color } }
layer3Color: { value: [0.8, 0.2, 1.0, 1.0], editor: { type: color } }
layer1Radius: { value: 1.0, range: [0.5, 2.0] }
layer2Radius: { value: 1.2, range: [0.7, 2.5] }
layer3Radius: { value: 1.5, range: [1.0, 3.0] }
rotationSpeed1: { value: 1.0, range: [0.0, 5.0] }
rotationSpeed2: { value: -1.5, range: [-5.0, 5.0] }
rotationSpeed3: { value: 0.8, range: [0.0, 5.0] }
interference: { value: 0.3, range: [0.0, 1.0] }
shieldStrength: { value: 1.0, range: [0.0, 3.0] }
noiseTexture: { value: white }
}%

CCProgram multi-shield-vs %{
precision highp float;
#include <cc-global>
#include <cc-local>

in vec3 a_position;
in vec3 a_normal;
in vec2 a_texCoord;

out vec3 v_worldPos;
out vec3 v_worldNormal;
out vec2 v_uv;
out float v_distanceFromCenter;

vec4 vert() {
vec4 worldPos = cc_matWorld * vec4(a_position, 1);
v_worldPos = worldPos.xyz;
v_worldNormal = normalize((cc_matWorldIT * vec4(a_normal, 0)).xyz);
v_uv = a_texCoord;
v_distanceFromCenter = length(a_position);

return cc_matViewProj * worldPos;
}
}%

CCProgram multi-shield-fs %{
precision highp float;
#include <cc-global>
#include <cc-environment>

uniform sampler2D noiseTexture;
uniform vec4 layer1Color;
uniform vec4 layer2Color;
uniform vec4 layer3Color;
uniform float layer1Radius;
uniform float layer2Radius;
uniform float layer3Radius;
uniform float rotationSpeed1;
uniform float rotationSpeed2;
uniform float rotationSpeed3;
uniform float interference;
uniform float shieldStrength;

in vec3 v_worldPos;
in vec3 v_worldNormal;
in vec2 v_uv;
in float v_distanceFromCenter;

// 旋转六边形网�? float rotatedHexGrid(vec2 uv, float rotation, float scale) {
float c = cos(rotation);
float s = sin(rotation);
mat2 rot = mat2(c, -s, s, c);
uv = rot * uv;

vec2 gridUV = uv * scale;
vec2 grid = abs(fract(gridUV) - 0.5) / fwidth(gridUV);
float gridLines = min(grid.x, grid.y);
return 1.0 - min(gridLines, 1.0);
}

vec4 frag() {
vec3 normal = normalize(v_worldNormal);
vec3 viewDir = normalize(cc_cameraPos.xyz - v_worldPos);

// 层级判断
float layer1Mask = smoothstep(layer1Radius - 0.1, layer1Radius, v_distanceFromCenter);
float layer2Mask = smoothstep(layer2Radius - 0.1, layer2Radius, v_distanceFromCenter);
float layer3Mask = smoothstep(layer3Radius - 0.1, layer3Radius, v_distanceFromCenter);

// 旋转网格
float grid1 = rotatedHexGrid(v_uv, cc_time.x * rotationSpeed1, 15.0);
float grid2 = rotatedHexGrid(v_uv, cc_time.x * rotationSpeed2, 20.0);
float grid3 = rotatedHexGrid(v_uv, cc_time.x * rotationSpeed3, 25.0);

// 噪声干扰
vec4 noise = texture(noiseTexture, v_uv + cc_time.x * 0.2);
float noiseInterference = noise.r * interference;

// 菲涅尔反�? float fresnel = 1.0 - max(0.0, dot(normal, viewDir));
fresnel = pow(fresnel, 2.0);

// 层级效果合成
vec3 shieldFinal = vec3(0.0);
float finalAlpha = 0.0;

// 第一�? if (layer1Mask > 0.0) {
vec3 layer1 = layer1Color.rgb * grid1 * (1.0 + noiseInterference);
layer1 += layer1Color.rgb * fresnel;
shieldFinal += layer1 * layer1Mask * shieldStrength;
finalAlpha += layer1Mask * 0.3;
}

// 第二�? if (layer2Mask > 0.0) {
vec3 layer2 = layer2Color.rgb * grid2 * (1.0 + noiseInterference);
layer2 += layer2Color.rgb * fresnel;
shieldFinal += layer2 * layer2Mask * shieldStrength;
finalAlpha += layer2Mask * 0.25;
}

// 第三�? if (layer3Mask > 0.0) {
vec3 layer3 = layer3Color.rgb * grid3 * (1.0 + noiseInterference);
layer3 += layer3Color.rgb * fresnel;
shieldFinal += layer3 * layer3Mask * shieldStrength;
finalAlpha += layer3Mask * 0.2;
}

// 边缘增强
shieldFinal += mix(layer1Color.rgb, layer3Color.rgb, 0.5) * fresnel;
finalAlpha += fresnel * 0.4;

return vec4(shieldFinal, finalAlpha);
}
}%

🔧 TypeScript控制系统

力场控制�?

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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
import { Component, Material, Color, Vec3, _decorator } from 'cc';

const { ccclass, property, menu } = _decorator;

@ccclass('ForceFieldController')
@menu('Custom/ForceFieldController')
export class ForceFieldController extends Component {

@property({ type: Color, displayName: '力场颜色' })
public shieldColor: Color = new Color(50, 200, 255, 255);

@property({ range: [0.0, 1.0], displayName: '透明�? })
public transparency: number = 0.3;

@property({ range: [5.0, 100.0], displayName: '网格密度' })
public gridScale: number = 20.0;

@property({ range: [0.01, 0.2], displayName: '网格厚度' })
public gridThickness: number = 0.05;

@property({ range: [0.0, 10.0], displayName: '能量流�? })
public energySpeed: number = 2.0;

@property({ range: [0.1, 5.0], displayName: '菲涅尔强�? })
public fresnelPower: number = 2.0;

@property({ type: Vec3, displayName: '冲击点位�? })
public impactPosition: Vec3 = new Vec3(0, 0, 0);

@property({ range: [0.1, 10.0], displayName: '冲击半径' })
public impactRadius: number = 2.0;

@property({ range: [0.0, 10.0], displayName: '冲击强度' })
public impactIntensity: number = 3.0;

@property({ displayName: '力场类型' })
public forceFieldType: ForceFieldType = ForceFieldType.Sphere;

@property({ displayName: '启用多层防护' })
public enableMultiLayer: boolean = false;

@property({ range: [0.0, 3.0], displayName: '护盾强度' })
public shieldStrength: number = 1.0;

private _material: Material | null = null;
private _isActive: boolean = false;
private _impactTimer: number = 0;
private _impactActive: boolean = false;

// 力场类型枚举
public enum ForceFieldType {
Sphere = 'sphere-force-field',
Impact = 'impact-force-field',
Magnetic = 'magnetic-field',
MultiLayer = 'multi-layer-shield'
}

onLoad() {
const renderer = this.getComponent('cc.MeshRenderer');
if (renderer && renderer.material) {
this._material = renderer.material;
this.updateMaterial();
}
}

update(deltaTime: number) {
if (this._isActive) {
if (this._impactActive) {
this._impactTimer += deltaTime;
// 冲击效果会自动衰�? if (this._impactTimer > 3.0) {
this._impactActive = false;
this._impactTimer = 0;
}
}
this.updateMaterial();
}
}

private updateMaterial() {
if (!this._material) return;

// 基础力场参数
this._material.setProperty('shieldColor', this.shieldColor);
this._material.setProperty('transparency', this.transparency);
this._material.setProperty('gridScale', this.gridScale);
this._material.setProperty('gridThickness', this.gridThickness);
this._material.setProperty('energySpeed', this.energySpeed);
this._material.setProperty('fresnel_power', this.fresnelPower);

// 冲击效果参数
this._material.setProperty('impactPosition', this.impactPosition);
this._material.setProperty('impactRadius', this.impactRadius);
this._material.setProperty('impactIntensity', this.impactIntensity);

// 多层防护参数
if (this.enableMultiLayer) {
this._material.setProperty('shieldStrength', this.shieldStrength);
}
}

// 公共接口
public setForceFieldType(type: ForceFieldType) {
this.forceFieldType = type;
console.log(`切换到力场类�? ${type}`);
this.updateMaterial();
}

public activateShield() {
this._isActive = true;
this.transparency = 0;

// 激活动�? let elapsed = 0;
const activate = (dt: number) => {
elapsed += dt;
const t = Math.min(elapsed / 1.0, 1.0);

this.transparency = t * 0.3;
this.shieldStrength = t * 2.0;
this.updateMaterial();

if (t < 1.0) {
this.scheduleOnce(activate, 0);
}
};

this.scheduleOnce(activate, 0);
}

public deactivateShield() {
const originalTransparency = this.transparency;
const originalStrength = this.shieldStrength;

let elapsed = 0;
const deactivate = (dt: number) => {
elapsed += dt;
const t = Math.min(elapsed / 0.8, 1.0);

this.transparency = originalTransparency * (1.0 - t);
this.shieldStrength = originalStrength * (1.0 - t);
this.updateMaterial();

if (t >= 1.0) {
this._isActive = false;
} else {
this.scheduleOnce(deactivate, 0);
}
};

this.scheduleOnce(deactivate, 0);
}

public triggerImpact(worldPosition: Vec3, intensity: number = 3.0) {
this.impactPosition.set(worldPosition);
this.impactIntensity = intensity;
this._impactActive = true;
this._impactTimer = 0;

// 切换到冲击力场模�? this.setForceFieldType(ForceFieldType.Impact);

this.updateMaterial();
}

public setShieldColor(color: Color) {
this.shieldColor = color;
this.updateMaterial();
}

public setShieldStrength(strength: number) {
this.shieldStrength = strength;
this.updateMaterial();
}

// 预设效果
public applyDefensiveShield() {
this.shieldColor = new Color(100, 150, 255, 255); // 蓝色
this.gridScale = 20.0;
this.energySpeed = 1.0;
this.transparency = 0.4;
this.setForceFieldType(ForceFieldType.Sphere);
}

public applyAttackShield() {
this.shieldColor = new Color(255, 100, 100, 255); // 红色
this.gridScale = 15.0;
this.energySpeed = 3.0;
this.transparency = 0.6;
this.setForceFieldType(ForceFieldType.Impact);
}

public applyAdvancedShield() {
this.enableMultiLayer = true;
this.shieldStrength = 2.0;
this.transparency = 0.3;
this.setForceFieldType(ForceFieldType.MultiLayer);
}

public applyMagneticField() {
this.shieldColor = new Color(200, 100, 255, 255); // 紫色
this.energySpeed = 2.5;
this.transparency = 0.5;
this.setForceFieldType(ForceFieldType.Magnetic);
}

// 特殊效果
public shieldOverload(duration: number = 3.0) {
const originalColor = this.shieldColor.clone();
const originalIntensity = this.impactIntensity;

// 过载效果
this.shieldColor = new Color(255, 255, 100, 255); // 黄色
this.impactIntensity = 5.0;
this.energySpeed = 8.0;

this.scheduleOnce(() => {
this.shieldColor.set(originalColor);
this.impactIntensity = originalIntensity;
this.energySpeed = 2.0;
this.updateMaterial();
}, duration);

this.updateMaterial();
}

public emergencyShield() {
// 紧急护�?- 快速激�? this.shieldColor = new Color(255, 200, 100, 255); // 橙色
this.shieldStrength = 3.0;
this.transparency = 0.8;
this.energySpeed = 5.0;

this.activateShield();
}

public adaptiveShield(threatLevel: number) {
// 自适应护盾 - 根据威胁等级调整
threatLevel = Math.max(0, Math.min(1, threatLevel));

const baseColor = new Color(100, 200, 255, 255);
const alertColor = new Color(255, 100, 100, 255);

// 颜色插�? this.shieldColor.r = Math.lerp(baseColor.r, alertColor.r, threatLevel);
this.shieldColor.g = Math.lerp(baseColor.g, alertColor.g, threatLevel);
this.shieldColor.b = Math.lerp(baseColor.b, alertColor.b, threatLevel);

// 参数调整
this.shieldStrength = 1.0 + threatLevel * 2.0;
this.transparency = 0.3 + threatLevel * 0.4;
this.energySpeed = 1.0 + threatLevel * 4.0;

this.updateMaterial();
}

public resetToDefault() {
this.shieldColor = new Color(50, 200, 255, 255);
this.transparency = 0.3;
this.gridScale = 20.0;
this.gridThickness = 0.05;
this.energySpeed = 2.0;
this.fresnelPower = 2.0;
this.shieldStrength = 1.0;
this.enableMultiLayer = false;
this.updateMaterial();
}
}

// 导出枚举
export { ForceFieldType } from './ForceFieldController';

📖 本章总结

通过本章学习,我们掌握了:

  • �?力场视觉效果的基本原理和特征
  • �?球形护盾、冲击反应、磁场力线实�?- �?多层防护系统和高级特�?- �?完整的TypeScript控制系统和预设效�?- �?科幻游戏中力场特效的实际应用

🚀 下一步学�?

掌握�?D力场着色器后,建议继续学习�?
👉 �?0.4章:3D顶点动画着色器

💡 实践练习

  1. 创建一个可交互的防护盾系统
  2. 实现多种威胁等级的自适应护盾
  3. 开发磁场可视化和科幻界面特�?

系列导航