第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着色器物理渲染高品质3D游戏
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
// builtin-unlit特点
- 无光照计算
- 支持纹理采样
- 支持顶点颜色
- 支持透明度测试
- 多种混合模式

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

// 主要参数
mainTexture: 主纹理
mainColor: 主颜色
tilingOffset: 纹理平铺和偏移
alphaThreshold: 透明度阈值

使用示例

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
@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
13
14
15
// builtin-sprite特效 - 优化2D渲染
- 支持九宫格拉伸
- 支持图集纹理
- 内置颜色混合
- 支持遮罩和裁剪
// 适用场景
- 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
// builtin-terrain特点
- 多层纹理混合
- 高度图支持
- 法线贴图
- 细节纹理
- LOD优化

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

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

🌟 PBR着色器详解

builtin-standard(标准PBR着色器)

基于物理的渲染着色器,提供最真实的材质表现:

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
@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
12
13
14
15
16
// builtin-toon特点
- 卡通风格光照
- 多级亮度划分
- 轮廓线渲染
- 平面化阴影
- 色彩饱和度增强
// 适用场景
- 卡通风格游戏
- 动漫角色
- 简化的3D场景
- 艺术化效果
// 关键参数
baseMap: 基础纹理
baseColor: 基础颜色
shadeMap: 阴影贴图
shadingGrade: 阴影等级

builtin-hair(毛发着色器)

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 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
55
56
@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
39
// 灰度效果控制
@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
24
25
@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
15
16
17
// 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
// ui-graphics特点
- 矢量图形渲染
- 抗锯齿支持
- 渐变填充
- 描边效果
- 动态生成

// 适用场景
- 动态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
// 性能排序(从高到低)
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
18
19
@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
64
65
@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. Cocos Creator PBR基础原理详解 - 深入PBR着色器
  2. Cocos Creator卡通渲染着色器实现 - 卡通着色器实现
  3. 第9.1章:2D渐变精灵着色器 - 2D精灵特效
  4. 第10.4章:3D顶点动画着色器 - 高级粒子着色器

💡 总结

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

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

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

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