第12.2章:Legacy Shader函数详解

在Legacy Shader中,函数是实现复杂效果的核心工具。本教程将深入讲解Legacy Shader中的函数定义、参数传递、优化技巧和最佳实践。

🎯 学习目标

  • 掌握Legacy Shader中函数的定义和使�?- 理解函数参数传递机�?- 学会函数优化和性能调优
  • 了解常用函数库的设计模式

📋 前置知识

  • 已完成第12.1章Legacy Shader介绍
  • 熟悉GLSL函数语法
  • 理解GPU并行计算特点

📝 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
// Legacy Shader函数定义基础
CCProgram function-basics %{
precision highp float;

// 基本函数定义
float simpleFunction(float input) {
return input * 2.0;
}

// 多参数函�? vec3 calculateColor(vec3 baseColor, float intensity, float gamma) {
vec3 result = baseColor * intensity;
return pow(result, vec3(1.0 / gamma));
}

// 向量函数
vec2 rotateUV(vec2 uv, float angle) {
float c = cos(angle);
float s = sin(angle);
mat2 rotMatrix = mat2(c, -s, s, c);
return rotMatrix * (uv - 0.5) + 0.5;
}

// 矩阵函数
mat3 createRotationMatrix(vec3 axis, float angle) {
axis = normalize(axis);
float s = sin(angle);
float c = cos(angle);
float oc = 1.0 - c;

return mat3(
oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s,
oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s,
oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c
);
}
}%

参数传递机�?

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
// 参数传递类型详�?CCProgram parameter-passing %{
// 值传�?(默认)
float valueParameter(float x) {
x *= 2.0; // 不会影响原始�? return x;
}

// 输入参数 (in)
float inputParameter(in float x) {
return x * x; // 只读参数
}

// 输出参数 (out)
void outputParameter(float input, out float result) {
result = sqrt(input); // 结果通过参数返回
}

// 输入输出参数 (inout)
void inoutParameter(inout vec3 color) {
color = normalize(color); // 修改原始�? color *= 1.2;
}

// 多重输出示例
void calculateLighting(vec3 normal, vec3 lightDir, vec3 viewDir,
out float diffuse, out float specular, out float fresnel) {
diffuse = max(0.0, dot(normal, lightDir));

vec3 halfDir = normalize(lightDir + viewDir);
specular = pow(max(0.0, dot(normal, halfDir)), 32.0);

fresnel = pow(1.0 - max(0.0, dot(normal, viewDir)), 2.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
// 数学工具函数�?CCProgram math-library %{
// 常量定义
#define PI 3.14159265359
#define TAU 6.28318530718
#define E 2.71828182846
#define GOLDEN_RATIO 1.61803398875

// 基础数学函数
float saturate(float x) {
return clamp(x, 0.0, 1.0);
}

vec3 saturate(vec3 x) {
return clamp(x, vec3(0.0), vec3(1.0));
}

float remap(float value, float oldMin, float oldMax, float newMin, float newMax) {
return newMin + (value - oldMin) * (newMax - newMin) / (oldMax - oldMin);
}

// 平滑插值函�? float smoothstep01(float x) {
return x * x * (3.0 - 2.0 * x);
}

float smootherstep(float edge0, float edge1, float x) {
x = saturate((x - edge0) / (edge1 - edge0));
return x * x * x * (x * (x * 6.0 - 15.0) + 10.0);
}

// 三角函数扩展
float sinWave(float x, float frequency, float amplitude, float phase) {
return sin(x * frequency + phase) * amplitude;
}

float cosWave(float x, float frequency, float amplitude, float phase) {
return cos(x * frequency + phase) * amplitude;
}

// 距离函数
float distance2D(vec2 a, vec2 b) {
vec2 delta = a - b;
return sqrt(delta.x * delta.x + delta.y * delta.y);
}

float distanceSquared(vec3 a, vec3 b) {
vec3 delta = a - b;
return dot(delta, delta);
}

// 角度计算
float angleBetween(vec3 a, vec3 b) {
return acos(dot(normalize(a), normalize(b)));
}

// 随机数函�? float random(float x) {
return fract(sin(x * 12.9898) * 43758.5453);
}

