第12.1章:Legacy Shader系统介绍
Legacy Shader是Cocos Creator提供的传统着色器编写方式,相比Surface Shader提供了更底层的控制能力。本教程将全面介绍Legacy Shader的特点、应用场景和基本使用方法。
🎯 学习目标
- 理解Legacy Shader与Surface Shader的区�?- 掌握Legacy Shader的基本语法和结构
- 学会Legacy Shader的编写和调试技�?- 了解Legacy Shader的适用场景
📋 前置知识
- 已完成Surface Shader章节的学�?- 熟悉GLSL语法基础
- 理解渲染管线和着色器执行流程
🔧 Legacy Shader概述
Legacy Shader vs Surface Shader
Legacy Shader和Surface Shader的主要区别:
Surface Shader (高级抽象):
- 框架控制渲染流程
- 简化开发复杂度
- 有限的自定义能力
- 适用于标准PBR材质和快速开�?
Legacy Shader (底层控制): - 完全手动控制渲染流程
- 需要深入理解图形学原理
- 完全自定义能�?- 适用于特殊效果和高级技�?
Legacy Shader特点
*优势�?
- 完全控制渲染流程
- 可以实现任意复杂的效�?- 直接访问GPU功能
- 不受框架限制
*劣势�?
- 开发复杂度�?- 需要手动处理兼容�?- 调试困难
- 维护成本�?
📝 Legacy Shader基本结构
完整的Legacy 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 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
| // Legacy Shader完整示例 CCEffect %{ techniques: - name: opaque passes: - vert: legacy-vs:vert frag: legacy-fs:frag properties: &props mainTexture: { value: grey, target: mainTexture } mainColor: { value: [1, 1, 1, 1], target: mainColor } roughness: { value: 0.5, target: pbrParams.y } metallic: { value: 0.0, target: pbrParams.z } rasterizerState: cullMode: back depthStencilState: depthTest: true depthWrite: true }%
// 顶点着色器 CCProgram legacy-vs %{ precision highp float; // 输入属�? in vec3 a_position; in vec3 a_normal; in vec2 a_texCoord; // 输出到片段着色器 out vec3 v_position; out vec3 v_normal; out vec2 v_uv; out vec3 v_worldPos; // Uniform变量 uniform CCGlobal { mat4 cc_matView; mat4 cc_matViewInv; mat4 cc_matProj; mat4 cc_matViewProj; vec4 cc_cameraPos; vec4 cc_time; vec4 cc_screenSize; }; uniform CCLocal { mat4 cc_matWorld; mat4 cc_matWorldIT; }; void vert() { vec4 position = vec4(a_position, 1.0); // 世界空间变换 vec4 worldPos = cc_matWorld * position; v_worldPos = worldPos.xyz; // 法线变换 v_normal = normalize((cc_matWorldIT * vec4(a_normal, 0.0)).xyz); // UV坐标 v_uv = a_texCoord; // 投影变换 gl_Position = cc_matViewProj * worldPos; } }%
// 片段着色器 CCProgram legacy-fs %{ precision highp float; // 输入变量 in vec3 v_position; in vec3 v_normal; in vec2 v_uv; in vec3 v_worldPos; // 输出颜色 layout(location = 0) out vec4 fragColor; // 材质参数 uniform sampler2D mainTexture; uniform vec4 mainColor; uniform vec4 pbrParams; // y: roughness, z: metallic // 光照相关 uniform CCForwardLight { vec4 cc_mainLitDir; vec4 cc_mainLitColor; vec4 cc_ambientSky; vec4 cc_ambientGround; }; void frag() { // 基础颜色 vec4 baseColor = texture(mainTexture, v_uv) * mainColor; // 简单光照计�? vec3 normal = normalize(v_normal); vec3 lightDir = normalize(-cc_mainLitDir.xyz); float NdotL = max(dot(normal, lightDir), 0.0); // 最终颜�? vec3 finalColor = baseColor.rgb * cc_mainLitColor.rgb * NdotL; finalColor += cc_ambientSky.rgb * baseColor.rgb * 0.2; fragColor = vec4(finalColor, baseColor.a); } }%
|
🔧 Legacy Shader核心组件
1. CCEffect配置
1 2 3 4 5 6 7 8 9 10 11
| CCEffect: techniques: - name: opaque - vert: shader-vs:vert frag: shader-fs:frag properties: mainColor: { value: [1,1,1,1], target: mainColor } rasterizerState: depthStencilState: depthWrite: true
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| // 内置Uniform�?CCProgram uniform-blocks %{ // 全局变量�? uniform CCGlobal { mat4 cc_matView; // 视图矩阵 mat4 cc_matProj; // 投影矩阵 mat4 cc_matViewProj; // 视图投影矩阵 vec4 cc_cameraPos; // 摄像机位�? vec4 cc_time; // 时间信息 vec4 cc_screenSize; // 屏幕尺寸 }; // 本地变量�? uniform CCLocal { mat4 cc_matWorld; // 世界矩阵 mat4 cc_matWorldIT; // 世界逆转置矩�? }; // 光照变量�? uniform CCForwardLight { vec4 cc_mainLitDir; // 主光源方�? vec4 cc_mainLitColor; // 主光源颜�? vec4 cc_ambientSky; // 天空环境�? vec4 cc_ambientGround; // 地面环境�? }; }%
|
3. 顶点输入属�?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| // 标准顶点属�?CCProgram vertex-attributes %{ // 位置属�?(必须) in vec3 a_position; // 法线属�? in vec3 a_normal; // 纹理坐标 in vec2 a_texCoord; in vec2 a_texCoord1; // 第二套UV // 切线属�? in vec4 a_tangent; // xyz: 切线, w: 手�? // 顶点颜色 in vec4 a_color; // 骨骼动画属�? in vec4 a_joints; // 关节索引 in vec4 a_weights; // 权重 }%
|
🎨 Legacy Shader应用场景
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
| // 自定义卡通光照模�?CCProgram toon-lighting %{ vec3 calculateToonLighting(vec3 baseColor, vec3 normal, vec3 lightDir) { float NdotL = dot(normal, lightDir); // 阶梯化光�? float toonFactor; if (NdotL > 0.8) { toonFactor = 1.0; } else if (NdotL > 0.4) { toonFactor = 0.7; } else if (NdotL > 0.0) { toonFactor = 0.4; } else { toonFactor = 0.1; } return baseColor * toonFactor; } void frag() { vec3 normal = normalize(v_normal); vec3 lightDir = normalize(-cc_mainLitDir.xyz); vec3 lighting = calculateToonLighting( texture(mainTexture, v_uv).rgb, normal, lightDir ); fragColor = vec4(lighting, 1.0); } }%
|
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
| // 玻璃材质效果 CCProgram glass-material %{ uniform sampler2D envMap; uniform vec4 glassParams; // x: refraction, y: reflection, z: thickness vec3 calculateGlassEffect(vec3 normal, vec3 viewDir) { float refractiveIndex = glassParams.x; float reflectionStrength = glassParams.y; // 反射 vec3 reflectionDir = reflect(-viewDir, normal); vec3 reflection = textureCube(envMap, reflectionDir).rgb; // 菲涅尔效�? float fresnel = pow(1.0 - max(0.0, dot(normal, viewDir)), 2.0); // 混合反射 vec3 finalColor = reflection * fresnel * reflectionStrength; return finalColor; } void frag() { vec3 normal = normalize(v_normal); vec3 viewDir = normalize(cc_cameraPos.xyz - v_worldPos); vec3 glassColor = calculateGlassEffect(normal, viewDir); fragColor = vec4(glassColor, 0.8); // 半透明 } }%
|
🔍 Legacy 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
| // 调试可视化着色器 CCProgram debug-visualizer %{ uniform vec4 debugMode; // x: mode vec3 visualizeNormals(vec3 normal) { return normal * 0.5 + 0.5; // 映射到[0,1]范围 } vec3 visualizeUV(vec2 uv) { return vec3(uv, 0.0); } void frag() { int mode = int(debugMode.x); vec3 debugColor; if (mode == 0) { // 法线可视�? debugColor = visualizeNormals(normalize(v_normal)); } else if (mode == 1) { // UV坐标可视�? debugColor = visualizeUV(v_uv); } else { // 默认颜色 debugColor = vec3(1, 0, 1); } fragColor = vec4(debugColor, 1.0); } }%
|
📝 开发最佳实�?
代码组织
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| // 良好的代码组织结�?CCProgram shader-utils %{ // 常量定义 #define PI 3.14159265359 #define EPSILON 0.001 // 通用函数�? float saturate(float x) { return clamp(x, 0.0, 1.0); } // 光照计算函数 float distributionGGX(float NdotH, float roughness) { float a = roughness * roughness; float a2 = a * a; float denom = NdotH * NdotH * (a2 - 1.0) + 1.0; return a2 / (PI * denom * denom); } }%
|
平台兼容�?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| // 平台兼容性处�?CCProgram compatibility %{ precision mediump float; // 移动端优�? #ifdef CC_USE_MOBILE precision mediump float; #define HIGH_QUALITY 0 #else precision highp float; #define HIGH_QUALITY 1 #endif // 条件编译 #if HIGH_QUALITY float calculateHighQualityEffect() { // 高质量实�? return complexCalculation(); } #else float calculateHighQualityEffect() { // 简化版实现 return simpleCalculation(); } #endif }%
|
📝 本章小结
通过本教程,你应该掌握了�?
- Legacy Shader概念: 理解Legacy Shader的特点和适用场景
- 基本结构: 掌握Legacy Shader的语法和组织结构
- 核心组件: 了解CCEffect、Uniform块、顶点属性等核心概念
- 实际应用: 学会使用Legacy Shader实现复杂效果
🚀 下一步学�?
继续深入学习Legacy Shader的高级功能!🎮