双源混合
双源混合允许片元着色器为单个颜色附件输出两种颜色。第一种是参与混合的颜色值,第二种可选作混合因子。这支持亚像素文字抗锯齿和高级合成等无法通过单个片元输出表达的效果。
平台支持
双源混合在两个图形后端上都是可选能力:
- WebGPU 使用
dual-source-blending设备特性和 WGSL 语言扩展。 - WebGL 2 使用
WEBGL_blend_func_extended扩展。
PlayCanvas 通过同一个能力标志暴露两者:
const device = app.graphicsDevice;
if (!device.supportsDualSourceBlending) {
// Use a fallback material or rendering path.
}
该能力可用时,引擎还会定义 CAPS_DUAL_SOURCE_BLENDING。在 WebGPU 上,引擎为使用该功能的片元着色器变体添加 enable dual_source_blending;。
混合因子
可以通过四种混合因子引用第二个片元输出:
| 混合因子 | 说明 |
|---|---|
BLENDMODE_SRC1_COLOR | 第二源颜色 |
BLENDMODE_ONE_MINUS_SRC1_COLOR | 1 减去第二源颜色 |
BLENDMODE_SRC1_ALPHA | 第二源 alpha |
BLENDMODE_ONE_MINUS_SRC1_ALPHA | 1 减去第二源 alpha |
仅在 device.supportsDualSourceBlending 为 true 时使用这些常量。
StandardMaterial
材质的 BlendState 使用任一第二源因子时,会自动启用双源混合,无需单独的材质设置。关于混合状态如何与其他透明选项配合,参见透明度。
首先覆盖 outputPS 代码块,写入主、次片元输出。若支持两个图形后端,应同时提供 GLSL 和 WGSL 版本:
const material = new pc.StandardMaterial();
material.useLighting = false;
material.useTonemap = false;
material.getShaderChunks(pc.SHADERLANGUAGE_GLSL).set('outputPS', `
gl_FragColor = vec4(0.45, 0.02, 0.02, 0.0);
pcFragColorSecondary = vec4(0.0, 0.85, 0.18, 1.0);
`);
material.getShaderChunks(pc.SHADERLANGUAGE_WGSL).set('outputPS', `
output.color = vec4f(0.45, 0.02, 0.02, 0.0);
output.colorSecondary = vec4f(0.0, 0.85, 0.18, 1.0);
`);
然后配置混合状态。下面对 RGB 计算 source0 + destination * source1:
material.blendState = new pc.BlendState(
true,
pc.BLENDEQUATION_ADD,
pc.BLENDMODE_ONE,
pc.BLENDMODE_SRC1_COLOR,
pc.BLENDEQUATION_ADD,
pc.BLENDMODE_ZERO,
pc.BLENDMODE_ONE
);
material.update();
这里,gl_FragColor / output.color 是 source0,pcFragColorSecondary / output.colorSecondary 是 source1。第二个值参与混合,但不会写入独立的颜色附件。
ShaderMaterial
ShaderMaterial 也使用由 BlendState 驱动的相同行为。在片元着色器中写入两个输出,并赋予包含第二源因子的混合状态。引擎会自动为该材质生成双源着色器变体。
直接使用 ShaderDefinitionUtils.createDefinition 创建着色器定义时,传入 useDualSourceBlending: true。StandardMaterial 和 ShaderMaterial 无需这个底层选项。
限制
- 渲染目标必须恰好具有一个颜色附件。双源混合不能与多渲染目标结合。
- 支持情况取决于设备,因此赋予第二源混合因子前,始终检查
device.supportsDualSourceBlending。 - 双源混合按材质和绘制调用独立选择。同一渲染通道中的其他材质无需提供双源输出。
示例
双源混合示例先渲染黑白棋盘,再在上方绘制双源混合的四边形。黑格仅接收红色主输出,白格还会贡献绿色的第二输出。