float random(vec2 st) {
return fract(sin(dot(st.xy, vec2(12.9898, 78.233))) * 43758.5453123);
}

vec2 random2D(vec2 st) {
st = vec2(dot(st, vec2(127.1, 311.7)), dot(st, vec2(269.5, 183.3)));
return -1.0 + 2.0 * fract(sin(st) * 43758.5453123);
}
}%

颜色处理函数�?

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
// 颜色处理函数�?CCProgram color-library %{
// RGB与HSV转换
vec3 rgb2hsv(vec3 c) {
vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));

float d = q.x - min(q.w, q.y);
float e = 1.0e-10;
return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}

vec3 hsv2rgb(vec3 c) {
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
return c.z * mix(K.xxx, saturate(p - K.xxx), c.y);
}

// 伽马校正
vec3 linearToGamma(vec3 color) {
return pow(color, vec3(1.0 / 2.2));
}

vec3 gammaToLinear(vec3 color) {
return pow(color, vec3(2.2));
}

// 色调调整
vec3 adjustHue(vec3 color, float hueShift) {
vec3 hsv = rgb2hsv(color);
hsv.x += hueShift;
hsv.x = fract(hsv.x); // 保持在[0,1]范围
return hsv2rgb(hsv);
}

vec3 adjustSaturation(vec3 color, float saturationMultiplier) {
vec3 hsv = rgb2hsv(color);
hsv.y *= saturationMultiplier;
hsv.y = saturate(hsv.y);
return hsv2rgb(hsv);
}

vec3 adjustBrightness(vec3 color, float brightnessOffset) {
return color + vec3(brightnessOffset);
}

// 对比度调�? vec3 adjustContrast(vec3 color, float contrast) {
return (color - 0.5) * contrast + 0.5;
}

// 色彩平衡
vec3 colorBalance(vec3 color, vec3 shadows, vec3 midtones, vec3 highlights) {
float luminance = dot(color, vec3(0.299, 0.587, 0.114));

float shadowWeight = 1.0 - smoothstep(0.0, 0.5, luminance);
float highlightWeight = smoothstep(0.5, 1.0, luminance);
float midtoneWeight = 1.0 - shadowWeight - highlightWeight;

return color * (shadows * shadowWeight + midtones * midtoneWeight + highlights * highlightWeight);
}

// 温度调整 (色温)
vec3 adjustTemperature(vec3 color, float temperature) {
// 简化的色温调整
float factor = temperature / 6500.0; // 标准色温
if (factor > 1.0) {
// 偏暖色调
color.r *= 1.0 + (factor - 1.0) * 0.3;
color.b *= 1.0 - (factor - 1.0) * 0.2;
} else {
// 偏冷色调
color.r *= factor;
color.b *= 1.0 + (1.0 - factor) * 0.3;
}
return color;
}
}%

噪声函数�?

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
// 噪声生成函数�?CCProgram noise-library %{
// 值噪�?(Value Noise)
float valueNoise(vec2 st) {
vec2 i = floor(st);
vec2 f = fract(st);

// 四个角的随机�? float a = random(i);
float b = random(i + vec2(1.0, 0.0));
float c = random(i + vec2(0.0, 1.0));
float d = random(i + vec2(1.0, 1.0));

// 平滑插�? vec2 u = f * f * (3.0 - 2.0 * f);

return mix(a, b, u.x) + (c - a) * u.y * (1.0 - u.x) + (d - b) * u.x * u.y;
}

