💡 个人专栏 ShaderMyHead 的附录。
一、Cocos Creator 内置着色器变量
1.1 顶点着色器输入变量 (Vertex Attributes)
均是以 a_ 开头的变量:
基础顶点属性
- a_position :顶点空间位置,vec3 类型
- a_normal :顶点法线,vec3 类型
- a_texCoord :主纹理 UV 坐标,定义了顶点在 2D 纹理图像上的对应位置,vec2 类型
- a_color :顶点颜色,vec4 类型
- a_tangent :切线向量,vec4 类型
次要 UV 和光照贴图
- a_texCoord1 :第二套 UV 坐标,用于光照贴图等
蒙皮动画相关
- a_joints :骨骼索引,通常为 vec4 或 u32vec4 类型
- a_weights :骨骼权重,通常为 vec4 类型
- a_jointAnimInfo :骨骼动画信息
实例化相关
- a_matWorld0 、 a_matWorld1 、 a_matWorld2 :实例化世界矩阵
- a_lightingMapUVParam :光照贴图UV参数
- a_localShadowBiasAndProbeId :阴影偏移和反射探针ID
- a_reflectionProbeData :反射探针数据
- a_sh_linear_const_r/g/b :球谐函数光照系数
形变动画相关
- a_vertexId :顶点ID,用于形变动画
粒子系统相关
- a_position_starttime :粒子中心位置和开始时间
- a_size_uv :粒子大小和 UV 信息
- a_rotation_uv :粒子旋转和 UV 信息
- a_dir_life :粒子初始速度和生命周期
- a_rndSeed :随机种子
- a_texCoord1 :粒子大小
- a_texCoord2 :粒子旋转
- a_texCoord3 :网格顶点
- a_texCoord4 :位置和帧索引
- a_color1 :速度和缩放
特殊用途
- a_lineDistance :线距离
- a_dist :距离
- a_batch_id :批处理 ID
- a_batch_uv :批处理 UV
- a_color2 :第二套颜色(用于 Spine 动画)
1.2 全局 Uniform 变量 (UBO)
指通过 Uniform Buffer Objects (UBO) 定义的全局变量,请查阅官方文档《Cocos Shader 内置全局 Uniform》。
留意变量在使用时,需要先引入对应的着色器片段(Chunk):
// cc-local.chunk 的变量引入 cc-local
#include <cc-local>
// cc-global.chunk 的变量引入 cc-global
#include <cc-global>
二、GLSL 内置方法 (持续完善中)
2.1 纹理相关
texture
对一个纹理(采样器)进行采样,返回采样结果。
-
语法
texture(sampler2D sampler, vec2 coord [, float bias]) texture(samplerCube sampler, vec3 coord [, float bias]) -
参数
名称 类型 描述 sampler sampler2D/samplerCube平面或立方体的纹理采样器 coord vec要采样的纹理坐标 [可选] bias vec采样偏移量,如果没有提供则默认为 0 -
返回值
纹理的 RGBA 信息,
vec4类型。
textureSize
获取纹理的尺寸,返回纹理的宽度和高度。
⚠️ 不推荐在 Cocos Creator 中使用此函数,该函数属于 GLSL ES 3.00,与 Cocos Creator 默认使用的 GLSL ES 1.00 不兼容。
且该函数在运行时返回的是整个图集尺寸而非子纹理尺寸,容易导致错误。
-
语法
textureSize(sampler2D sampler [, int lod = 0]) textureSize(samplerCube sampler [, int lod = 0]) -
参数
名称 类型 描述 sampler sampler2D/samplerCube平面或立方体的纹理采样器 [可选] lod intLevel of Detail,是纹理的 Mipmap 层级。 0:默认值,表示最基础的纹理尺寸(原始大小);1:表示第一级 mipmap(宽高都减半);2:再减半,以此类推。 -
返回值
二维返回纹理的宽度和高度,
ivec2类型。 三维返回纹理的宽度、高度和面数,ivec3类型。
2.2 数学公式相关
三角函数
函数返回两个向量的点积(也称为内积)。两个向量的点积等于它们的长度乘积再乘以它们的夹角的余弦值。
-
语法
sin(float x); // 正弦函数 cos(float x); // 余弦函数 tan(float x); // 正切函数 asin(float x); // 反正弦函数,返回 [-π/2, π/2] acos(float x); // 反余弦函数,返回 [0, π] atan(float x); // 反正切函数,返回 [-π/2, π/2] sinh(float x); // 双曲正弦函数 cosh(float x); // 双曲余弦函数 tanh(float x); // 双曲正切函数 asinh(float x); // 反双曲正弦函数 acosh(float x); // 反双曲余弦函数 atanh(float x); // 反双曲正切函数 -
返回值
float类型。
mod
取余方法,计算给定两个数相除后的余数。
-
语法
mod(a, b); -
参数
名称 类型 描述 a float,vec2,vec3,vec4,int,ivec2,ivec3,ivec4,bool,bvec2,bvec3,bvec4,mat2,mat3,mat4被除数 b 同 a除数 -
返回值
返回
a除以b后的余数,类型同a。 -
示例
float a = 16.0; float b = 3.0; float result = mod(a, b); // result = 1.0
exp
计算以自然底数 e 为底的指数函数值。
-
语法
exp(float x); -
返回值
float类型,返回e的x次方。
log
计算以自然底数 e 为底的指数函数值。
-
语法
log(float x, float base); -
参数
名称 类型 描述 x float要计算对数的值,必须为正数 base float对数的底数,必须为正数 -
返回值
float类型。 -
示例
float result = log(8.0, 2.0); // 3.0
sqrt
计算给定参数的平方根。
-
语法
sqrt(float x); -
参数
名称 类型 描述 x float要计算的值,必须为非负数,否则会返回 NaN -
返回值
float类型,对应x的平方根。
dot
函数返回两个向量的点积(也称为内积)。两个向量的点积等于它们的长度乘积再乘以它们的夹角的余弦值。
-
语法
dot(vec2 x, vec2 y); dot(vec3 x, vec3 y); dot(vec4 x, vec4 y); -
参数
名称 类型 描述 x 向量 第一个向量 y 标量 与 x同维度的另一个向量 -
返回值
float类型:- 对于
vec2:dot(a,b) = a.x * b.x + a.y * b.y; - 对于
vec3:dot(a,b) = a.x * b.x + a.y * b.y + a.z * b.z; - 对于
vec4:dot(a,b) = a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w。
- 对于
pow
计算指定数值的幂次方。
-
语法
pow(x, y); -
参数
名称 类型 描述 x float底数 y float指数 -
返回值
float类型 -
示例
float result = pow(2.0, 3.0); // 8.0
2.3 取值相关
abs
取绝对值:
float a = abs(-5.0); // 5.0
float b = abs(3.0); // 3.0
ceil 和 floor
向上取整(ceil)和向下取整(floor):
float a = 3.14;
float b = ceil(a); // 4.0
vec2 v1 = vec2(1.2, 2.7);
vec2 v2 = ceil(v1); // vec2(2.0, 3.0)
floor(3.7); // 3
floor(0.2); // 0
floor(-2.8); // -3
min 和 max
可传入多个参数,返回传入参数的最小或最大值:
min(1.0, 2.0, 3.0); // 1.0
max(1.0, 2.0, 3.0); // 3.0
若传入的是向量,则返回向量各元素中最小或最大值所组成的新向量:
vec3 u = vec3(2.0, 3.0, 1.0);
vec3 v = vec3(1.0, 4.0, 2.0);
vec3 min_val = min(u, v); // (1.0, 3.0, 1.0)
vec3 max_val = min(u, v); // (2.0, 4.0, 2.0)
fract
获取给定数字的小数部分:
float a = 3.14;
float b = -2.5;
float c = 5.0;
float fa = fract(a); // 0.14
float fb = fract(b); // -0.5
float fc = fract(c); // 0.0
clamp
限制一个值的范围在指定的最小值和最大值之间。该函数返回一个限制后的值,相当于:
clamp(x, min, max) = min(max(x, min), max)
-
语法
clamp(float x, float minVal, float maxVal) clamp(vec2 x, vec2 minVal, vec2 maxVal) clamp(vec3 x, vec3 minVal, vec3 maxVal) clamp(vec4 x, vec4 minVal, vec4 maxVal) -
参数
名称 类型 描述 x 标量或向量 需要限制范围的值 minVal 同 x限制范围的最小值 maxVal 同 x限制范围的最大值 -
返回值
标量或向量,同
x的类型。 -
示例
vec3 v = vec3(1.2, -0.5, 2.0); vec3 clampedV = clamp(v, vec3(0.0), vec3(3.0)); // (1.2, 0.0, 2.0)
2.4 计算相关
distance
计算两个点的欧几里得距离。
-
语法
distance(p0, p1) -
参数
名称 类型 描述 p0 vec第一个点的坐标 p1 vec第二个点的坐标 -
返回值
两个点的欧几里得距离,
float类型。
length
计算一个向量的长度(模),其实际计算公式为:
length(x) = sqrt(dot(x, x));
-
语法
length(vec2 x); length(vec3 x); length(vec4 x); -
参数
名称 类型 描述 x 向量 要被计算的向量 -
返回值
返回一个非负数的
float。
step
用于返回 0.0 或 1.0 的规范化跃迁函数。
-
语法
step(edge, x) -
参数
名称 类型 描述 edge float阈值 x float输入值 -
返回值
float类型:- 当
x < edge:返回0.0; - 当
x >= edge:返回1.0;
- 当
smoothstep
smoothstep函数是用于实现平滑插值的函数之一,它可以在指定起止边界的范围内,将一个给定的值进行平滑插值。例如在着色器计算过程中,将颜色值进行平滑渐变,从而实现渐变效果。
与 step 函数的区别如下:
-
语法
smoothstep(edge0, edge1, x) -
参数
名称 类型 描述 edge0 float起始边界 edge1 float终止边界,必须大于 edge0x float输入值 -
返回值
float类型:- 当
x <= edge0:返回0.0; - 当
x >= edge1:返回1.0; - 当
x在(edge0, edge1)之间时,返回一个范围在[0, 1]之间的平滑插值(非线性)。
- 当
-
示例
下方代码中,随着 x 的增大,输出的 val 会是 0 到 1 之间的平滑变化曲线:
for (float x = 0.0; x <= 1.0; x += 0.1) { float val = smoothstep(0.0, 1.0, x); }
mix
用于混合两个标量、向量或颜色的函数。它的作用是基于第三个参数 alpha,在两个值之间进行线性插值。
-
语法
mix(x, y, alpha) -
参数
名称 类型 描述 x 标量、向量或颜色 起始值 y 标量、向量或颜色 结束值 alpha float插值因子,在 [0.0, 1.0]之间 -
返回值
返回
x * (1 - alpha) + y * alpha。
normalize
将一个向量归一化,等同于向量除以自身的模(长度),常用于计算光照、法线等。
-
语法
normalize(x) -
参数
名称 类型 描述 x vec2、vec3常规为法线向量 -
返回值
返回返回一个长度为
1的向量,等价于x / length(x)。若
x是一个零向量,则返回的也是零向量。
三、GLSL 内置变量和常量
在 GLSL 中有许多由 gl_ 为前缀的内置变量/常量。
💡 不推荐在 Cocos Creator 中使用这些变量,因为会破坏引擎的抽象层,导致 WebGL、Vulkan、Metal 等后端渲染接口的兼容性问题。此处仅供读者了解 GLSL 底层知识。
3.1 顶点着色器(Vertex Shader)的 GLSL 内置变量
-
gl_Position- 用途:定义顶点在裁剪空间中的最终位置(必须赋值)。
- 类型:
vec4(向量类型,下一小节会介绍)。
-
gl_PointSize- 用途:设置点的渲染大小(以像素为单位)。
- 类型:
float。
-
gl_VertexID- 用途:当前顶点的索引(从 0 开始递增)。
- 类型:
int。
-
gl_InstanceID-
用途:实例化渲染时的实例索引(需配合
gl.drawArraysInstanced使用)。 -
类型:
int。
-
3.2 片段着色器(Fragment Shader)的 GLSL 内置变量
-
gl_FragCoord- 用途:当前片段的窗口相对坐标(
x, y为像素位置,z为深度值)。 - 类型:
vec4(只读)。
- 用途:当前片段的窗口相对坐标(
-
gl_FrontFacing- 用途:判断当前片段是否属于正面(由顶点顺序决定)。
- 类型:
bool(只读)。
-
gl_PointCoord- 用途:在绘制
gl.POINTS时,获取当前点在纹理坐标系中的坐标(范围[0,1])。 - 类型:
vec2(只读)。
- 用途:在绘制
-
gl_FragDepth- 用途:手动设置片段的深度值(默认由
gl_FragCoord.z决定)。 - 类型:
float。 - 注意:修改此值可能导致性能下降(需启用
EXT_frag_depth扩展)。
- 用途:手动设置片段的深度值(默认由
3.3 GLSL 内置常量
GLSL 中存在一些只读的内置常量(较少情况会用上):
gl_MaxVertexAttribs:支持的顶点属性最大数量。gl_MaxCombinedTextureImageUnits:所有着色器阶段(顶点+片段)可同时使用的总纹理单元数。gl_MaxVertexTextureImageUnits:顶点着色器可单独使用的纹理单元数。gl_MaxVaryingComponents:顶点着色器和片元着色器之间可以传递的最大varying分量数。
四、UV 坐标
UV 坐标是计算机图形学中用于将2D纹理映射到3D模型表面的坐标系统,它定义了纹理图像上的点与模型表面顶点之间的对应关系。
4.1 字母含义
- U:纹理的水平轴(相当于笛卡尔坐标的X轴)
- V:纹理的垂直轴(相当于笛卡尔坐标的Y轴)
💡 为了不与常规坐标的 X、Y 坐标轴混淆,UV 坐标采用了 U 和 V 作为坐标轴名称。
4.2 取值范围
无论是 U 还是 V,其值的取值范围固定为 [0.0, 1.0](无论纹理实际分辨率是多少)。
示意图:
4.3 动态纹理合批的影响
在 Cocos Creator 中,如果对 SpriteFrame 资源启用 Packable 属性,则会在运行时对纹理进行动态合批以提升性能:
纹理合批(Texture Batching)表示将多张不同的小纹理(贴图)合并到一张大纹理图集(Atlas)中,可以减少 GPU 切换纹理、Draw Call 的次数,从而提升渲染效率。
但是动态合批后,小纹理被「裁剪」并重新排布到大图中的某个区域,原本 [0, 1] 区间的 UV 坐标必须映射到新图集中对应的子区域 UV。
这会导致一个问题 ———— 如果纹理使用了着色器,且对 UV 做了偏移、缩放等处理,则纹理合批后会导致着色器效果异常。
因此如果发现你的着色器效果跟在编辑器中调试的效果不一致(在编辑器中表现正常,在其它平台表现异常),可以先检查下相关 SpriteFrame 资源是否勾选上了 Packable 属性。
💡 如果你的着色器直接用了传入的 UV,且没有做额外的变换,则无需担心动态合批的影响,因为引擎会帮你处理好这块的转换。
💡 基于同样的原因,静态合图(例如在图片资源文件夹下创建的自动图集配置(
auto-atlas.pac))也会导致一样的问题。
另外,若你使用了 Cocos Creator 内置的功能节点(例如 Button、SpriteSplash 等),这些节点的 Sprite 组件中 SpriteFrame 一般都是绑定的内置图片(一般都是 default_ 开头的名称,例如 Button 的 SpriteFrame 文件名为 default_btn_normal):
这些内置图片都是开启 packable 功能的,也会触发相关问题。
五、齐次坐标
齐次坐标(Homogeneous Coordinates)是计算机图形学中用于表示几何变换(如旋转、平移、缩放等)的一种数学工具。它通过增加一个额外的维度(通常用 w 表示)来扩展笛卡尔坐标系。
5.1 定义
在二维中,一个点 (x, y) 的齐次坐标是 (x, y, w);在三维中,一个点 (x, y, z) 的齐次坐标为 (x, y, z, w)。
5.2 核心特性
-
尺度不变性:
(x, y, w) ≡ (kx, ky, kw)(k ≠ 0)表示同一个点。例如:
(2,3,1) ≡ (4,6,2) ≡ (1,1.5,0.5)都表示笛卡尔点(2,3)。 -
无穷远点表示:
w = 0时表示无穷远处的点(理想点)。例如:
(1,2,0)表示方向向量(1,2)。
5.3 为何需要齐次坐标?
原因:为了在图形学中,统一使用矩阵来表示所有的空间变换,特别是平移。
例如在 3D 空间中,旋转和缩放都可以用 3×3 矩阵完成,但平移是个加法操作,无法用 3×3 矩阵乘法实现;
通过引入齐次坐标,我们可以用 4×4 矩阵来统一处理平移的问题:
表示原始点 (
x, y) 平移 (dx, dy)。
这样,旋转、缩放、平移都可以用一个矩阵搞定,非常高效。
5.4 在 Cocos Creator 中的应用
在 Cocos Creator 的顶点着色器中,常用于计算裁剪空间:
vec4 pos = vec4(a_position, 1); // 扩展齐次坐标的 w 分量,便于后续计算
#if USE_LOCAL
// 将顶点位置从局部空间(local space)转换到世界空间(world space)。
// cc_matWorld 是一个内置的世界矩阵变量。
pos = cc_matWorld * pos;
#endif
// 将顶点位置从当前空间(可能是局部空间或世界空间,取决于前面的条件)转换到裁剪空间(clip space)坐标。
// cc_matViewProj 是一个内置的视图投影矩阵变量。
pos = cc_matViewProj * pos;
六、NDC 标准化设备坐标
NDC(Normalized Device Coordinates)标准化设备坐标也常称为归一化设备坐标,是一个标准的笛卡尔坐标系,用于在图形学中统一描述屏幕空间。
它是顶点着色器输出位置 gl_Position 做透视除法(除以 w 分量)之后得到的空间坐标:
vec3 ndc = gl_Position.xyz / gl_Position.w;
💡 在图形学的渲染管线中,所有顶点坐标最终都必须转换为 NDC 空间范围,才能被 GPU 渲染在屏幕上正确的位置。
6.1 取值范围
| 轴向 | 范围 |
|---|---|
| X | -1.0 到 1.0(左到右) |
| Y | -1.0 到 1.0(下到上) |
| Z | -1.0 到 1.0(OpenGL) 0.0 到 1.0(Cocos / Metal / DirectX) |
以 Cocos Creator 标准为例,NDC 空间示意图如下:
6.2 在 Cocos Creator 中的应用
虽然前文提到「所有顶点坐标最终都必须转换为 NDC 空间范围」,但我们在顶点着色器中只需要返回裁剪空间坐标(在下一节介绍):
CCProgram vs %{
precision highp float;
#include <cc-global>
in vec3 a_position;
vec4 vert() {
vec4 pos = vec4(a_position, 1);
// 将顶点位置转换到裁剪空间(clip space)
pos = cc_matViewProj * pos;
return pos;
}
}%
这是因为 GPU 后续(在图元装配阶段结束后)会自动将其转换为 NDC 坐标,而无需开发者手动转换。
七、裁剪空间坐标
在图形管线中,坐标的空间转换完整流程如下:
模型空间 → 世界空间 → 视图空间 → 裁剪空间 → NDC 空间 → 设备屏幕空间
因此在了解裁剪空间的概念前,还需了解模型空间、世界空间和视图空间。
7.1 模型空间/本地空间
在游戏引擎中,每个 2D 或 3D 模型(及它们的每个顶点)都具备相应的模型空间坐标,它等同于 Cocos Creator 中的本地空间坐标。
例如下图的 2D 模型(一个带有 Sprite 组件的节点)的模型空间坐标(本地坐标) 为 X=356, Y=-135,可以在属性检查器中的 Position 中查看和修改该节点的坐标值:
7.2 世界空间
等同于 Cocos Creator 中的世界空间坐标,即游戏场景空间内的统一坐标体系。
当我们在顶点着色器使用 a_position 内置变量时,如果是 Sprite、Label、UI 等简单的 2D 节点,Cocos Creator 已经帮我们把 a_position 从模型空间坐标转换为世界空间坐标了。
如果是复杂的模型(例如 Spine 动画、3D 模型等),a_position 仅表示顶点的模型空间坐标,需乘以世界空间矩阵变量才能得到对应的世界空间坐标:
vec4 pos = vec4(a_position, 1);
// 将顶点位置从模型空间/本地空间(local space)转换到世界空间(world space)。
// cc_matWorld 是一个内置的世界矩阵变量。
pos = cc_matWorld * pos;
7.3 视图空间
这个世界上存在不计其数的物质,每个物质都有它们各自的位置,但我们当下所能看到的物质,仅基于我们(眼睛)所在的地方。
放到游戏引擎中,这个“能看到哪些物质”的限制就是摄像机的位置和朝向了。
因此视图空间也称为摄像机空间,是最终经过 Camera + 投影转换后映射到屏幕的空间。
常规使用内置的摄像机变换矩阵变量 cc_matView,乘以顶点的世界空间坐标,即可得到顶点的视图空间坐标:
vec4 pos = vec4(a_position, 1);
pos = cc_matWorld * pos; // 世界空间坐标
pos = cc_matView * pos; // 视图空间坐标
7.4 裁剪空间
假设我们站在一个房间里,我们只能看到视线所及范围内的物质,例如无法看到后脑勺后面的东西。
在游戏引擎中,摄像机也有对应的视锥体,只要顶点落在摄像机的视锥体内部,就属于可以被渲染的顶点,否则会被裁剪掉。而这块空间的计算,称之为裁剪空间(Clip Space)的转换。
摄像机的 FOV (Field of View,视野角)、近远裁剪面、正交尺寸、宽高比等投影参数,是裁剪空间的关键因素,它们直接决定了哪些内容可以被渲染到屏幕上。
常规我们会使用内置的 cc_matProj 或 cc_matViewProj 矩阵变量,来进一步计算得到裁剪空间坐标:
vec4 pos = vec4(a_position, 1);
pos = cc_matWorld * pos; // 世界空间坐标
pos = cc_matView * pos; // 视图空间坐标
pos = cc_matProj * pos; // 裁剪空间坐标
// 等同于
vec4 pos = vec4(a_position, 1);
pos = cc_matWorld * pos; // 世界空间坐标
pos = cc_matViewProj * pos; // 裁剪空间坐标
💡 裁剪空间决定了「可以」渲染到屏幕上的内容,但 GPU 会最终根据画布尺寸适配规则、设备屏幕分辨率,来进一步剔除设备视口外的内容。
八、Cocos Creator 智能宏
Cocos Creator 内置了大量的智能宏,这些宏如果在着色器中使用到,就会在材质面板中自动显示(留意以 CC_ 开头的宏不会在材质面板出现),且默认值均为 0。
开发者可以通过这些宏来控制着色器的不同功能和渲染路径,以下为参考清单:
8.1 渲染相关宏
材质和纹理宏
- USE_TEXTURE - 使用纹理
- USE_NORMAL_MAP - 使用法线贴图
- USE_EMISSIVE_MAP - 使用自发光贴图
- USE_SPECULAR_MAP - 使用高光贴图
- USE_PBR_MAP - 使用PBR贴图
- USE_OCCLUSION_MAP - 使用遮挡贴图
- USE_ALPHA_TEST - 使用Alpha测试
- USE_VERTEX_COLOR - 使用顶点颜色
- USE_TWOSIDE - 双面渲染
- HAS_SECOND_UV - 有第二套UV
光照和阴影宏
- CC_USE_IBL - 使用基于图像的光照
- CC_USE_LIGHTMAP - 使用光照贴图
- CC_USE_HDR - 使用HDR
- CC_USE_FOG - 使用雾效
- CC_USE_ACCURATE_FOG - 使用精确雾效
- CC_FORWARD_ADD - 前向渲染附加通道
- CC_SUPPORT_CASCADED_SHADOW_MAP - 支持级联阴影贴图
- CC_USE_REFLECTION_PROBE - 使用反射探针
- CC_USE_DIFFUSEMAP - 使用漫反射贴图
动画和变形宏
- CC_USE_SKINNING - 使用骨骼动画
- CC_USE_MORPH - 使用变形动画
- CC_USE_BAKED_ANIMATION - 使用烘焙动画
- CC_USE_REAL_TIME_JOINT_TEXTURE - 使用实时关节纹理
- CC_JOINT_UNIFORM_CAPACITY - 关节uniform容量
实例化和批处理宏
- USE_INSTANCING - 使用实例化渲染
- USE_BATCHING - 使用批处理
8.2 Surface Shader 相关宏
基础功能宏
- CC_SURFACES_USE_TANGENT_SPACE - 使用切线空间
- CC_SURFACES_USE_VERTEX_COLOR - 使用顶点颜色
- CC_SURFACES_USE_SECOND_UV - 使用第二套UV
- CC_SURFACES_USE_TWO_SIDED - 双面渲染
- CC_SURFACES_USE_LIGHT_MAP - 使用光照贴图
- CC_SURFACES_FLIP_UV - 翻转UV
- CC_SURFACES_USE_REFLECTION_DENOISE - 使用反射降噪
光照相关宏
- CC_SURFACES_LIGHTING_USE_FRESNEL - 使用菲涅尔
- CC_SURFACES_USE_LEGACY_COMPATIBLE_LIGHTING - 使用兼容光照
- CC_SURFACES_LIGHTING_ANISOTROPIC_ENVCONVOLUTION_COUNT - 各向异性环境卷积数量
- CC_SURFACES_LIGHTING_DISABLE_DIFFUSE - 禁用漫反射
- CC_SURFACES_LIGHTING_DISABLE_SPECULAR - 禁用高光
顶点修改宏
- CC_SURFACES_VERTEX_MODIFY_LOCAL_POS - 修改本地位置
- CC_SURFACES_VERTEX_MODIFY_WORLD_POS - 修改世界位置
- CC_SURFACES_VERTEX_MODIFY_CLIP_POS - 修改裁剪位置
- CC_SURFACES_VERTEX_MODIFY_WORLD_NORMAL - 修改世界法线
- CC_SURFACES_VERTEX_MODIFY_UV - 修改UV
- CC_SURFACES_VERTEX_MODIFY_SHADOW_BIAS - 修改阴影偏移
片段修改宏
- CC_SURFACES_FRAGMENT_MODIFY_BASECOLOR_AND_TRANSPARENCY - 修改基础颜色和透明度
- CC_SURFACES_FRAGMENT_MODIFY_WORLD_NORMAL - 修改世界法线
- CC_SURFACES_FRAGMENT_MODIFY_EMISSIVE - 修改自发光
- CC_SURFACES_FRAGMENT_MODIFY_PBRPARAMS - 修改PBR参数
- CC_SURFACES_FRAGMENT_MODIFY_ANISOTROPY_PARAMS - 修改各向异性参数
- CC_SURFACES_FRAGMENT_MODIFY_SHARED_DATA - 修改共享数据
- CC_SURFACES_FRAGMENT_ALPHA_CLIP_ONLY - 仅Alpha裁剪
Toon 渲染宏
- CC_SURFACES_FRAGMENT_MODIFY_TOON_STEP_AND_FEATHER - 修改卡通步长和羽化
- CC_SURFACES_FRAGMENT_MODIFY_TOON_SHADOW_COVER - 修改卡通阴影覆盖
- CC_SURFACES_FRAGMENT_MODIFY_TOON_SPECULAR - 修改卡通高光
传输宏
- CC_SURFACES_TRANSFER_LOCAL_POS - 传输本地位置
- CC_SURFACES_TRANSFER_CLIP_POS - 传输裁剪位置
8.3 引擎功能宏
调试和性能宏
- CC_USE_DEBUG_VIEW - 使用调试视图
- CC_USE_PROFILER - 使用性能分析器
- CC_USE_FLOAT_OUTPUT - 使用浮点输出
- CC_USE_RGBE_OUTPUT - 使用RGBE输出
平台和设备宏
- CC_DEVICE_SUPPORT_FLOAT_TEXTURE - 设备支持浮点纹理
- CC_DEVICE_MAX_VERTEX_UNIFORM_VECTORS - 设备最大顶点uniform向量数
- CC_DEVICE_MAX_FRAGMENT_UNIFORM_VECTORS - 设备最大片段uniform向量数
- CC_DEVICE_CAN_BENEFIT_FROM_INPUT_ATTACHMENT - 设备可从输入附件受益
- CC_PLATFORM_ANDROID_AND_WEBGL - Android和WebGL平台
渲染管线宏
- CC_FORCE_FORWARD_SHADING - 强制前向着色
- CC_USE_SURFACE_SHADER - 使用Surface着色器
- CC_USE_METAL - 使用Metal
- CC_USE_WGPU - 使用WebGPU
- CC_USE_ENVMAP - 使用环境贴图
- CC_USE_LIGHT_PROBE - 使用光照探针
集群光照宏
- CC_ENABLE_CLUSTERED_LIGHT_CULLING - 启用集群光照剔除
8.4 特殊效果宏
后处理宏
- USE_RGBE_CUBEMAP - 使用RGBE立方体贴图
- USE_SEQUENCE_ANIM - 使用序列动画
- USE_HORIZONTAL - 使用水平
- USE_VERTICAL - 使用垂直
- USE_PIXEL_ALIGNMENT - 使用像素对齐
Toon 着色器宏
- USE_OUTLINE_PASS - 使用轮廓通道
- USE_1ST_SHADE_MAP - 使用第一阴影贴图
- USE_2ND_SHADE_MAP - 使用第二阴影贴图
高级材质宏
- USE_COAT_DATA_MAP - 使用涂层数据贴图
- USE_FLAKE - 使用薄片
- USE_SHEEN_DATA_MAP - 使用光泽数据贴图
- USE_SHEEN_COLOR_MAP - 使用光泽颜色贴图
- USE_SSS_MAP - 使用次表面散射贴图
- USE_NORMALMAP - 使用法线贴图
- USE_PBR - 使用PBR
九、纹理过滤
在着色器中使用 texture 对纹理进行采样时,GPU 需要根据当前的 UV 坐标,决定从纹理中取出哪个像素的颜色值。但 UV 坐标是连续的浮点数,而纹理是离散的像素点,因此这就涉及到: 「浮点数坐标」如何映射到「像素颜色」 。
纹理过滤(Filtering)提供了多个方案来解决上述问题,常见的过滤方式包括了NEAREST(最近点采样)、LINEAR(线性插值采样)和 MIPMAP Filtering(多级渐远纹理)。
在 Cocos Creator 中,纹理文件的「过滤模式」属性会有多个方案给你选择:
9.1 NEAREST(最近点采样)
- 原理:取最靠近的像素的颜色,不做插值。
- 效果:像素感强,马赛克感明显,适合像素风格游戏。
- 优点:性能快、结果可控,没有边缘插值导致的问题。
- 缺点:缩放时锯齿严重,不平滑。
9.2 LINEAR(线性插值采样)
- 原理:采样周围的 2×2 像素,按 UV 的偏移做双线性插值(Bilinear)。
- 效果:平滑、柔和,适合大多数正常纹理缩放。
- 优点:常规使用推荐,视觉平滑。
- 缺点:在贴图边缘采样时会混色,容易导致“白边”问题。
9.3 MIPMAP Filtering(多级渐远纹理)
当纹理被缩得特别小时,单靠 LINEAR 或 NEAREST 会产生锯齿或闪烁问题。
Mipmap 是一系列分辨率逐渐缩小的纹理版本,用于低分辨率采样时自动选用更小级别的贴图。
常见 Mipmap 模式:
| 模式名 | 说明 |
|---|---|
NEAREST_MIPMAP_NEAREST | 最近 mipmap + 最近点 |
LINEAR_MIPMAP_NEAREST | 最近 mipmap + 线性采样 |
NEAREST_MIPMAP_LINEAR | 线性混合 mipmap + 最近点 |
LINEAR_MIPMAP_LINEAR(常用) | 线性混合 mipmap + 线性采样(即 trilinear filtering) |
⚠️ Mipmap 会增加显存和加载时间,如果不需要缩放或不希望边缘模糊,可以关闭。