第10.2章:3D全息投影着色器

全息投影效果是科幻游戏中的经典视觉特效,能够营造未来科技感。本章将详细介绍如何实现逼真的全息投影着色器。

🎯 学习目标

  • 理解全息投影的视觉特�?- 掌握扫描线和干扰效果实现
  • 学会创建动态闪烁和透明度变�?- 理解3D空间中的全息视觉效果

💡 全息投影原理

视觉特征分析

全息投影具有以下特征�?

1
2
3
4
5
// 全息投影关键要素
1. 透明�?- 半透明效果
2. 扫描�?- 水平扫描条纹
3. 闪烁 - 随机信号干扰
4. 边缘�?- 菲涅尔反�?5. 颜色偏移 - RGB通道分离

效果组成

1
基础材质 �?透明度处�?�?扫描�?�?干扰效果 �?边缘�?    �?        �?        �?        �?        �?  albedo   alpha     scanlines  glitch   fresnel

🔧 基础全息效果

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
CCEffect %{
techniques:
- name: basic-hologram
passes:
- vert: hologram-vs:vert
frag: hologram-fs:frag
blendState:
targets:
- blend: true
blendSrc: src_alpha
blendDst: one_minus_src_alpha
rasterizerState:
cullMode: none
properties: &props
mainTexture: { value: white }
hologramColor: { value: [0.2, 0.8, 1.0, 1.0], editor: { type: color } }
transparency: { value: 0.7, range: [0.0, 1.0] }
scanlineCount: { value: 50.0, range: [10.0, 200.0] }
scanlineSpeed: { value: 2.0, range: [0.0, 10.0] }
scanlineIntensity:{ value: 0.3, range: [0.0, 1.0] }
flickerSpeed: { value: 5.0, range: [0.0, 20.0] }
flickerIntensity: { value: 0.2, range: [0.0, 1.0] }
rimPower: { value: 2.0, range: [0.1, 5.0] }
rimIntensity: { value: 1.5, range: [0.0, 3.0] }
}%