// 梯度噪声 (Gradient Noise)
float gradientNoise(vec2 st) {
vec2 i = floor(st);
vec2 f = fract(st);

// 四个角的梯度向量
vec2 ga = random2D(i + vec2(0.0, 0.0));
vec2 gb = random2D(i + vec2(1.0, 0.0));
vec2 gc = random2D(i + vec2(0.0, 1.0));
vec2 gd = random2D(i + vec2(1.0, 1.0));

// 计算从角点到当前点的向量
vec2 va = f - vec2(0.0, 0.0);
vec2 vb = f - vec2(1.0, 0.0);
vec2 vc = f - vec2(0.0, 1.0);
vec2 vd = f - vec2(1.0, 1.0);

// 计算点积
float a = dot(ga, va);
float b = dot(gb, vb);
float c = dot(gc, vc);
float d = dot(gd, vd);

// 平滑插�? vec2 u = smoothstep(0.0, 1.0, f);

return mix(mix(a, b, u.x), mix(c, d, u.x), u.y);
}

// 分形噪声 (Fractal Noise)
float fractalNoise(vec2 st, int octaves) {
float value = 0.0;
float amplitude = 0.5;
float frequency = 1.0;

for (int i = 0; i < octaves; i++) {
value += amplitude * gradientNoise(st * frequency);
amplitude *= 0.5;
frequency *= 2.0;
}

return value;
}

// 简化版Simplex噪声
float simplexNoise(vec2 v) {
const vec4 C = vec4(0.211324865405187, // (3.0-sqrt(3.0))/6.0
0.366025403784439, // 0.5*(sqrt(3.0)-1.0)
-0.577350269189626, // -1.0 + 2.0 * C.x
0.024390243902439); // 1.0 / 41.0

vec2 i = floor(v + dot(v, C.yy));
vec2 x0 = v - i + dot(i, C.xx);

vec2 i1;
i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0);

vec4 x12 = x0.xyxy + C.xxzz;
x12.xy -= i1;

i = mod289(i);
vec3 p = permute(permute(i.y + vec3(0.0, i1.y, 1.0)) + i.x + vec3(0.0, i1.x, 1.0));

vec3 m = max(0.5 - vec3(dot(x0, x0), dot(x12.xy, x12.xy), dot(x12.zw, x12.zw)), 0.0);
m = m * m;
m = m * m;

vec3 x = 2.0 * fract(p * C.www) - 1.0;
vec3 h = abs(x) - 0.5;
vec3 ox = floor(x + 0.5);
vec3 a0 = x - ox;

m *= 1.79284291400159 - 0.85373472095314 * (a0 * a0 + h * h);

vec3 g;
g.x = a0.x * x0.x + h.x * x0.y;
g.yz = a0.yz * x12.xz + h.yz * x12.yw;
return 130.0 * dot(m, g);
}

// 辅助函数
vec3 mod289(vec3 x) {
return x - floor(x * (1.0 / 289.0)) * 289.0;
}

vec3 permute(vec3 x) {
return mod289(((x * 34.0) + 1.0) * x);
}
}%

🔧 光照计算函数

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
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
// PBR光照计算函数�?CCProgram pbr-lighting %{
struct MaterialData {
vec3 albedo;
float metallic;
float roughness;
vec3 normal;
vec3 emission;
float ao;
};

struct LightData {
vec3 direction;
vec3 color;
float intensity;
};

// 菲涅尔反�?(Fresnel)
vec3 fresnelSchlick(float cosTheta, vec3 F0) {
return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0);
}

vec3 fresnelSchlickRoughness(float cosTheta, vec3 F0, float roughness) {
return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(1.0 - cosTheta, 5.0);
}

// 法线分布函数 (Normal Distribution Function - GGX/Trowbridge-Reitz)
float distributionGGX(vec3 N, vec3 H, float roughness) {
float a = roughness * roughness;
float a2 = a * a;
float NdotH = max(dot(N, H), 0.0);
float NdotH2 = NdotH * NdotH;

float num = a2;
float denom = (NdotH2 * (a2 - 1.0) + 1.0);
denom = PI * denom * denom;

return num / denom;
}

