第 8 章练习:多个图形与 RGB 叠加
对应教程:08 多个图形与 RGB 叠加
起始示例:三个圆的 RGB 叠加,修改 08-rgb-overlap.js 和需要时的 08-rgb-overlap.html。
练习 1:手算同一片元的三种结果
设某片元的三个遮罩分别为 redMask = 0.8、greenMask = 0.5、blueMask = 0.1,颜色增益为 1.0。
**目标:**分别算出纯 RGB 通道叠加得到的颜色、按红→绿→蓝顺序用 mix 覆盖得到的颜色,以及并集遮罩值。
**完成标准:**能说明三种结果为什么不同;数值允许小数点后两位的四舍五入。
练习 2:改变覆盖顺序
**目标:**新增“红→蓝→绿顺序覆盖”模式,与原来的红→绿→蓝模式并存。
**要求:**保持三个遮罩及圆心不变,只调整 mix 的调用顺序;新增下拉选项。
**完成标准:**三个圆完全重叠的位置在原模式偏蓝,在新模式偏绿;软边仍可看到下层颜色。
<details> <summary>提示</summary>
在遮罩值为 1 的位置,最后一次 mix 会完全覆盖前面的结果。
</details>
练习 3:在重叠处取平均颜色
**目标:**新增模式,把 vec3(redMask, greenMask, blueMask) 视为三个颜色的总贡献;当总遮罩大于 1 时,按总遮罩归一化,使重叠区域不因简单相加而持续变亮。
**要求:**使用 max(total, 1.0) 作除数,避免单个软边区域被额外放大;新增下拉选项。比较它与默认 RGB 叠加模式。
**完成标准:**一个完整圆的纯色区域基本不变;两个完整圆交叠时颜色大致是两色各半;三圆完整交叠时大致为三通道各三分之一。
<a id=“reference-answers”></a>
第 8 章练习参考解答
对应练习:多个图形与 RGB 叠加。
练习 1:手算同一片元的三种结果
- 纯 RGB 通道叠加:
vec3(0.8, 0.5, 0.1)。 - 顺序覆盖,从黑色开始:红之后
(0.8, 0, 0);绿之后(0.4, 0.5, 0);蓝之后(0.36, 0.45, 0.1)。 - 并集:
max(0.8, 0.5, 0.1) = 0.8,灰度颜色为(0.8, 0.8, 0.8)。
顺序覆盖每一步都保留前一结果的 1 - mask 部分,再加入当前图形的 mask 部分;它不是直接相加。
练习 2:改变覆盖顺序
在 08-rgb-overlap.html 增加:
<option value="4">按 R → B → G 顺序覆盖</option>
在片元着色器中,把原来的最终 else 并集分支改成 else if (uMode == 3),随后增加:
} else if ( uMode == 4 ) {
color = vec3( 0.0 );
color = mix( color, vec3( 1.0, 0.0, 0.0 ), redMask );
color = mix( color, vec3( 0.0, 0.0, 1.0 ), blueMask );
color = mix( color, vec3( 0.0, 1.0, 0.0 ), greenMask );
}
三个遮罩都为 1 时,最后一行得到绿色。原 uMode == 2 分支仍按红→绿→蓝的顺序执行,可以直接对照。
练习 3:在重叠处取平均颜色
继续增加下拉选项:
<option value="5">按遮罩总量取平均</option>
在模式判断末尾增加:
} else if ( uMode == 5 ) {
vec3 contributions = vec3( redMask, greenMask, blueMask );
float total = redMask + greenMask + blueMask;
color = contributions / max( total, 1.0 );
}
只有一个完整圆时 total = 1.0,颜色与默认模式一致;两个完整圆交叠时 total = 2.0,两个通道各为 0.5;三个完整圆交叠时 total = 3.0,三个通道各为 1/3。软边若总量小于 1,分母固定为 1,因此不会把微弱边缘放大成满亮度。这是平均贡献的效果,不是物理加光,也不是按顺序覆盖。