第4.1章:内置着色器概览

Cocos Creator提供了丰富的内置着色器,覆盖了从基础渲染到高级PBR的各种需求。了解这些内置着色器的特性和使用场景,有助于快速选择合适的渲染方案,也为自定义着色器开发提供参考。

🎯 学习目标

通过本章学习,你将掌握:

  • Cocos Creator内置着色器的完整分�?- 各类着色器的特性和适用场景
  • 着色器参数配置和优化技�?- 如何选择合适的着色器类型
  • 内置着色器的扩展和自定义方�?

📋 内置着色器分类

整体架构�?

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
graph TD
A[内置着色器] --> B[基础着色器]
A --> C[PBR着色器]
A --> D[2D着色器]
A --> E[特效着色器]
A --> F[UI着色器]

B --> B1[builtin-unlit]
B --> B2[builtin-sprite]
B --> B3[builtin-terrain]

C --> C1[builtin-standard]
C --> C2[builtin-toon]
C --> C3[builtin-hair]
C --> C4[builtin-cloth]

D --> D1[sprites-default]
D --> D2[sprites-gray]
D --> D3[sprites-additive]

E --> E1[builtin-billboard]
E --> E2[builtin-particle]
E --> E3[builtin-trail]

F --> F1[ui-default]
F --> F2[ui-graphics]
F --> F3[ui-sprite]

分类详解

类别用�?性能开销适用场景
基础着色器简单渲�?�?原型开发、性能敏感场景
PBR着色器物理渲染�?高品�?D游戏
2D着色器精灵渲染�?2D游戏、UI元素
特效着色器视觉特效�?粒子系统、特�?
UI着色器界面渲染�?用户界面

🔧 基础着色器详解

builtin-unlit(无光照着色器�?

最基础的着色器,不计算光照,性能最优:

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
// builtin-unlit特�?- 无光照计�?- 支持纹理采样
- 支持顶点颜色
- 支持透明度测�?- 多种混合模式

// 适用场景
�?UI背景和装�?�?天空盒和远景
�?简单的2D元素
�?原型开�?�?移动端性能优化

// 主要参数
mainTexture: 主纹�?mainColor: 主颜�?
tilingOffset: 纹理平铺和偏�?alphaThreshold: 透明度阈�?```

#### 使用示例

```typescript
@ccclass('UnlitShaderDemo')
export class UnlitShaderDemo extends Component {
@property(MeshRenderer)
meshRenderer: MeshRenderer = null!;

@property(Texture2D)
mainTexture: Texture2D = null!;

start() {
// 创建无光照材�? const material = Material.createWithBuiltin('builtin-unlit', 0);

// 配置基础参数
material.setProperty('mainTexture', this.mainTexture);
material.setProperty('mainColor', Color.WHITE);
material.setProperty('tilingOffset', new Vec4(1, 1, 0, 0));

// 应用材质
this.meshRenderer.setMaterial(material, 0);
}

// 动态修改颜�? animateColor() {
const material = this.meshRenderer.getMaterial(0);
if (material) {
const time = director.getTotalTime();
const hue = (time * 0.5) % 1.0;
const color = Color.fromHSV(hue, 1.0, 1.0);
material.setProperty('mainColor', color);
}
}
}