// 几何遮蔽函数 (Geometry Function)
float geometrySchlickGGX(float NdotV, float roughness) {
float r = (roughness + 1.0);
float k = (r * r) / 8.0;

float num = NdotV;
float denom = NdotV * (1.0 - k) + k;

return num / denom;
}

float geometrySmith(vec3 N, vec3 V, vec3 L, float roughness) {
float NdotV = max(dot(N, V), 0.0);
float NdotL = max(dot(N, L), 0.0);
float ggx2 = geometrySchlickGGX(NdotV, roughness);
float ggx1 = geometrySchlickGGX(NdotL, roughness);

return ggx1 * ggx2;
}

// PBR BRDF计算
vec3 calculatePBR(MaterialData material, LightData light, vec3 viewDir) {
vec3 lightDir = normalize(-light.direction);
vec3 halfwayDir = normalize(lightDir + viewDir);

// 基础反射�? vec3 F0 = mix(vec3(0.04), material.albedo, material.metallic);

// Cook-Torrance BRDF
float NDF = distributionGGX(material.normal, halfwayDir, material.roughness);
float G = geometrySmith(material.normal, viewDir, lightDir, material.roughness);
vec3 F = fresnelSchlick(max(dot(halfwayDir, viewDir), 0.0), F0);

vec3 kS = F;
vec3 kD = vec3(1.0) - kS;
kD *= 1.0 - material.metallic;

vec3 numerator = NDF * G * F;
float denominator = 4.0 * max(dot(material.normal, viewDir), 0.0) * max(dot(material.normal, lightDir), 0.0) + 0.001;
vec3 specular = numerator / denominator;

float NdotL = max(dot(material.normal, lightDir), 0.0);

vec3 diffuse = kD * material.albedo / PI;
return (diffuse + specular) * light.color * light.intensity * NdotL;
}

// 环境光照计算
vec3 calculateAmbientLighting(MaterialData material, vec3 viewDir, samplerCube irradianceMap, samplerCube prefilterMap, sampler2D brdfLUT) {
vec3 F0 = mix(vec3(0.04), material.albedo, material.metallic);
vec3 F = fresnelSchlickRoughness(max(dot(material.normal, viewDir), 0.0), F0, material.roughness);

vec3 kS = F;
vec3 kD = 1.0 - kS;
kD *= 1.0 - material.metallic;

// 漫反射环境光
vec3 irradiance = textureCube(irradianceMap, material.normal).rgb;
vec3 diffuse = irradiance * material.albedo;

// 镜面反射环境�? vec3 reflectionDir = reflect(-viewDir, material.normal);
float maxReflectionLOD = 4.0; // 预滤波贴图的最大LOD
vec3 prefilteredColor = textureLod(prefilterMap, reflectionDir, material.roughness * maxReflectionLOD).rgb;

vec2 brdf = texture(brdfLUT, vec2(max(dot(material.normal, viewDir), 0.0), material.roughness)).rg;
vec3 specular = prefilteredColor * (F * brdf.x + brdf.y);

vec3 ambient = (kD * diffuse + specular) * material.ao;
return ambient;
}
}%

自定义光照模�?

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
// 自定义光照模型函数库
CCProgram custom-lighting %{
// 卡通光照模�? vec3 calculateToonLighting(vec3 baseColor, vec3 normal, vec3 lightDir, float steps) {
float NdotL = dot(normal, lightDir);
NdotL = NdotL * 0.5 + 0.5; // 重映射到[0,1]

// 量化光照
float quantized = floor(NdotL * steps) / steps;

return baseColor * quantized;
}

// 卡通边缘光
vec3 calculateToonRimLight(vec3 normal, vec3 viewDir, vec3 rimColor, float rimPower, float rimIntensity) {
float rim = 1.0 - saturate(dot(normal, viewDir));
rim = pow(rim, rimPower);
return rimColor * rim * rimIntensity;
}

