着色器代码块迁移
简介
PlayCanvas 引擎的材质着色器代码块系统正在进行大幅调整,以支持更灵活的材质系统。背景参见此页面。
为帮助迁移现有自定义代码块,本页按引擎版本列出变更,从 v1.51 开始。
代码块 API 版本
引擎调试版检测到覆盖的代码块时,会向运行时控制台报告 API 变更。例如:

更新到最新 API 后,必须标记版本。例如自定义材质代码块更新到引擎 v2.8 后,按如下方式指定:
const materialChunksGLSL = material.getShaderChunks(pc.SHADERLANGUAGE_GLSL);
materialChunksGLSL.set('diffusePS', '...');
material.shaderChunksVersion = '2.8';
完成后,控制台不再显示版本警告。
代码块变更
以下按引擎版本列出变更。
引擎 v2.23
场景环境纹理使用独立 uniform
v2.23 之前,场景环境图集和天空盒与材质自有环境纹理共用 texture_envAtlas 和 texture_cubeMap 名称:引擎将场景纹理复制到每个受场景环境照亮的 StandardMaterial 参数中。从 v2.23 开始,渲染器通过 scene_envAtlas 和 scene_skybox 提供场景纹理,材质只提供自有纹理。环境光照代码块通过 {LIT_ENV_ATLAS} 和 {LIT_ENV_CUBEMAP} 标记声明和采样,着色器生成器按变体将其解析为场景或材质 uniform。参见 PR #9364。
自定义覆盖若仍硬编码 texture_envAtlas 或 texture_cubeMap,在有独立 envAtlas 或 cubeMap 的材质上仍能工作;但受场景环境照亮的材质不会获得纹理:采样器未设置,着色器会采样恰好绑定到该纹理单元的任意纹理。
从 v2.23 开始,环境来源也完全二选一:材质具有任意自有环境纹理(envAtlas、cubeMap 或 sphereMap)时,反射、环境光和折射只使用材质纹理。只有 cubeMap 或 sphereMap 时,环境光来自固定 ambientLight,此前则来自场景图集。
受影响的代码块:
src/scene/shader-lib/glsl/chunks/lit/frag/ambient.jssrc/scene/shader-lib/glsl/chunks/lit/frag/reflectionEnv.jssrc/scene/shader-lib/glsl/chunks/lit/frag/reflectionEnvHQ.jssrc/scene/shader-lib/glsl/chunks/lit/frag/reflectionCube.jssrc/scene/shader-lib/wgsl/chunks/lit/frag/ambient.jssrc/scene/shader-lib/wgsl/chunks/lit/frag/reflectionEnv.jssrc/scene/shader-lib/wgsl/chunks/lit/frag/reflectionEnvHQ.jssrc/scene/shader-lib/wgsl/chunks/lit/frag/reflectionCube.js
**迁移:**在自定义 ambientPS、reflectionEnvPS、reflectionEnvHQPS 和 reflectionCubePS 中,将声明和所有采样处的 texture_envAtlas 改为 {LIT_ENV_ATLAS},texture_cubeMap 改为 {LIT_ENV_CUBEMAP}。WGSL 采样器同样使用 {LIT_ENV_ATLAS}Sampler。随后设置 material.shaderChunksVersion = '2.23'。
迁移前(GLSL):
uniform sampler2D texture_envAtlas;
vec3 linearA = {reflectionDecode}(texture2D(texture_envAtlas, uv0));
迁移后(GLSL):
uniform sampler2D {LIT_ENV_ATLAS};
vec3 linearA = {reflectionDecode}(texture2D({LIT_ENV_ATLAS}, uv0));
迁移前(WGSL):
var texture_envAtlas: texture_2d<f32>;
var texture_envAtlasSampler: sampler;
let raw: vec4f = textureSample(texture_envAtlas, texture_envAtlasSampler, uv);
迁移后(WGSL):
var {LIT_ENV_ATLAS}: texture_2d<f32>;
var {LIT_ENV_ATLAS}Sampler: sampler;
let raw: vec4f = textureSample({LIT_ENV_ATLAS}, {LIT_ENV_ATLAS}Sampler, uv);
uScreenSize → screen_size
前向着色器应使用 screen_size。GLSL 声明由 uniform vec4 uScreenSize; 改为 uniform vec4 screen_size;,WGSL 由 uniform uScreenSize: vec4f; 改为 uniform screen_size: vec4f;,并更新全部引用。值仍是画布绘制缓冲区的宽、高及其倒数。
显式声明 uScreenSize 的现有着色器仍能使用,但调试构建会输出一次弃用警告。修改 material.shaderChunksVersion 不会消除此警告,必须重命名 uniform。
详情参见内置着色器 uniform。
引擎 v2.20
重构 MSDF 文本渲染
ElementComponent 文本使用的 msdfPS 已重构,按设计者预期的真实字形边缘渲染,并根据距离场梯度抗锯齿,修复会破坏细小连接处(例如 f 的横杠)的固定向内侵蚀。参见 PR #8935。
引擎不再设置 font_pxrange 和 font_textureWidth,代码块也移除了 map()。若旧版复制的自定义 msdfPS 仍引用这些 uniform,将读不到值(默认为 0,导致旧平滑算法除零),使文字损坏或不可见。
受影响的代码块:
src/scene/shader-lib/glsl/chunks/common/frag/msdf.jssrc/scene/shader-lib/wgsl/chunks/common/frag/msdf.js
**迁移:**参照最新代码块更新自定义 msdfPS,移除 font_pxrange、font_textureWidth 和 map() 引用,使用新的边缘与抗锯齿逻辑。有意调整字重时,使用逐字体的 font_sdfIntensity 或 outlineThickness,不要使用全局阈值偏移。
引擎 v2.16
高斯泼溅访问函数重命名
为保持 API 一致性,高斯泼溅着色器访问函数已统一为 getXXX() 命名。
| 旧版 | 新版 |
|---|---|
readCenter(source) | getCenter() |
readColor(source) | getColor() |
注意:getCenter() 加载其他函数共享的数据,必须先于 getRotation()、getScale() 或 getColor() 调用。不再需要 source 参数。
受影响的代码块:
src/scene/shader-lib/glsl/chunks/gsplat/vert/gsplat.jssrc/scene/shader-lib/wgsl/chunks/gsplat/vert/gsplat.js
移除 gsplatCustomizeVS 代码块
gsplatCustomizeVS 在 v2.16 移除,此前 v2.15 已弃用并改用 gsplatModifyVS。仍使用旧代码块会触发移除警告。
gsplatHelpers.js 中基于协方差的旧辅助函数 gsplatExtractSize、gsplatApplyUniformScale 和 gsplatMakeRound 也已移除。
迁移:
按下文 v2.15 指南改用 gsplatModifyVS,完整说明参见 v2.15 迁移指南。
引擎 v2.15
高斯泼溅着色器自定义
gsplatCustomizeVS 已弃用,由 gsplatModifyVS 替代。新 API 使用旋转四元数和缩放向量代替协方差矩阵,更加高效。参见 PR #8246。
旧版(gsplatCustomizeVS) | 新版(gsplatModifyVS) |
|---|---|
modifyCenter(inout vec3 center) | modifySplatCenter(inout vec3 center) |
modifyCovariance(originalCenter, modifiedCenter, inout covA, inout covB) | modifySplatRotationScale(originalCenter, modifiedCenter, inout rotation, inout scale) |
modifyColor(center, inout color) | modifySplatColor(center, inout color) |
辅助函数变更:
| 旧版 | 新版 |
|---|---|
gsplatApplyUniformScale(covA, covB, scale) | scale *= factor(直接相乘) |
gsplatExtractSize(covA, covB) | gsplatGetSizeFromScale(scale) |
gsplatMakeRound(covA, covB, radius) | gsplatMakeSpherical(scale, radius) |
迁移示例(GLSL):
迁移前:
void modifyCenter(inout vec3 center) {
center.y += 1.0;
}
void modifyCovariance(vec3 originalCenter, vec3 modifiedCenter, inout vec3 covA, inout vec3 covB) {
gsplatApplyUniformScale(covA, covB, 2.0);
}
void modifyColor(vec3 center, inout vec4 color) {
color.rgb *= 0.5;
}
迁移后:
void modifySplatCenter(inout vec3 center) {
center.y += 1.0;
}
void modifySplatRotationScale(vec3 originalCenter, vec3 modifiedCenter, inout vec4 rotation, inout vec3 scale) {
scale *= 2.0;
}
void modifySplatColor(vec3 center, inout vec4 color) {
color.rgb *= 0.5;
}
JavaScript 用法:
// Before
gsplatMaterial.getShaderChunks(shaderLanguage).set('gsplatCustomizeVS', customShader);
// After
gsplatMaterial.getShaderChunks(shaderLanguage).set('gsplatModifyVS', customShader);
引擎 v2.6
引擎内部代码块
以下顶点代码块已移除,由单个 litMainVS 替代:
endVSstartVSbaseVSviewNormalVSbaseNineSlicedVS
lightmapDirAddPS 已移除,其功能整合到 lightmapAddPS。
TBNderivativePS 和 TBNObjectSpacePS 已移除,功能整合到 TBNPS。
startPS 已移除,之后会加入更大的替代代码块。
outputAlphaOpaquePS 和 outputAlphaPremulPS 合并到 outputAlphaPS。
cubeMapProjectBoxPS 和 cubeMapProjectNonePS 合并到 cubeMapProjectPS。
envMultiplyPS 和 envConstPS 合并到 envProcPS。
aoSpecOccSimplePS、aoSpecOccConstSimplePS、aoSpecOccPS 和 aoSpecOccConstPS 合并为 aoSpecOccPS。
shadowSampleCoordPS 已移除,内容并入 lightFunctionPS。
以下反射代码块的纹理解码函数提供方式略有变化:$DECODE 改为 {reflectionDecode},$DECODE_CUBEMAP 改为 {reflectionCubemapDecode}。受影响的代码块:
reflectionEnvPSreflectionEnvHQPSreflectionCubePSreflectionSpherePS
以下环境光代码块已移除,并合并为单个 ambientPS:
ambientConstantPSambientEnvPSambientSHPS
引擎 v2.5
以下代码块已移除,由单个 fogPS 替代:
fogExpPSfogExp2PSfogLinearPSfogNonePS
以下代码块已移除,由单个 gammaPS 替代:
gamma1_0PSgamma2_2PS
引擎 v1.70
| 代码块 | 变更 |
|---|---|
refractionDynamicPS |
|
refractionCubePS |
|
引擎 v1.65
1.62 将前后端代码块之间传值的全局变量组织为 LitShaderArguments、IridescenceArgs、ClearcoatArgs 和 SheenArgs 结构。但这在 Android 上导致多种兼容问题,因此 1.65 改回全局变量。例如 litShaderArgs.albedo 变为 litArgs_albedo。
新的全局变量如下:
// Surface albedo absorbance
vec3 litArgs_albedo;
// Transparency
float litArgs_opacity;
// Emission color
vec3 litArgs_emission;
// Normal direction in world space
vec3 litArgs_worldNormal;
// Ambient occlusion amount, range [0..1]
float litArgs_ao;
// Light map color
vec3 litArgs_lightmap;
// Light map direction
vec3 litArgs_lightmapDir;
// Surface metalness factor, range [0..1]
float litArgs_metalness;
// The f0 specularity factor
vec3 litArgs_specularity;
// Specularity intensity factor, range [0..1]
float litArgs_specularityFactor;
// The microfacet glossiness factor, range [0..1]
float litArgs_gloss;
// Glossiness of the sheen layer, range [0..1]
float litArgs_sheen_gloss;
// The color of the f0 specularity factor for the sheen layer
vec3 litArgs_sheen_specularity;
// Transmission factor (refraction), range [0..1]
float litArgs_transmission;
// Uniform thickness of medium, used by transmission, range [0..inf]
float litArgs_thickness;
// Index of refraction
float litArgs_ior;
// Iridescence effect intensity, range [0..1]
float litArgs_iridescence_intensity;
// Thickness of the iridescent microfilm layer, value is in nanometers, range [0..1000]
float litArgs_iridescence_thickness;
// The normal used for the clearcoat layer
vec3 litArgs_clearcoat_worldNormal;
// Intensity of the clearcoat layer, range [0..1]
float litArgs_clearcoat_specularity;
// Glossiness of clearcoat layer, range [0..1]
float litArgs_clearcoat_gloss;
以下代码块签名改为接收独立成员,而非整个结构:
- endPS
- metalnessModulatePS
- outputAlphaPS
- outputAlphaPremulPS
- fresnelSchlickPS
- iridescenceDiffractionPS
- lightmapAddPS
- lightmapDirAddPS
- refractionCubePS
- refractionDynamicPS
引擎 v1.62
PlayCanvas 有两组着色器代码块:前端提供参数值,传给称为后端的光照算法。
1.62 更明确地区分二者,让传给后端的值预先定义清楚,而非自动生成。这样完全自定义的着色器也能像原生材质一样接入光照代码。
为适应该拆分,几乎全部后端代码块均有变化。自定义后端块必须从使用全局变量,迁移为使用光照后端传入的参数。
这也让一些专门用于清漆等功能的代码块变得多余,因为不再依赖全局值后,函数可以复用。
变更
此版本破坏了大部分 lit/frag 代码块兼容性。多数签名改为接收所需值,而非依赖全局变量;不过着色器仍设置多数全局值。例如:
vec3 combineColor() {
vec3 ret = vec3(0);
ret = dAlbedo * dDiffuseLight;
...
}
现在表示为:
vec3 combineColor(vec3 albedo, vec3 sheenSpecularity, float clearcoatSpecularity) {
vec3 ret = vec3(0);
ret = albedo * dDiffuseLight;
...
}
此前的全局值在 1.62 中打包到结构,主要结构 LitShaderArgs 定义如下:
struct LitShaderArguments
{
// Transparency
float opacity;
// Normal direction in world space
vec3 worldNormal;
// Surface albedo absorbance
vec3 albedo;
// Transmission factor (refraction), range [0..1]
float transmission;
// Uniform thickness of medium, used by transmission, range [0..inf]
float thickness;
// The f0 specularity factor
vec3 specularity;
// The microfacet glossiness factor, range [0..1]
float gloss;
// Surface metalness factor, range [0..1]
float metalness;
// Specularity intensity factor, range [0..1]
float specularityFactor;
// Ambient occlusion amount, range [0..1]
float ao;
// Emission color
vec3 emission;
// Light map color
vec3 lightmap;
// Light map direction
vec3 lightmapDir;
// Iridescence extension arguments
IridescenceArgs iridescence;
// Clearcoat extension arguments
ClearcoatArgs clearcoat;
// Sheen extension arguments
SheenArgs sheen;
};
最后三个参数是着色扩展。IridescenceArgs 定义如下:
struct IridescenceArgs
{
// Iridescence effect intensity, range [0..1]
float intensity;
// Thickness of the iridescent microfilm layer, value is in nanometers, range [0..1000]
float thickness;
};
ClearcoatArgs:
struct ClearcoatArgs
{
// Intensity of the clearcoat layer, range [0..1]
float specularity;
// Glossiness of clearcoat layer, range [0..1]
float gloss;
// The normal used for the clearcoat layer
vec3 worldNormal;
};
SheenArgs:
struct SheenArgs
{
// Glossiness of the sheen layer, range [0..1]
float gloss;
// The color of the f0 specularity factor for the sheen layer
vec3 specularity;
};
| 代码块 | 变更 |
|---|---|
ambient(Constant/Env/SH) |
|
aoDiffuseOcc |
|
aoSpec(Occ/OccConst/OccConstSimple/OccSimple) |
|
combine |
|
clusteredLight |
|
clusteredLightShadow |
|
combine |
|
end |
|
fallOff(InvSquared/Linear) |
|
fresnelSchlick |
|
iridescenceDiffraction |
|
lightDiffuseLambert |
|
lightSheen |
|
lightSpecular(AnisoGGX/Blinn/Phong) |
|
lightmap(DirAdd/Add) |
|
ltc |
|
metalnessModulate |
|
output(Alpha/AlphaPremul) |
|
reflDir(Aniso) |
|
reflection(CC/Cube/Env/EnvHQ/Sphere/SphereLow) |
|
reflectionSheen |
|
refraction(Cube/Dynamic) |
|
shadow(Common/Coord/CoordPerspZBuffer |
|
shadow(EVSM/EVSMn/Standard/StandardGL2/VSM8) |
|
spot |
|
TBN(-/ObjectSpace/derivative/fast) |
|
引擎 v1.60
| 代码块 | 变更 |
|---|---|
clearCoatGlossPS |
|
glossPS |
|
sheenGlossPS |
|
引擎 v1.57
1.57 修改了几乎全部前端代码块,以减少着色器采样器数量。这是可选功能,但建议遵循相同风格。受影响的代码块:
| 代码块 |
|---|
aoPS |
clearCoatPS |
clearCoatGlossPS |
clearCoatNormalPS |
diffusePS |
diffuseDetailMapPS |
emissivePS |
metalnessPS |
normalMapPS |
normalDetailMapPS |
opacityPS |
parallaxPS |
sheenPS |
sheenGlossPS |
specularPS |
specularityFactorPS |
thicknessPS |
transmissionPS |
自定义前端代码块若复用现有材质采样器,也支持此方式。需要:
- 移除代码块中的采样器 uniform 声明。
- 将采样器名称替换为
$SAMPLER宏。
例如:
uniform sampler2D texture_aoMap;
void getAO() {
dAo = 1.0;
#ifdef MAPTEXTURE
dAo *= texture2DBias(texture_aoMap, $UV, textureBias).$CH;
#endif
#ifdef MAPVERTEX
dAo *= saturate(vVertexColor.$VC);
#endif
}
改为:
void getAO() {
dAo = 1.0;
#ifdef MAPTEXTURE
dAo *= texture2DBias($SAMPLER, $UV, textureBias).$CH;
#endif
#ifdef MAPVERTEX
dAo *= saturate(vVertexColor.$VC);
#endif
}
这样引擎可自动选择采样器 uniform,减少总数。注意,仅前端代码块支持。
引擎 v1.56
| 代码块 | 变更 |
|---|---|
combineXXXX |
|
refractionPS |
|
refractionCubePS |
|
refractionDynamicPS |
|
sheenPS |
|
sheenGlossPS |
|
reflectionEnvHQPS |
|
thicknessPS |
|
bakeDirLmEndPs |
|
bakeLmEndPS |
|
引擎 v1.55
| 代码块 | 变更 |
|---|---|
clearCoatNormalPS |
|
clusteredLightPS |
|
combinePS |
|
combineXXXX |
|
diffusePS |
|
diffuseDetailMapPS |
|
endPS |
|
emissivePS |
|
fresnelSchlickPS |
|
lightmapSingleVert.js |
|
lightmapDirPS, lightmapSinglePS |
|
lightmapAddPS, lightmapDirAddPS |
|
lightSpecularAnisoGGXPS |
|
lightSpecularBlinnPS, lightSpecularPhongPS |
|
ltcPS |
|
normalMapFastPS |
|
normalMapPS |
|
normalDetailMapPS |
|
normalVertexPS |
|
metalnessPS |
|
metalnessModulatePS |
|
reflectionCC |
|
specularAaNonePS, specularAaToksvigPS, specularAaToksvigFastPS |
|
startPS |
|
specularPS |
|
specularityFactorPS |
|