�?.1章:宏定义系�? 宏定义系统是Cocos Shader的强大特性之一,它允许开发者通过条件编译、参数化配置和代码生成来创建灵活且高效的着色器。本章将深入探讨宏系统的各种用法和最佳实践�?
🎯 学习目标 通过本章学习,你将掌握:
Cocos Shader宏系统的工作原理 条件编译的各种使用场�?- 宏参数与动态配置技�?- 性能优化中的宏应�?- 大型项目中的宏管理策�? 💡 宏系统基础 宏定义的基本语法 1 2 3 4 5 6 7 8 9 10 #define MACRO_FUNCTION(x, y) ((x) + (y)) #define MACRO_VALUE 1 #else #define MACRO_VALUE 0 #endif
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 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 CCEffect %{ techniques: - name: opaque passes: - vert: macro-demo-vs:vert frag: macro-demo-fs:frag properties: &props mainTexture: { value: white } useNormalMap: { value: false , editor: { type: boolean } } useEmissive: { value: false , editor: { type: boolean } } useAO: { value: false , editor: { type: boolean } } - name: transparent passes: - vert: macro-demo-vs:vert frag: macro-demo-fs:frag rasterizerState: &trasparent_rs cullMode: none blendState: &transparent_bs targets: - blend: true blendSrc: src_alpha blendDst: one_minus_src_alpha properties: *props }% CCProgram macro-demo-vs %{ #include <surface-vertex> }% CCProgram macro-demo-fs %{ #include <surface-fragment> #pragma define-meta HAS_EMISSIVE editor { tab: "Feature", type: boolean } #pragma define-meta HAS_AO editor { tab: "Feature", type: boolean } uniform sampler2D mainTexture; #if HAS_NORMAL_MAP uniform sampler2D normalTexture; #endif #if HAS_EMISSIVE uniform sampler2D emissiveTexture; #endif #if HAS_AO uniform sampler2D aoTexture; #endif void surf (in SurfaceIn In, inout SurfaceOut Out) { vec4 albedo = texture (mainTexture, In.uv); #if HAS_NORMAL_MAP vec3 normalMap = texture (normalTexture, In.uv).xyz * 2.0 - 1.0 ; Out.normal = normalize (In.worldTangent.xyz * normalMap.x + In.worldBinormal * normalMap.y + In.worldNormal * normalMap.z); #else Out.normal = normalize (In.worldNormal); #endif #if HAS_EMISSIVE Out.emissive = texture (emissiveTexture, In.uv).rgb; #else Out.emissive = vec3 (0.0 ); #endif #if HAS_AO Out.ao = texture (aoTexture, In.uv).r; #else Out.ao = 1.0 ; #endif Out.albedo = albedo; Out.metallic = 0.0 ; Out.roughness = 0.5 ; } }%
🔧 条件编译详解 基础条件编译 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 #define ENABLE_SHADOWS 1 #define ENABLE_FOG 0 #if ENABLE_SHADOWS float calculateShadow(vec4 shadowCoord) { return 1.0 ; } #endif #if ENABLE_FOG vec3 applyFog(vec3 color, float distance ) { return color; } #endif void surf(in SurfaceIn In, inout SurfaceOut Out) { vec3 finalColor = calculateLighting(In); #if ENABLE_SHADOWS float shadow = calculateShadow(In.shadowCoord); finalColor *= shadow; #endif #if ENABLE_FOG finalColor = applyFog(finalColor, length (In.viewPos)); #endif Out.albedo = vec4 (finalColor, 1.0 ); }
多级条件编译 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 #define QUALITY_LOW 0 #define QUALITY_MEDIUM 1 #define QUALITY_HIGH 2 #define QUALITY_ULTRA 3 #ifndef RENDER_QUALITY #define RENDER_QUALITY QUALITY_MEDIUM #endif #define ENABLE_NORMAL_MAPPING 1 #else #define ENABLE_NORMAL_MAPPING 0 #endif #if RENDER_QUALITY >= QUALITY_HIGH #define ENABLE_PARALLAX_MAPPING 1 #define SHADOW_MAP_SIZE 2048 #else #define ENABLE_PARALLAX_MAPPING 0 #define SHADOW_MAP_SIZE 1024 #endif #if RENDER_QUALITY >= QUALITY_ULTRA #define ENABLE_SCREEN_SPACE_REFLECTIONS 1 #define MAX_LIGHT_COUNT 8 #else #define ENABLE_SCREEN_SPACE_REFLECTIONS 0 #define MAX_LIGHT_COUNT 4 #endif
平台特定编译 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 #ifdef CC_PLATFORM_MOBILE #define USE_PRECISION_OPTIMIZATION 1 #define MAX_TEXTURE_SIZE 1024 precision mediump float ; #else #define USE_PRECISION_OPTIMIZATION 0 #define MAX_TEXTURE_SIZE 2048 precision highp float ; #endif #ifdef CC_PLATFORM_WEBGL #define WEBGL_COMPATIBILITY 1 #else #define WEBGL_COMPATIBILITY 0 #endif return vec3 (1.0 ); } #define calculateLighting calculateLightingMobile #else } #define calculateLighting calculateLightingDesktop #endif
📊 宏参数与动态配�? 参数化宏系统 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 #define LIGHTING_MODEL_LAMBERT 0 #define LIGHTING_MODEL_PHONG 1 #define LIGHTING_MODEL_BLINN_PHONG 2 #define LIGHTING_MODEL_PBR 3 #ifndef LIGHTING_MODEL #define LIGHTING_MODEL LIGHTING_MODEL_PBR #endif #ifndef TEXTURE_CHANNEL_COUNT #define TEXTURE_CHANNEL_COUNT 4 #endif #ifndef MAX_DIRECTIONAL_LIGHTS #define MAX_DIRECTIONAL_LIGHTS 1 #endif #ifndef MAX_POINT_LIGHTS #define MAX_POINT_LIGHTS 4 #endif #ifndef MAX_SPOT_LIGHTS #define MAX_SPOT_LIGHTS 2 #endif uniform vec4 directionalLights[MAX_DIRECTIONAL_LIGHTS];uniform vec4 pointLights[MAX_POINT_LIGHTS];uniform vec4 spotLights[MAX_SPOT_LIGHTS];
功能组合�? 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 #define FEATURE_NORMAL_MAPPING 0x0002 #define FEATURE_PARALLAX 0x0004 #define FEATURE_EMISSION 0x0008 #define FEATURE_TRANSPARENCY 0x0010 #define FEATURE_ANIMATION 0x0020 #define FEATURE_INSTANCING 0x0040 #define FEATURE_LOD 0x0080 #define PRESET_SIMPLE (FEATURE_BASIC) #define PRESET_STANDARD (FEATURE_BASIC | FEATURE_NORMAL_MAPPING) #define PRESET_ADVANCED (FEATURE_BASIC | FEATURE_NORMAL_MAPPING | FEATURE_PARALLAX) #define PRESET_FULL (FEATURE_BASIC | FEATURE_NORMAL_MAPPING | FEATURE_PARALLAX | FEATURE_EMISSION) #ifndef SHADER_FEATURES #define SHADER_FEATURES PRESET_STANDARD #endif vec4 albedo = texture (mainTexture, In.uv); #if HAS_FEATURE(FEATURE_NORMAL_MAPPING) vec3 normalMap = texture (normalTexture, In.uv).xyz * 2.0 - 1.0 ; Out.normal = applyNormalMap(In, normalMap); #else Out.normal = normalize (In.worldNormal); #endif #if HAS_FEATURE(FEATURE_PARALLAX) vec2 parallaxUV = calculateParallaxUV(In); albedo = texture (mainTexture, parallaxUV); #endif #if HAS_FEATURE(FEATURE_EMISSION) #else Out.emissive = vec3 (0.0 ); #endif Out.albedo = albedo; }
🎨 宏的高级应用 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 #define DECLARE_TEXTURE_UNIFORM(name, index) \ uniform sampler2D name; \ uniform vec4 name##_ST; \ vec2 TRANSFORM_TEX_##name(vec2 uv) { \ return uv * name##_ST.xy + name##_ST.zw; \ } DECLARE_TEXTURE_UNIFORM(mainTexture, 0 ) DECLARE_TEXTURE_UNIFORM(normalTexture, 1 ) DECLARE_TEXTURE_UNIFORM(emissiveTexture, 2 ) #define GENERATE_LIGHTING_FUNCTION(name, equation) \ vec3 calculate##name##Lighting(vec3 normal, vec3 lightDir, vec3 viewDir, \ vec3 lightColor, vec3 albedo) { \ return equation; \ } GENERATE_LIGHTING_FUNCTION(Lambert, albedo * lightColor * max (dot (normal, lightDir), 0.0 )) GENERATE_LIGHTING_FUNCTION(Phong, albedo * lightColor * max (dot (normal, lightDir), 0.0 ) + lightColor * pow (max (dot (reflect (-lightDir, normal), viewDir), 0.0 ), 32.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 31 32 33 34 35 { int var = 0 ; code } \ { int var = 1 ; code } #define UNROLL_LOOP_4(code, var) \ { int var = 0 ; code } \ { int var = 1 ; code } \ { int var = 2 ; code } \ { int var = 3 ; code } #define UNROLL_LOOP_8(code, var) \ UNROLL_LOOP_4(code, var) \ { int var = 4 ; code } \ { int var = 5 ; code } \ { int var = 6 ; code } \ { int var = 7 ; code } vec3 totalLight = vec3 (0.0 ); #if MAX_POINT_LIGHTS <= 4 UNROLL_LOOP_4({ if (i < MAX_POINT_LIGHTS) { totalLight += calculatePointLight(In, albedo, normal, pointLights[i]); } }, i) #else for (int i = 0 ; i < MAX_POINT_LIGHTS; i++) { totalLight += calculatePointLight(In, albedo, normal, pointLights[i]); } #endif return totalLight; }
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 #define DEBUG_ONLY(code) code #define DEBUG_OUTPUT(var, color) Out.albedo = vec4(color, 1.0); #else #define DEBUG_ONLY(code) #define DEBUG_OUTPUT(var, color) #endif #define PERF_COUNTER_START(name) float name##_start = cc_time.x; #define PERF_COUNTER_END(name) float name##_time = cc_time.x - name##_start; #define PERF_OUTPUT(name) DEBUG_OUTPUT(name##_time, vec3(name##_time)) #else #define PERF_COUNTER_START(name) #define PERF_COUNTER_END(name) #define PERF_OUTPUT(name) #endif PERF_COUNTER_START(lighting) vec3 lighting = calculateLighting(In); PERF_COUNTER_END(lighting) PERF_OUTPUT(lighting) DEBUG_ONLY({ if (debugMode == 1 ) { DEBUG_OUTPUT(lighting, lighting); return ; } }) Out.albedo = vec4 (lighting, 1.0 ); }
🔧 材质变体系统 宏驱动的材质变体 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 CCEffect %{ techniques: - name: opaque passes: - vert: variant-vs:vert frag: variant-fs:frag properties: &props mainTexture: { value: white } # 材质变体开�? enableNormalMap: { value: false, editor: { type: boolean } } enableEmission: { value: false , editor: { type: boolean } } enableTransparency: { value: false , editor: { type: boolean } } enableAnimation: { value: false , editor: { type: boolean } } }% CCProgram variant-vs %{ #include <surface-vertex> #if ENABLE_VERTEX_ANIMATION uniform float animationTime; uniform float animationAmplitude; uniform float animationFrequency; vec3 applyVertexAnimation(vec3 worldPos, vec3 normal) { float wave = sin (worldPos.x * animationFrequency + animationTime) * animationAmplitude; return worldPos + normal * wave; } #endif void vert() { SurfaceIn In; VertexInput(In); #if ENABLE_VERTEX_ANIMATION In.worldPos = applyVertexAnimation(In.worldPos, In.worldNormal); #endif SurfaceVertex(In); } }% CCProgram variant-fs %{ #include <surface-fragment> #pragma define-meta ENABLE_EMISSION editor { tab: "Material", type: boolean } #pragma define-meta ENABLE_TRANSPARENCY editor { tab: "Material", type: boolean } #pragma define-meta ENABLE_DETAIL_MAP editor { tab: "Material", type: boolean } uniform sampler2D mainTexture; #if ENABLE_NORMAL_MAP uniform sampler2D normalTexture; uniform float normalStrength; #endif #if ENABLE_EMISSION uniform sampler2D emissionTexture; uniform vec3 emissionColor; uniform float emissionIntensity; #endif #if ENABLE_TRANSPARENCY uniform float transparency; #endif #if ENABLE_DETAIL_MAP uniform sampler2D detailTexture; uniform float detailScale; #endif void surf(in SurfaceIn In, inout SurfaceOut Out) { vec2 uv = In.uv; #if ENABLE_DETAIL_MAP vec2 detailUV = uv * detailScale; vec4 detail = texture (detailTexture, detailUV); #endif vec4 albedo = texture (mainTexture, uv); #if ENABLE_DETAIL_MAP albedo.rgb *= detail.rgb * 2.0 ; #endif #if ENABLE_NORMAL_MAP vec3 normalMap = texture (normalTexture, uv).xyz * 2.0 - 1.0 ; normalMap.xy *= normalStrength; Out.normal = normalize (In.worldTangent.xyz * normalMap.x + In.worldBinormal * normalMap.y + In.worldNormal * normalMap.z); #else Out.normal = normalize (In.worldNormal); #endif #if ENABLE_EMISSION vec3 emission = texture (emissionTexture, uv).rgb * emissionColor * emissionIntensity; Out.emissive = emission; #else Out.emissive = vec3 (0.0 ); #endif #if ENABLE_TRANSPARENCY albedo.a *= transparency; #endif Out.albedo = albedo; Out.metallic = 0.0 ; Out.roughness = 0.5 ; Out.ao = 1.0 ; } }%
🎯 性能优化中的宏应�? 1. 精度控制�? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #define PRECISION_LOW lowp #define PRECISION_MEDIUM mediump #define PRECISION_HIGH highp #else #define PRECISION_LOW #define PRECISION_MEDIUM #define PRECISION_HIGH #endif PRECISION_HIGH vec3 worldPos = In.worldPos; PRECISION_MEDIUM vec3 normal = In.worldNormal; PRECISION_LOW vec3 color = texture (mainTexture, In.uv).rgb; return color * dot (normal, lightDirection); }
2. 常量折叠�? 1 2 3 4 5 6 7 8 9 10 11 12 13 #define TWO_PI (2.0 * PI) #define HALF_PI (PI * 0.5) #define INV_PI (1.0 / PI) #define INV_TWO_PI (1.0 / TWO_PI) #define SQRT2 1.41421356237 #define SQRT3 1.73205080757 #define GOLDEN_RATIO 1.61803398875 #define GAUSSIAN_OFFSETS { 0.0, 1.3846153846, 3.2307692308, 5.0769230769, 6.9230769231 }
3. 内联函数�? 1 2 3 4 5 6 7 8 9 10 11 12 13 #define FAST_SQRT(x) ((x) * inversesqrt(x)) #define FAST_LENGTH(v) sqrt(dot(v, v)) #define FAST_NORMALIZE(v) ((v) * inversesqrt(dot(v, v))) #define FAST_DISTANCE(a, b) length((a) - (b)) #define SATURATE(x) clamp(x, 0.0, 1.0) #define LINEARSTEP(edge0, edge1, x) SATURATE(((x) - (edge0)) / ((edge1) - (edge0))) #define SMOOTHERSTEP(x) ((x) * (x) * (3.0 - 2.0 * (x))) #define FAST_LOG2(x) log2(x) #define FAST_POW(x, y) exp2((y) * log2(x))
📋 宏管理最佳实�? 1. 宏命名规�? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #define USE_VERTEX_COLORS #define MAX_LIGHT_COUNT #define CC_PLATFORM_MOBILE #define CC_PLATFORM_WEBGL #define CC_PLATFORM_NATIVE #define DEBUG_SHOW_NORMALS #define DEBUG_WIREFRAME #define DEBUG_PERFORMANCE #define _INTERNAL_HELPER_MACRO #define _TEMP_CALCULATION
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 #ifndef RENDER_QUALITY #define RENDER_QUALITY 2 // 0=�? 1=�? 2=�? 3=超高 #endif #ifndef MAX_LIGHTS #define MAX_LIGHTS 4 #endif #ifdef CC_PLATFORM_MOBILE #define IS_MOBILE_PLATFORM 1 #else #define IS_MOBILE_PLATFORM 0 #endif #if RENDER_QUALITY >= 1 #define ENABLE_NORMAL_MAPPING 1 #else #define ENABLE_NORMAL_MAPPING 0 #endif #if RENDER_QUALITY >= 2 #define ENABLE_PARALLAX_MAPPING 1 #define ENABLE_DETAIL_TEXTURES 1 #else #define ENABLE_PARALLAX_MAPPING 0 #define ENABLE_DETAIL_TEXTURES 0 #endif #if RENDER_QUALITY >= 3 #define ENABLE_SCREEN_SPACE_REFLECTIONS 1 #define ENABLE_VOLUMETRIC_LIGHTING 1 #else #define ENABLE_SCREEN_SPACE_REFLECTIONS 0 #define ENABLE_VOLUMETRIC_LIGHTING 0 #endif #define FEATURE_ENABLED(feature) (feature == 1) #define MOBILE_OPTIMIZATION(mobile_code, desktop_code) \ IS_MOBILE_PLATFORM ? (mobile_code) : (desktop_code)
3. 宏文档化 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #pragma define-meta ENABLE_NORMAL_MAPPING range([0, 1]) default(1) #pragma define-meta ENABLE_PARALLAX_MAPPING range([0, 1]) default(0) #pragma define-meta MAX_LIGHT_COUNT range([1, 16]) default(4)
📖 本章总结 通过本章学习,我们深入掌握了�?
�?宏系统基础 :基本语法和Cocos Creator特有的宏机制 �?条件编译 :多级条件、平台特定和功能组合 �?**宏参数配�?*:参数化宏和动态配置技�?- �?高级应用 :代码生成、循环展开和调试宏 �?材质变体 :宏驱动的灵活材质系�?- �?性能优化 :精度控制、常量折叠和内联函数 �?管理实践 :命名规范、组织结构和文档�? 🚀 下一步学�? 掌握了宏定义系统后,建议继续学习�? 👉 �?.2章:函数重映射技术
💡 实践练习 基础练习 :创建一个支持多种质量等级的材质系统进阶练习 :实现基于宏的平台适配着色器高级练习 :设计完整的宏驱动材质变体系�?*参考资�?
系列导航