CCProgram hologram-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 hologram-fs %{
precision highp float;
#include <cc-global>
#include <cc-environment>

uniform sampler2D mainTexture;
uniform vec4 hologramColor;
uniform float transparency;
uniform float scanlineCount;
uniform float scanlineSpeed;
uniform float scanlineIntensity;
uniform float flickerSpeed;
uniform float flickerIntensity;
uniform float rimPower;
uniform float rimIntensity;

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

// 噪声函数
float noise(float x) {
return fract(sin(x) * 43758.5453);
}

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

// 基础纹理
vec4 albedo = texture(mainTexture, v_uv);

// 扫描线效�? float scanline = sin((v_uv.y + cc_time.x * scanlineSpeed) * scanlineCount * 3.14159);
scanline = scanline * 0.5 + 0.5;
scanline = 1.0 - scanlineIntensity + scanlineIntensity * scanline;

// 闪烁效果
float flicker = noise(cc_time.x * flickerSpeed);
flicker = 1.0 - flickerIntensity + flickerIntensity * flicker;

// 边缘光(菲涅尔)
float fresnel = 1.0 - max(0.0, dot(normal, viewDir));
fresnel = pow(fresnel, rimPower) * rimIntensity;

// 合成全息颜色
vec3 hologramFinal = hologramColor.rgb * albedo.rgb;
hologramFinal *= scanline * flicker;
hologramFinal += hologramColor.rgb * fresnel;

// 最终透明�? float finalAlpha = transparency * albedo.a * scanline * flicker;
finalAlpha += fresnel * 0.3;

return vec4(hologramFinal, 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
CCEffect %{
techniques:
- name: data-stream-hologram
passes:
- vert: data-hologram-vs:vert
frag: data-hologram-fs:frag
blendState:
targets:
- blend: true
blendSrc: src_alpha
blendDst: one
properties: &props
mainTexture: { value: white }
noiseTexture: { value: white }
hologramColor: { value: [0.0, 1.0, 0.8, 1.0], editor: { type: color } }
dataFlow: { value: [0.0, 1.0], editor: { type: vec2 } }
flowSpeed: { value: 3.0, range: [0.0, 10.0] }
dataScale: { value: 20.0, range: [5.0, 100.0] }
pixelationLevel: { value: 8.0, range: [1.0, 32.0] }
glitchIntensity: { value: 0.1, range: [0.0, 0.5] }
transparency: { value: 0.8, range: [0.0, 1.0] }
rimPower: { value: 1.5, range: [0.1, 5.0] }
}%

CCProgram data-hologram-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 data-hologram-fs %{
precision highp float;
#include <cc-global>
#include <cc-environment>

uniform sampler2D mainTexture;
uniform sampler2D noiseTexture;
uniform vec4 hologramColor;
uniform vec2 dataFlow;
uniform float flowSpeed;
uniform float dataScale;
uniform float pixelationLevel;
uniform float glitchIntensity;
uniform float transparency;
uniform float rimPower;

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);

// 像素化处�? vec2 pixelatedUV = floor(v_uv * pixelationLevel) / pixelationLevel;

// 数据流动
vec2 flowUV = pixelatedUV + dataFlow * cc_time.x * flowSpeed;

// 噪声采样(模拟数据流�? vec4 noise = texture(noiseTexture, flowUV * dataScale);

// 故障效果
vec2 glitchUV = pixelatedUV;
if (noise.r > 0.7) {
glitchUV.x += (noise.g - 0.5) * glitchIntensity;
}

// 基础纹理
vec4 albedo = texture(mainTexture, glitchUV);

// 数据流模�? float dataPattern = step(0.3, noise.r) * step(0.4, noise.g);

// 边缘�? float fresnel = 1.0 - max(0.0, dot(normal, viewDir));
fresnel = pow(fresnel, rimPower);

// 合成效果
vec3 hologramFinal = hologramColor.rgb * albedo.rgb;
hologramFinal += hologramColor.rgb * dataPattern * 0.5;
hologramFinal += hologramColor.rgb * fresnel;

float finalAlpha = transparency * albedo.a;
finalAlpha += dataPattern * 0.3;
finalAlpha += fresnel * 0.2;

return vec4(hologramFinal, 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
110
111
112
CCEffect %{
techniques:
- name: glitch-hologram
passes:
- vert: glitch-hologram-vs:vert
frag: glitch-hologram-fs:frag
blendState:
targets:
- blend: true
blendSrc: src_alpha
blendDst: one_minus_src_alpha
properties: &props
mainTexture: { value: white }
hologramColor: { value: [1.0, 0.3, 0.8, 1.0], editor: { type: color } }
glitchIntensity: { value: 0.1, range: [0.0, 0.5] }
glitchSpeed: { value: 10.0, range: [1.0, 30.0] }
rgbShift: { value: 0.02, range: [0.0, 0.1] }
scanlineFreq: { value: 800.0, range: [100.0, 2000.0] }
flickerThreshold: { value: 0.9, range: [0.5, 0.99] }
transparency: { value: 0.6, range: [0.0, 1.0] }
rimIntensity: { value: 2.0, range: [0.0, 5.0] }
}%

CCProgram glitch-hologram-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 glitch-hologram-fs %{
precision highp float;
#include <cc-global>
#include <cc-environment>

uniform sampler2D mainTexture;
uniform vec4 hologramColor;
uniform float glitchIntensity;
uniform float glitchSpeed;
uniform float rgbShift;
uniform float scanlineFreq;
uniform float flickerThreshold;
uniform float transparency;
uniform float rimIntensity;

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

// 随机函数
float random(vec2 uv) {
return fract(sin(dot(uv, vec2(12.9898, 78.233))) * 43758.5453);
}

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

vec2 uv = v_uv;

// 故障偏移
float glitchTime = cc_time.x * glitchSpeed;
float glitchNoise = random(vec2(floor(uv.y * 50.0), floor(glitchTime)));

if (glitchNoise > flickerThreshold) {
uv.x += (random(vec2(glitchTime)) - 0.5) * glitchIntensity;
}

// RGB通道分离
float r = texture(mainTexture, uv + vec2(rgbShift, 0.0)).r;
float g = texture(mainTexture, uv).g;
float b = texture(mainTexture, uv - vec2(rgbShift, 0.0)).b;
float a = texture(mainTexture, uv).a;

vec4 albedo = vec4(r, g, b, a);

// 扫描�? float scanline = sin(uv.y * scanlineFreq);
scanline = scanline * 0.04 + 0.96;

// 随机闪烁
float flicker = step(flickerThreshold, random(vec2(glitchTime * 0.1)));
flicker = mix(1.0, 0.3, flicker);

// 边缘�? float fresnel = 1.0 - max(0.0, dot(normal, viewDir));
fresnel = pow(fresnel, 2.0) * rimIntensity;

// 合成全息效果
vec3 hologramFinal = hologramColor.rgb * albedo.rgb * scanline * flicker;
hologramFinal += hologramColor.rgb * fresnel;

float finalAlpha = transparency * albedo.a * scanline * flicker;
finalAlpha += fresnel * 0.3;

return vec4(hologramFinal, 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
CCEffect %{
techniques:
- name: projection-bounds
passes:
- vert: bounds-vs:vert
frag: bounds-fs:frag
blendState:
targets:
- blend: true
blendSrc: src_alpha
blendDst: one_minus_src_alpha
properties: &props
mainTexture: { value: white }
hologramColor: { value: [0.2, 0.9, 1.0, 1.0], editor: { type: color } }
projectionCenter: { value: [0.0, 0.0, 0.0], editor: { type: vec3 } }
projectionRadius: { value: 5.0, range: [1.0, 20.0] }
fadeDistance: { value: 1.0, range: [0.1, 5.0] }
boundsIntensity: { value: 2.0, range: [0.0, 5.0] }
gridScale: { value: 10.0, range: [1.0, 50.0] }
gridThickness: { value: 0.1, range: [0.01, 0.5] }
transparency: { value: 0.7, range: [0.0, 1.0] }
}%

CCProgram bounds-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 bounds-fs %{
precision highp float;
#include <cc-global>
#include <cc-environment>

uniform sampler2D mainTexture;
uniform vec4 hologramColor;
uniform vec3 projectionCenter;
uniform float projectionRadius;
uniform float fadeDistance;
uniform float boundsIntensity;
uniform float gridScale;
uniform float gridThickness;
uniform float transparency;

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);

// 基础纹理
vec4 albedo = texture(mainTexture, v_uv);

// 距离投影中心的距�? float distanceToCenter = length(v_worldPos - projectionCenter);

// 投影范围衰减
float rangeFade = 1.0 - smoothstep(projectionRadius - fadeDistance, projectionRadius, distanceToCenter);

// 边界强化
float boundsMask = smoothstep(projectionRadius - fadeDistance * 0.5, projectionRadius - fadeDistance, distanceToCenter);
boundsMask *= boundsIntensity;

// 网格效果
vec2 gridUV = v_uv * gridScale;
vec2 grid = abs(fract(gridUV) - 0.5) / fwidth(gridUV);
float gridLines = min(grid.x, grid.y);
gridLines = 1.0 - min(gridLines, 1.0);
gridLines *= step(gridThickness, gridLines);

// 边缘�? float fresnel = 1.0 - max(0.0, dot(normal, viewDir));
fresnel = pow(fresnel, 2.0);

// 合成效果
vec3 hologramFinal = hologramColor.rgb * albedo.rgb * rangeFade;
hologramFinal += hologramColor.rgb * boundsMask;
hologramFinal += hologramColor.rgb * gridLines * 0.3;
hologramFinal += hologramColor.rgb * fresnel;

float finalAlpha = transparency * albedo.a * rangeFade;
finalAlpha += boundsMask * 0.5;
finalAlpha += gridLines * 0.2;
finalAlpha += fresnel * 0.3;

return vec4(hologramFinal, 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
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
import { Component, Material, Color, Vec3, _decorator } from 'cc';

const { ccclass, property, menu } = _decorator;

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

@property({ type: Color, displayName: '全息颜色' })
public hologramColor: Color = new Color(50, 200, 255, 255);

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

@property({ range: [10.0, 200.0], displayName: '扫描线数�? })
public scanlineCount: number = 50.0;

@property({ range: [0.0, 10.0], displayName: '扫描线速度' })
public scanlineSpeed: number = 2.0;

@property({ range: [0.0, 1.0], displayName: '扫描线强�? })
public scanlineIntensity: number = 0.3;

@property({ range: [0.0, 20.0], displayName: '闪烁速度' })
public flickerSpeed: number = 5.0;

@property({ range: [0.0, 1.0], displayName: '闪烁强度' })
public flickerIntensity: number = 0.2;

@property({ range: [0.0, 0.5], displayName: '故障强度' })
public glitchIntensity: number = 0.1;

@property({ range: [0.0, 0.1], displayName: 'RGB偏移' })
public rgbShift: number = 0.02;

@property({ displayName: '全息类型' })
public hologramType: HologramType = HologramType.Basic;

@property({ type: Vec3, displayName: '投影中心' })
public projectionCenter: Vec3 = new Vec3(0, 0, 0);

@property({ range: [1.0, 20.0], displayName: '投影范围' })
public projectionRadius: number = 5.0;

private _material: Material | null = null;
private _isProjecting: boolean = false;
private _glitchTimer: number = 0;

// 全息类型枚举
public enum HologramType {
Basic = 'basic-hologram',
DataStream = 'data-stream-hologram',
Glitch = 'glitch-hologram',
ProjectionBounds = 'projection-bounds'
}

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

update(deltaTime: number) {
if (this._isProjecting) {
this._glitchTimer += deltaTime;
this.updateMaterial();
}
}

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

// 基础全息参数
this._material.setProperty('hologramColor', this.hologramColor);
this._material.setProperty('transparency', this.transparency);
this._material.setProperty('scanlineCount', this.scanlineCount);
this._material.setProperty('scanlineSpeed', this.scanlineSpeed);
this._material.setProperty('scanlineIntensity', this.scanlineIntensity);
this._material.setProperty('flickerSpeed', this.flickerSpeed);
this._material.setProperty('flickerIntensity', this.flickerIntensity);

// 故障效果参数
this._material.setProperty('glitchIntensity', this.glitchIntensity);
this._material.setProperty('rgbShift', this.rgbShift);

// 投影边界参数
this._material.setProperty('projectionCenter', this.projectionCenter);
this._material.setProperty('projectionRadius', this.projectionRadius);
}

// 公共接口
public setHologramType(type: HologramType) {
this.hologramType = type;
// 这里可以切换不同的材质或technique
console.log(`切换到全息类�? ${type}`);
this.updateMaterial();
}

public startProjection() {
this._isProjecting = true;
this.transparency = 0;

// 渐入动画
let elapsed = 0;
const fadeIn = (dt: number) => {
elapsed += dt;
const t = Math.min(elapsed / 1.0, 1.0);

this.transparency = t * 0.7;
this.updateMaterial();

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

this.scheduleOnce(fadeIn, 0);
}

public stopProjection() {
// 渐出动画
const originalTransparency = this.transparency;

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

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

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

this.scheduleOnce(fadeOut, 0);
}

public setHologramColor(color: Color) {
this.hologramColor = color;
this.updateMaterial();
}

public setTransparency(transparency: number) {
this.transparency = transparency;
this.updateMaterial();
}

// 预设效果
public applyDataTerminalStyle() {
this.hologramColor = new Color(0, 255, 200, 255); // 青绿�? this.scanlineCount = 80.0;
this.scanlineSpeed = 1.5;
this.flickerIntensity = 0.1;
this.glitchIntensity = 0.05;
this.setHologramType(HologramType.DataStream);
}

public applyErrorMessageStyle() {
this.hologramColor = new Color(255, 100, 100, 255); // 红色
this.scanlineCount = 30.0;
this.scanlineSpeed = 5.0;
this.flickerIntensity = 0.8;
this.glitchIntensity = 0.3;
this.rgbShift = 0.05;
this.setHologramType(HologramType.Glitch);
}

public applyCharacterStyle() {
this.hologramColor = new Color(100, 150, 255, 255); // 蓝色
this.scanlineCount = 60.0;
this.scanlineSpeed = 2.0;
this.flickerIntensity = 0.15;
this.glitchIntensity = 0.02;
this.setHologramType(HologramType.Basic);
}

public applyMapProjectionStyle() {
this.hologramColor = new Color(150, 255, 150, 255); // 绿色
this.projectionRadius = 10.0;
this.transparency = 0.6;
this.setHologramType(HologramType.ProjectionBounds);
}

// 特殊效果
public triggerGlitch(duration: number = 2.0) {
const originalGlitch = this.glitchIntensity;
const originalRgb = this.rgbShift;

this.glitchIntensity = 0.5;
this.rgbShift = 0.1;

this.scheduleOnce(() => {
this.glitchIntensity = originalGlitch;
this.rgbShift = originalRgb;
this.updateMaterial();
}, duration);

this.updateMaterial();
}

public flashHologram(duration: number = 0.5) {
const originalTransparency = this.transparency;

let elapsed = 0;
const flash = (dt: number) => {
elapsed += dt;
const t = elapsed / duration;

if (t < 0.5) {
// 增强阶段
this.transparency = originalTransparency + (1.0 - originalTransparency) * (t * 2);
} else {
// 恢复阶段
this.transparency = 1.0 - (1.0 - originalTransparency) * ((t - 0.5) * 2);
}

this.updateMaterial();

if (t < 1.0) {
this.scheduleOnce(flash, 0);
} else {
this.transparency = originalTransparency;
this.updateMaterial();
}
};

this.scheduleOnce(flash, 0);
}

public colorCycle(colors: Color[], cycleDuration: number = 3.0) {
let colorIndex = 0;
const startColor = this.hologramColor.clone();

const cycle = () => {
const targetColor = colors[colorIndex % colors.length];

let elapsed = 0;
const transition = (dt: number) => {
elapsed += dt;
const t = Math.min(elapsed / (cycleDuration / colors.length), 1.0);

// 颜色插�? this.hologramColor.r = Math.lerp(startColor.r, targetColor.r, t);
this.hologramColor.g = Math.lerp(startColor.g, targetColor.g, t);
this.hologramColor.b = Math.lerp(startColor.b, targetColor.b, t);

this.updateMaterial();

if (t >= 1.0) {
startColor.set(targetColor);
colorIndex++;

if (colorIndex < colors.length) {
this.scheduleOnce(cycle, 0);
}
} else {
this.scheduleOnce(transition, 0);
}
};

this.scheduleOnce(transition, 0);
};

cycle();
}

public resetToDefault() {
this.hologramColor = new Color(50, 200, 255, 255);
this.transparency = 0.7;
this.scanlineCount = 50.0;
this.scanlineSpeed = 2.0;
this.scanlineIntensity = 0.3;
this.flickerSpeed = 5.0;
this.flickerIntensity = 0.2;
this.glitchIntensity = 0.1;
this.rgbShift = 0.02;
this.updateMaterial();
}
}

// 导出枚举
export { HologramType } from './HologramController';

📖 本章总结

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

  • �?全息投影的视觉特征和实现原理
  • �?扫描线、闪烁、故障等核心效果
  • �?数据流、故障、投影边界等高级变体
  • �?完整的TypeScript控制系统和预设效�?- �?科幻游戏中全息特效的实际应用

🚀 下一步学�?

掌握�?D全息投影着色器后,建议继续学习�?
👉 �?0.3章:3D力场着色器

💡 实践练习

  1. 创建一个科幻UI的全息显示系�?2. 实现角色投影通信效果
  2. 开发地图投影和数据可视化特�?

系列导航