builtin-sprite(精灵着色器�?

专为2D精灵设计的着色器�?

1
2
3
4
5
6
7
8
9
10
11
12
// builtin-sprite特�?- 优化�?D渲染
- 支持九宫格拉�?- 支持图集纹理
- 内置颜色混合
- 支持遮罩和裁�?
// 适用场景
�?2D游戏角色和道�?�?UI按钮和图�?�?动画精灵
�?2D特效

// 关键参数
mainTexture: 精灵纹理
color: 精灵颜色
isRGBE: 是否为RGBE格式

builtin-terrain(地形着色器�?

专为地形渲染优化的着色器�?

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
// builtin-terrain特�?- 多层纹理混合
- 高度图支�?- 法线贴图
- 细节纹理
- LOD优化

// 适用场景
�?开放世界地�?�?大型场景背景
�?自然环境渲染

// 主要参数
detailMap0-3: 细节贴图
normalMap0-3: 法线贴图
metallic0-3: 金属�?roughness0-3: 粗糙�?```

## 🌟 PBR着色器详解

### builtin-standard(标准PBR着色器�?
基于物理的渲染着色器,提供最真实的材质表现:

```typescript
@ccclass('PBRShaderSetup')
export class PBRShaderSetup extends Component {
@property(MeshRenderer)
meshRenderer: MeshRenderer = null!;

// PBR纹理
@property(Texture2D)
albedoMap: Texture2D = null!;

@property(Texture2D)
normalMap: Texture2D = null!;

@property(Texture2D)
metallicMap: Texture2D = null!;

@property(Texture2D)
roughnessMap: Texture2D = null!;

@property(Texture2D)
occlusionMap: Texture2D = null!;

start() {
this.setupPBRMaterial();
}

private setupPBRMaterial() {
// 创建标准PBR材质
const material = Material.createWithBuiltin('builtin-standard', 0);

// 基础颜色配置
material.setProperty('albedoMap', this.albedoMap);
material.setProperty('albedo', Color.WHITE);

// 法线贴图
material.setProperty('normalMap', this.normalMap);
material.setProperty('normalStrength', 1.0);

// 金属度和粗糙�? material.setProperty('metallicRoughnessMap', this.metallicMap);
material.setProperty('metallic', 0.5);
material.setProperty('roughness', 0.5);

// 环境遮挡
material.setProperty('occlusionMap', this.occlusionMap);
material.setProperty('occlusion', 1.0);

// 发光
material.setProperty('emissive', Color.BLACK);
material.setProperty('emissiveScale', new Vec3(1, 1, 1));

this.meshRenderer.setMaterial(material, 0);
}

// 预设材质配置
setupMetalMaterial() {
const material = this.meshRenderer.getMaterial(0);
if (material) {
material.setProperty('metallic', 1.0);
material.setProperty('roughness', 0.1);
material.setProperty('albedo', new Color(200, 200, 200, 255));
}
}

setupRubberMaterial() {
const material = this.meshRenderer.getMaterial(0);
if (material) {
material.setProperty('metallic', 0.0);
material.setProperty('roughness', 0.9);
material.setProperty('albedo', new Color(50, 50, 50, 255));
}
}

setupPlasticMaterial() {
const material = this.meshRenderer.getMaterial(0);
if (material) {
material.setProperty('metallic', 0.0);
material.setProperty('roughness', 0.3);
material.setProperty('albedo', new Color(100, 150, 200, 255));
}
}
}

builtin-toon(卡通着色器�?

实现卡通风格渲染的着色器�?

1
2
3
4
5
6
7
8
9
10
11
// builtin-toon特�?- 卡通风格光�?- 多级亮度划分
- 轮廓线渲�?- 平面化阴�?- 色彩饱和度增�?
// 适用场景
�?卡通风格游�?�?动漫角色
�?简化的3D场景
�?艺术化效�?
// 关键参数
baseMap: 基础纹理
baseColor: 基础颜色
shadeMap: 阴影贴图
shadingGrade: 阴影等级

builtin-hair(毛发着色器�?

专为毛发渲染设计的着色器�?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// builtin-hair特�?- Kajiya-Kay光照模型
- 各向异性反�?- 双层高光
- 半透明效果
- 噪声扰动

// 适用场景
�?角色毛发
�?动物皮毛
�?草地植被
�?纤维材质

// 主要参数
diffuseMap: 漫反射贴�?normalMap: 法线贴图
specularShift: 高光偏移
specularWidth: 高光宽度

🎨 2D着色器详解

sprites-default(默认精灵着色器�?

2D精灵的标准着色器�?

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
@ccclass('SpriteShaderController')
export class SpriteShaderController extends Component {
@property(Sprite)
sprite: Sprite = null!;

start() {
this.setupSpriteEffects();
}

private setupSpriteEffects() {
// 创建精灵材质
const material = Material.createWithBuiltin('sprites-default', 0);

// 应用到精�? this.sprite.customMaterial = material;

// 配置混合模式
this.setupBlendModes();
}

private setupBlendModes() {
// 正常混合
this.setBlendMode('normal');
}

setBlendMode(mode: string) {
const material = this.sprite.customMaterial;
if (!material) return;

switch (mode) {
case 'normal':
// 正常混合模式
break;
case 'additive':
// 使用加法混合着色器
const additiveMaterial = Material.createWithBuiltin('sprites-additive', 0);
this.sprite.customMaterial = additiveMaterial;
break;
case 'multiply':
// 使用乘法混合着色器
const multiplyMaterial = Material.createWithBuiltin('sprites-multiply', 0);
this.sprite.customMaterial = multiplyMaterial;
break;
}
}

// 动态颜色效�? startColorAnimation() {
this.schedule(() => {
const time = director.getTotalTime();
const hue = (time * 0.5) % 1.0;
const color = Color.fromHSV(hue, 1.0, 1.0);
this.sprite.color = color;
}, 0.016);
}
}

sprites-gray(灰度着色器�?

将精灵转换为灰度的着色器�?

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
// 灰度效果控制
@ccclass('GrayScaleEffect')
export class GrayScaleEffect extends Component {
@property(Sprite)
sprite: Sprite = null!;

@property({ range: [0, 1, 0.1] })
grayScale: number = 0;

private originalMaterial: Material | null = null;
private grayMaterial: Material | null = null;

start() {
this.originalMaterial = this.sprite.customMaterial;
this.grayMaterial = Material.createWithBuiltin('sprites-gray', 0);
}

update() {
// 根据灰度值切换材�? if (this.grayScale > 0.5) {
this.sprite.customMaterial = this.grayMaterial;
} else {
this.sprite.customMaterial = this.originalMaterial;
}
}

// 渐变灰度效果
fadeToGray(duration: number) {
tween(this)
.to(duration, { grayScale: 1 })
.start();
}

fadeToColor(duration: number) {
tween(this)
.to(duration, { grayScale: 0 })
.start();
}
}

�?特效着色器详解

builtin-billboard(广告牌着色器�?

始终面向相机的着色器�?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@ccclass('BillboardEffect')
export class BillboardEffect extends Component {
@property(MeshRenderer)
meshRenderer: MeshRenderer = null!;

@property(Texture2D)
billboardTexture: Texture2D = null!;

start() {
this.setupBillboard();
}

private setupBillboard() {
const material = Material.createWithBuiltin('builtin-billboard', 0);

// 配置广告牌参�? material.setProperty('mainTexture', this.billboardTexture);
material.setProperty('mainColor', Color.WHITE);

// 设置广告牌类�? material.setProperty('billboard', 1); // 0=�? 1=Y�? 2=自由

this.meshRenderer.setMaterial(material, 0);
}
}

builtin-particle(粒子着色器�?

专为粒子系统设计的着色器�?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// builtin-particle特�?- GPU实例化渲�?- 顶点动画支持
- 多种混合模式
- 纹理动画
- 软粒子效�?
// 适用场景
�?粒子特效
�?爆炸效果
�?魔法特效
�?环境粒子

// 关键参数
mainTexture: 粒子纹理
startColor: 起始颜色
endColor: 结束颜色

🖥�?UI着色器详解

ui-default(默认UI着色器�?

UI元素的标准着色器�?

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
@ccclass('UIShaderController')
export class UIShaderController extends Component {
@property(Graphics)
graphics: Graphics = null!;

start() {
this.setupUIEffects();
}

private setupUIEffects() {
// 创建UI材质
const material = Material.createWithBuiltin('ui-default', 0);

// 应用到Graphics组件
this.graphics.customMaterial = material;

// 绘制基础图形
this.drawShapes();
}

private drawShapes() {
this.graphics.clear();

// 绘制圆形
this.graphics.circle(100, 100, 50);
this.graphics.fillColor = Color.RED;
this.graphics.fill();

// 绘制矩形
this.graphics.rect(200, 50, 100, 100);
this.graphics.fillColor = Color.BLUE;
this.graphics.fill();
}
}

ui-graphics(图形UI着色器�?

专为Graphics组件优化的着色器�?

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
// ui-graphics特�?- 矢量图形渲染
- 抗锯齿支�?- 渐变填充
- 描边效果
- 动态生�?
// 适用场景
�?动态UI图形
�?数据可视�?�?进度条和仪表
�?自定义控�?```

## 🎛�?着色器选择指南

### 性能对比

```typescript
// 性能排序(从高到低)
const shaderPerformance = {
'builtin-unlit': 10, // 最�? 'sprites-default': 9, // 很快
'ui-default': 8, // �? 'builtin-billboard': 7, // 较快
'builtin-toon': 6, // 中等
'builtin-particle': 5, // 中等
'builtin-standard': 3, // 较慢
'builtin-hair': 2, // �? 'builtin-cloth': 1 // 最�?};

// 移动端推�?const mobileRecommended = [
'builtin-unlit',
'sprites-default',
'builtin-toon' // 简化版�?];

// 高端设备推荐
const highEndRecommended = [
'builtin-standard',
'builtin-hair',
'builtin-cloth'
];

选择决策�?

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
@ccclass('ShaderSelector')
export class ShaderSelector {
static selectShader(requirements: ShaderRequirements): string {
if (requirements.is2D) {
return requirements.needsEffects ? 'sprites-additive' : 'sprites-default';
}

if (requirements.isUI) {
return requirements.needsGraphics ? 'ui-graphics' : 'ui-default';
}

if (requirements.isParticle) {
return 'builtin-particle';
}

if (requirements.needsRealism) {
if (requirements.isHair) return 'builtin-hair';
if (requirements.isCloth) return 'builtin-cloth';
return 'builtin-standard';
}

if (requirements.isToon) {
return 'builtin-toon';
}

return 'builtin-unlit'; // 默认选择
}
}

interface ShaderRequirements {
is2D: boolean;
isUI: boolean;
isParticle: boolean;
needsRealism: boolean;
needsEffects: boolean;
needsGraphics: boolean;
isToon: boolean;
isHair: boolean;
isCloth: boolean;
performancePriority: 'high' | 'medium' | 'low';
}

🔧 内置着色器自定�?

基于内置着色器的扩�?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@ccclass('CustomUnlitShader')
export class CustomUnlitShader extends Component {
createCustomUnlit(): Material {
// 基于builtin-unlit创建自定义版�? const material = Material.createWithBuiltin('builtin-unlit', 0);

// 添加自定义宏定义
material.recompileShaders({
CUSTOM_ANIMATION: true,
WAVE_EFFECT: true
});

// 设置自定义参�? material.setProperty('waveSpeed', 2.0);
material.setProperty('waveAmplitude', 0.1);

return material;
}
}

着色器变体管理

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
@ccclass('ShaderVariantManager')
export class ShaderVariantManager extends Component {
private variants: Map<string, Material> = new Map();

start() {
this.createVariants();
}

private createVariants() {
// 创建标准变体
this.variants.set('standard', Material.createWithBuiltin('builtin-standard', 0));

// 创建简化变�? const simplified = Material.createWithBuiltin('builtin-standard', 0);
simplified.recompileShaders({
USE_NORMAL_MAP: false,
USE_OCCLUSION_MAP: false
});
this.variants.set('simplified', simplified);

// 创建高质量变�? const highQuality = Material.createWithBuiltin('builtin-standard', 0);
highQuality.recompileShaders({
USE_IBL: true,
USE_REFLECTION_PROBE: true,
HIGH_QUALITY_LIGHTING: true
});
this.variants.set('highQuality', highQuality);
}

getVariant(name: string): Material | null {
return this.variants.get(name) || null;
}

// 根据设备性能选择变体
selectByPerformance(): Material {
const deviceLevel = this.getDevicePerformanceLevel();

switch (deviceLevel) {
case 'high':
return this.getVariant('highQuality')!;
case 'medium':
return this.getVariant('standard')!;
case 'low':
return this.getVariant('simplified')!;
default:
return this.getVariant('standard')!;
}
}

private getDevicePerformanceLevel(): string {
// 根据设备信息判断性能等级
const devicePixelRatio = screen.devicePixelRatio;
const screenSize = screen.windowSize;
const totalPixels = screenSize.width * screenSize.height * devicePixelRatio;

if (totalPixels > 2073600) { // 大于1080p
return 'high';
} else if (totalPixels > 921600) { // 大于720p
return 'medium';
} else {
return 'low';
}
}
}

📚 下一步学�?

完成内置着色器概览后,建议深入学习�?

  1. 第4.3章:PBR着色器基础原理 - 深入PBR着色器
  2. 第4.4章:卡通着色器实现 - 卡通着色器实现
  3. 第9.1章:2D渐变精灵着色器 - 2D精灵特效
  4. 第10.4章:3D顶点动画着色器 - 高级粒子着色器

💡 总结

通过本章学习,你现在应该了解了:

  • �?Cocos Creator内置着色器的完整分�?- �?各类着色器的特性和适用场景
  • �?如何根据需求选择合适的着色器
  • �?内置着色器的自定义和扩展方�?- �?性能优化和设备适配策略

内置着色器是快速开发的重要工具,掌握它们的特性和用法能大大提高开发效率。同时,理解内置着色器的实现原理也为自定义着色器开发奠定了基础�?

建议:在实际项目中,优先使用内置着色器满足需求。只有在内置着色器无法满足特殊需求时,才考虑自定义开发。这样既能保证质量,又能提高开发效率�?