// Oren-Nayar漫反射模�?(适用于粗糙表�?
float calculateOrenNayar(vec3 normal, vec3 lightDir, vec3 viewDir, float roughness) {
float NdotL = dot(normal, lightDir);
float NdotV = dot(normal, viewDir);

float angleVN = acos(NdotV);
float angleLN = acos(NdotL);

float alpha = max(angleVN, angleLN);
float beta = min(angleVN, angleLN);
float gamma = dot(viewDir - normal * NdotV, lightDir - normal * NdotL);

float roughnessSquared = roughness * roughness;

float A = 1.0 - 0.5 * (roughnessSquared / (roughnessSquared + 0.57));
float B = 0.45 * (roughnessSquared / (roughnessSquared + 0.09));

float L1 = max(0.0, NdotL) * (A + B * max(0.0, gamma) * sin(alpha) * tan(beta));

return L1;
}

// Minnaert月球表面反射模型
float calculateMinnaert(vec3 normal, vec3 lightDir, vec3 viewDir, float k) {
float NdotL = max(0.0, dot(normal, lightDir));
float NdotV = max(0.0, dot(normal, viewDir));

return NdotL * pow(NdotL * NdotV, k - 1.0);
}

// 各向异性反射模�? vec3 calculateAnisotropic(vec3 normal, vec3 tangent, vec3 lightDir, vec3 viewDir,
float roughnessU, float roughnessV, vec3 specularColor) {
vec3 bitangent = cross(normal, tangent);

vec3 halfDir = normalize(lightDir + viewDir);
float NdotH = dot(normal, halfDir);
float TdotH = dot(tangent, halfDir);
float BdotH = dot(bitangent, halfDir);

float exponent = -2.0 * ((TdotH * TdotH) / (roughnessU * roughnessU) + (BdotH * BdotH) / (roughnessV * roughnessV)) / (1.0 + NdotH);
float anisotropic = sqrt(max(0.0, dot(normal, lightDir) / dot(normal, viewDir))) * exp(exponent);

return specularColor * anisotropic;
}

// 子表面散射近�? vec3 calculateSubsurfaceScattering(vec3 normal, vec3 lightDir, vec3 viewDir,
vec3 thickness, vec3 subsurfaceColor, float power) {
vec3 backLight = lightDir + normal * 0.5; // 背光方向
float backLightDot = max(0.0, dot(-viewDir, backLight));

vec3 subsurface = subsurfaceColor * pow(backLightDot, power) * thickness;
return subsurface;
}
}%

🎯 函数优化技�?

性能优化函数

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
// 性能优化函数示例
CCProgram optimization-techniques %{
// 快速平方根倒数 (用于归一�?
float fastInverseSqrt(float x) {
// 注意:现代GPU通常内置了高效的rsqrt指令
return 1.0 / sqrt(x);
}

// 快速pow近似 (适用于特定情�?
float fastPow(float base, float exp) {
// 仅适用于正数base和小整数exp
if (exp == 2.0) return base * base;
if (exp == 3.0) return base * base * base;
if (exp == 4.0) {
float squared = base * base;
return squared * squared;
}
return pow(base, exp); // 回退到标准pow
}

// 向量长度的平�?(避免sqrt计算)
float lengthSquared(vec3 v) {
return dot(v, v);
}

// 分支优化:使用mix代替if-else
vec3 conditionalColor(float condition, vec3 colorA, vec3 colorB) {
// 使用mix而不是if-else可以避免分支
return mix(colorB, colorA, step(0.5, condition));
}

// 查找表优�? float lookupTable(float input, sampler2D lutTexture) {
// 将计算结果预存在纹理�? return texture(lutTexture, vec2(input, 0.0)).r;
}

// 分级细节 (LOD) 函数
float calculateLOD(vec3 worldPos, vec3 cameraPos) {
float distance = length(worldPos - cameraPos);
return log2(distance / 10.0); // 10为基础距离
}

