Files
engine/docs
shensi.zxd dd02420acc feat(core): GPU Instancing 自动合批(cherry-pick from galacean/engine#2957)
从 PR https://github.com/galacean/engine/pull/2957 (feat/gpu-instancing)
cherry-pick 69 个 commit 到 fix/shaderlab 分支,压缩为单次提交。

## 核心改动

### 新增文件
- `InstanceBuffer.ts` — UBO-based 实例数据管理,将多个 renderer 的
  worldMatrix/shaderData 打包到一个 UBO 中
- `VertexMergeBatcher.ts` — 替代旧 BatchUtils,统一 2D/3D 合批入口
- `ShaderBlockProperty.ts` — UBO block 属性描述
- `ShaderProgramMap.ts` — 替代旧 ShaderProgramPool,支持 instancing layout 缓存
- `ConstantBufferBindingPoint.ts` — UBO binding point 枚举

### 修改文件
- `MeshRenderer._canBatch/_batch` — 同 mesh+material+macros 自动合批判定
- `SkinnedMeshRenderer` — 标记不可 GPU instance
- `RenderQueue` — 按 material/primitive 排序(替代按距离排序),
  渲染时检测 instanced batch 并通过 InstanceBuffer 一次 draw
- `RenderElement` — 扁平化(移除 SubRenderElement),支持 instancedRenderers 列表
- `ShaderFactory` — UBO 布局计算、instancing GLSL 注入(RENDERER_GPU_INSTANCE macro)
- `ShaderPass` — 编译时检测 GPU instance macro,注入 UBO 声明
- `ShaderProgram` — 存储 instanceLayout
- `Renderer` — 移除 batched 相关字段

### 删除文件
- `BatchUtils.ts` → 替换为 `VertexMergeBatcher.ts`
- `SubRenderElement.ts` → 合并到 `RenderElement.ts`
- `ShaderProgramPool.ts` → 替换为 `ShaderProgramMap.ts`

## cherry-pick 冲突解决记录

fix/shaderlab 分支和 PR 基线 (dev/2.0) 的差异主要在以下文件:

1. **ShaderPass.ts** — fix/shaderlab 使用 `Shader._shaderLab._parseMacros`
   处理 ShaderLab 宏,而 PR 使用 `ShaderMacroProcessor.evaluate`(fix/shaderlab
   上不存在)。解决方式:保留 fix/shaderlab 的宏处理,加入 PR 的 instancing
   UBO 注入逻辑。
2. **Transform.glsl** — fix/shaderlab 已有 `camera_VPMat` 声明,PR 也添加了。
   解决方式:合并两边声明。
3. **UIRenderer.ts** — PR 将 `BatchUtils` 重命名为 `VertexMergeBatcher`,
   `batchFor2D` 重命名为 `batch`。fix/shaderlab 的 UI 包未同步。
   解决方式:手动更新 UI 包的 import 和调用。
4. **GLSLIfdefResolver.ts** — PR 早期 commit 新增此文件,后续 commit 删除。
   cherry-pick 后 ShaderPass.ts 残留了 import。解决方式:删除无用 import。

## 验证结果

CarParking 游戏 DrawCall 从 905 降至 ~80(同 mesh+material 的座椅、轮子等
自动合批)。
2026-04-23 17:26:31 +08:00
..