vec3 applyLODOptimization(vec3 worldPos, vec3 cameraPos, vec3 normal) {
float lod = calculateLOD(worldPos, cameraPos);

if (lod > 2.0) {
// 远距离:简化计�? return vec3(0.5); // 简单灰�? } else if (lod > 1.0) {
// 中距离:中等质量
return normal * 0.5 + 0.5; // 法线映射
} else {
// 近距离:高质量计�? return calculateComplexLighting(normal);
}
}

vec3 calculateComplexLighting(vec3 normal) {
// 复杂光照计算的占位符
return normal;
}
}%

内存优化技�?

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
// 内存和带宽优�?CCProgram memory-optimization %{
// 数据打包:将多个值打包到单个向量�? vec4 packNormalAndRoughness(vec3 normal, float roughness) {
return vec4(normal, roughness);
}

void unpackNormalAndRoughness(vec4 packed, out vec3 normal, out float roughness) {
normal = packed.xyz;
roughness = packed.w;
}

// 法线压缩:存储两个分量,计算第三�? vec2 encodeNormal(vec3 normal) {
return normal.xy;
}

vec3 decodeNormal(vec2 encoded) {
vec3 normal;
normal.xy = encoded;
normal.z = sqrt(max(0.0, 1.0 - dot(normal.xy, normal.xy)));
return normalize(normal);
}

// 球面映射法线编码
vec2 encodeSphericalNormal(vec3 normal) {
vec2 encoded = normalize(normal.xy) * sqrt(-normal.z * 0.5 + 0.5);
return encoded * 0.5 + 0.5;
}

vec3 decodeSphericalNormal(vec2 encoded) {
vec2 fenc = encoded * 4.0 - 2.0;
float f = dot(fenc, fenc);
float g = sqrt(1.0 - f / 4.0);
vec3 normal;
normal.xy = fenc * g;
normal.z = 1.0 - f / 2.0;
return normalize(normal);
}

// 颜色精度优化
vec3 quantizeColor(vec3 color, float levels) {
return floor(color * levels) / levels;
}

// 半精度浮点数优化提示
#ifdef CC_USE_MOBILE
#define PRECISION mediump
#else
#define PRECISION highp
#endif

PRECISION float optimizedCalculation(PRECISION float input) {
return input * input; // 在移动端使用mediump精度
}
}%

📝 函数调试和测�?

调试辅助函数

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
// 调试工具函数
CCProgram debug-utilities %{
// 可视化浮点�? vec3 visualizeFloat(float value) {
return vec3(value);
}

// 可视化向量长�? vec3 visualizeVectorLength(vec3 vector) {
float length = length(vector);
return vec3(length);
}

// 热力图可视化
vec3 heatmapVisualization(float intensity) {
intensity = saturate(intensity);

if (intensity < 0.25) {
return mix(vec3(0,0,1), vec3(0,1,1), intensity * 4.0);
} else if (intensity < 0.5) {
return mix(vec3(0,1,1), vec3(0,1,0), (intensity - 0.25) * 4.0);
} else if (intensity < 0.75) {
return mix(vec3(0,1,0), vec3(1,1,0), (intensity - 0.5) * 4.0);
} else {
return mix(vec3(1,1,0), vec3(1,0,0), (intensity - 0.75) * 4.0);
}
}

// 网格可视�? float gridPattern(vec2 uv, float gridSize) {
vec2 grid = abs(fract(uv * gridSize) - 0.5) / fwidth(uv * gridSize);
float line = min(grid.x, grid.y);
return 1.0 - min(line, 1.0);
}

// 性能计数�? float performanceCounter() {
// 用于测量函数调用次数或复杂度
return 1.0; // 占位�? }
}%

📝 本章小结

通过本教程,你应该掌握了�?

  1. 函数定义: Legacy Shader中函数的完整语法和最佳实�?2. *参数传�?: 理解in、out、inout参数的使用场�?3. *函数库设�?: 学会构建模块化、可复用的函数库
  2. 性能优化: 掌握函数级别的性能优化技�?5. *调试技�?: 学会使用调试函数定位和解决问�?

🚀 下一步学�?

继续学习Legacy Shader与Surface Shader的深度对比!🎮